Symfony2 form component - date widget not working with mongodb - symfony

Form field declaration:
$builder->add('birthday', 'date', array('label' => 'Data urodzenia:', 'years' => range(date('Y'), date('Y')-100)), 'required' => false);
Corresponding document field declaration:
/**
* #ODM\Field(type="date")
*/
protected $birthday;
/**
* Set bitrhday
*
* #param \DateTime $birthday
*/
public function setBirthday(\DateTime $birthday)
{
$this->birthday = $birthday;
}
/**
* Get bitrhday
*
* #return \DateTime $birthday
*/
public function getBirthday()
{
return $this->birthday;
}
When I set data in form value is saved to database correctly, but widget isn`t populated with data form database field when I visit form page after saving.
Other fields in form works as expected.
It`s sf2 bug or my mistake?

First, birthday seems to be misspelled. Setbitrhday & Getbitrhday
Second, ODM does not support the DateTime field type. ODM only supports the field type Date. See ODM Field Type Reference
ORM, on the otherhand does support the DateTime field type. See ORM Field Type Reference

Related

SonataAdminBundle, How can I display list of a ManyToOne in the show view?

Using the SonataAdminBundle on a Symfony Application, I'm trying to display a set of previously stored records of a child entity in the SHOW view
The application is about logging visit details for a visit, where I have a visit entity with a visitDetail property set as OneToMany:
Entity\Visit.php
/**
* #var \AppBundle\Entity\VisitDetail
*
* #ORM\OneToMany(targetEntity="AppBundle\Entity\VisitDetail", cascade={"all"}, mappedBy="visitVisit", orphanRemoval=true ))
* #ORM\OrderBy({"visitDetailId" = "ASC"})
*/
private $visitDetail;
And in the VisitDetail Entity I have a the properties like: Type, Date, Comments etc..
As for the Sonata Side I have:
VisitAdmin.php
// Fields to be shown on show action
protected function configureShowFields(ShowMapper $showMapper)
{
$showMapper->add('visitDetail')
}
How can I display all the records in visitDetail that belongs to the visit?
One way to do that is to create a __toString() function in your VisitDetail entity, where you return the properties you want to show of course.

symfony symfony3 new single ManyToOne object ( owning side of the association )

I have Cases, which also have Attachments. This is coded as a Case entity with the OneToMany association to Attachment entity. The Attachment entity has a ManyToOne association to Case entity. The code:
class Case {
/**
* #var integer
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="Attachment", mappedBy="case",cascade={"persist"})
*/
protected $attachments;
class Attachment
{
/**
* #var integer
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Case", inversedBy="attachments")
* #ORM\JoinColumn(name="case_id", referencedColumnName="id")
*/
protected $case;
}
Im trying the following. I pretend to show/open the whole case into a single page. Inside the page, there will be the attachment list. At the end of that list, I pretend to put a form for new attachment submissions.
So I have written a controller to show the case, and I have created a new attachment form (AttachmentType ) and place it in the middle of the twig template, passing it into the render call of the action as a argument.
// CaseController.php
/**
* #Route("/cases/show/{case}", name="showCase", requirements={ "case" : "\d+" } )
*/
public function showCaseAction(Request $request, $case)
{
$theCase = $this->getDoctrine()->getRepository('AppBundle:Case')->findOneById( $case );
$attachment = new Attachment();
$attachment->setCase( $theCase );
$attachmentForm = $this->createForm(AttachmentType::class, $attachment);
if ( ! $theCase ) {
$this->addFlash('danger', $this->get('translator')->trans('cases.show.case_not_found', [ '%case%' => $case ] ) );
}
return $this->render('cases/caseContainer.html.twig', array( 'case' => $theCase, 'attachmentform' => $attachmentForm->createView() ) );
}
And also I have written a newAttachmentAction into the controller to perform the attachment creation.
I stop writting my code here. I dont want to condition the possible answers.
My problem is that im not able to figure out how to recover the Case object when the newAttachmentAction is called, so I can do the association. I cant figure out if i should place something ( HiddenType,EntityType,etc ) into the Attachment Form Builder to store the Case object, or maybe would be better to use some other Symfony mechanism (Services, Closure, StorageTokens). I have made a wide search along the web, but i have read some many articles, that Im stucked ! Im probably missing the right search keywords.
I hope i have made my self clear, and therefore someone can point me into the right direction to find an example or a tutorial.
Best regards and many many thanks for your time and attention !
For creating a Case, i will add a HiddenType for attachment property inside the CaseformType.
Set data_class to Attachment
When you will create the form, you will pass a new instance of Case with the attachment reference.
After the post, when you will receive the form data, you will have the linked object

How specify parameter's format in Nelmio ApiDocBundle

I use input property of #ApiDoc annotation for specifieng of parameters of my api that are form's fields.
* #ApiDoc(
* section="User",
* resource=true,
* input={
* "class"="Nik\UserBundle\Form\UserType",
* },
* ....
data_class of form is a entity that have constraint validation for properties.
I expect that nelmio api doc specify parameter format as validation constraints of entity, but format are empty.
How can i specify parameter formats in nelmio ApiDocBundle?
EDIT:
maybe i write a bad question.
we can specify parsers for input & output, if we no specify parser for these, it call all parser for input & output, then all parser are called for UserType.
nelmio have a parser named ValidationParser that have a method named parseConstraint that set format for input & output, but this method is not called for my document, why?
Format column is designed only for datetime, date and choice types.
For datetime and date it represents the date format like Y-m-d H:i:s and the array of choices for choice.
I haven't found any documentation about it, so I had to look through the source code. This is FormTypeParser class, the place where FormType is actually parsed and and you can see how format field is set.
In FormTypeParserTest class you can see how to use it. Just pass the string parameter with format name for one of the available types and the parser will handle it.
UPDATE: You are to define your constrains inside your FormType class.
For example:
class TestType extends AbstractType
{
/**
* #Assert\Type("string")
* #Assert\Length(min="10", max="255")
* #Assert\Regex("/^[^<>]+$/i")
*/
private $title;
/**
* #Assert\Type("string")
* #Assert\Length(min="10", max="255")
* #Assert\Regex("/^[^<>]+$/i")
*/
private $content;
/**
* #Assert\Date()
*/
private $created;
public function getName()
{
return 'test';
}
}
will be parsed into:
ValidationParser in
doParse() method finds all constrains defined in your FormType class and then executes parseConstraint() method for each of them.
You can also use FormTypeParser as I described above. For example:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('created', 'date', array('label' => 'Created', 'format' => 'yyyy-MM-dd'))
->add('color', 'choice', array('label' => 'Color', 'choices' => array('grey' => '#CCCCCC', 'red' => '#FF0000')))
->add('save', 'submit');
}
will be parsed as:
Hope it helps now!
i submit a pull request that use validation metadata for format property.
you can see this PR here
As you can see here you can specify filter in annotation like it done documentation example.
Here part of this example:
/**
* This is the documentation description of your method, it will appear
* on a specific pane. It will read all the text until the first
* annotation.
*
* #ApiDoc(
* resource=true,
* description="This is a description of your API method",
* filters={
* {"name"="a-filter", "dataType"="integer"},
* {"name"="another-filter", "dataType"="string", "pattern"="(foo|bar) ASC|DESC"}
* }
* )
*/
public function getAction()
{
}

Unable to deal with MySQL column of type "SET" in Sonata Admin

I have a column in MySQL table defined as follows:
`fuel_type` set('gasoline','diesel','LPG','CNG','ethanol','bio-diesel','hydrogen') DEFAULT NULL,
I generated entities usingn doctrine's database introspection feature. The generated code in the entity in question is this:
/**
* #var simplearray
*
* #ORM\Column(name="fuel_type", type="simplearray", nullable=true)
*/
private $fuelType;
/**
* Set fuelType
*
* #param \simplearray $fuelType
* #return NomEngine
*/
public function setFuelType(\simplearray $fuelType)
{
$this->fuelType = $fuelType;
return $this;
}
/**
* Get fuelType
*
* #return \simplearray
*/
public function getFuelType()
{
return $this->fuelType;
}
In my sonata admin class the configureFormsFields method is thefined this way:
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('name')
->add('fuel_type', 'choice', array(
'choices' => array(
'gasoline' => 'Gasoline',
'diesel' => 'Diesel',
'LPG' => 'LPG',
'CNG' => 'CNG',
'ethanol' => 'Ethanol',
'bio-diesel' => 'Bio Diesel',
'hydrogen' => 'Hydrogen'
),
'multiple' => true,
'required' => false
));
;
}
The problem is that after I try to save record in the database I get this exception:
Unknown column type "simplearray" requested. Any Doctrine type that you use has to be registered with \Doctrine\DBAL\Types\Type::addType(). You can get a list of all the known types with \Doctrine\DBAL\Types\Type::getTypesMap(). If this error occurs during database introspection then you might have forgot to register all database types for a Doctrine Type. Use AbstractPlatform#registerDoctrineTypeMapping() or have your custom types implement Type#getMappedDatabaseTypes(). If the type name is empty you might have a problem with the cache or forgot some mapping information.
500 Internal Server Error - DBALException
I tried a couple of things to resolve this issue:
I noticed, that the generated type is 'simplearray', but in doctrine this type is 'simple_array'. I thought there was a typo.
Without success I tried to map simplearray to simple_array in config.yml :
doctrine:
dbal:
mapping_types:
simplearray: simple_array
After that I tried to change simplearray to simple_array in the entity. I got this error:
Catchable Fatal Error: Argument 1 passed to Acme\AdminBundle\Entity\Engine::setFuelType() must be an instance of simple_array, array given,
I thought that the admin class was passing array, and the entity was expecting simple_array, so I changed simple_array to array in the entity.
Now the error was this:
Could not convert database value "" to Doctrine Type array 500 Internal Server Error - ConversionException
Any insights about dealing with set columns in Sonata Admin will be greatly appreciated!
Your entity setter & getter are wrong too and should deals with a PHP array as Doctrine is converting it, I think you must change them to:
/**
* Set fuelType
*
* #param array $fuelType
*
* #return NomEngine
*/
public function setFuelType(array $fuelType)
{
$this->fuelType = $fuelType;
return $this;
}
/**
* Get fuelType
*
* #return array
*/
public function getFuelType()
{
return $this->fuelType;
}
It seems that Doctrine doesn't handle well the set syntax in MySQL. I see 2 ways you could solve your issue:
Change your MySQL schema to put in a json array or a varchar instead of your set. Probably the fastest way.
You might not have the luxury to change your schema. In that case, define a custom Doctrine type to suit your needs as described there: http://docs.doctrine-project.org/en/2.0.x/cookbook/mysql-enums.html#solution-2-defining-a-type ; you'll need then to register it to Symfony as explained there: http://symfony.com/doc/current/cookbook/doctrine/dbal.html#registering-custom-mapping-types
Hope it helps!

Entity form field and validation in Symfony2?

In my form I have field of type entity. How to disable validation of that entity when the form is submitted? This entity is already persisted in database, so there is no point for validator to validate this entity from my point of view.
EDIT:
Code looks like this:
class SearchRequest
{
/**
* #ORM\ManyToOne(targetEntity="ArticlePattern")
* #ORM\JoinColumn(name="article_pattern_id", onDelete="CASCADE")
* #Assert\NotBlank
*/
private $articlePattern;
}
form field:
$builder
->add('articlePattern', 'entity', array('class' => 'LonbitItssBundle:ArticlePattern')
Validation groups won't work because what I want to accomplish is for validator to check the constraint #Assert\NotBlank on $articlePattern field, but I don't want him to check the constraints defined in class ArticlePattern. So in other words, I want prevent validator from descending inside the $articlePattern object, but I want the constraint placed on $articlePattern field itself to be validated.
Any idea how to do that?
EDIT2:
Validation groups will work. So the final solution is to add groups={"search_request"} constraint option (name of the group is arbitrary) to every field assertion in SearchRequest class, like this:
/**
* #Assert\NotBlank(groups={"search_request"})
*/
private $articlePattern;
That way, validation won't descend to associated objects (assuming they don't belong to - in this case - "search_request" group).
1) If you want to disable this field, just don't use it in your class form ! (and remove it from the template)
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('content')
->add('username')
//->add('yourEntity')
;
}
2) Or better, use validation groups. You create a validation_group which don't call your validator entity and then you use this group in your class form:
public function getDefaultOptions(array $options)
{
return array(
'data_class' => 'Sybio\BuzzBundle\Entity\SearchRequest',
'csrf_protection' => true,
'csrf_field_name' => '_token',
'intention' => '865c0c0b4ab0e063e5caa3387c1a8741',
'validation_groups' => array('without_article_pattern_ckecking'),
);
}
In your Entity class:
/**
* #ORM\ManyToOne(targetEntity="ArticlePattern")
* #ORM\JoinColumn(name="article_pattern_id", onDelete="CASCADE")
* #Assert\NotBlank(
* groups={"without_article_pattern_ckecking"}
* )
*/
private $articlePattern;
Your form will only validate validators that refer to without_article_pattern_ckecking group, so it should not test validators inside your ArticlePattern entity if they don't have this validation group.
I hope this helps you !

Resources