I've created my own data transformer, as explained in the dedicated cookbook, here is my reverse transformation:
public function reverseTransform($val)
{
// ...
// My logic here
// ...
// If $val is not valid
throw new TransformationFailedException(
'My custom error message'
);
}
The question is: how do I get the "custom error message" thrown? I would like to display it as the error message of my form field. How do I do that?
Thanks!
Sort answer is: You don't. The transformers job is to, well, transform and not to do error checking.
Add a constraint to the field which will check the transformed value and take care of error messaging.
Related
Is it possible to check which Constraint was violated after form submit?
I want to make specific action after submiting but only if particular error appears (custom constraint).
Yes you can. It's not a very clean way (since it's a pretty custom use case of forms), but it's possible.
Here's a simple code sample. It may not handle some edge cases, but works for my forms:
//You can get errors from form like this:
$errors = $form->getErrors(true);
// Or like this if you want to check a particular field of your form
$errors = $form->get('someField')->getErrors(true);
//Now you have to iterate them and check
//if it's the error that you're looking for
foreach($errors as $error) {
//From the error you can get the constraint that caused it.
$constraint = $error->getCause()->getConstraint();
//Check if the constraint is the instace of the class
//that you're insterested in.
//It's ISBN validator in my example.
if($constraint instanceof Symfony\Component\Validator\Constraints\Isbn) {
// do anything you want.
break;
}
}
How can I write the two lines of code below into one line of code:
$service_review->user_id=\Auth::user();
$user_service->service_reviews()->save($service_review);
The reason being that the line including Auth::user() is throwing an error since it's a foreign key in my "service_reviews" table and so "DOESN'T HAVE A DEFAULT VALUE"
The problem is if I give precedence to:
\Auth::user()->service_reviews()->save($service_review);
Then in this case, the authorized user is fetched but my user_service_id now throws the error as "DOESN'T HAVE A DEFAULT VALUE".
The code of my store method (This is from my ReviewsController that is based on a Nested Route:
Route::resource("services.reviews", "ReviewsController"); is as follows:
public function store(ReviewsRequest $request, $id){
$service_review = new Service_review($request->all());
$user_service = User_service::findOrFail($id);
$service_review->user_id=\Auth::user();
$user_service->service_reviews()->save($service_review);
return redirect("reviews");
I reckon passing them in one line of code will solve this error.
Yes your're right #MinaAbadir
I ended up doing it as follows:
public function store(ReviewsRequest $request, $id){
$service_review = new Service_review($request->all());
$user_service = User_service::findOrFail($id);
$service_review->user_id = \Auth::user()->email;
$user_service->service_reviews()->save($service_review);
return redirect("reviews");
}
It seems calling the specific column you want retrieved negates the foreign key problem. Maybe MySQL figures out the relationship via Eloquent. Let me know if I can clean this up further.
How do I replace an assertion error message? If I call $this->assertTrue(false, 'message'), it will display both the string "message" and also another message stating that false is not true. How do I get it to only output the message that I chose? Is this even possible?
code-crutch which comes to my mind when I faced the same problem:
public function assertTrue($condition, $message = '')
{
if (!$condition) $this->fail($message);
}
With PHPUnit 6 you must have got one assertion at least, so i suggest a little edited #avolkov answer:
public function assertTrue($condition, $message = '')
{
if (!$condition){
$this->fail($message); //This will cause test fail with your message
}
else{
$this->anything(); //This will eliminate error which says that your test doesn't have assertion
}
}
It's not possible.
Why would you want to do so? Never encountered a case in which the default message is not helpful in any way. The custom message should add information, not replace the default one.
Edit
The basic question here is "when does the $op parameter get defined as 'search'"?
I am trying to create a custom search in an implementation of hook_search(). I have been looking through the Drupal documentation for the method here: http://api.drupal.org/api/drupal/developer--hooks--core.php/function/hook_search/6
I know the method is running because I can slip a die('killed inside of implementation of hook_search()') into the top of the function and see the output.
In the following code, the script is never killed so that I can see the output search caught inside of my_search(). This leads me to believe that the 'search' case of the switch statement is never firing. Does anybody know where I might go from here?
/**
* Implementation of hook_search()
*/
function my_search($op = 'search', $keys = NULL) {
switch($op)
{
case 'search':
die('search caught inside of my_search()');
break;
}
}
First things first.
Assuming your module is called 'my', try to go to URL /search/my/whatever - probably you will see access forbidden page (assuming you do not have anything more in your code besides what you have pasted in your question).
That's because you do not return anything when search module calls your hook with $op = 'name' (see _search_menu() in search.module). You need to return "a translated name defining the type of items that are searched for with this module ('content', 'users', ...)" - see http://api.drupal.org/api/drupal/developer--hooks--core.php/function/hook_search/6 And access forbidden gone.
Once this is done, search will call your hook again (actually, there are quite a few calls, you can for example drupal_set_message($op) in your hook to see them all), and one of those calls will be with $op = "search" as well (coming from search_data() in search.module).
While working with Hibernate Validator, I noticed that the #NotEmpty and #NotNull annotations produce duplicate messages in the InvalidValue array returned by getInvalidValues(...).
If I specify a message like #NotEmpty(message = "My error message."), then I'll get one InvalidValue of "My error message." and a second of "may not be null or empty"
If i don't include a message (eg #NotEmpty by itself), then I get two copies of the InvalidValue with a message field of "may not be null or empty".
Why does Hibernate Validator do this?? Shouldn't I get one message, either the value that I override using the parameter, or the default message, but not both??
For some more context:
I am extending ClassValidator<T> with my own ClassValidator<MyClass> implementation. I do so to add some custom validations which cannot be done by annotation. I need to see the run time value of more than one property of the class in order to determine the validation.
I get the validations when I call myClassValidator.getInvalidValues(), which I override. Inside my implementation of getInvalidValues() I call super.getInvalidValues() to create the initial error list, and then I add my custom errors to that list. In any case, the call to super.getInvalidValues() contains the duplicate messages, one matching the message property passed into the annotation, and a second with the stock value of the annotation message.
Justin,
I've been working with Hibernate Validator for the last couple of months. While I have not run into the same issue that you've described, I also have not extended ClassValidator. For custom validation, the Hibernate Reference Guide indicates that writing custom constraints is the way to go.
I have been able to use the built-in constraints almost exclusively on my current project. In one case, where I needed to do some very specific calculations on an integer field, I wrote a custom constraint as described in the reference guide; it was a breeze.
Speaking to your specific problem, I wrote a simple test app as a sort of sanity check on my part:
import org.hibernate.validator.*;
public class HibernateValidatorTest {
#NotEmpty
#NotNull
private String validateMe;
public static void main ( String[] args ) {
ClassValidator<HibernateValidatorTest> validator =
new ClassValidator<HibernateValidatorTest>( HibernateValidatorTest.class );
InvalidValue[] inVals =
validator.getInvalidValues( new HibernateValidatorTest() );
for ( InvalidValue inVal : inVals ) {
System.out.println( inVal.getMessage() );
}
}
}
With both Hibernate constraints on the validateMe field, the console output is:
may not be null or empty
may not be null
Removing one or the other has the expected effect of printing only a single message to the console.
I hope this is helpful.
Brian T. Grant