Symfony + Doctrine + Annotation validation not work in forms - forms

I'm using doctrine annotations in my entities definition to define each variable behavior, i.e.:
#ORM\Column(type="string", length=50, nullable=false)
If I submit the form leaving the field empty, it pass the validation, but (of corse) I receive an error about the INSERT statement, because he cannot insert NULL value.
How this could be possible?

This is because Symfony does not automatically validate your form input based on Doctrine annotations.
Symfony2 ships with a Validator component that makes this task easy and transparent though. This component is based on the JSR303 Bean Validation specification.
Read up on the implementation at http://symfony.com/doc/current/book/validation.html
Here is an example of Validator annotation that might assist you:
// Acme/TaskBundle/Entity/Example.php
use Symfony\Component\Validator\Constraints as Assert;
class Example
{
/**
* #Assert\NotBlank()
* #Assert\MaxLength(50)
* #ORM\Column(type="string", length=50, nullable=false)
*/
public $parameter;
}

Related

Removing ChoiceType transformers during Pre Submit events

I have a form with a collection subform inside. In the subform, there is a choiceType field for the attribute "resourceId". Its data are populated by ajax, with Select2 js plugin (because its data depends on another choice, in which you select the resource type).
In the specific case that i have already a value in resourceId choice, i can't validate my field :
transformationFailure: TransformationFailedException {#4328 ▼
#message: "Unable to reverse value for property path "resourceId": The choice "bd922d35fb828da6e39edf3c7927511c9a6be025" does not exist or is not unique"
This is due because i have to add the default value of the field by javascript (thanks Select2).
I need to cancel the validation on the field, but even if i use the ResetViewTransformers() in the BuildForm method and by rebuilding the field in the PreSubmit event, it still doesn't validate.
TL;DR : How can i cancel validation during PreSubmit event ? (only on my field if possible)
Found the solution. I was going in the wrong direction.
All i had to do was overriding the ChoiceType class and disable the ViewTransformers, then use the new class :
class NonTransformedChoiceType extends ChoiceType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder->resetModelTransformers();
$builder->resetViewTransformers();
}
}
add some jquery and add the .ignore class to your specific form field. If you load whole form i suggest loading them seperately so that way you can easily add it.
$("#myform").validate({
ignore: ".ignore, :hidden"
})
Hidden will also make sure that any fields you do hide, for other reason will not be affacted and then give errors, reference: here

Typo3 frontend plugin, use _POST data in the controller

I wrote a very simple extension in typo3 v7.6.11 with the extension builder where a visitor can ask for a taxi-ride.
everything works, only that I need to make the request more appealing by asking the pick-up point and the drop-off point ... that request goes to the actual form like this in the template (requestPid is the id of the page with the form):
<f:form pageUid="{settings.additional.requestPid}" action="form" name="request" object="{Request}">
<f:render partial="Ticket/RequestNewFields" />
<f:form.submit value="{f:translate(key: 'tx_wmnltickets_domain_model_ticket.admin.continue')}" />
</f:form>
but the formAction in the controler doesn't actually ask anything from the model (getArguments() I tried);
/**
* action form
*
* #return void
*/
public function formAction() {
$this->request->getArguments();
}
the request does send the $_POST but I see no way to get it into the form ...
if you'd like to see more code to understand, just ask, I don't know what you'd be looking for ...
Your form action should has the request parameter from you form:
/**
* action form
*
* #param array $request
*
* #return void
*/
public function formAction($request) {
}
Then you can access the data with $request['origin']
I'm not sure if the variable $request is allowed as argument. Maybe you must rename it in the function and in your fluid template if it doesn't work.
Did you create the extension with the builder? The easiest way is to create the fields (pickup-point, dropoff-point) in the builder, then create a createAction or newAction (not sure how it is called in the builder). It will create the template for the createAction where you can just copy/paste the <f:form...
There is a way to access directly POST/GET parameters (It is not recomended to use it directly when you can make it with the clean extbase way):
$myVar = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('myVar');

TYPO3 Fluid: Map m:n values from multiple select form to model

I have a m:n relation in my domain model:
inquiry is the aggregate root in my domain model
several investigators can be assigned to each inquiry.
In the inquiry model this is defined:
/**
* #var Tx_Extbase_Persistence_ObjectStorage<Tx_MyExt_Domain_Model_Investigator>
*/
protected $investigator;
The investigator domain model is mapped to the fe_user table of TYPO3, which is noted properly in the configuration (ext_typoscript_setup.txt):
config.tx_extbase{
persistence{
classes{
Tx_MyExt_Domain_Model_Investigator {
mapping {
recordType = Tx_Extbase_Domain_Model_FrontendUser
tableName = fe_users
}
}
}
This works fine, I can display and edit inquiry records in the backend and frontend. However, when I want to change the investigators assigned to one inquiry (from edit action), I get an exception after submitting my form:
#1297759968: Exception while property mapping at property path "investigator":
No converter found which can be used to convert from "array" to
"Tx_Extbase_Persistence_ObjectStorage"
The multiselect-box that I use for this is created like that:
<f:form.select multiple="true" size="10" property="investigator"
value="{inquiry.investigator}" options="{allInvestigators}"
optionLabelField="name" />
Which is rendered like this:
<select name="tx_myext_inquiry[inquiry][investigator][]" size="10" multiple="true">
<option value="362">John Doe</option>
<option value="590">Jane Doe</option>
<option selected="selected" value="361">Steve Miller</option>
<option value="720">James Brown</option>
<option value="726">Janis Joplin</option>
</select>
{allInvestigators} is an array with all users from the group "investigators".
The values already stored are marked with "selected", which proves that some of my code is correct ;).
I tried fiddling around with the type converter (Tx_Extbase_Property_TypeConverter_PersistentObjectConverter Dok) in the InquiryController to cast my array to an object, but it to no avail. The field investigator is passed as an array to the update action, which triggers the exception.
I spend five hours on this now, need to move on.
How can I get rid of this error message?
Is converting the array to an object the right approach at all?
(Any questions for more details will be answered ASAP)
Edit:
Environment: TYPO3 version 6.1.1, Fluid 6.1.0, Extbase 6.1.0
I found the culprit in the model definition in Classes/Domain/Model/Inquiry.php
/**
* #var Tx_Extbase_Persistence_ObjectStorage<Tx_MyExt_Domain_Model_Investigator>
*/
protected $investigator;
I changed (part of) the #var annotation to name space style:
/**
* #var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<Tx_MyExt_Domain_Model_Investigator>
*/
protected $investigator;
Now the update process works. I guess in our project we need to standardize the model to name spaces.
If this is a bug, I will file it at forge.typo3.org.
This is currently a known problem in the 6.* branches of TYPO3.
See http://forge.typo3.org/issues/54289 there is currently a patch pending to get this fixed.
I have tested it with TYPO3 6.1 and TYPO3 6.2-dev from GIT and can't reproduce this problem. So it would be nice if you can give up some environment informations. Please start with your current TYPO3-Version.

Symfony2: #Assert\MaxLength and input maxlength attribute

I got a Doctrine entity having one field:
/**
* #PHPCRODM\String()
* #Assert\MaxLength(255)
*/
protected $title;
Is it possible to force a maxlength attribute for the input generated from this field, without having to specify it manually?
Apparently, PHPCRODM does not accept such an option. Sad... :(
[Creation Error] The annotation #PHPCRODM\String declared on property [...]\Article::$title does not have a property named "length". Available properties: type, translated, name, property, multivalue, assoc, nullable
Should create a PR when I'll get some free time. :)

Overriding Form Validation messages on symfony2

How to override the form validation messages in symfony2. Though there is a validation.xml file related model classes. I think it validates a form based on html5.
"Please match the requested format", "Please fill out this field". Is there any way to override this validation messages.
Please help me in this regard, i am stuck for more than a day, as i am totally new to symfony
Those messages you see are HTML5 validation messages which are created by the browser. If you want to override them you need to add an oninvalid attribute to the input tag associated with that field. You can do this in two ways:
In your controller or form type, add this attribute to the form field:
$builder->add('email', 'email',array(
'attr'=>array('oninvalid'=>"setCustomValidity('Would you please enter a valid email?')")
));
Or, in your twig template, add this attribute when rendering the form field:
{{ form_row(form.email, { 'attr': {'oninvalid': "setCustomValidity('Please give me a nice email')"} }) }}
You can change the message of each validator thanks to the message option when declaring the assert:
/**
* #ORM\Column(type="string", length=255, unique=true)
* #Assert\NotBlank(
* message="You have to choose a username (this is my custom validation message).",
* groups={"registration", "account", "oauth"}
* )
Also you can apply translation by creating the file MyBundle/Resources/translations/validators.fr.xliff