Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Symfony2] Questions fréquemment posées

Merci de ne pas y poster vos questions.

27 décembre 2012 à 14:31:58

Citation : Zazou

Un format twig dans la liste par contre, là ça aurait du sens.

Je crois me souvenir l'avoir proposé, à mes débuts sur le forum (à l'époque de la V3 :papy: ), mais je n'avais pas été très clair ni adéquat, donc c'est passé à la trappe.

En gros, comme php dans la liste est était un alias de html+php, je proposais twig pour alias de html+django.

-
Edité par Ymox 1 mai 2013 à 7:59:05

  • Partager sur Facebook
  • Partager sur Twitter
OC à changer FAQ PHP • Et avant celaTutoriel WAMP • Code illisible ? Un p'tit 👍 ici@Zeste de Savoir
8 janvier 2013 à 16:14:05

Un site utile à ajouter à la faq:
http://www.kitpages.fr/fr/cms/22/aide-memoire-symfony2

A noter que l'auteur du site tien régulièrement la page à jour et qu'il y a plus de mémo dans le menu à gauche.
  • Partager sur Facebook
  • Partager sur Twitter
DigitalOcean - Heberger vos sites sur le cloud à partir de 5$ par mois.
27 mars 2013 à 15:09:38

FAQ développement Symfony2 sous Mac OS X

Si vous préférez développer avec votre propre environnement, et non passer par MAMP etc

Ce tuto est fait pour vous

Il est simple, clair et précis. On utilise alors apache/php de base, on installe mysql, et on paramètre php pour coller avec la config requise Symfony2

Pré requis : il faut s'y connaitre en ligne de commande, car ce n'est pas du clic clic ;)

  • Partager sur Facebook
  • Partager sur Twitter
I'll be back soon...
29 mars 2013 à 13:36:34

Salut à tous,

A la validation de mon formulaire j'ai l'erreur ci-dessous, pourquoi ? Le jeton CSRF est invalide. Veuillez renvoyer le formulaire

Réponse : un formulaire dont l'attribut "action" pointe vers une mauvaise route (exemple : la route d'ajout lors de la modification d'un article) déclenche également cette erreur. Si votre formulaire est utilisé pour la création comme pour ma modification, laissez action="" vide.

<form action="{{ path('votre_route') }}" method="post" {{ form_enctype(form) }}>

Devient alors :

<form action="" method="post" {{ form_enctype(form) }}>

-
Edité par Ensareab 29 mars 2013 à 14:04:20

  • Partager sur Facebook
  • Partager sur Twitter
29 mars 2013 à 13:53:50

Salut,

Ce n'est pas une question fréquemment posée elle n'a pas sa place ici.

  • Partager sur Facebook
  • Partager sur Twitter
29 mars 2013 à 13:57:03

Salut Winzou,

En fait, si. J'ai remarqué que l'attribut action devait être vide. Et le problème d'avoir la route "ajouter" quand on modifie l'article génère également chez moi un problème de CSRF, qui lui est évoqué dans ce topic.

[Edit] J'ai modifié mon post pour le faire coller à la question en question

-
Edité par Ensareab 29 mars 2013 à 14:05:18

  • Partager sur Facebook
  • Partager sur Twitter
29 mars 2013 à 15:35:46

Cela n'a rien à voir avec symfony en fait, c'est juste un problème de HTML ça ... Un action vide revient à ne pas mettre l'attribut du tout d'ailleurs, et le formulaire redirigera alors vers la même page. C'est tout. Du moment que l'action du formulaire amène vers la bonne page, le traitement sera effectué sans problème.
  • Partager sur Facebook
  • Partager sur Twitter
29 mars 2013 à 22:33:59

Bonjour,

Pour mon tout premier post sur ce forum, j'aimerais vous partager une ressource que j'ai trouvé par hasard : 

http://www.symfony2cheatsheet.com/

C'est une page qui regroupe toute les fonctionnalités courantes de Symfony2 qui pourrait être très utile en guise de pense-bête. ;)

  • Partager sur Facebook
  • Partager sur Twitter
3 mai 2013 à 20:07:19

J'ai plusieurs catégories, j'aimerais afficher dans ma vue le nombre d'articles que contiennent chacune d'elles, comment faire ?

Réponse:

{% for category in categories %}

    {{ category.articles|length }} {# retourne le nombre d'élément si utilisé sur un array #}
       OU
    {{ category.mods.count }} {# retourne le nombre d'élément si utilisé sur un array #}

{% endfor %}

C'est tout, pas besoin de requêtes supplémentaire ou de quoi que ce soit coté controller :)

-
Edité par Axel.B 3 mai 2013 à 20:13:36

  • Partager sur Facebook
  • Partager sur Twitter
DigitalOcean - Heberger vos sites sur le cloud à partir de 5$ par mois.
19 mai 2013 à 1:40:40

J'ai cette erreur, comment faire ?

An exception occurred while executing '... FOREIGN KEY (...) REFERENCES ... (id)':
Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`symfony`.<result 2 when explaining filename '...'>, CONSTRAINT `...` FOREIGN KEY (`..._id`) REFERENCES `...` (`id`))


Cette erreur survient lorsque l'on a une entité existante déjà matérialisée dans la base de donnée.

Imaginez que vous souhaitez ajouter cette relation facultative ( facultative car JoinColumn(nullable=false) )

    /**
     * @ORM\ManyToOne(targetEntity="Kyna\CollectionBundle\Entity\Categorymaster")
     * @ORM\JoinColumn(nullable=false)
     */
    private $categorymaster;


A la mise à jour, Doctrine vas vous créer la colonne dans votre table, puis vas vous afficher l'erreur dans la console car les entrées existantes dans votre table auront pour valeur 0 (null) d'assigner à la colonne que vous venez de créer, hors vous avez bien indiqué
@ORM\JoinColumn(nullable=false) qui interdit la valeur null.

Ce qu'il faut faire lors de l'ajout de votre attribut à votre entité, c'est passer nullable à true, mettre à jour votre base de donnée, ensuite la passer à false et la mettre à nouveau à jour, vous êtes donc obligé de procéder en deux étapes. Cette erreur ne surviendra jamais si vous ajoutez nullable=true a une entité existante déjà présente en bdd, car la première étape aura déjà été passé par le passé au moment de la création de votre entité si vous avez mis votre bdd à jour à ce moment là.

-
Edité par Axel.B 1 juin 2013 à 21:11:12

  • Partager sur Facebook
  • Partager sur Twitter
DigitalOcean - Heberger vos sites sur le cloud à partir de 5$ par mois.
11 juin 2013 à 12:57:38

Citation

J'ai une erreur
An exception has been thrown during the rendering of a template ("No route found for "GET MonEntite:uneAction")
Mais je n'ai pas de route, j'utilise {% render %} ! Qu'est-ce qui ne va pas ?

  Réponse: {% render %} comportait une faille de sécurité, qui a été comblée depuis la version 2.2 de Symfony. Il faut désormais utiliser {{ render() }}   N.B. : le tutoriel en parle ;)

  Citation

Comment puis-je générer un lien avec une ancre (la partie après le #) dans Twig, pour avoir quelque chose comme mon/url#monAncre ? N'y a-t-il pas moyen de le faire avec {{ path() }} ?

  Réponse: non, vous êtes obligé de mettre cette partie à la main, hors de la fonction {{ path() }}, donc {{ path(…) }}#uneAncre. Notez que si vous utilisez des ancres qui sont basées sur une propriété d'une entité (slug d'un titre d'article, de section, etc., ou ID d'une entité), c'est relativement facile. Il suffit de faire {{ path(…) ~ '#' ~ entite.propriete }}.

  Citation

J'ai des pages statiques dans mon application, mais je n'aimerais pas avoir à changer partout où j'ai des liens qui mènent vers ces pages quand je change leur URL ! Y a-t-il une solution ?

  Réponse: Oui, mais ça demandera évidemment quelques changements. Il est possible de rendre des templates sans aucun contrôleur, mais liés à une vue, ce qui nous va très bien pour des pages statiques. On va donc créer une route qui ne fera que rendre la page statique, qu'il vous faudra simplement renommer (si ce n'est pas déjà le cas) avec l'extension .html.twig. Ensuite de quoi, créez votre route comme suit :

ma_route_pour_ma_page_statique:
  path: mon/url
  defaults:
_controller: FrameworkBundle:Template:template
template: 'MonBôBundle:Static:monTemplateDePageStatique.html.twig'</pre>
Ne changez pas ce qu'il y a après _controller, c'est un contrôleur par défaut, nécessaire dans ce cas

  Du coup, vous pourrez utiliser {{ path([le nom d'une route pour une page statique]) }}, et quand vous changerez l'URL, ce sera à un seul endroit.

</pre>

-
Edité par Ymox 18 janvier 2015 à 13:55:50

  • Partager sur Facebook
  • Partager sur Twitter
OC à changer FAQ PHP • Et avant celaTutoriel WAMP • Code illisible ? Un p'tit 👍 ici@Zeste de Savoir
25 juillet 2013 à 17:53:56

J'ai supprimé un fichier lié à une annotation ainsi que l'annotation mais l'application en prod me dit qu'elle ne peut plus avoir accès au fichier (par exemple un repository) alors que je ne m'en sers plus. Pourtant j'ai vidé le cache et en dev tout fonctionne !


Réponse : Vous avez probablement activé le cache apc pour les métadonnées de doctrine en prod. metadata_cache_driver: apc. Ce qui n'est pas un mal au contraire mais cela a quelques inconvénients. Vous devez maintenant vider le cache apc à chaque fois que vous faites une modification sur les annotations en prod. Pour cela utiliser la commande php app/console doctrine doctrine:cache:clear-metadata. Si cela ne fonctionne toujours pas utiliser la manière forte, redémarrer apache !

  • Partager sur Facebook
  • Partager sur Twitter
13 août 2013 à 21:39:47

Comment utiliser une méthode personnel du repository dans un ParamConverter ?

Réponse : Il peut-être intéressant d'utiliser une méthode personnel lorsqu'on utilise un param converter. Par exemple pour faire une jointure. Pour ça il suffit de le spécifier dans l'annotation.

/**
 * @Route("/blog/article/{id}")
 * @ParamConverter("article", class="SdzBlogBundle:Article", options={"repository_method" = "findWithComments"})
 */
public function showAction(Article $article)
{
}


Attention: Ne fonctionne qu'à partir de la version 2.2 de symfony

Edit: @Ymox: J'ai corrigé l'ambiguité. Merci !

-
Edité par Malian 14 août 2013 à 9:34:48

  • Partager sur Facebook
  • Partager sur Twitter
18 août 2013 à 12:29:26

[Doctrine2] J'essaye de récupérer les 5 derniers éléments avec le queryBuilder, qui contient une jointure one-to-many ou many-to-many mais cela ne fonctionne pas, souvent je n'ai que 1 seul élément.

Réponse : Si vous essayez de récupérer les 5 dernières news avec les commentaires par exemple, en utilisant simplement le LIMIT de sql ou le setFirstResult, setMaxResults du queryBuilder, cela ne fonctionnera pas et c'est un comportement voulu pour le moment. En effet, lorsque Doctrine va récupérer les éléments en base de donnée, lors d'une jointure, il y a plus de lignes récupérées que d'éléments réels si la jointure n'est pas one-to-one. C'est doctrine qui se charge de réassembler le tout ! Seulement il ne va alors récupérer que 5 éléments, puisque c'est ce que vous avez demandé...

Oui, mais alors comment je fais moi ?: Heureusement Doctrine a pensé à tout ! Il suffit pour cela d'utiliser la classe Paginator de Doctrine ! Et de procéder comme ceci

$queryBuilder =
    $this
    ->createQueryBuilder('a')
    ->leftJoin('a.commentaires', 'c')
    ->addSelect('c');
    ->setFirstResult(0)
    ->setMaxResults(5);

$query = $queryBuilder->getQuery();

$paginator = new Paginator($query, true);

Le second paramètre, définit ici à true, permet de dire à Doctrine: "Attention bonhomme, j'ai des jointures supra compliquées ! Tu gères ça pour moi stp !". Admirez le résultat ! 

Si vous voulez vous n'êtes pas obligé de transformer votre queryBuilder en query. La classe Paginator s'en chargera !

Bonus: Si vous n'avez pas besoin de faire de join compliqué (ça marche aussi avec) et que vous voulez récupérer x news et en plus savoir combien vous en avez en tout, la classe Paginator vous permet de le faire ! Elle implémente les classes Countable et IteratorAggregate. Tout ce qu'il vous faut pour créer un système de pagination maison !

Attention: Ne fonctionne que à partir de Doctrine 2.2

PS: L'équipe de Doctrine espère pouvoir automatiser ce comportement dans une futur version.
PPS: Oui c'est un topic pour une faq Symfony2. Mais les débutants ils font pas la différence, na ! 

-
Edité par Malian 18 août 2013 à 12:33:49

  • Partager sur Facebook
  • Partager sur Twitter
18 août 2013 à 13:05:06

[JMSSecurityExtraBundle] J'ai envie de créer une expression de sécurité supplémentaire afin de ne pas dupliquer mon code. Je n'ai pas non plus envie d'utiliser le système d'annotation de JMSDiExtraBundle. Comment puis-je faire ?

Réponse : Si vous ne voulez pas utiliser le système d'annotation de JMSDiExtraBundle, vous pouvez utiliser votre service comme n'importe quel autre service. Il suffit pour ça de le déclarer dans le DI. En ce qui concerne l'expression que vous voulez ajouter il faudra utiliser le tag security.expressions.function_evaluator pour chaque fonction que vous voulez déclarer en tant qu'expression.

Exemple :

        <service id="demo_bundle.security.expressions" class="Acme/DemoBundle/Security/Expressions">
            <argument type="service" id="security.context" />
            <tag name="security.expressions.function_evaluator" function="canEditUser" method="canEdit" />
        </service>

On peut omettre l'attribut "method" si la méthode porte le même nom que la fonction. Ici, "function" représente l'expression qu'on veut utiliser et "method" représente la méthode de la classe qui va être appelée.

Attention : Ne fonctionne qu'avec JMSSecurityExtraBundle supérieur à 1.3.

PS pour Winzou. C'est avancé et pas courant comme question, mais elle a déjà été posée et je préfère la voir dans un fond de la faq que de devoir chercher sur le SDZ avec le système de recherche actuel. Libre à toi de l'y mettre ou non.

  • Partager sur Facebook
  • Partager sur Twitter
23 août 2013 à 14:07:57

Pourquoi ai-je l'erreur suivante : Call to undefined method FOS\UserBundle\Doctrine\UserManager::getRepository() (J'utilise FOSUserBundle qui fonctionne très bien avec toutes les autres fonctionnalités)

Réponse :

Lorsque l'on utilise un entity manager personnel (même si l'entity user hérite de celle de FOSUB), il faut passer par les méthodes classiques d'accès au manager et au repository, tel que:

$em = $this->getDoctrine()->getManager();
$repository = $em->getRepository('MnUserBundle:User')
                 ->findContacts($contact);


Alexandre

-
Edité par Frackup 23 août 2013 à 16:59:10

  • Partager sur Facebook
  • Partager sur Twitter
23 août 2013 à 14:18:09

Et la réponse avescera ?
  • Partager sur Facebook
  • Partager sur Twitter
27 septembre 2013 à 14:01:14

@Frackup, tu peux également préciser qu'il est inutile de faire un persist() avant le flush(), le manager de FOS s'en charge :)

Question :

Comment organiser une requête sous forme de tableau que l'on nome soit même et exécuter un setMaxResult sur un élément d'une requête en particulier et non pas tout ce qu'elle retourne ?

Réponse :

    public function getModsWeeklyMostViewed($nombre = null)
    {
        $query = $this->_em->createQuery(

        "SELECT m, SUM(v.views) AS totalView
         FROM KynaModsBundle:Mods m

         INNER JOIN m.views v

         WHERE m.id = v.mod
         AND v.date > :dateLimit

         GROUP BY m.id
         ORDER BY totalView DESC
        "
        )->setParameter('dateLimit', new \dateTime('-7days'));

if($nombre) {
 $query->setMaxResults($nombre);
}
return $query->getResult(); }


Ici, une clé "totalView" contenant la somme de notre nombre de vus sera créé, c'est le AS totalView qui permet ça, vous pouvez renommer facilement totalView par n'importe quoi pour avoir une clé portant le nom de votre choix et ainsi pouvoir organiser et nomer les éléments de votre tableau.

Il serait par exemple possible de faire SELECT m AS JeContientLesMods.

Ensuite, j'ai déjà eu des problèmes avec setMaxResults, dans ce type de requête, le setMaxResults réglé à 10 vas prendre 10 résultats, mais non pas 10 mods, si j'ai 10 mods mais que le premiers contient 8 view, 8+1 = 9, la requête récupérera un mod, ses 8 vus et un mod supplémentaire affin d'arriver à 10 ce qui pose un gros problème vus que cela fausse totalement la requête.

Pour pallier à ce problème, il faut utiliser GROUP BY m.id, qui vas grouper les mods ensemble dans la requête affin que le setMaxResults() compte bien le nombre de mod et non pas le nombre de mod mélangé aux vus.

Voilà, j’espère avoir été clair, c'est pas très simple à expliquer et c'est un problème que j'ai résolu il y a déjà environ 5 mois  ^^

-
Edité par Axel.B 27 septembre 2013 à 14:02:41

  • Partager sur Facebook
  • Partager sur Twitter
DigitalOcean - Heberger vos sites sur le cloud à partir de 5$ par mois.
11 décembre 2013 à 22:08:06

Question :

J'ai un formulaire imbriqué et mes @Assert ne fonctionnant pas, pourquoi ?

Réponse :

En regardant la class Form et en faisant une petite recherche, on peut remarquer un attribut "cascade_validation" qui peut valoir soit "true", soit "false", en fait par défaut un formulaire imbriqué ne s'occupe pas de valider automatiquement les "sous-formulaire", pour activer la validation de ces derniers, il vous faut ajouter ceci dans votre formType en dessous de "data_class" :

        $resolver->setDefaults(array(
            'data_class' => ........................,
            'cascade_validation' => true
        ));


Exemple :

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        parent::setDefaultOptions($resolver);

        $resolver->setDefaults(array(
            'data_class' => 'Kyna\CollectionBundle\Entity\ImageCollection',
            'cascade_validation' => true
        ));
    }

Voilà c'est tout, par ailleurs je ne comprends pas que ce comportement ne soit pas celui par défaut, dans le cas d'un upload de fichier, ça pourrait faire passer n'importe quel fichier peu importe l’extension et la taille de celui-ci, bref pour moi ça passe comme une faille de sécurité même...

-
Edité par Axel.B 11 décembre 2013 à 22:14:21

  • Partager sur Facebook
  • Partager sur Twitter
DigitalOcean - Heberger vos sites sur le cloud à partir de 5$ par mois.
19 décembre 2013 à 14:40:40

Question :
Comment faire une redirection depuis une route

Réponse : Il faut utiliser un controller déjà définit dans FrameworkBundle :

  • FrameworkBundle:Redirect:urlRedirect Si vous voulez faire une redirection à partir du pattern
  • FrameworkBundle:Redirect:redirect Si vous voulez faire une redirection à partir d'une route (Si la route vers laquelle on est redirigée a des paramètres sans aucune valeur par défaut, il faut que la route de redirection possède ces paramètres) Plus d'informations sur cette page de documentation.

Par exemple, pour faire une redirection en gardant une locale par défaut :

mon_bundle_accueill:
   resource: "@MonBundle/Controller"
   type: annotation
   prefix:   /{_locale}
   defaults: {_locale: en}
   requirements:
   _locale: en|fr

mon_bundle_language: pattern: / defaults: {_controller: "FrameworkBundle:Redirect:redirect", route: "page_index", permanent: true}

</pre>

Bonus On peut utiliser un autre contrôleur de ce même bundle pour rendre des pages statiques comme évoqué par Ymox.

-
Edité par KenshiWado 19 décembre 2013 à 15:02:07

  • Partager sur Facebook
  • Partager sur Twitter
Entraidons-nous sur un site inachevé, c'est tellement mieux ! | JSDZ@Toulouse
13 mai 2014 à 13:59:50

Pourquoi mes formulaires sous OVH envoient des données vides ?

Réponse
Cela peut venir de la configuration d'OVH. En effet, via votre FTP favori, vous devriez trouver à la racine de votre serveur, un petit fichier nommé ".ovhconfig" (valable uniquement depuis Hébergements Web 2014). Ce fichier permet de configurer certaines valeurs qui concernent le fonctionnement de votre serveur. Voici les valeurs par défaut :

app.engine=php
app.engine.version=5.4
http.firewall=none
environment=production

Pour ma part, j'ai dû mettre les valeurs suivantes afin d'avoir des formulaires fonctionnels :

app.engine=phpcgi
app.engine.version=AUTO
http.firewall=none
environment=production

Voici également un lien vous permettant de consulter toutes les configurations possibles : http://www.ovh.com/fr/g1175.format_du_point_ovhconfig

-
Edité par Akalaa 14 mai 2014 à 9:44:42

  • Partager sur Facebook
  • Partager sur Twitter
20 mai 2014 à 13:38:28

J'ai des entités embarquées dans une autre, mais elles ne sont pas validées !

  Réponse : pour que la validation des entités embarquées soit aussi effectuée, il faut le spécifier dans les règles de validation. De manière simplifiée, cela se traduit par l'ajout de @Assert\Valid dans les annotations des propriétés impliquées dans les relations.

Hé, mais avec des groupes de validation, ça ne fonctionne pas  :'(

  Réponse : effectivement, si vous utilisez des groupes de validation, il faut paramétrer le formulaire parent à l'aide de 'cascade_validation' comme dans cet exemple :

$resolver->setDefaults(array(
'data_class' =&gt; 'Mon\BôBundle\Entity\MonEntite',
'cascade_validation' =&gt; true

));

</pre>

-
Edité par Ymox 20 mai 2014 à 15:06:53

  • Partager sur Facebook
  • Partager sur Twitter
OC à changer FAQ PHP • Et avant celaTutoriel WAMP • Code illisible ? Un p'tit 👍 ici@Zeste de Savoir
21 mai 2014 à 15:00:47

Question: Winzou nous a dit qu'avec l'ORM on ne devait plus penser en termes de base de donnée, mais en objet... Mais je n'arrive toujours pas à comprendre la logique des relations, entité propriétaire/inverse, etc...

  Réponse : En fait si vous avez déjà des connaissances en bases de données, il sera sûrement plus simple au départ de toujours penser aux bases de données quand vous faites vos relations. Je vais vous l'expliquer comme moi je l'ai ressenti, car les annotations doctrines, au final, se basent beaucoup sur la logique des clés étrangères. Pour cela je vais reprendre les principales relations utilisées et les comparer avec ce qu'on doit avoir en base de données.

Pour qu'on se mette bien d'accord, on va utiliser à chaque fois l'entité User (soit la table user) comme classe propriétaire de la relation.

ManyToOne/OneToMany

La relation ManyToOne permet d'associer une clé étrangère de la table user à l'identifiant de la classe visée par la propriété targetEntity. Imaginons qu'on ai une entité Entreprise qui est associé à la table 'entreprise'.

Logiquement on a un utilisateur qui ne peut faire parti que d'une entreprise, mais l'entreprise peut avoir plusieurs utilisateurs. C'est comme ça qu'on définit la relation ManyToOne (many pour l'entité ciblée, donc Entreprise et one pour l'entité actuelle, donc User). Dans ce cas tout va bien ! Mais si on veut récupérer la relation inverse, on a le droit à la bidirectionnalité mais on ne sait pas toujours ce qu'il se passe en base de données. La relation inverse du ManyToOne est donc le OneToMany et en fait, il n'y a rien du tout qui se fait en base de données ! OneToMany correspond à un tableau (une liste d'utilisateurs de l'entreprise dans notre cas) et ça, en base de donnée, on oublie ! Surtout pas de tableau en base de données, même si certaines SGBD le permettent ! Donc s'il y a du tableau en jeu, vous pouvez être sûr de ne pas être du côté propriétaire ;) .

La véritable difficulté est de déterminer qui a le inversedBy et qui a le mappedBy

  • inversedBy: (inversée par) Si on est du côté propriétaire, c'est ça qu'on met. (Et oui, on ne va pas inverser le côté inverse)
  • mappedBy: (mappée par) Si on est du côté inversé, c'est lui qu'on veut mapper ;)
<?php

/*
 * @ORM\Table(name="user")
 * @ORM\Entity()
 */
class User
{
	/**
	 * @ORM\Id
	 * @ORM\Column(type="integer")
	 * @ORM\GeneratedValue(strategy="AUTO")
	 */
	private $id;

	/**
	 * @ORM\ManyToOne(targetEntity="Entreprise", inversedBy="users")
	 */
	private $entreprise;
}

/*
 * @ORM\Table(name="entreprise")
 * @ORM\Entity()
 */
class Entreprise
{
	/**
	 * @ORM\Id
	 * @ORM\Column(type="integer")
	 * @ORM\GeneratedValue(strategy="AUTO")
	 */
	private $id;

	/**
	 * @ORM\OneToMany(targetEntity="User", mappedBy="entreprise")
	 */
	private $entreprise;
} 
Attention ! Derrière on a la base de donnée, on a dit qu'on voulait notre clé étrangère, mais on ne lui a jamais dit à quelle propriété on voulait la lier ! Par défaut Doctrine se lie directement à la propriété id de la table ciblée. Fort heureusement, on l'a. Mais si ce n'était pas le cas, qu'on avait appelé cet identifiant `idEntreprise`, il aurait fallu le préciser avec le paramètre `referencedColumnName`.
/**
 * @ORM\ManyToOne(...)
 * @ORM\JoinColumn(referencedColumnName="idEntreprise")
 */

OneToOne

Le OneToOne fonctionne de la même façon que le ManyToOne à l'exception que les colonnes fonctionnent exclusivement par paire. Imaginons que dans notre base, on ne veuille pas deux personnes qui aient la même adresse, on aura une table adresse. Par contre, le propriétaire peut être soit l'un soit l'autre. On a une base de données derrière, donc même si on peut choisir au pif grâce à la bidirectionnalité, laquelle des deux tables sera propriétaire, on ne fait pas ça !!! On choisi en fonction de notre application. Si on veut pouvoir, principalement, trouver une adresse d'un utilisateur, alors User sera propriétaire et aura le inversedBy.

ManyToMany

Enfin le ManyToMany s'utilise comme le OneToOne, on n'a pas de restriction sur le choix du propriétaire, mais encore mieux, ça n'aura aucun impact en base de données ! En fait la configuration de base de cette relation est assez "magique". On définit la classe ciblée, et sans rien nous demander d'autre, ça nous crée une table intermédiaire. Par exemple, nos utilisateurs ont des responsabilités, et ces responsabilités peuvent être prises par plusieurs personnes. On se rend compte que des deux côtés on est obligé d'avoir un tableau, mais en base de données, ça ne se fait pas !

Donc une base se crée pour qu'au final des relations se fassent comme si on avait ces deux relations suivies User --[OneToMany]--> UserResponsabilite --[ManyToOne]--> Responsabilite

/** @ManyToMany(targetEntity="Responsabilite") */
private $responsabilites;

Et ça va créer une nouvelle table nommé user_responsabilité avec deux clés étrangères user_id et responsabilite_id, en paire de clés primaires, sans rien demander... Si vous voulez garder la main sur tout ce qui se crée (je rappelle qu'on a une base de donnée, si on a choisi une autre politique de nommage, il faut la respecter), c'est tout de suite plus verbeux:

    /**
     * @ManyToMany(targetEntity="Responsabilite")
     * @JoinTable(name="user_responsabilite",
     *      joinColumns={@JoinColumn(name="responsabilite_id", referencedColumnName="id")},
     *      inverseJoinColumns={@JoinColumn(name="responsabilite_id", referencedColumnName="id")}
     *      )
     */
    private $responsabilites;

C'est un peu long, donc si j'ai oublié quelque chose ou que des points ne sont pas clairs, dites le moi par mp, surtout pas sur ce sujet, vos messages seront supprimés.

-
Edité par KenshiWado 21 mai 2014 à 15:12:48

  • Partager sur Facebook
  • Partager sur Twitter
Entraidons-nous sur un site inachevé, c'est tellement mieux ! | JSDZ@Toulouse
31 juillet 2014 à 16:14:53

Mes messages d'erreurs dans mon formulaire ne sont pas traduits?!? J'ai pourtant rempli le fichier messages.fr.yml! :o

 
Réponse : Les traductions pour les erreurs de validations dans un formulaire se font dans le fichier validators.fr.yml et ne se servent pas du fichier messages.fr.yml.

Mais?!? J'ai crée le fichier et ça ne marche toujours pas! J'ai oublié quelque chose?


Réponse : Et oui, après avoir ajouté un fichier de traduction, même en environnement de developpement, il faut faire un petit:

php app/console cache:clear



  • Partager sur Facebook
  • Partager sur Twitter
15 janvier 2015 à 0:12:58

Je ne sais pas vraiment comment structurer mon projet. Quelle est la meilleure méthode ?

 
Réponse : Le site officiel de Symfony propose une documentation (pour le moment en anglais et en italien) sur les meilleures pratiques à avoir lors de l'élaboration d'un projet Symfony à l'adresse suivante : http://symfony.com/doc/current/best_practices/index.html

  • Partager sur Facebook
  • Partager sur Twitter
Staff 18 janvier 2015 à 11:20:00

Bonjour à toutes et à tous,

J'écris ce petit message pour vous annoncer que je viens à l'instant de nettoyer complètement cette FAQ en supprimant tous les messages masqués ainsi que d'autres messages qui n'avaient rien à faire là.

On est d'ailleurs passé de 5 pages à 3 pages, cela donne un bon coup de jeune à ce sujet :)

A l'avenir, tout message qui n'a pas sa place ici sera supprimé afin que ce sujet reste clair.

Seuls les messages respectant le format Question/Réponse sont autorisés ainsi que les remarques à propos de ces messages.

Si vous avez une questions à poser, je vous invite donc à créer votre propre topic.


EDIT: vu le nombre de membres qui postent ici sans prendre le temps de lire mon message, je prends l'initiative de fermer ce sujet (cela devient lassant de supprimer manuellement les messages en envoyant un MP aux membres en question pour leur expliquer cette suppression).

Du coup, pour ajouter une vrai question/réponse, il faut envoyer un MP à un membre du Staff pour demander la réouverture temporaire du sujet ;)

-
Edité par lorrio 24 septembre 2015 à 16:03:22

  • Partager sur Facebook
  • Partager sur Twitter