I have 2 entities, Reply and Post.
These are linked as ManyToMany with Post being the owner.
I have created a form for Reply to add new replies to the post, but the for some reason the replies are not showing up in the for loop in Twig.
In the database the new replies are listed and saved yet it's not displaying?
I've setup fixtures for linking replies to posts and it displays just fine in the for loop, just not for the new replies created in the form?
What am I missing here?
ReplyForm
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('author')
->add('body')
->add('post', 'submit');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\DemoBundle\Entity\Reply'
));
}
public function getName()
{
return 'acme_demobundle_reply';
}
Twig
{% for reply in post.replies %}
<hr>
<p><small>Reply from <em>{{ reply.author.name }}</em> on {{ reply.createdAt|date }}</small></p>
<p>{{ reply.body }}</p>
{% endfor %}
Controller
public function createReplyAction(Request $request, $slug)
{
$post = $this->getDoctrine()->getRepository('AcmeDemoBundle:Post')
->findOneBy(array(
'slug' => $slug
));
if (null == $post) {
throw $this->createNotFoundException('Post was not found');
}
$reply = new Reply();
$reply->addPost($post);
$form = $this->createForm(new ReplyType(), $reply);
$form->handleRequest($request);
if ($form->isValid()) {
$this->getDoctrine()->getManager()->persist($reply);
$this->getDoctrine()->getManager()->flush();
return $this->redirect($this->generateUrl('acme_core_post_show', array(
'slug' => $slug
)));
}
return array(
'post' => $post,
'form' => $form->createView()
);
}
Reply entity
/**
* #ORM\ManyToMany(targetEntity="Post", mappedBy="replies")
*/
protected $post;
/**
* Constructor
*/
public function __construct()
{
$this->post = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add post
*
* #param \Acme\DemoBundle\Entity\Post $post
* #return Reply
*/
public function addPost(\Acme\DemoBundle\Entity\Post $post)
{
$this->post[] = $post;
return $this;
}
/**
* Remove post
*
* #param \Acme\DemoBundle\Entity\Post $post
*/
public function removePost(\Acme\DemoBundle\Entity\Post $post)
{
$this->post->removeElement($post);
}
/**
* Get post
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getPost()
{
return $this->post;
}
Post entity
/**
* #return Array Collection
*
* #ORM\ManyToMany(targetEntity="Reply", inversedBy="post")
* #JoinTable(name="posts_replies",
* joinColumns={#JoinColumn(name="post_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="reply_id", referencedColumnName="id")}
* )
*/
protected $replies;
/**
* Constructor
*/
public function __construct()
{
$this->replies = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add replies
*
* #param \Acme\DemoBundle\Entity\Reply $replies
* #return Post
*/
public function addReply(\Acme\DemoBundle\Entity\Reply $replies)
{
$replies->addPost($this);
$this->replies[] = $replies;
return $this;
}
/**
* Remove replies
*
* #param \Acme\DemoBundle\Entity\Reply $replies
*/
public function removeReply(\Acme\DemoBundle\Entity\Reply $replies)
{
$this->replies->removeElement($replies);
}
/**
* Get replies
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getReplies()
{
return $this->replies;
}
Remove the following:
$replies->addPost($this); from Post entity
and add in
$post->addReply($this); under addPost for Reply entity.
Shouldn't you construct your $replies property as an ArrayCollection in your Post Entity?
public function __construct()
{
$this->replies = new \Doctrine\Common\Collections\ArrayCollection();
}
the entity Post's annotation is wrong, try this one:
/**
* #ORM\ManyToMany(targetEntity="Reply", inversedBy="post")
* #ORM\JoinTable(name="posts_replies",
* joinColumns={#ORM\JoinColumn(name="post_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="reply_id", referencedColumnName="id")}
* )
*/
private $replies;
Related
I have 2 "simple" entities, and i want to do the classical form embedding
but i have this error : "Neither the property "itemcode" nor one of the methods "getItemcode()", "itemcode()", "isItemcode()", "hasItemcode()", "__get()" exist and have public access in class "NWA\ItemSelectorBundle\Entity\ItemSelector"."
I've seen many posts with this error, but none provided the solution
In the entities i have getItemCode() but why would it be public ?
What is wrong with my construction?
Thank you in advance
Here are my entities (parts relevant to the properties at fault)
class ItemSelector
{
/**
* #var Items[]
*
* #ORM\OneToMany(targetEntity="NWA\ItemSelectorBundle\Entity\Item", mappedBy="itemselector", cascade={"all"})
*/
protected $items;
/**
* Class constructor
*/
public function __construct()
{
$this->items = new ArrayCollection();
}
/**
* Add item
*
* #param \NWA\ItemSelectorBundle\Entity\Item $item
*
* #return ItemSelector
*/
public function addItem(\NWA\ItemSelectorBundle\Entity\Item $item)
{
$this->items[] = $item;
//$item->setItemselector($this);
return $this;
}
/**
* Remove item
*
* #param \NWA\ItemSelectorBundle\Entity\Item $item
*/
public function removeItem(\NWA\ItemSelectorBundle\Entity\Item $item)
{
$this->items->removeElement($item);
}
/**
* Get items
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getItems()
{
return $this->items;
}
}
and
class Item
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="itemcode", type="string", length=255)
*/
protected $itemcode;
/**
* #var ItemSelector
*
* #ORM\ManyToOne(targetEntity="NWA\ItemSelectorBundle\Entity\ItemSelector", inversedBy="items")
* #ORM\JoinColumn(name="itemselector_id", referencedColumnName="id")
*/
protected $itemselector;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set itemcode
*
* #param string $itemcode
*
* #return Item
*/
public function setItemcode($itemcode)
{
$this->itemcode = $itemcode;
return $this;
}
/**
* Get itemcode
*
* #return string
*/
public function getItemcode()
{
return $this->itemcode;
}
/**
* Set itemselector
*
* #param \NWA\ItemSelectorBundle\Entity\ItemSelector $itemselector
*
* #return Item
*/
public function setItemselector(\NWA\ItemSelectorBundle\Entity\ItemSelector $itemselector = null)
{
$this->itemselector = $itemselector;
return $this;
}
/**
* Get itemselector
*
* #return \NWA\ItemSelectorBundle\Entity\ItemSelector
*/
public function getItemselector()
{
return $this->itemselector;
}
}
Then the Form constructors
class ItemSelectorType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(
'itemcode', 'collection', array(
'type' => new ItemType(),
'prototype' => true,
'allow_add' => true,
'allow_delete' => true
)
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'NWA\ItemSelectorBundle\Entity\ItemSelector',
'translation_domain' => 'resource'
));
}
/**
* #return string
*/
public function getName()
{
return 'nwa_itemselector';
}
}
and
class ItemType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(
'itemcode', 'text', array(
'label' => 'Code'
)
);
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'NWA\ItemSelectorBundle\Entity\Item'
));
}
/**
* #return string
*/
public function getName()
{
return 'nwa_itemselectorbundle_item';
}
}
And finally the call in the Controller
public function chooseAction(Request $request, ItemSelector $itemSelector)
{
$form = $this->get('form.factory')
->create(new ItemSelectorType(), $itemSelector);
$form->handleRequest($request);
if ($form->isValid()) {
}
return array(
'_resource' => $itemSelector,
'form' => $form->createView(),
);
}
Maybe you need to rename your field name itemcode to items in ItemSelectorType.
->add(
'items', 'collection', array(
'type' => new ItemType(),
'prototype' => true,
'allow_add' => true,
'allow_delete' => true
)
);
I'm using A2lix Translation Form Bundle and Doctrine Behaviors Translatable in a project where I have two entities: company and files. Company has some translatable fields so I have a CompanyTranslations Entity for that. One company can have one file so Company and file are mapped with an OneToOne unidirectional reference. The company file is translatable so the property is in the CompanyTranslation file.
CompanyTranslation:
class CompanyTranslation
{
use ORMBehaviors\Translatable\Translation;
/**
* #ORM\OneToOne(targetEntity="File", cascade={"persist"})
* #ORM\JoinColumn(name="translatable_file_id", referencedColumnName="id")
* #Assert\Valid()
* #Assert\Type(type="MyApp\CoreBundle\Entity\File")
**/
private $translatableFile;
/**
* Set translatableFile
*
* #param $translatableFile
*/
public function setTranslatableFile(File $translatableFile = null)
{
$this->translatableFile = $translatableFile;
}
/**
* Get translatableFile
*
* #return $translatableFile
*/
public function getTranslatableFile()
{
return $this->translatableFile;
}
}
File:
class File
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
public $filePath;
/**
* #Assert\File()
*/
private $file;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set filePath
*
* #param string $filePath
*/
public function setFilePath($filePath)
{
$this->filePath = $filePath;
}
/**
* Get filePath
*
* #return string
*/
public function getFilePath()
{
return $this->filePath;
}
/**
* Set file
*
* #param UploadedFile $file
*/
public function setFile(UploadedFile $file = null)
{
$this->file = $file;
}
/**
* Get file
*
* #return UploadedFile
*/
public function getFile()
{
return $this->file;
}
}
File Form Type:
class FileType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('file', 'file', array(
'label' => false
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'MyApp\CoreBundle\Entity\File'
));
}
public function getName()
{
return 'file_form';
}
}
Company Form Type:
class CompanyType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('translations', 'a2lix_translationsForms', array(
'locales' => $this->languages,
'form_type' => new FileType(),
'form_options' => array(
'data_class' => 'MyApp\CoreBundle\Entity\File',
'required' => false,
'validation_groups' => array('file_upload')
)
));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
parent::setDefaultOptions($resolver);
$resolver->setDefaults(array(
'data_class' => 'MyApp\CoreBundle\Entity\Company'
));
}
}
The error is this one:
The form's view data is expected to be an instance of class MyApp\CoreBundle\Entity\File, but is an instance of class MyApp\CoreBundle\Entity\CompanyTranslation. You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms an instance of class MyApp\CoreBundle\Entity\CompanyTranslation to an instance of MyApp\CoreBundle\Entity\File.
I already set the data_class of the File Type Form and the data_class of the field to null but also to MyApp\CoreBundle\Entity\File. Both send me errors. I don't know what's happening.
Could anyone help?
Thanks!
I have document called aboutMe
and it has another embedded document called projects to add many projects (prototype)
The projects has project name and image for the project.
i created a formType for aboutMe document and i embedded the project form inside the aboutMe form to be able to add many projects prototype.
The problem is updating the project->image when the user didn't change the old project image.
doctrine updating the old embedded project document with a null image.
I Need to keep the old image name if the user didn't upload a new one
/**
* #MongoDB\Document
* #MongoDB\HasLifecycleCallbacks
*/
class AboutMeIndex {
/**
* #var integer
*
* #MongoDB\Id(strategy="INCREMENT")
*/
protected $id;
/**
* #var array
*
* #MongoDB\EmbedMany(targetDocument="AboutMeProjects", strategy="set")
*/
protected $projects = array();
public function __construct()
{
$this->projects = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Remove project
*
* #param TimesSell\CoreBundle\Document\Profile\AboutMe\AboutMeProjects $project
*/
public function removeProject(\TimesSell\CoreBundle\Document\Profile\AboutMe\AboutMeProjects $project)
{
$this->projects->removeElement($project);
}
/**
* Get projects
*
* #return Doctrine\Common\Collections\Collection $projects
*/
public function getProjects()
{
return $this->projects;
}
/**
* Add certification
*
* #param TimesSell\CoreBundle\Document\Profile\AboutMe\AboutMeCertifications $certification
*/
public function addCertification(\TimesSell\CoreBundle\Document\Profile\AboutMe\AboutMeCertifications $certification)
{
$this->certifications[] = $certification;
}
//=================================================================================//
public function fileGetter($file){
if(method_exists($this, 'get' . ucfirst($file))) {
return call_user_func(array($this, 'get' . ucfirst($file)));
}
else {
throw new \Exception("Couldn't Find Method name get" . ucfirst($file));
}
}
protected function getUploadRootDir($uploadDir)
{
return __DIR__.'/../../../../../../web/uploads/'.$this->getUploadDir($uploadDir);
}
protected function getUploadDir($uploadDir)
{
return $uploadDir;
}
public function uploadEmbeddedPhotos($file, $uploadDir)
{
if (null === $this->fileGetter($file)) {
return;
}
foreach ($this->fileGetter($file) as $galleryPhoto){
$pictureName = uniqid().'.'.$galleryPhoto->getImage()->guessExtension();
$galleryPhoto->getImage()->move($this->getUploadRootDir($uploadDir),$pictureName);
$this->path = $galleryPhoto->getImage()->getClientOriginalName();
$galleryPhoto->setImage($pictureName);
}
}
public function deleteImage($image, $uploadDir){
#unlink($this->getUploadRootDir($uploadDir).$image);
}
//=================================================================================//
/**
* #MongoDB\EmbeddedDocument
*
*/
class AboutMeProjects {
/**
* #var integer
*
* #MongoDB\Id(strategy="INCREMENT")
*/
protected $id;
/**
* #var string
*
* #MongoDB\String
*/
protected $projectName;
/**
* #var string
*
* #Assert\Image(
* maxSize = "20000k",
* mimeTypes = {"image/gif", "image/jpeg", "image/png"},
* mimeTypesMessage = "Please upload a valid picture"
* )
* #Assert\Regex(
* pattern="/[a-zA-Z0-9]+/",
* match=true,
* message="Special characters are not allowed"
* )
*
* #MongoDB\String
*/
protected $image;
/**
* #var string
*
* #MongoDB\String
*/
protected $desc;
/**
* Get id
*
* #return int_id $id
*/
public function getId()
{
return $this->id;
}
/**
* Set projectName
*
* #param string $projectName
* #return self
*/
public function setProjectName($projectName)
{
$this->projectName = $projectName;
return $this;
}
/**
* Get projectName
*
* #return string $projectName
*/
public function getProjectName()
{
return $this->projectName;
}
/**
* Set image
*
* #param string $image
* #return self
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
/**
* Get image
*
* #return string $image
*/
public function getImage()
{
return $this->image;
}
/**
* Set desc
*
* #param string $desc
* #return self
*/
public function setDesc($desc)
{
$this->desc = $desc;
return $this;
}
/**
* Get desc
*
* #return string $desc
*/
public function getDesc()
{
return $this->desc;
}
}
class AboutMeIndexType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstName')
->add('projects', 'collection', array(
'type' => new ProjectsType(),
'prototype' => true,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'required' => false
))
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AboutMeIndex'
));
}
/**
* #return string
*/
public function getName()
{
return 'AbourMe';
}
}
class ProjectsType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('projectName','text',array('attr'=> array('class'=>'form-control', 'placeholder' => 'Project name') ))
->add('image','file',array('data_class' => null,'attr'=> array('class'=>'form-control col-lg-2 file-inputs') ))
->add('desc','textarea',array('attr'=> array('class'=>'form-control', 'data-provide' => 'markdown', 'placeholder' => 'Description') ))
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AboutMeProjects'
));
}
/**
* #return string
*/
public function getName()
{
return 'ProjectsType';
}
}
And here's the controller that i want to be able to keep the old image
/**
* Edits an existing aboutMeIndex document.
*
* #Route("/profile/about-me/update", name="profile_about_me_update")
* #Method("PUT")
* #Template()
*/
public function updateAction(Request $request)
{
$dm = $this->get('doctrine.odm.mongodb.document_manager');
$user = $this->getUser();
$entity = $dm->getRepository('AboutMeIndex')->findOneBy(array('user.$id' => (int)$user->getId()));
if (!$entity) {
throw $this->createNotFoundException('Unable to find entity Document.');
}
$editForm = $this->createForm(new AboutMeIndexType(), $entity);
$editForm->submit($request);
if ($editForm->isValid()) {
if($entity->getProjects()->getImage() is newImage){
$entity->uploadEmbeddedPhotos('projects', 'profile/aboutMe/');
}else{
// Keep the old Image
}
$dm->persist($entity);
$dm->flush();
}
}
I have user model + user type, register model + register type... When i Execute it id doesn't validate user (inner data) model. Code below...
User model:
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Security\Core\User\UserInterface;
use Serializable;
/**
* User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="Site\MainBundle\Entity\Repository\UserRepository")
*/
class User implements UserInterface, Serializable
{
/**
* #return array|\Symfony\Component\Security\Core\User\Role[]
*/
public function getRoles()
{
return array('ROLE_USER');
}
/**
*
*/
public function eraseCredentials()
{
}
/**
* #return string
*/
public function serialize()
{
return serialize(array($this->id));
}
/**
* #param string $serialized
*/
public function unserialize($serialized)
{
list ($this->id,) = unserialize($serialized);
}
/**
*
*/
public function __construct()
{
$this->isActive = false;
$this->salt = md5(uniqid(null, true));
}
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
public function getID()
{
return $this->id;
}
/**
* #var string
*
* #ORM\Column(name="username", type="string", length=255, nullable=false)
* #Assert\NotBlank(message="User name cannot be blank.")
*/
private $username;
public function setUserName($userName)
{
$this->username = $userName;
return $this;
}
public function getUserName()
{
return $this->username;
}
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=255, nullable=false)
* #Assert\NotBlank(message="Password cannot be blank.")
*/
private $password;
public function setPassword($password)
{
$this->password = $password;
return $this;
}
public function getPassword()
{
return $this->password;
}
/**
* #var string
*
* #ORM\Column(name="salt", type="string", length=255, nullable=false)
*/
private $salt;
public function setSalt($salt)
{
$this->salt = $salt;
return $this;
}
public function getSalt()
{
return $this->salt;
}
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=255, nullable=false)
* #Assert\NotBlank(message="E-Mail cannot be blank.")
* #Assert\Email(message="Invalid email address.")
*/
private $email;
public function setEmail($email)
{
$this->email = $email;
return $this;
}
public function getEmail()
{
return $this->email;
}
/**
* #var bool
*
* #ORM\Column(name="isActive", type="boolean", nullable=false)
*/
private $isActive;
public function setIsActive($isActive)
{
$this->isActive = $isActive;
return $this;
}
public function getIsActive()
{
return $this->isActive;
}
}
User Type:
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class UserType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('username', 'text', array('label' => 'User name'))
->add(
'password',
'repeated',
array(
'label' => 'Password',
'first_name' => 'password',
'second_name' => 'confirm',
'type' => 'password'
)
)
->add('email', 'text', array('label' => 'E-Mail'));
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
array(
'data_class' => 'Site\MainBundle\Entity\User',
'required' => false
)
);
}
/**
* #return string
*/
public function getName()
{
return 'main_user';
}
}
Register model:
use Symfony\Component\Validator\Constraints as Assert;
use Site\MainBundle\Entity\User;
/**
* Register
*/
class Register
{
/**
* #var Site\MainBundle\Entity\User
*
* #Assert\Type(type="Site\MainBundle\Entity\User")
* #Assert\Valid()
*/
protected $user;
public function setUser(User $user)
{
$this->user = $user;
return $this;
}
public function getUser()
{
return $this->user;
}
/**
* #var boolean
*
* #Assert\NotBlank(message="No terms accepted.")
* #Assert\True(message="You have to accept terms to be registered.")
*/
protected $terms;
public function setTerms($terms)
{
$this->terms = (Boolean)$terms;
return $this;
}
public function getTerms()
{
return $this->terms;
}
}
Register Type:
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Site\MainBundle\Form\UserType;
class RegisterType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('user', new UserType())
->add('terms', 'checkbox');
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
array(
'data_class' => 'Site\MainBundle\Entity\Register',
'required' => false
)
);
}
/**
* #return string
*/
public function getName()
{
return 'main_register';
}
}
And controller with twig. Part of twig:
{% block page_content %}
<form method="post" action="{{ path('main_register') }}">
{{ form_errors(formRegister.user.username) }}
{{ form_row(formRegister.user.username) }}
{{ form_errors(formRegister.user.password.password) }}
{{ form_row(formRegister.user.password.password) }}
{{ form_errors(formRegister.user.password.confirm) }}
{{ form_row(formRegister.user.password.confirm) }}
{{ form_errors(formRegister.user.email) }}
{{ form_row(formRegister.user.email) }}
{{ form_errors(formRegister.terms) }}
{{ form_row(formRegister.terms) }}
<button type="submit">Register</button>
</form>
{% endblock %}
Register Controller:
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Site\MainBundle\Form\RegisterType;
use Site\MainBundle\Entity\Register;
/**
* RegisterController
*/
class RegisterController extends Controller
{
public function defaultAction()
{
$formRegister = $this->createForm(new RegisterType(), new Register());
if ($this->getRequest()->isMethod('post')) {
$formRegister->handleRequest($this->getRequest());
if ($formRegister->isValid()) {
echo 'form is valid';
}
}
$twig = 'SiteMainBundle:register:default.html.twig';
$data = array(
'formRegister' => $formRegister->createView()
);
return $this->render($twig, $data);
}
}
Where can be problem? Help please with it.
Updated
echo "<pre>";
echo $formRegister->getErrorsAsString();
echo '</pre>';
says:
user:
username:
No errors
password:
password:
No errors
confirm:
No errors
email:
No errors
terms:
ERROR: No terms accepted.
ERROR: You have to accept terms to be registered.
As you can see model User is not validated AT ALL... =\
Found, finally.
Bug is in this part. I wanted to disable this way browser validation...
'required' => false
BUT. This "guys" (I mean developers),compare two things in one setting. So if we set 'required' to false our fields won't be validated. And if true it will be validate BUT ALSO WITH browser validator.. =\ Maybe someone know how to avoid it (browser validation) NOT by editing twig file (some options or other setting)?
PS: To avoid browser i changed twig.
<form method="post" action="{{ path('main_register') }}" novalidate>
If you wanna do it by code, in your Controller, your code should be like:
class RegisterController extends Controller
{
public function defaultAction()
{
$formRegister = $this->createForm(new RegisterType(), new Register(), array(
'attr'=> array('novalidate'=>'novalidate'),
));
With the therd parĂ¡meter of "createForm", you can modified the form (for example: acction, class, etc).
I normaly use:
$form = $this->createForm(new RegistroType(), $usuario, array(
'action' => $this->generateUrl('jgo_registro'),
'method' => 'POST',
'attr'=> array('novalidate'=>'novalidate'),
));
I am trying to set up some embedded forms using this guide.
I have two models set up in my application, Lesson and Evaluation.
Each Lesson can have multiple Evaluations.
I have a form set up where the user can create a lesson and also as many evaluations as they want within that lesson. When the form is submitted, it creates the lesson record and all of the evaluation records successfully, however the evaluation records that get created are not linked to the parent lesson (the lesson_id field is just left blank).
Can anyone help?
Any advice appreciated.
Thanks.
My Model classes are set up like this:
Evaluation:
class Evaluation
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Lesson", inversedBy="evaluations")
* #ORM\JoinColumn(name="lesson_id", referencedColumnName="id")
*/
protected $lesson;
/**
* Set lesson
*
* #param \LessonBundle\Entity\Lesson $lesson
* #return Evaluation
*/
public function setLesson(\LessonBundle\Entity\Lesson $lesson = null)
{
$this->lesson = $lesson;
return $this;
}
/**
* Get lesson
*
* #return \LessonBundle\Entity\Lesson
*/
public function getLesson()
{
return $this->lesson;
}
}
And the Lesson:
class Lesson
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="Evaluation", mappedBy="lesson", cascade={"persist"})
*/
protected $evaluations;
public function __construct()
{
$this->evaluations = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Add evaluations
*
* #param \DS\LessonBundle\Entity\Evaluation $evaluations
* #return Lesson
*/
public function addEvaluation(\LessonBundle\Entity\Evaluation $evaluations)
{
$this->evaluations[] = $evaluations;
return $this;
}
/**
* Remove evaluations
*
* #param \DS\LessonBundle\Entity\Evaluation $evaluations
*/
public function removeEvaluation(\LessonBundle\Entity\Evaluation $evaluations)
{
$this->evaluations->removeElement($evaluations);
}
/**
* Get evaluations
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getEvaluations()
{
return $this->evaluations;
}
public function setEvaluations(ArrayCollection $evaluations)
{
foreach ($evaluations as $evaluation) {
$evaluation->setLesson($this);
}
$this->evaluations = $evaluations;
}
}
My Controller method:
public function newAction()
{
$lesson = new Lesson;
$evaluation1 = new Evaluation();
$lesson->getEvaluations()->add($evaluation1);
$form = $this->createForm(new LessonType(), $lesson);
$request = $this->getRequest();
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getEntityManager();
$em->persist($lesson);
$em->flush();
return $this->redirect($this->generateUrl('lesson_list'));
}
}
return $this->render('LessonBundle:Lesson:new.html.twig', array('form' => $form->createView()));
}
And my forms:
class LessonType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('evaluations', 'collection', array(
'type' => new EvaluationType(),
'allow_add' => true,
'by_reference' => false,
));
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => 'LessonBundle\Entity\Lesson',
);
}
public function getName()
{
return 'Lesson';
}
}
And:
class EvaluationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('report');
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => 'LessonBundle\Entity\Evaluation',
);
}
public function getName()
{
return 'Evaluation';
}
}
And finally, my form twig template:
{% extends '::base.html.twig' %}
{% block content %}
<form class="vertical" action="" method="post" {{ form_enctype(form) }}>
{{ form_errors(form) }}
<ul class="collectionholder" data-prototype="{{ form_widget(form.evaluations.vars.prototype)|e }}">
{% for evaluation in form.evaluations %}
<li>{{ form_row(evaluation) }}</li>
{% endfor %}
</ul>
{{ form_rest(form) }}
<input type="submit" />
</form>
{% endblock %}
In your class Lesson entity add:
/**
* Add evaluations
*
* #param \DS\LessonBundle\Entity\Evaluation $evaluations
* #return Lesson
*/
public function addEvaluation(\LessonBundle\Entity\Evaluation $evaluations)
{
$this->evaluations[] = $evaluations;
$evaluations->setLesson($this);
return $this;
}