Bonjour la communauté Grafikart

Tout d'abord merci pour votre travail.
Je suis sur symfony 3.1.10 ( Je suis sur symfony depuis 1 mois).
Je rencontre une difficulté avec le formBuilder - j'ai du mal à saisir tout son potentiel.
Je vous présente ma 1ere problématique. Merci pour votre indulgence.

Ce que je fais

J'ai une relation ManyToMany entre category et advert.

step by step

Voici ma relation sur l'entité advert

 /**
     * @ORM\ManyToMany(targetEntity="BE\PlateformBundle\Entity\Category", cascade={"persist"})
     * @ORM\JoinTable(name="be_advert_category")
     */
    private $categories;

Voici mes getters/setters

    /**
     * Add category
     *
     * @param Category $category
     */
    public function addCategory(Category $category)
    {
        $this->categories[] = $category;

    }

    /**
     * Remove category
     *
     * @param Category $category
     */
    public function removeCategory(Category $category)
    {
        $this->categories->removeElement($category);
    }

    /**
     * Get categories
     *
     * @return ArrayCollection
     */
    public function getCategories()
    {
        return $this->categories;
    }

Sachant que je me retrouve avec un ArrayCollection, j'ai ajouté à mon entité User

use Doctrine\Common\Collections\ArrayCollection;

et j'ai affecté l'arrayCollection pour categories comme ceci

    public function __construct()
    {
        $this->date             = new \Datetime();
        $this->categories   = new ArrayCollection();
        $this->applications = new ArrayCollection();
    }

Si j'ai bien compris ce que je fais -> c'est advert qui est propriétaire de la relation ManyToMany et c'est unidirectionnel. * Si je dis une bétise - prévenez moi, merci

Je n'ai aucun traitement qui définit la relation sur l'entité Category.

Ce que je veux

Voici mon formBuilder:

<?php

namespace BE\PlateformBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class AdvertType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
            $builder
                    ->add('date', DateType::class, array('widget' => 'single_text'))
                    ->add('title', TextType::class)
                    ->add('content', TextareaType::class)
                    ->add('published', CheckboxType::class)
                    //->add('author', TextType::class)
                    ->add('image',  ImageType::class)
                    ->add('categories', EntityType::class, array(
                            'class' => 'BEPlateformBundle:Category',
                            'choice_label' => 'name',
                    ))
                    ->add('save',       SubmitType::class)
            ;
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'BE\PlateformBundle\Entity\Advert'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'be_plateformbundle_advert';
    }

}

Voici mon addAction du AdvertController

        public function addAction(Request $request)
        {
            //On récupére l'entity Manager
            $em = $this->getDoctrine()->getManager();

            $advert = new Advert();

            $user = $this->getUser();
            //var_dump($user);

            //$advert->setAuthor($user);
            //var_dump($advert);

            $form = $this->createForm(AdvertType::class, $advert);
            //var_dump($form);die();

            if ($request->isMethod('POST') && $form->handleRequest($request)->isValid()) 
            {

                //On persist et flush 
                $em->persist($advert);
                $em->flush();

                $request->getSession()->getFlashBag()->add('notice', 'Annonce bien enregistrée.');

                // Puis on redirige vers la page de visualisation de cettte annonce
                return $this->redirectToRoute('be_plateform_view', array('id' => $advert->getId()));
            }

            return $this->render('BEPlateformBundle:Advert:add.html.twig', array(
                'form'      => $form->createView(),
            ));
        }

Mon form s'affiche correctement - il me propose bien la liste des catégories.

Si je submit celui-ci, j'ai ce message d'erreur.

Ce que j'obtiens

\NoSuchPropertyException: "Could not determine access type for property "categories"."

J'ai du mal à saisir pourquoi -> est ce parceque j'ai un arrayCollection et cela suppose donc que je dois utiliser un type en adéquation avec cet arrayCollection sur mon formBuilder. Si oui/non - je veux bien un eclaircissement et vos remarques, etc..
->comment ecrire la partie du form concernant category.

->add('categories', EntityType::class, array(
                            'class' => 'BEPlateformBundle:Category',
                            'choice_label' => 'name',
                    ))

Mon objectif est de bien comprendre "le formbuilder" et le "propertyAccessor".
-> Ma dernière question peut paraitre idiote: -> y'a t'il une correlation ou au contraire une divergence entre propertyAccessor et methode __tostring

Merci pour le temps que vous passerez sur ce post. Merci pour votre indulgence - continuez grafikart c'est génial

Je vous mets mon stackTrace si besoin:

[1] Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException: Could not determine access type for property "categories".
    at n/a
        in C:\wamp\www\labsymf\vendor\symfony\symfony\src\Symfony\Component\PropertyAccess\PropertyAccessor.php line 614

    at Symfony\Component\PropertyAccess\PropertyAccessor->writeProperty(array(object(Advert), object(Advert)), 'categories', object(Category))
        in C:\wamp\www\labsymf\vendor\symfony\symfony\src\Symfony\Component\PropertyAccess\PropertyAccessor.php line 202

    at Symfony\Component\PropertyAccess\PropertyAccessor->setValue(object(Advert), object(PropertyPath), object(Category))
        in C:\wamp\www\labsymf\vendor\symfony\symfony\src\Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper.php line 93

    at Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper->mapFormsToData(object(RecursiveIteratorIterator), object(Advert))
        in C:\wamp\www\labsymf\vendor\symfony\symfony\src\Symfony\Component\Form\Form.php line 618

    at Symfony\Component\Form\Form->submit(array('date' => '2017-01-30', 'categories' => '1', 'title' => 'test insertion form - FormAdvert', 'content' => 'blabla', 'published' => '1', 'save' => '', '_token' => 'RR1wUrNQ73T2jDVjTjg0MAbsJKuQP3sTSYlPA0yGe1E', 'image' => array('file' => object(UploadedFile))), true)
        in C:\wamp\www\labsymf\vendor\symfony\symfony\src\Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler.php line 113

    at Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler->handleRequest(object(Form), object(Request))
        in C:\wamp\www\labsymf\vendor\symfony\symfony\src\Symfony\Component\Form\Form.php line 488

    at Symfony\Component\Form\Form->handleRequest(object(Request))
        in C:\wamp\www\labsymf\src\BE\PlateformBundle\Controller\AdvertController.php line 103

    at BE\PlateformBundle\Controller\AdvertController->addAction(object(Request))
        in  line 

    at call_user_func_array(array(object(AdvertController), 'addAction'), array(object(Request)))
        in C:\wamp\www\labsymf\vendor\symfony\symfony\src\Symfony\Component\HttpKernel\HttpKernel.php line 153

    at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), '1')
        in C:\wamp\www\labsymf\vendor\symfony\symfony\src\Symfony\Component\HttpKernel\HttpKernel.php line 68

    at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), '1', true)
        in C:\wamp\www\labsymf\vendor\symfony\symfony\src\Symfony\Component\HttpKernel\Kernel.php line 169

    at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
        in C:\wamp\www\labsymf\web\app_dev.php line 30

1 réponse


lalwende
Auteur
Réponse acceptée

Après réflexion, mon problème est résolu. - ps: le markdown plante - j'ai pas trouvé pourquoi - je poste comme ça dsl

                            'class' => 'BEPlateformBundle:Category',
                            'multiple' => true,

C'est donc bien l'idée d'avoir une collection d'objet qui est envoyée à notre formbuilder qui -> oblige a affecter 'multiple'=> true
C'est totalement logique ;) - comme quoi poser les choses c'est une étape du debug.

Prochaine étape -> affecter le user de la session en cours -> à l'author de l'advert.
-> vérifier mes entités - ma relation
-> regarder la doc pour trouver le bonne méthode. voir si il existe une best practice
-> sachant que je serais amené à faire çà régulièrement -> associer un user à l'author -> voir si cela nécessite un service

Si je rencontre des difficultés - je posterais un nouveau message. :)

Celui-ci peut etre cloturer.