Symfony/Doctrine - Twig_Error_Runtime: 可捕获的致命错误:无法将Doctrine\ORM\PersistentCollection类的对象转换为字符串。

3

我在我的 Symfony 项目中有这个实体:

/**
 * 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

如您所见,我有一个关于$ensemblesManyToOne关系和一个关于$typesactiviteManyToMany关系。

我有以下SQL请求:

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

PhpMyAdmin 上,SQL 请求非常有效,因此我需要在我的 Symfony 项目中导入我的 SQL 请求(使用 Doctrine 的 DQL)。

我在我的 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');

看起来它只能用于ManyToOne关系。我在html.twig中使用<table>标签展示结果,代码如下:

<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>

但我遇到了这个错误:

[语义错误] 第0行,第328列附近的'typesactivite': 错误: 无效的PathExpression。应该是StateFieldPathExpression或SingleValuedAssociationField。


最后更新时间


根据Doctrine参考文档和Symfonybook的建议,我尝试在控制器中按照以下方式编写代码(删除了查询请求):

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

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

但是现在出现了这个错误:

在模板渲染期间抛出了一个异常(“可捕获的致命错误:在C:\wamp\www.........\app\cache\dev\twig\bf\66\146a31a62bf6f2a549d2604fb5be9c4530ab760a10169af08e8a5b72e9ee.php的第127行中,无法将Doctrine\ORM\PersistentCollection类的对象转换为字符串”)MySpaceGestionPatrimoinesBundle:Batiments:indexBatiments.html.twig中的第60行。

如您所见,在我的twig中,一切都是正确的。有人可以帮忙吗?

感谢您的帮助。

7个回答

3

感觉我找到了解决方案,多亏了另一个开发者(顺便再次感谢)。

看看这里:实际上你需要在twig中进行循环。

因此,在你的代码中应该是这样的:

<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>

希望这能对你有所帮助。


确实,您的解决方案对我有用,虽然存在一些错误,但它显示了我想要的结果。我将阅读Twig文档,并为我的代码调整更好的解决方案。谢谢您和所有为这个问题做出贡献的开发人员。 - french_dev
@french_dev,不用客气,请随时联系我。看起来我们都在一个类似的Symfony项目上工作。 - user4460771

1
尝试这个(使用@Gregsparrow的建议):
$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('...') ;

它是否匹配?


1
我已经尝试过这个,但是出现了以下错误: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
请检查我的更新,似乎在查询构建器(queryBuilder)方面我做错了事情,即使我结合了你的两个建议。我哪里做错了? - french_dev

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

正确

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

我认为你的建议是最好的,但我有一个新的错误,请查看我的问题中的更新2。我对Doctrine不熟悉,在开始时并不简单。也许我应该使用这样的东西:->join('b.ensembles','e') 而不是 ->leftJoin("Ensemble", "e", \Doctrine\ORM\Query\Expr\Join::WITH, "b.ensembles = e.id") 对吧?顺便说一句,谢谢你的帮助。 - french_dev
尝试移除 ->from("Batiments", "b") 并保留其他代码。 - Gregsparrow

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');

请记住您正在使用的是Doctrine,因此在您的Symfony项目中不存在交叉表batiments_typesactivite,请考虑面向对象和对象关系。

更新

这是否匹配:

   $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
你应该尝试这段代码,实际上使用了fetch join
    $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 ));
}

根据Doctrine参考文档这里中的join参数,也许您需要在DQL请求中使用FETCH JOIN。
它是否与您的问题匹配?

1
@french_dev,你在实体中导入了(Doctrine Prompt命令行)gettersetter吗? - user4460771
实际上,我必须生成getter和setter。现在,在我清除缓存后,我又遇到了另一个错误。请查看我问题中的最新更新。谢谢。 - french_dev
1
@french_dev,针对你的最新更新,你是否在映射实体中添加了__toString 方法这里有一个例子。 - user4460771

1
根据http://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html#many-to-many-unidirectionalhttp://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html#many-to-many-bidirectional,你需要的不是一个整数值,而是一个完整的表格来连接两个实体。 如果我正确理解你的模型,一个“Batiment”可以有多个“Type d'activité”,反之亦然,因此你需要一个名为“BatimentTypeActivite”的中间表格。 生成的表格应该如下所示:

Batiment id name

Activte id name

BatimentActivite id_batiment id_activite


我会阅读文档并尝试您的建议,谢谢。实际上,在我的phpMyAdmin中,我有一个名为batiments_typesactivite的数据透视表,因为它具有多个[N,N]关系。 - french_dev
如果我真正理解在我的Symfony项目中如何使用Doctrine,那么我需要像这个stackoverflow问题的答案中提到的那样创建交叉表,对吗?这里 - french_dev
1
我不知道你的batiments_typesactivite表里面有什么,但是如果你有一些数据(除了Batimend.id和Activite.id之外),你必须创建一个BatimentsTypesactivite实体,在Batiment和TypeActivite中添加ManyToOne关系(各一个),然后在BatimentsTypesactivite实体中添加两个OneToMany关系以反映这一点。 - Patrick Laxton
我认为你应该在TypesActivite实体中添加一个“ORM\JoinColumn”注释,而不是在Batiments实体中使用“inverseJoinColumns”注释。 - Patrick Laxton
显示剩余4条评论

0

或许 IDENTITY 可以帮助你... IDENTITY(b.typesactivite)

编辑

另一种选择是这样的

假设 $qb 是您的查询构建器实例

$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");

我已经尝试使用IDENTITY(b.typesactivite) = ta.id代替b.typesactivite = ta.id,但是我仍然遇到了相同的错误,即**[语义错误]第0行第337列附近的'typesactivite)':错误:无效的PathExpression。必须是SingleValuedAssociationField**。 - french_dev
如果我使用 $qb,我认为我必须在一个仓库(repository)中创建一个 queryBuilder ,不是吗? - french_dev
2
$qb = $this->em->getRepository("CoreBundle:Manga")->createQueryBuilder('m'); 请构建一个新的QueryBuilder对象。 - Gregsparrow
@ Gregsparrow,请查看我的更新,似乎我在 queryBuilder 方面做错了,谢谢。 - french_dev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接