3

I have this entity in my symfony project:

/**
 * Batiments
 *
 * @ORM\Table(name="batiments")
 * @ORM\Entity
 * @ORM\Entity(repositoryClass="MySpace\DatabaseBundle\Repository\BatimentsRepository")
 */
class Batiments
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

/**
     * @var string
     *
     * @ORM\Column(name="nom", type="string", length=150, nullable=true)
     */
    private $nom;

    /**
     * @ORM\ManyToOne(targetEntity="MySpace\DatabaseBundle\Entity\Ensembles")
     * @ORM\JoinColumn(nullable=false)
     */
    private $ensembles;

    /**
 * @ORM\ManyToMany(targetEntity="MySpace\DatabaseBundle\Entity\Typesactivite")
 * @ORM\JoinTable(name="batiments_typesactivite",
 *      joinColumns={@ORM\JoinColumn(name="batiments_id", referencedColumnName="id", nullable=false)},
 *      inverseJoinColumns={@ORM\JoinColumn(name="typesactivite_id", referencedColumnName="id", nullable=false)}
 *      )
 */
private $typesactivite;

//getters and setters

As you can see, I have a relation ManyToOne for the $ensembles and a ManyToMany relation for $typesactivite.

I have this SQL request:

SELECT b.referenceBatiment, b.nom, e.nom, p.nom, b.surfaceChauffee, ta.type
FROM `batiments` b, `ensembles` e, `parcsimmobilier` p, `typesactivite` ta, `batiments_typesactivite` bta
WHERE b.ensembles_id = e.id
AND e.parcsimmobilier_id = p.id
AND b.id = bta.batiments_id
AND ta.id = bta.typesactivite_id
GROUP BY p.nom, e.nom, b.nom, ta.type

On PhpMyAdmin the SQL request works very well, and so I have to import my SQl request in my Symfony Project (DQL with Doctrine).

I try this in my controller.php:

$query=$em->createQuery('SELECT b
                         FROM MySpaceDatabaseBundle:Ensembles e,  MySpaceDatabaseBundle:Typesactivite ta, MySpaceDatabaseBundle:Parcsimmobilier p, MySpaceDatabaseBundle:Batiments b
                         WHERE b.ensembles = e.id
                         AND b.typesactivite = ta.id');

It seems to work but just for the ManyToOne relation. I display the result in a <table> tag in html.twig like this:

<table id="dataTablesBatiments" class="table table-bordered table-hover" cellspacing="0" width="100%">
                <thead>
                  <tr>
                    <th>Référence</th>
                    <th>Parc</th>
                    <th>Nom</th>
                    <th>Ensemble</th>
                    <th>Type d'activité</th>
                    <th>Surface</th>
                    <th></th>
                  </tr>
                </thead>
                <tbody>
                  {% for batiments in batiment %}
                    <tr>
                      <td>{{ batiments.referencebatiment }}</td>
                      <td>{{ batiments.ensembles.parcsimmobilier }}</td>
                      <td>{{ batiments.nom }}</td>
                      <td>{{ batiments.ensembles }}</td>
                      <td>{{ batiments.typesactivite }}</td>
                      <td>{{ batiments.surfacechauffee }}</td>
                      <td><a href=""><button class="btn btn-warning btn-xs">Modifier</button></a></td>
                    </tr>
                  {% endfor %}
              </tbody>
            </table>

but I have this error:

[Semantical Error] line 0, col 328 near 'typesactivite': Error: Invalid PathExpression. StateFieldPathExpression or SingleValuedAssociationField expected.


LAST UPDATE


With all the suggestion I try to do this according to doctrine reference documentation and Symfonybook. Here's the code in my controller after removing the query request:

$em=$this->getDoctrine()->getManager();
        $batiment = $em->getRepository('MySpaceDatabaseBundle:Batiments')->findAll();

        return $this->render('MySpaceGestionPatrimoinesBundle:Batiments:indexBatiments.html.twig', array('batiment' => $batiment ));
}

But this error occured now:

An exception has been thrown during the rendering of a template ("Catchable Fatal Error: Object of class Doctrine\ORM\PersistentCollection could not be converted to string in C:\wamp\www.........\app\cache\dev\twig\bf\66\146a31a62bf6f2a549d2604fb5be9c4530ab760a10169af08e8a5b72e9ee.php line 127") in MySpaceGestionPatrimoinesBundle:Batiments:indexBatiments.html.twig at line 60.

Like you can see, in my twig, all is right. Someone?

Thank you for the help.

french_dev
  • 2,117
  • 10
  • 44
  • 85

7 Answers7

3

It seems like I found the solution thanks to another developper (thank you again by the way).

Look at here: in fact you have to make a loop in your twig.

For it should be something like this in your code:

<tbody>
       {% for batiments in batiment %}
         <tr>
           <td>{{ batiments.referencebatiment }}</td>
           <td>{{ ... }}</td>
           <!-- your loop here -->
           <td>
             {% for batiments in batiments.typesactivite %}
               {{ batiments.type }}
             {% endfor %}
           </td>
        {% endfor %}
</tbody>

Hope It helps you.

Community
  • 1
  • 1
  • indeed your solution works for me, with some errors but it displays me the results I want. I'm going to read the Twig documentation, and adapt a better solutions for my code. Thank you, and all of the developpers who contribuates to this questions. – french_dev Jan 28 '15 at 19:48
  • @french_dev, you're welcome, don't hesitate to contact me. It seems like we both work on a Symfony project with similarities. –  Jan 28 '15 at 19:51
1

try this (with @Gregsparrow suggestion):

$qb = $this-> $em->getRepository("YourBundle:Batiments")
                        ->createQueryBuilder('b');

// @Gregsparrows suggestion queryBuilder
$qb ->select("b")
    ->from("Batiments", "b")
    ->leftJoin(...")
    ->leftJoin("...");

$batiment = $qb->getResult();

return $this->render('...') ;

Does it matches?

  • 1
    I already try this and I have this error `Catchable Fatal Error: Object of class Doctrine\ORM\EntityManager could not be converted to string in: "C: My/path/to/project... at line"` – french_dev Jan 26 '15 at 14:24
  • check my update, It seems like I am doing wrong for the **queryBuilder**, even if I combine your two suggestions. What am I doing wrong? – french_dev Jan 26 '15 at 14:39
1

Wrong

$batiment = $em->getRepository('MySpaceDatabaseBundle:Batiments');
$qb = $this->$em->createQueryBuilder(b);

Right

$qb = $em->getRepository('MySpaceDatabaseBundle:Batiments')->createQueryBuilder('b');
french_dev
  • 2,117
  • 10
  • 44
  • 85
Gregsparrow
  • 1,332
  • 1
  • 11
  • 13
  • I think your suggestion is the best, but I have a new error, check my **update 2** in my question. I am new with Doctrine, it's not simple at the beginning. Maybe I should use something like this: `->join('b.ensembles','e')` **instead of** `->leftJoin("Ensemble", "e", \Doctrine\ORM\Query\Expr\Join::WITH, "b.ensembles = e.id")` no? thank you for the help by the way. – french_dev Jan 27 '15 at 06:08
  • Try to remove `->from("Batiments", "b")` and retain other code. – Gregsparrow Jan 27 '15 at 09:48
1

maybe you shouldtry something like this:

$batiments = $this->createQueryBuilder('b')
->join('b.ensembles', 'e')
->join('b.typesactivites', 'ta')
->addSelect('e')
->addSelect('ta')
->where('b.ensembles = :ensembles')
->andWhere('b.typesactivite= :typesactivite');

Try to remember that you use Doctrine, so the pivot table batiments_typesactivite does not exist in your symfony project, think in OOP and object relation.


UPADTE

does this match:

   $batiments = $this->createQueryBuilder('b')
    ->join('b.ensembles', 'e')
    ->join('b.typesactivites', 'ta')
    ->addSelect('e')
    ->addSelect('ta')
    ->where('b.ensembles = :ensembles')
    ->andWhere('b.typesactivite= :typesactivite');

$batiment = $query->getResult();
1

According to http://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html#many-to-many-unidirectional and http://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html#many-to-many-bidirectional, what you need between your two entities is not an integer value, but a whole table. If I understand your model correctly, a "Batiment" can have multiple "Type d'activité", and vice-versa, thus you need a "BatimentTypeActivite" table in-between. The resulting tables would look something like this :

Batiment id name

Activte id name

BatimentActivite id_batiment id_activite

  • I'm going to read the doc and try your suggestion, thank you. Indeed, in my phpMyAdmin I have a pivot table named `batiments_typesactivite`, because of the multiple `[N,N]` relations. – french_dev Jan 27 '15 at 10:02
  • if I really understand what I have to do with doctrine in my symfony project, I have to create the pivot table like mentionned in the answer of this stackoverflow question [here](http://stackoverflow.com/questions/15616157/doctrine-2-and-many-to-many-link-table-with-an-extra-field), right? – french_dev Jan 27 '15 at 10:27
  • 1
    I don't know what's inside your batiments_typesactivite table, but yes, if you have some data inside (other than just Batimend.id and Activite.id), you have to create a BatimentsTypesactivite entity, add a ManyToOne relation in Batiment and TypeActivite (one each), then add two One ToMany relations in the BatimentsTypesactivite entity to reflect that. – Patrick Laxton Jan 27 '15 at 11:00
  • in PhpMyAdmin in my pivot table `batiments_typesactivite` I have just the two ids, i.e **batiments_id** and **typesactivite_id**, so I'm going to follow your suggestion. There're **no datas** in this pivot table, just the two ids. Thank you. – french_dev Jan 27 '15 at 11:05
  • however I have some datas (phpMyAdmin) in the two other tables, i.e in batiments and in typesactivite. I create the pivot table in my symfony project. But even if there the relations between the three tables, there's no data in my table batiments_typesactivite I just created in phpMyAdmin. It is normal? – french_dev Jan 27 '15 at 12:04
  • 2
    You don't need to create a BatimentTypeActivite Symfony entity to match your batiments_typesactivite MySQL table. Follow the second link (http://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html#many-to-many-bidirectional,) and adapt it to your code : you'll just have to add the "@JoinTable(name="batiments_typesactivite")" annotation to one of the two entity classes – Patrick Laxton Jan 27 '15 at 13:13
  • I wrote this lines in my Batiments.php: `/** *@ORM\ManyToMany(targetEntity="Enexgir\DatabaseBundle\Entity\Typesactivite") * @ORM\JoinTable(name="batiments_typesactivite", * joinColumns={@ORM\JoinColumn(name="batiments_id", referencedColumnName="id", nullable=false)}, * inverseJoinColumns {@ORM\JoinColumn(name="typesactivite_id", referencedColumnName="id", nullable=false)} * ) */` So now, If I try my request, I have the same error as mentionned in my question: **_'typesactivite': Error: Invalid PathExpression. StateFieldPathExpression / SingleValuedAssociationField expected._** – french_dev Jan 27 '15 at 15:09
  • I think you should add a "ORM\JoinColumn" annotation in the TypesActivite entity, instead of this "inverseJoinColumns " annotation in the Batiments entity – Patrick Laxton Jan 27 '15 at 15:21
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/69676/discussion-between-french-dev-and-patrick-laxton). – french_dev Jan 27 '15 at 15:31
1

You should try this code, with fetch join in fact:

    $queryBatiments = $em->createQuery('SELECT b, ta, e
                                    FROM MySpaceDatabaseBundle:Batiments b
                                    JOIN b.typesactivite ta
                                    JOIN b.ensembles e
                                    WHERE b.ensembles = e.id');

    $batiment = $queryBatiments->getResult();

    return $this->render ('MySpaceGestionPatrimoinesBundle:Batiments:indexBatiments.html.twig', array ('batiment' => $batiment ));
}

According to the join argument in Doctine reference doc here, maybe you have to proceed your DQL request with a FETCH JOIN.

Does It matches with your problem?

french_dev
  • 2,117
  • 10
  • 44
  • 85
  • 1
    @french_dev, did you import (doctrine prompt cmd line) **getters** and **setters** in your entity? –  Jan 28 '15 at 08:44
  • Indeed, i have to generate the getters and setters. Now I have another error after I cleared the cache. See my last update in my question. Thank you – french_dev Jan 28 '15 at 09:08
  • 1
    @french_dev, for you last update, do you add the `__toString ` **method** in your mapped entities, [here](http://stackoverflow.com/questions/14923359/symfony2-tostring-error) an example –  Jan 28 '15 at 10:32
0

Maybe IDENTITY will help you ... IDENTITY(b.typesactivite)

Edit

And alternative is something like that

Assuming $qb is your query builder instance

$qb->select("b")->from("Batiments", "b")
   ->leftJoin("Ensemble", "e", \Doctrine\ORM\Query\Expr\Join::WITH, "b.ensembles = e.id")
   ->leftJoin("Typesactivite", "ta",  \Doctrine\ORM\Query\Expr\Join::WITH, "b.typesactivite = ta.id");
Gregsparrow
  • 1,332
  • 1
  • 11
  • 13
  • I already try to make `IDENTITY(b.typesactivite) = ta.id` instead of `b.typesactivite = ta.id` but I have the same error i.e **[Semantical Error] line 0, col 337 near 'typesactivite)': Error: Invalid PathExpression. Must be a SingleValuedAssociationField.** – french_dev Jan 26 '15 at 13:27
  • if I use `$qb`, I think I have to **create** a _queryBuilder_ in a **repository** isn't it? – french_dev Jan 26 '15 at 13:31
  • 2
    http://doctrine-orm.readthedocs.org/en/latest/reference/query-builder.html#constructing-a-new-querybuilder-object `$qb = $this->em->getRepository("CoreBundle:Manga")->createQueryBuilder('m');` – Gregsparrow Jan 26 '15 at 13:42
  • @ Gregsparrow, check my update, It seems like I am doing wrong for the **queryBuilder**, thank you. – french_dev Jan 26 '15 at 14:39