Symfony2 valid constraint on form element does not show custom error message - forms

I am constructing a form for users to submit a DMCA complaint, and one of the design requirements is to allow them to enter one or more URLs. To that end, I've created an entity (DMCAComplaint), and a child entity (DMCAComplaintURL) which is joined to DMCAComplaint in a Doctrine OneToMany relationship.
In order to validate the URL entries via regex, I have the following assertion set up:
// src: Bundle/Event/DMCAComplaintURL.php
/**
* #var string
*
* #ORM\Column(name="url", type="string", length=255, nullable=false)
* #Assert\Regex(
* pattern="/(https?:\/\/)?([\w].)*example.com(\/.*)?/"),
* message="Please enter a URL within our site"
* )
*/
protected $url;
And in the complaint:
// src: Bundle/Entity/DMCAComplaint.php
/**
* #var \DMCAComplaintURL
*
* #ORM\OneToMany(targetEntity="DMCAComplaintURL", mappedBy="dmcaComplaint", cascade={"persist"})
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id", referencedColumnName="dmca_complaint_id")
* })
* #Assert\Valid
*/
protected $urls;
While the assertion works, it only gives the following error: This value is not valid. I would like it to have a custom message, as outlined in the DMCAComplaintUrl $url property. Is there a way to make this bubble up to the Valid assertion? or can I use something else to get what I need?

Set error_bubbling to true on your form field:
http://symfony.com/doc/current/reference/forms/types/text.html#error-bubbling

Related

Invalid text representation: 7 ERROR: invalid input syntax for uuid: "test"

I'm using Symfony 3.2 with doctrine and postgresql.
I've created an entity with a uuid as primary key.
My entity definition:
/**
* Booking
*
* #ORM\Table(name="booking")
* #ORM\Entity(repositoryClass="AppBundle\Repository\BookingRepository")
* #ORM\EntityListeners({"AppBundle\EventListener\BookingListener"})
*/
class Booking {
/**
* #var string
*
* #ORM\Column(type="guid")
* #ORM\Id
* #ORM\GeneratedValue(strategy="UUID")
*/
private $id;
}
In my controller I have a show action like this:
/**
* #Route("booking/{id}", name="booking_show")
* #Method({"GET"})
*/
public function showAction(Request $request, Booking $booking) {
...
}
Everything seems to work fine, but when I try to load a route putting an wrong value as an ID (i.e. /booking/hello123), I receive a:
SQLSTATE[22P02]: Invalid text representation: 7 ERROR: invalid input syntax for uuid: "hello123"
Instead I would expect a 404.
Is there a way to capture this exception and redirect to a 404 page?
You can make use of Route Requirements - you can specify what conditions your parameter need to match to "qualify" to a certain route. This requirement is a regex, so all you need to do is to write a regex for an UUID
/**
* #Route("booking/{id}", name="booking_show", requirements={"id": "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"})
* #Method({"GET"})
*/
public function showAction(Request $request, Booking $booking) {
...
}
NOTE: Regex used above is just first result I found in Google for UUID regex, I didn't verify if it works
In the end if your id does not match regex, it does not match route and you should get 404.
you need to change the showaction
/**
* #Route("booking/{id}", name="booking_show")
* #Method({"GET"})
*/
public function showAction(Request $request,$bookingID) {
$em = $this->getDoctrine()->getManager();
$booking = $em->getRepository('AppBundle:Entity')->find(bookingID);
if(!$booking)
$this->createNotFoundException('No entity found with id :'.$bookingID);
...
}

Persisting a document suddenly stops returning next identifier value (ALNUM strategry)

I have Symfony 2.6 application and using doctrine-odm-bundle 3.0.2 (doctrine-odm: 1.1.2, mongodb: 1.4.0).
My document has referenceMany and referenceOne in attributes and when I create new instance of it, fill fields and persist - it goes fine in the begining. I can create few nearly empty documents, with referenced document(s) or without and it works fine. At some point I am trying to add new item in the database and getting an error:
E11000 duplicate key error collection: test.Product index: _id_ dup key: { : 0 }
The message is clear - I can see that there was a document added to the collection with id = 0, therefore second one can't go -> duplicate entry. But why it suddenly starts to return "0" for id? Even though, I checked doctrine_increment_ids collection - counter for id is being incremented. But $product->getId() becomes "0" after persist.
If I drop the database and start all over - it works, I can still add new products in the collection. Let's say I successfully created 12 products. Creating 13th resulting a document with id=0 being persisted in the collection. 14th fails with duplicate error.
Can you please help to troubleshoot or suggest an idea where does it go wrong?
P.S> I am not considering an upgrade of Symfony2 (at this point) neither as doctrine-odm-bundle (it depends on newer Symfony2 as well) - migration efforts are quite high and I am not sure it will fix the issue. First I want to find out the root cause.
// Document Product
/**
* #MongoDB\Document
* #MongoDB\HasLifecycleCallbacks
*/
class Product
{
/** #MongoDB\Id(strategy="ALNUM", type="int") */
protected $id;
/**
* #Gedmo\ReferenceOne(type="entity", class="Entity\User", inversedBy="products", identifier="userId")
*/
protected $user;
/**
* #MongoDB\Field(name="user_id", type="int")
*/
protected $userId;
/**
* #MongoDB\ReferenceMany(
* targetDocument="Picture",
* discriminatorMap={"file" = "File", "picture" = "Picture"},
* discriminatorField="discr",
* defaultDiscriminatorValue="picture"
* )
* #Assert\Valid
*/
protected $pictures;
...
}
// Entity User
/**
* User entity
* #ORM\Entity
* #ORM\Table(name="users")
*/
class User
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var ArrayCollection $textures
*
* #Gedmo\ReferenceMany(type="document", class="Document\Product", mappedBy="user")
*/
protected $products;
...
}
// Document Picture
/**
* #MongoDB\Document
* #MongoDB\InheritanceType("SINGLE_COLLECTION")
* #MongoDB\DiscriminatorField("discr")
* #MongoDB\DiscriminatorMap({"file" = "File", "picture" = "Picture"})
* #MongoDB\DefaultDiscriminatorValue("picture")
* #MongoDB\HasLifecycleCallbacks
*/
class Picture
{
/**
*
* #MongoDB\Id(strategy="ALNUM", type="int")
*/
protected $id;
/**
* #MongoDB\ReferenceOne(targetDocument="Product")
*
* #var Product $product
*/
protected $product;
...
}
Documentation reading always helps (generation strategies). Basically, strategy="ALNUM" and type="int" just can't go together :)
Change strategy to INCREMENT and remove type="int" if you want to have integers in your _id.
Or you can change type to string to continue with _id being an alphanumeric string.

zend2 + doctrine 2 Uncaught exception 'Doctrine\Common\Annotations\AnnotationException' $jobId does not exist

I am new to zend 2 and Doctrine 2. I tried to create an entity class but got the following message:
Fatal error: Uncaught exception
'Doctrine\Common\Annotations\AnnotationException' with message
'[Semantical Error] The annotation "#Doctrine\ORM\Mapping\jobId" in
property Workers\Entity\Jobsought::$jobId does not exist, or could not
be auto-loaded
Below is the entity class
namespace Workers\Entity;
use Doctrine\ORM\Mapping as ORM;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\Factory as InputFactory;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;
/**
*
*
* #ORM\Entity
* #ORM\Table(name="worker_main_jobsort")
* #property int $jobId
*/
class Jobsought implements InputFilterAwareInterface
{
protected $inputFilter;
/**
* #ORM\jobId
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $jobId;
/**
* Magic getter to expose protected properties.
*
* #param string $property
* #return mixed
*/
public function __get($property)
{
return $this->$property;
}
/**
* Magic setter to save protected properties.
*
* #param string $property
* #param mixed $value
*/
public function __set($property, $value)
{
$this->$property = $value;
}
}
Any ideas why the ORM cannot map it? The table exist in my database.
Also just started out using the two of these combined - but think I know what your issue is.
First off, you can't try specifying any "strange" (according to doctrine strange) annotations without using the #ignore directive.
Secondly, I think you're trying to say with #property int $jobId that "$jobId" is your PK? Well you're already doing so when you say #ORM\GeneratedValue(strategy="AUTO"), telling doctrine to map jobid to be your PK. Also, I read somewhere that adding name="job_id" to your #Column annotation is good practice, but don't quote me on that. Guess it doesn't really matter.
Hope this helps!
Edit -
My bad, also missed that you need to remove #ORM\jobId as it's not a valid doctrine annotation (jobId that is). Just specify it as #ORM\Id and you should be fine.

An error occurred while trying to call Controller->createAction()

I am trying to create something with extbase, but the error-message I get is not very helpful. I took the blog_example extension as a guide. A (maybe) important difference is: I don't have a database table because I want to write a custom domain repository that connects to an external servive through REST.
The actual error message (displayed above the plugin, not as an exception message):
An error occurred while trying to call Tx_MyExt_Controller_SubscriptionController->createAction()
Classes/Controller/SubscriptionController:
Stripped down to the important parts.
class Tx_MyExt_Controller_SubscriptionController extends Tx_Extbase_MVC_Controller_ActionController
{
/**
* #var Tx_MyExt_Domain_Repository_SubscriberRepository
*/
protected $subscriberRepository;
/**
* #return void
*/
public function initializeAction()
{
$this->subscriberRepository = t3lib_div::makeInstance('Tx_MyExt_Domain_Repository_SubscriberRepository');
}
/**
* #param Tx_MyExt_Domain_Model_Subscriber $subscriber
* #dontvalidate $subscriber
* #return string The rendered view
*/
public function newAction(Tx_MyExt_Domain_Model_Subscriber $subscriber = null)
{
$this->view->assign('subscriber', $subscriber);
}
/**
* #param Tx_MyExt_Domain_Model_Subscriber $subscriber
* #return string The rendered view
*/
public function createAction(Tx_MyExt_Domain_Model_Subscriber $subscriber)
{ }
}
Classes/Domain/Model/Subscriber
class Tx_MyExt_Domain_Model_Subscriber extends Tx_Extbase_DomainObject_AbstractEntity
{
/**
* #var string
* #dontvalidate
*/
protected $email = '';
/**
* #param string $email
* #return void
*/
public function setEmail($email)
{
$this->email = $email;
}
/**
* #return string
*/
public function getEmail()
{
return $this->email;
}
}
Resources/Private/Templates/Subscription/new
<f:form action="create" controller="Subscription" objectName="Subscriber" object="{subscriber}" method="post">
<f:form.textfield property="email"></f:form.textfield>
<f:form.submit value="submit"></f:form.submit>
</f:form>
Facts
Adding $subscriber = null removes the message. But $subscriber is null then
A var_dump($this->request->getArguments()); displays the form's fields
There is an index action, and it is also the first action defined in ext_localconf.php
The hints and solutions I found aren't working for me, so I hope someone can guide me into the right direction.
I've got the same bug.
If you pass an Model as argument to an method, it will also validate the model fields.
I've had this annotation on my model property:
/**
*
* #var \string
* #validate NotEmpty
*/
It validates the "#validate" annotation.
The field in the database was empty so i got the error message
An error occurred while trying to call ...
It would be good if there was a better error message.
You need to customize the validation annotation or verify that the property is not empty in the database
Hope it helps somebody
In addtion: check any Validations in your Model and your TCA. If a field is marked as #validate NotEmpty in your Model and is not marked appropriately in the TCA, a record can be saved ignoring the #validate settings in the Model. This can happen if you change the Model and/or TCA after creating records.
An example:
Field 'textfield' is set to not validate, both in the TCA and the Model. You create a new record and save it without filling in the field 'textfield' (you can, it is not set to validate). You then change the Model setting 'textfield' to #validate NotEmpty and then try to show the record on the FE, you will get the error.
The solution for that example:
Simply remove the validation in your Model OR check validations in the TCA and Model so that they work together.
--
A German blog post covers this solution: http://www.constantinmedia.com/2014/04/typo3-extbase-an-error-occurred-while-trying-to-call-anyaction/
just override the template method getErrorFlashMessage in yout controller to provide a custom error message...
/**
* A template method for displaying custom error flash messages, or to
* display no flash message at all on errors. Override this to customize
* the flash message in your action controller.
*
* #return string|boolean The flash message or FALSE if no flash message should be set
* #api
*/
protected function getErrorFlashMessage() {
return 'An error occurred while trying to call ' . get_class($this) . '->' . $this->actionMethodName . '()';
}
classic case of "start over from scratch and it works, and if you compare it you have the same code, though".
I updated the code in the question, maybe it helps someone.

Troubleshooting "[Syntax Error] Expected PlainValue, got ')'"

I am getting this error in my annotations docblock for Doctrine 2:
Doctrine\Common\Annotations\AnnotationException: [Syntax Error] Expected PlainValue, got ')'
After looking for an answer I found this reference Stackoverflow Question 3500125 which in essence says to put quotes around all values in annotations.
With the annotation block I have this does not seem possible. here is my example that is throwing the error.
/**
* #var tags
*
* #ManyToMany(targetEntity="namespace\to\tag")
* #JoinTable(name="content_tag",
* joinColumns={
* #JoinColumn(name="content_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* #JoinColumn(name="tag_id", referencedColumnName="id")
* }
* ) // This is the line indicated by the error
*/
private $tags;
If I follow the advice of the answer I found in stack overflow which is to quote out the values, my code will be like this:
/**
* #var tags
*
* #ManyToMany(targetEntity="namespace\to\tag")
* #JoinTable(name="content_tag",
* joinColumns="{
* #JoinColumn(name="content_id", referencedColumnName="id")
* }",
* inverseJoinColumns="{
* #JoinColumn(name="tag_id", referencedColumnName="id")
* }" // Note the extra quotation marks
* )
*/
private $tags;
Which is not right at all.
For people who have come here but not because of doctrine, my mistake was using single quotes instead of double quotes in the #Routes annotation.
WRONG:
/**
* #Route('/home')
*/
RIGHT
/**
* #Route("/home")
*/
It was a silly mistake, the error string was not very helpful as it pointed to the line i showed in my question as the line that the error was on. The fact was that this entity was extending a parent object, the parent had the #Entity tag but the child did not, i moved it and everything works fine.
I Just had the same kind of error by using an assert for an entity :
* #Assert\Email(
* message = "The email '{{ value }}' is not a valid email.",
* mode = 'strict',
* normalizer = 'trim'
* )
Turning it into
* #Assert\Email(
* message = "The email '{{ value }}' is not a valid email.",
* mode = "strict",
* normalizer = "trim"
* )
Fixed it :)