How to access form elements in controller symfony2 - symfony

I've generated the form through entity generator,
I've extended the Cobrand Controller
class CobrandController extends Controller
{
public function createAction()
{
// the key used to lookup the template
$templateKey = 'edit';
if (false === $this->admin->isGranted('CREATE')) {
throw new AccessDeniedException();
}
$object = $this->admin->getNewInstance();
$this->admin->setSubject($object);
/** #var $form \Symfony\Component\Form\Form */
$form = $this->admin->getForm();
$form->setData($object);
if ($this->getRestMethod()== 'POST') {
// $cobrand = new Cobrand();
$em=$this->getDoctrine()->getManager();
$cobrand=new Cobrand($em);
$form->bind($this->get('request'));
$isFormValid = $form->isValid();
// persist if the form was valid and if in preview mode the preview was approved
if ($isFormValid && (!$this->isInPreviewMode() || $this->isPreviewApproved())) {
$this->admin->create($object);
if ($this->isXmlHttpRequest()) {
return $this->renderJson(array(
'result' => 'ok',
'objectId' => $this->admin->getNormalizedIdentifier($object)
));
}
$this->addFlash('sonata_flash_success','flash_create_success');
// redirect to edit mode
return $this->redirectTo($object);
}
// show an error message if the form failed validation
if (!$isFormValid) {
if (!$this->isXmlHttpRequest()) {
$this->addFlash('sonata_flash_error', 'flash_create_error');
}
} elseif ($this->isPreviewRequested()) {
// pick the preview template if the form was valid and preview was requested
$templateKey = 'preview';
$this->admin->getShow();
}
}
$view = $form->createView();
// set the theme for the current Admin Form
$this->get('twig')->getExtension('form')->renderer->setTheme($view, $this->admin->getFormTheme());
return $this->render($this->admin->getTemplate($templateKey), array(
'action' => 'create',
'form' => $view,
'object' => $object,
));
}
}
Here's my entity code,
class Cobrand
{
/**
* #var \DateTime
*/
private $created;
/**
* #var \DateTime
*/
private $updated;
/**
* #var string
*/
private $name;
/**
* #var string
*/
private $code;
/**
* #var string
*/
private $logo;
/**
* #var boolean
*/
private $cobrandedProductsOnly;
/**
* #var integer
*/
private $id;
/**
* #var \Doctrine\Common\Collections\Collection
*/
private $productPrices;
/**
* #var \Doctrine\Common\Collections\Collection
*/
private $promocodes;
/**
* Constructor
*/
public function __construct()
{
$this->productPrices = new \Doctrine\Common\Collections\ArrayCollection();
$this->promocodes = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Set created
*
* #param \DateTime $created
* #return Cobrand
*/
public function setCreated($created)
{
$this->created = $created;
return $this;
}
/**
* Get created
*
* #return \DateTime
*/
public function getCreated()
{
return $this->created;
}
/**
* Set updated
*
* #param \DateTime $updated
* #return Cobrand
*/
public function setUpdated($updated)
{
$this->updated = $updated;
return $this;
}
/**
* Get updated
*
* #return \DateTime
*/
public function getUpdated()
{
return $this->updated;
}
/**
* Set name
*
* #param string $name
* #return Cobrand
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set code
*
* #param string $code
* #return Cobrand
*/
public function setCode($code)
{
$this->code = $code;
return $this;
}
/**
* Get code
*
* #return string
*/
public function getCode()
{
return $this->code;
}
}
User will enter the values on the form and I wan't to access those values in the createAction method of controller.
I want to change the value of $name in the controller.
How to access this ?
Thanks,
Faisal Nasir

Try this after binding request
$form->get('name')->setData('new value');

Related

Symfony 3.4: Issues on saving an Object ArrayCollection OneToMany

I need your help on my problem for saving my data in table.
I use fosUserBundle and have different user types (Admin, Pro, Client) that are classes extending a base User entity.
I also have a Language entity linked to the User with a one-to-many association.
To subscribe, a userClient needs to check by checkbox the language(s) that he speaks.
The form page is ok, it displays the UserClient form (+ the parent User form) with the list of languages as checkboxes.
The problem is the data saved in table.
I have the same values in the language column:
O:43:"Doctrine\Common\Collections\ArrayCollection":1:{s:53:"Doctrine\Common\Collections\ArrayCollectionelements";a:2:{i:0;O:32:"LanguagesBundle\Entity\Languages":10:{s:36:"LanguagesBundle\Entity\Languagesid";i:2;s:38:"LanguagesBundle\Entity\Languagesname";s:7:"English";s:44:"LanguagesBundle\Entity\Languagesshort_slug";s:2:"en";s:43:"LanguagesBundle\Entity\Languageslong_slug";s:5:"en_EN";s:43:"LanguagesBundle\Entity\LanguagesisDefault";b:0;s:43:"LanguagesBundle\Entity\LanguagesupdatedAt";O:8:"DateTime":3:{s:4:"date";s:26:"2018-04-20 22:46:48.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:12:"Europe/Paris";}s:43:"LanguagesBundle\Entity\LanguagesimageFile";N;s:39:"LanguagesBundle\Entity\Languagesimage";s:39:"Flag_of_United_Kingdom_-_Circle-512.png";s:43:"LanguagesBundle\Entity\LanguagesimageSize";i:37621;s:44:"LanguagesBundle\Entity\LanguagesuserClient";N;}i:1;O:32:"LanguagesBundle\Entity\Languages":10:{s:36:"LanguagesBundle\Entity\Languagesid";i:1;s:38:"LanguagesBundle\Entity\Languagesname";s:9:"Français";s:44:"LanguagesBundle\Entity\Languagesshort_slug";s:2:"fr";s:43:"LanguagesBundle\Entity\Languageslong_slug";s:5:"fr_FR";s:43:"LanguagesBundle\Entity\LanguagesisDefault";b:1;s:43:"LanguagesBundle\Entity\LanguagesupdatedAt";O:8:"DateTime":3:{s:4:"date";s:26:"2018-04-20 22:45:50.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:12:"Europe/Paris";}s:43:"LanguagesBundle\Entity\LanguagesimageFile";N;s:39:"LanguagesBundle\Entity\Languagesimage";s:31:"Flag_of_France_-_Circle-512.png";s:43:"LanguagesBundle\Entity\LanguagesimageSize";i:23352;s:44:"LanguagesBundle\Entity\LanguagesuserClient";N;}}}
Here's my code:
User.php
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use UserBundle\Entity\UserAdmin;
use UserBundle\Entity\UserProfessional;
use UserBundle\Entity\UserClient;
use UserBundle\Entity\Adress;
/**
* #ORM\Entity
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="discr", type="string")
* #ORM\DiscriminatorMap({"client" = "UserClient", "professional"="UserProfessional", "admin"="UserAdmin"})
*/
abstract class User extends BaseUser {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=255)
*/
protected $firstname;
//[...] getters and setters
Entity: UserClient.php
<?php
// src/UserBundle/Entity/UserGuest.php
namespace UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
*/
class UserClient extends User {
/**
* #ORM\Column(type="array")
* #ORM\OneToMany(targetEntity="LanguagesBundle\Entity\Languages", mappedBy="userClient")
*/
private $languages;
public function __construct() {
parent::__construct();
$this->languages = new ArrayCollection();
}
/**
* Set languages
*
* #param array $languages
*
* #return UserClient
*/
public function setLanguages($languages)
{
$this->languages = $languages;
}
/**
* Get languages
*
* #return array
*/
public function getLanguages()
{
return $this->languages;
}
/**
* Add language
*
* #param \LanguagesBundle\Entity\Languages $language
*
* #return UserClient
*/
public function addLanguage(LanguagesBundle\Entity\Languages $language)
{
$this->languages[] = $language;
return $this;
}
/**
* Remove language
*
* #param \LanguagesBundle\Entity\Languages $language
*/
public function removeLanguage(\LanguagesBundle\Entity\Languages $language)
{
$this->languages->removeElement($language);
}
}
Entity Languages.php
<?php
namespace LanguagesBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* #ORM\Entity
*
* #Vich\Uploadable
*/
class Languages
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #var string
*
* #ORM\Column(type="string")
* #Assert\NotBlank()
*/
private $name;
/**
* #ORM\Column(type="string", length=2, unique=true)
*/
private $short_slug;
/**
* #var string
*
* #ORM\Column(type="string", length=5, unique=true)
* #Assert\NotBlank()
*/
private $long_slug;
/**
* #var string
*
* #ORM\Column(type="boolean", nullable=true)
*/
private $isDefault;
/**
* #ORM\Column(type="datetime")
* #var \DateTime
*/
private $updatedAt;
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Assert\File(
* maxSize="1M",
* mimeTypes={"image/png", "image/jpeg", "image/pjpeg"}
* )
* #Vich\UploadableField(mapping="language_images", fileNameProperty="image", size="imageSize")
* #var File
*/
private $imageFile;
/**
* #ORM\Column(type="string", length=255, nullable = true)
* #var string
*/
private $image;
/**
* #ORM\Column(type="integer")
*
* #var integer
*/
private $imageSize;
/**
* #ORM\ManyToOne(targetEntity="UserBundle\Entity\UserClient", inversedBy="languages")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $userClient;
/**
* If manually uploading a file (i.e. not using Symfony Form) ensure an instance
* of 'UploadedFile' is injected into this setter to trigger the update. If this
* bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
* must be able to accept an instance of 'File' as the bundle will inject one here
* during Doctrine hydration.
*
* #param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
*/
public function setImageFile(?File $image = null): void
{
$this->imageFile = $image;
if (null !== $image) {
// It is required that at least one field changes if you are using doctrine
// otherwise the event listeners won't be called and the file is lost
$this->updatedAt = new \DateTimeImmutable();
}
}
public function getImageFile()
{
return $this->imageFile;
}
/**
* Constructor
*/
public function __construct()
{
$this->updatedAt = new \DateTime();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Languages
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set shortSlug
*
* #param string $shortSlug
*
* #return Languages
*/
public function setShortSlug($shortSlug)
{
$this->short_slug = $shortSlug;
return $this;
}
/**
* Get shortSlug
*
* #return string
*/
public function getShortSlug()
{
return $this->short_slug;
}
/**
* Set longSlug
*
* #param string $longSlug
*
* #return Languages
*/
public function setLongSlug($longSlug)
{
$this->long_slug = $longSlug;
return $this;
}
/**
* Get longSlug
*
* #return string
*/
public function getLongSlug()
{
return $this->long_slug;
}
/**
* Set isDefault
*
* #param boolean $isDefault
*
* #return Languages
*/
public function setIsDefault($isDefault)
{
$this->isDefault = $isDefault;
return $this;
}
/**
* Get isDefault
*
* #return boolean
*/
public function getIsDefault()
{
return $this->isDefault;
}
/**
* Set updatedAt
*
* #param \DateTime $updatedAt
*
* #return Languages
*/
public function setUpdatedAt($updatedAt)
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* Get updatedAt
*
* #return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
/**
* Set image
*
* #param string $image
*
* #return Languages
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
/**
* Get image
*
* #return string
*/
public function getImage()
{
return $this->image;
}
/**
* Set imageSize
*
* #param integer $imageSize
*
* #return Languages
*/
public function setImageSize($imageSize)
{
$this->imageSize = $imageSize;
return $this;
}
/**
* Get imageSize
*
* #return integer
*/
public function getImageSize()
{
return $this->imageSize;
}
/**
* Set userClient
*
* #param \UserBundle\Entity\UserClient $userClient
*
* #return Languages
*/
public function setUserClient(\UserBundle\Entity\UserClient $userClient = null)
{
$this->userClient = $userClient;
return $this;
}
/**
* Get userClient
*
* #return \UserBundle\Entity\UserClient
*/
public function getUserClient()
{
return $this->userClient;
}
/**
* {#inheritdoc}
*/
public function __toString()
{
return $this->getName() ?: '-';
}
}
My FormType: RegistrationTypeClient.php
<?php
// src/UserBundle/Form/UserContactFormType.php
namespace UserBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use LanguagesBundle\Services\LanguagesService;
use LanguagesBundle\Entity\Languages ;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
class RegistrationClientType extends AbstractType {
protected $service;
public function buildForm(FormBuilderInterface $builder, array $options) {
parent::buildForm($builder, $options);
$builder
->add('languages', EntityType::class, [
'class' => 'LanguagesBundle:Languages',
'choice_label' => 'name',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->orderBy('u.name', 'ASC');
},
'label' => 'Langues',
'expanded' => true,
'multiple' => true,
])
;
}
public function getParent() {
// on inclut le formulaire de base d'inscription utilisateur
return 'UserBundle\Form\RegistrationType';
}
public function getBlockPrefix() {
return 'app_user_registration_client';
}
// For Symfony 2.x
public function getName() {
return $this->getBlockPrefix();
}
public function configureOptions(OptionsResolver $resolver) {
$resolver
->setDefaults(array(
'data_class' => \UserBundle\Entity\UserClient::class,
))
//->setRequired('service_languages');
;
}
}
And my Controller:
public function registerClientAction(Request $request) {
/** #var $formFactory FactoryInterface */
//$formFactory = $this->get('fos_user.registration_pro.form.factory');
/** #var $userManager UserManagerInterface */
$userManager = $this->get('fos_user.user_manager');
/** #var $dispatcher EventDispatcherInterface */
$dispatcher = $this->get('event_dispatcher');
$user = new UserClient();
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
$form = $this->createForm(RegistrationClientType::class, $user);
$form->setData($user);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);
$userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('fos_user_registration_confirmed');
$response = new RedirectResponse($url);
}
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
return $response;
}
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_FAILURE, $event);
if (null !== $response = $event->getResponse()) {
return $response;
}
}
return $this->render('UserBundle\Registration\register_client.html.twig', array(
'form' => $form->createView(),
));
}
Here's a picture showing the data saved in the table
I need the languages to be stored in the database as an array for userClient.
Could you help me please.
Thank's for re-edit my question Philip-B-
Thank's for your reading also.
I have resolve my problem by adding a foreach to transform my object to array:
The code is in my controller:
if ($form->isValid()) {
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);
foreach ($user->getLanguages() as $value) {
$langue[] = $value->getShortSlug();
}
$user->setLanguages($langue);
$userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('fos_user_registration_confirmed');
$response = new RedirectResponse($url);
}
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
return $response;
}

Symfony EntityType doesn't show all records when multiple and expanded are disabled

Why does database records prohibited to show all records when I use drop down field in Symfony 3.
I have form which has EntityType:class, I use this form to display the records from my db into drop down html entity.
The problem is when I set expanded and multiple to false just to set the field in drop down. Not all records are showing. But, if I activated those two parameters in true, complete records are showing.
Here's my code in form.
->add('currency', EntityType::class, [
'class' => BranchCurrency::class,
'choice_value' => 'id',
'choice_label' => function($currency){
return $currency->getName() . ' (' . $currency->getCode() .') - '.$currency->getRate().'';
},
'placeholder' => 'Choose currency',
'query_builder' => function (BranchCurrencyRepository $er) {
return $er->findAllActiveBuyingCurrencies();
},
'multiple' => false, <--- If I set this parameter to false, not all records are showing.
'expanded' => false, <--- If I set this parameter to false, not all records are showing.
])
UPDATE:
In case you need to see the Entity class and Repository class.
/**
* #ORM\Entity
* #ORM\Table(name="branch_currency")
* #UniqueEntity(
* fields={"branch", "currency"},
* message="This currency is already using on this branch.",
* errorPath="branch"
* )
* #ORM\Entity(repositoryClass="MontealBundle\Repository\BranchCurrencyRepository")
* #ORM\HasLifecycleCallbacks()
*/
class BranchCurrency
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Branch", inversedBy="branchCurrency")
* #ORM\JoinColumn(nullable=false)
*/
private $branch;
/**
* #ORM\ManyToOne(targetEntity="Currency", inversedBy="assignedCurrencies")
* #ORM\JoinColumn(nullable=false)
*/
private $currency;
/**
* #ORM\Column(type="decimal", precision=10, scale=4)
* #Assert\NotBlank()
*/
private $rate;
/**
* #ORM\Column(type="integer", nullable=true)
*/
private $type;
/**
* #ORM\Column(type="string", nullable=true)
*/
private $code;
/**
* #ORM\Column(type="string", nullable=true)
*/
private $name;
/**
* #ORM\Column(type="datetime")
*/
private $createdAt;
/**
* #ORM\Column(type="datetime", nullable=true)
*/
private $updatedAt;
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
/**
* #return mixed
*/
public function getBranch()
{
return $this->branch;
}
/**
* #param mixed $branch
*/
public function setBranch($branch)
{
$this->branch = $branch;
}
/**
* #return mixed
*/
public function getCurrency()
{
return $this->currency;
}
/**
* #param mixed $currency
*/
public function setCurrency($currency)
{
$this->currency = $currency;
}
/**
* #return mixed
*/
public function getCode()
{
return $this->code;
}
/**
* #param mixed $code
*/
public function setCode($code)
{
$this->code = $code;
}
/**
* #return mixed
*/
public function getRate()
{
return $this->rate;
}
/**
* #param mixed $rate
*/
public function setRate($rate)
{
$this->rate = $rate;
}
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* #return mixed
*/
public function getType()
{
return $this->type;
}
/**
* #return mixed
*/
public function getName()
{
return $this->name;
}
/**
* #param mixed $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* #param mixed $type
*/
public function setType($type)
{
$this->type = $type;
}
/**
* #ORM\PrePersist
*/
public function setCreatedAt()
{
$this->createdAt = new \DateTime();
}
public function getUpdatedAt()
{
return $this->updatedAt;
}
/**
* #ORM\PreUpdate()
*/
public function setUpdatedAt()
{
$this->updatedAt = new \DateTime();
}
public function __toString() {
return $this->name;
}
}
Repository
class BranchCurrencyRepository extends EntityRepository
{
public function findAllActiveBuyingCurrencies() {
return $this->createQueryBuilder('bc')
->where('bc.type = :type')
->setParameter('type', 1)
->orderBy('bc.currency', 'ASC');
// $queryBuilder = $this->createQueryBuilder('bc')
// ->orWhere('bc.type =:type')
// ->setParameter('type', 2)
// ->orderBy('bc.currency', 'asc')
// ->setMaxResults(10);
}
}

ManyToOne many Posts for one User -> creates new User by creating a Post

I am using Symfony and Doctrine.
I have two Entities, User and Pots.
Every logged User can create as many Post he want to.
Every Post is associated to one User.
Thats the Workflow: I log in with an User, this user create a Post. A New Post is saved in the Database with a foreigkey on the User wo create it.
Problem: when the User create the Post, the post ist create, but a new User is created too. The new Post is asssociate to the new Users and not to the logged User.
USER ENTITY:
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\Post;
/**
* #ORM\Entity
* #ORM\Table(name= "User")
*/
class User
{
/**
* #ORM\Column(type = "integer")
* #ORM\Id
* #ORM\GeneratedValue("AUTO")
*/
private $id;
/**
* #ORM\Column(type = "string", length = 50)
*/
private $account;
/**
* #ORM\Column(type = "string", length = 22)
*/
private $password;
/**
* #ORM\Column(type = "string", length = 100)
*/
private $email;
/**
* #ORM\Column(type = "integer", length = 1)
*/
private $type;
/**
*
* #ORM\OneToMany(targetEntity="Post", mappedBy="user")
*/
private $posts;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set account
*
* #param string $account
*
* #return User
*/
public function setAccount($account)
{
$this->account = $account;
return $this;
}
/**
* Get account
*
* #return string
*/
public function getAccount()
{
return $this->account;
}
/**
* Set password
*
* #param string $password
*
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set mail
*
* #param string $mail
*
* #return User
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get mail
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set type
*
* #param integer $type
*
* #return User
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* Get type
*
* #return integer
*/
public function getType()
{
return $this->type;
}
/**
* Constructor
*/
public function __construct()
{
$this->posts = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add post
*
* #param \AppBundle\Entity\Post $post
*
* #return User
*/
public function addPost(\AppBundle\Entity\Post $post)
{
$this->posts[] = $post;
return $this;
}
/**
* Remove post
*
* #param \AppBundle\Entity\Post $post
*/
public function removePost(\AppBundle\Entity\Post $post)
{
$this->posts->removeElement($post);
}
/**
* Get posts
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getPosts()
{
return $this->posts;
}
}
POST ENTITY:
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\User;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* #ORM\Entity
* #ORM\Table(name = "Post")
* #Vich\Uploadable
*/
class Post
{
/**
* #ORM\Column(type = "integer")
* #ORM\Id
* #ORM\GeneratedValue("AUTO")
*/
private $id;
/**
* #ORM\Column(type = "string", length = 25)
*/
private $title;
/**
* #ORM\Column(type = "string", length = 255)
*/
private $text;
/**
* #ORM\Column(type= "string", length = 250)
*/
private $pic;
/**
* #Vich\UploadableField(mapping="post_file", fileNameProperty="pic")
*
*/
private $picFile;
/**
* #ORM\ManyToOne(targetEntity="User", inversedBy="posts", cascade={"persist"})
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
public function getPicFile(){
return $this->picFile;
}
public function setPicFile(File $picFile = null){
$this->picFile = $picFile;
return $this;
}
/**
* Set user
*
* #param \AppBundle\Entity\User $user
*
* #return Coach
*/
public function setUser(\AppBundle\Entity\User $user = null)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* #return \AppBundle\Entity\User
*/
public function getUser()
{
return $this->user;
}
/**
* Set title
*
* #param string $title
*
* #return Post
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set text
*
* #param string $text
*
* #return Post
*/
public function setText($text)
{
$this->text = $text;
return $this;
}
/**
* Get text
*
* #return string
*/
public function getText()
{
return $this->text;
}
/**
* Set pic
*
* #param string $pic
*
* #return Post
*/
public function setPic($pic)
{
$this->pic = $pic;
return $this;
}
/**
* Get pic
*
* #return string
*/
public function getPic()
{
return $this->pic;
}
/**
* Set id
*
* #param integer $id
*
* #return Post
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
}
CONTROLLER:
NOTE: Here is take the logged User from the SESSION. This works, i output the id from the User i use and it was the correct id.
public function FrameCoachNewAction(Request $request)
{
$session = $request->getSession();
$session->start();
$user = $session->get('user');
$post = new Post();
$form = $this->createForm(PostType::class, $post);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()){
$post = $form->getData();
$post->setUser($user);
$doct = $this->getDoctrine()->getManager();
$doct->persist($post);
$doct->flush();
//return New Response($post->getUser()->getId());
return $this->RedirectToRoute('app_frame_coach');
}else{
return $this->render('/frame/frame_coach_new.html.twig', array('form' => $form->createView(), 'user' => $user));
}
}
I left the Entity like you said, but i changed the Controller to. The Session User Object dind't work to associate it to the Post. So I just toke the ID from the Session and then search the user object again throw that id in the database and used this instade.
public function FrameCoachNewAction(Request $request)
{
$session = $request->getSession();
$session->start();
$users = $session->get('user');
$repo = $this->getDoctrine()->getRepository(User::class);
$user = $repo->find($users->getId());
$post = new Post();
$form = $this->createForm(PostType::class, $post);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()){
$doct = $this->getDoctrine()->getManager();
$post = $form->getData();
$post->setUser($user);
$doct->persist($post);
$doct->flush();
//return New Response($post->getUser()->getId());
return $this->RedirectToRoute('app_frame_coach');
}else{
return $this->render('/frame/frame_coach_new.html.twig', array('form' => $form->createView(), 'user' => $user));
}
}
The user is the strong side so you should move the cascade={"persist"} option to user, then the user can save the post not the other way. It seems the cascade={"persist"} option is rewriting the setUser method. When you use the cascade={"persist"} option that entity would create the targetEntity.
In addition to #Juan I. Morales Pestana
class User
{
// ...
/**
*
* #ORM\OneToMany(
* targetEntity="Post",
* mappedBy="user",
* cascade={"persist"}
* )
*/
private $posts;
// ...
/**
* Constructor
*/
public function __construct()
{
$this->posts = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add post
*
* #param \AppBundle\Entity\Post $post
*
* #return User
*/
public function addPost(\AppBundle\Entity\Post $post)
{
$this->posts[] = $post;
$post->setUser($this);
return $this;
}

Symfony2 DQL on Fos Userbundle entity

I'm implementing a search on a website and for simplicity i've decided to create a class that does the hard work.
Basically my class takes the EntityManager and the Entities in which i want to search and creates the DQL and executes the query. For normal entities this works totally fine but when i pass the User entity (Extended from fos user bundle entity) i get this error :
[Semantical Error] line 0, col 139 near 'last_login LIKE': Error: Class Soundmerger\UserBundle\Entity\User has no field or association named last_login
The dql query generated seems fine and as it works for the other entities i doubt it comes form there.
Here is my Search class :
use Doctrine\Common\Util\Debug;
use Doctrine\ORM\EntityManager;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Query;
class Search {
private $em;
private $searchables;
public function __construct(EntityManager $em, ArrayCollection $searchables){
$this->em = $em;
$this->searchables = $searchables;
}
public function search($query){
$words = explode("+", $query);
$qb = array();
$results = array();
foreach($this->searchables as $qNumber => $searchable){
$qb[$qNumber] = "SELECT s FROM $searchable s ";
$columns = $this->em->getClassMetadata($searchable)->getColumnNames();
foreach($words as $i => $word){
foreach($columns as $k => $column){
$string = "s.$column LIKE '%$word%'";
if($i == 0 && $k == 0){
$qb[$qNumber] .= "WHERE $string";
} else {
$qb[$qNumber] .= "OR $string";
}
}
}
$res[] = $this->em->createQuery($qb[$qNumber])->getResult(Query::HYDRATE_SIMPLEOBJECT);
}
return $this->formatSearch($res);
}
private function formatSearch($results){
$formatedResult = array();
foreach($results as $k => $result){
if(!empty($result)){
$formatedResult[$k]["type"] = get_class($result[0]);
$formatedResult[$k]["data"] = $result[0];
}
}
return $formatedResult;
}
}
And my Controller for the search :
/**
* #Route("/search/{query}")
* #Template()
*/
public function indexAction($query)
{
$em = $this->getDoctrine()->getManager();
$searchables = new ArrayCollection(
array(
"SoundmergerUserBundle:Professional",
"SoundmergerFaqBundle:Faq",
"SoundmergerUserBundle:User",
));
$search = new Search($em, $searchables);
return array('search' => $search->search($query));
}
And finally my user entity :
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
* #AttributeOverrides({
* #AttributeOverride(name="emailCanonical",
* column=#ORM\Column(
* name = "emailCanonical",
* type = "string",
* length = 255,
* nullable = true
* )
* ),
* #AttributeOverride(name="email",
* column=#ORM\Column(
* name = "email",
* type = "string",
* length = 255,
* nullable = true
* )
* ),
* #AttributeOverride(name="username",
* column=#ORM\Column(
* name = "username",
* type = "string",
* length = 255,
* unique = false
* )
* ),
* #AttributeOverride(name="usernameCanonical",
* column=#ORM\Column(
* name = "usernameCanonical",
* type = "string",
* length = 255,
* unique = false
* )
* ),
* })
*/
class User extends BaseUser
{
const STRUCTURE_SOLO = "solo";
const STRUCTURE_GROUP = "group";
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", nullable=true)
* #var string
*/
protected $nomProfile = null;
/**
* #ORM\Column(type="text", nullable=true)
* #var string
*/
protected $description = null;
/**
* #ORM\Column(type="string", nullable=true)
* #var string
*/
protected $type = null;
/**
* #ORM\Column(type="string")
* #var string
*/
protected $structure = self::STRUCTURE_SOLO;
/**
* #ORM\Column(type="string", nullable=true)
* #var string
*/
protected $tel = null;
/**
* #ORM\Column(type="string", nullable=true)
* #var string
*/
protected $site = null;
/**
* #ORM\Column(type="boolean")
* #var bool
*/
protected $firstLogin = true;
/**
* #ORM\OneToOne(targetEntity="Soundmerger\MainBundle\Entity\Address", cascade={"persist"})
*/
protected $address;
/**
* #ORM\OneToMany(targetEntity="Soundmerger\MainBundle\Entity\Style", mappedBy="user", cascade={"persist"})
*/
protected $styles;
/**
* #ORM\OneToMany(targetEntity="Soundmerger\UserBundle\Entity\Member", mappedBy="user")
* #ORM\JoinColumn(nullable=true)
*/
protected $members;
/** #ORM\Column(name="discogs_id", type="string", length=255, nullable=true) */
protected $discogs_id;
/** #ORM\Column(name="discogs_access_token", type="string", length=255, nullable=true) */
protected $discogs_access_token;
public function __construct()
{
parent::__construct();
$this->members = new ArrayCollection();
$this->styles = new ArrayCollection();
}
/**
* Get id
* #return string
*/
public function getId()
{
return $this->id;
}
/**
* Get NomProfile
* #return string
*/
public function getNomProfile()
{
return $this->nomProfile;
}
/**
* Get type
* #return string
*/
public function getType()
{
return $this->type;
}
/**
* Get structure
* #return string
*/
public function getStructure()
{
return $this->structure;
}
/**
* Get tel
* #return string
*/
public function getTel()
{
return $this->tel;
}
/**
* Get site
* #return string
*/
public function getSite()
{
return $this->site;
}
/**
* Get description
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set nomProfile
* #param string $nomProfile
* #return \Soundmerger\UserBundle\Entity\Utilisateur
*/
public function setNomProfile($nomProfile)
{
$this->nomProfile = $nomProfile;
return $this;
}
/**
* Set type
* #param string $type
* #return \Soundmerger\UserBundle\Entity\Utilisateur
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* Set structure
* #param string $structure
* #return \Soundmerger\UserBundle\Entity\Utilisateur
*/
public function setStructure($structure)
{
if (!in_array($structure, array(self::STRUCTURE_SOLO, self::STRUCTURE_GROUP))) {
throw new \InvalidArgumentException("Invalid structure");
}
$this->structure = $structure;
return $this;
}
/**
* Set tel
* #param string $tel
* #return \Soundmerger\UserBundle\Entity\Utilisateur
*/
public function setTel($tel)
{
$this->tel = $tel;
return $this;
}
/**
* Set site
* #param string $site
* #return \Soundmerger\UserBundle\Entity\Utilisateur
*/
public function setSite($site)
{
$this->site = $site;
return $this;
}
/**
* Set description
* #param type $description
* #return \Soundmerger\UserBundle\Entity\Utilisateur
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Set the first login
* #param bool $firstLogin
* #return \Soundmerger\UserBundle\Entity\Utilisateur
*/
public function setFirstLogin($firstLogin)
{
$this->firstLogin = $firstLogin;
return $this;
}
/**
* Is it the first login
* #return bool returns true if its the first login, false otherwise
*/
public function isFirstLogin()
{
return $this->firstLogin;
}
/**
* Set address
*
* #param Address $address
* #return $this
*/
public function setAddress(Address $address)
{
$this->address = $address;
return $this;
}
/**
* Get adress
*
* #return mixed
*/
public function getAddress()
{
return $this->address;
}
/**
* #return Style
*/
public function getStyles()
{
return $this->styles;
}
/**
* #param Style $style
* #return $this
*/
public function addStyle(Style $style)
{
if (!$this->styles->contains($style)) {
$style->setUser($this);
$this->styles->add($style);
}
return $this;
}
public function setStyles(PersistentCollection $styles)
{
foreach ($styles as $style) {
$this->addStyle($style);
}
}
/**
* #return ArrayCollection
*/
public function getMembers()
{
return $this->members;
}
/**
* #param Member $members
*/
public function addMember(Member $member)
{
if (!$this->members->contains($member)) {
$this->members->add($member);
}
return $this;
}
public function setDiscogsId($discogs_id)
{
$this->discogs_id = $discogs_id;
return $this;
}
public function getDiscogsId()
{
return $this->discogs_id;
}
public function setDiscogsAccessToken($discogs_access_token)
{
$this->discogs_access_token = $discogs_access_token;
return $this;
}
public function getDiscogsAccessToken()
{
return $this->discogs_access_token;
}
public function isRegisteredWithDiscogs(){
return $this->discogs_id != null;
}
}
Any ideas on why this is only happening with the user entity (it must be due to the inheritance but i can't seem to find a way round it)
btw : its a university project so the idea of using an external bundle for the search is not really possible.
Thanks for any help
Dan

Symfony 2 Form Validation: missing name of property in validation message

I don't understand why some constraints does not insert name of property in error message after validation. I have this entity class:
<?php
namespace AC\OperaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use AC\UserBundle\Entity\Utente;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Class Episodio
* #package AC\OperaBundle\Entity
* #ORM\Entity(repositoryClass="AC\OperaBundle\Repository\EpisodioRepository")
* * #ORM\Table(
* name="ac_Episodio",
* uniqueConstraints={#ORM\UniqueConstraint(name="unique_idx", columns={"opera", "numero_episodio", "extra"})},
* indexes={ #ORM\Index(name="opera_idx", columns={"opera"}),
* #ORM\Index(name="numero_episodio_idx", columns={"numero_episodio"}),
* #ORM\Index(name="extra_idx", columns={"extra"}),
* #ORM\Index(name="attivo_idx", columns={"attivo"}) })
*/
class Episodio {
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var Opera
*
* #ORM\ManyToOne(targetEntity="AC\OperaBundle\Entity\Opera", inversedBy="episodi")
* #ORM\JoinColumn(name="opera", referencedColumnName="id", nullable=false)
*/
protected $opera;
/**
* #var string
*
* #ORM\Column(name="numero_episodio", type="string", length=5, nullable=false)
*/
protected $numero_episodio;
/**
* #var string
*
* #ORM\Column(name="extra", type="string", length=30, nullable=false)
*/
protected $extra;
/**
* #var string
*
* #ORM\Column(name="titolo_italiano", type="string", length=150, nullable=false)
* #Assert\NotBlank()
*/
protected $titolo_italiano;
/**
* #var string
*
* #ORM\Column(name="titolo_originale", type="string", length=150, nullable=false)
* #Assert\NotBlank()
*/
protected $titolo_originale;
/**
* #var \DateTime
*
* #ORM\Column(name="data_ita", type="date", nullable=true)
* #Assert\Date()
*/
protected $data_ita;
/**
* #var \DateTime
*
* #ORM\Column(name="data_jap", type="date", nullable=true)
* #Assert\Date()
*/
protected $data_jap;
/**
* #var int
*
* #ORM\Column(name="durata", type="smallint", nullable=false, options={"default" = 0})
*/
protected $durata;
/**
* #var string
*
* #ORM\Column(name="trama", type="text", nullable=false)
*/
protected $trama;
/**
* #var int
*
* #ORM\Column(name="ordine", type="smallint", nullable=false, options={"default" = 0})
*/
protected $ordine;
/**
* #var int
*
* #ORM\Column(name="promosso", type="integer", nullable=false, options={"default" = 0})
*/
protected $promosso;
/**
* #var int
*
* #ORM\Column(name="rimandato", type="integer", nullable=false, options={"default" = 0})
*/
protected $rimandato;
/**
* #var int
*
* #ORM\Column(name="bocciato", type="integer", nullable=false, options={"default" = 0})
*/
protected $bocciato;
/**
* #var boolean
*
* #ORM\Column(name="fansub", type="boolean", nullable=false)
*/
protected $fansub;
/**
* #var boolean
*
* #ORM\Column(name="attivo", type="boolean", nullable=false)
*/
protected $attivo;
/**
* #var \DateTime
*
* #ORM\Column(name="data_aggiornamento", type="date")
*/
protected $data_aggiornamento;
/**
* #var Utente
*
* #ORM\ManyToOne(targetEntity="AC\UserBundle\Entity\Utente")
* #ORM\JoinColumn(name="utente_aggiornamento", referencedColumnName="id", nullable=true)
*/
protected $utente_aggiornamento;
/**
* #param boolean $attivo
*/
public function setAttivo($attivo)
{
$this->attivo = $attivo;
}
/**
* #return boolean
*/
public function getAttivo()
{
return $this->attivo;
}
/**
* #param int $bocciato
*/
public function setBocciato($bocciato)
{
$this->bocciato = $bocciato;
}
/**
* #return int
*/
public function getBocciato()
{
return $this->bocciato;
}
/**
* #param \DateTime $data_aggiornamento
*/
public function setDataAggiornamento($data_aggiornamento)
{
$this->data_aggiornamento = $data_aggiornamento;
}
/**
* #return \DateTime
*/
public function getDataAggiornamento()
{
return $this->data_aggiornamento;
}
/**
* #param \DateTime $data_ita
*/
public function setDataIta($data_ita)
{
$this->data_ita = $data_ita;
}
/**
* #return \DateTime
*/
public function getDataIta()
{
return $this->data_ita;
}
/**
* #param \DateTime $data_jap
*/
public function setDataJap($data_jap)
{
$this->data_jap = $data_jap;
}
/**
* #return \DateTime
*/
public function getDataJap()
{
return $this->data_jap;
}
/**
* #param int $durata
*/
public function setDurata($durata)
{
$this->durata = $durata;
}
/**
* #return int
*/
public function getDurata()
{
return $this->durata;
}
/**
* #param string $extra
*/
public function setExtra($extra)
{
$this->extra = $extra;
}
/**
* #return string
*/
public function getExtra()
{
return $this->extra;
}
/**
* #param boolean $fansub
*/
public function setFansub($fansub)
{
$this->fansub = $fansub;
}
/**
* #return boolean
*/
public function getFansub()
{
return $this->fansub;
}
/**
* #param int $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #param string $numero_episodio
*/
public function setNumeroEpisodio($numero_episodio)
{
$this->numero_episodio = $numero_episodio;
}
/**
* #return string
*/
public function getNumeroEpisodio()
{
return $this->numero_episodio;
}
/**
* #param \AC\OperaBundle\Entity\Opera $opera
*/
public function setOpera($opera)
{
$this->opera = $opera;
}
/**
* #return \AC\OperaBundle\Entity\Opera
*/
public function getOpera()
{
return $this->opera;
}
/**
* #param int $ordine
*/
public function setOrdine($ordine)
{
$this->ordine = $ordine;
}
/**
* #return int
*/
public function getOrdine()
{
return $this->ordine;
}
/**
* #param int $promosso
*/
public function setPromosso($promosso)
{
$this->promosso = $promosso;
}
/**
* #return int
*/
public function getPromosso()
{
return $this->promosso;
}
/**
* #param int $rimandato
*/
public function setRimandato($rimandato)
{
$this->rimandato = $rimandato;
}
/**
* #return int
*/
public function getRimandato()
{
return $this->rimandato;
}
/**
* #param string $titolo_italiano
*/
public function setTitoloItaliano($titolo_italiano)
{
$this->titolo_italiano = $titolo_italiano;
}
/**
* #return string
*/
public function getTitoloItaliano()
{
return $this->titolo_italiano;
}
/**
* #param string $titolo_originale
*/
public function setTitoloOriginale($titolo_originale)
{
$this->titolo_originale = $titolo_originale;
}
/**
* #return string
*/
public function getTitoloOriginale()
{
return $this->titolo_originale;
}
/**
* #param string $trama
*/
public function setTrama($trama)
{
$this->trama = $trama;
}
/**
* #return string
*/
public function getTrama()
{
return $this->trama;
}
/**
* #param \AC\UserBundle\Entity\Utente $utente_aggiornamento
*/
public function setUtenteAggiornamento($utente_aggiornamento)
{
$this->utente_aggiornamento = $utente_aggiornamento;
}
/**
* #return \AC\UserBundle\Entity\Utente
*/
public function getUtenteAggiornamento()
{
return $this->utente_aggiornamento;
}
}
In the controller perform the classi call at the $form->isValid() method to check validation. If there are errors i call $form->getErrorsAsString() and this is the result:
ERROR: This value should not be blank.
ERROR: This value should not be blank.
numeroEpisodio:
No errors
titoloItaliano:
No errors
titoloOriginale:
No errors
dataIta:
ERROR: This value is not valid.
dataJap:
ERROR: This value is not valid.
durata:
No errors
trama:
No errors
extra:
No errors
fansub:
No errors
The property that use #Assert\NotBlank() dose not put property name in error message! And for this reason i have the first two error line with e generic:
ERROR: This value should not be blank.
ERROR: This value should not be blank.
I i don't know who is the property that failed the validation. I look in the source code of Symfony Component and i see that for not blank constraint:
/**
* #author Bernhard Schussek <bschussek#gmail.com>
*
* #api
*/
class NotBlankValidator extends ConstraintValidator
{
/**
* {#inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof NotBlank) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\NotBlank');
}
if (false === $value || (empty($value) && '0' != $value)) {
$this->context->addViolation($constraint->message);
}
}
}
And for data constraint:
/**
* #author Bernhard Schussek <bschussek#gmail.com>
*
* #api
*/
class DateValidator extends ConstraintValidator
{
const PATTERN = '/^(\d{4})-(\d{2})-(\d{2})$/';
/**
* {#inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Date) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Date');
}
if (null === $value || '' === $value || $value instanceof \DateTime) {
return;
}
if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
throw new UnexpectedTypeException($value, 'string');
}
$value = (string) $value;
if (!preg_match(static::PATTERN, $value, $matches) || !checkdate($matches[2], $matches[3], $matches[1])) {
$this->context->addViolation($constraint->message, array('{{ value }}' => $value));
}
}
}
The important difference is $this->context->addViolation($constraint->message); VS $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
Why?
This is core part of controller
if ($request->getMethod() == 'POST') {
try {
$form->handleRequest($request);
if ($form->isValid()) {
/* #var $item Episodio */
$item = $form->getData();
$em->persist($item);
$em->flush();
$msg = new Message(true, Message::OK_MESSAGE);
} else {
$msg = new Message(false, Message::KO_MESSAGE);
$errors = Utility::getErrorMessages($form);
$msg->setData($errors);
}
} catch (\Exception $ex) {
$msg = new Message(false, $ex->getMessage());
}
return new Response($this->get('jms_serializer')->serialize($msg, 'json'));
}
This is utility class that fetch error from form
class Utility {
static function getErrorMessages(\Symfony\Component\Form\Form $form) {
$errors = array();
foreach ($form->getErrors() as $key => $error) {
$template = $error->getMessageTemplate();
$parameters = $error->getMessageParameters();
foreach($parameters as $var => $value){
$template = str_replace($var, $value, $template);
}
$errors[$key] = $template;
}
//if ($form->hasChildren()) {
foreach ($form->all() as $child) {
if (!$child->isValid()) {
$errors[$child->getName()] = Utility::getErrorMessages($child);
}
}
//}
return $errors;
}
}
Form Class
class EpisodioForm extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('numeroEpisodio', 'text');
$builder->add('titoloItaliano', 'text',array());
$builder->add('titoloOriginale', 'text');
$builder->add('dataIta', 'date', array('widget' => 'single_text', 'format' => 'dd/MM/yyyy'));
$builder->add('dataJap', 'date', array('widget' => 'single_text', 'format' => 'dd/MM/yyyy'));
$builder->add('durata', 'text');
$builder->add('trama', 'textarea');
$builder->add('extra', 'text');
$builder->add('fansub', 'checkbox');
}
/**
* Returns the name of this type.
*
* #return string The name of this type
*/
public function getName()
{
return "episodio_form";
}
}
The version of framework is Symfony 2.4
Why $this->context->addViolation($constraint->message); VS $this->context->addViolation($constraint->message, array('{{ value }}' => $value));?
This is because the date constraint validator shows the value which failed to validate in the error message, e.g.
45.04.2014 is not a valid date.
whereas the NotBlank constraint validator doesn't need to, since the value causing the error is always empty.
Putting the property name in the error message
This could be achieved:
by changing the annotations for the constraints in your entity to something like:
class Episodio {
/**
* #Assert\NotBlank(message="'titolo_italiano' should not be blank.")
*/
protected $titolo_italiano;
/**
* #Assert\NotBlank(message="'titolo_originale' should not be blank.")
*/
protected $titolo_originale;
}
I left out the column definitions and the other fields in the entity for the sake of readability.
OR by defining a custom validator which passes the name of the property to the error message:
The constraint:
class MyCustomNotBlank extends NotBlank
{
public $message = "'{{ propertyName }}' should not be blank.";
}
The validator:
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class MyCustomNotBlankValidator extends ConstraintValidator
{
public function validate($value, Constraint $constraint)
{
if (!$value) {
$this->context->addViolation(
$constraint->message,
array('{{ propertyName}}' => $this->context->getPropertyPath())
);
}
}
}
This shows you how to define a custom validation constraint:
http://symfony.com/doc/current/cookbook/validation/custom_constraint.html
Obtaining a key-value array with property name and error message
Afaik, there is no function in Symfony2's form component which does that, so it has to be implemented.
See https://stackoverflow.com/a/13763053/277106 . You can add that function to a service for reusability. In your (AJAX) controller you can then do:
public function someAction(Request $request)
{
$errors = array();
$form = $this->createForm(new MyType);
if (!$form->bindRequest($request)->isValid()) {
$errors = $this->myFormService->getErrorMessages($form);
}
else {
// save the entity
}
return JsonResponse($errors);
}

Resources