【问题标题】:Doctrine: Object of class User could not be converted to string教义:用户类的对象无法转换为字符串
【发布时间】:2014-01-06 02:17:27
【问题描述】:

我不断收到 Doctrine 的这个错误:

PHP Catchable fatal error:  Object of class User could not be converted to string in vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php on line 1337

在我的系统中,用户可以在一对多关系中拥有许多权限。我已经建立了一个UserPermission 实体。它们看起来像这样(我删除了一些注释、getter 和 setter 以减少混乱):

class User {

   /**
    * @ORM\Column(name="user_id", type="integer", nullable=false)
    * @ORM\Id
    * @ORM\GeneratedValue(strategy="IDENTITY")
    */
   protected $id;

   public function getId()
   {
      return $this->id;
   }

   /**
    * @ORM\OneToMany(targetEntity="Permission", mappedBy="user", cascade={"persist"})
    */
   protected $permissions;

   public function getPermissions()
   {
      return $this->permissions;
   }

}

class Permission {

   /**
    * @ORM\Column(name="user_id", type="integer")
    * @ORM\ManyToOne(targetEntity="User", inversedBy="permissions")
    */
   protected $user;

   public function getUser()
   {
      return $this->user;
   }

   public function setUser( $user )
   {
      $this->user = $user;

      return $this;
   }
}

当我将新的Permission 添加到User 时出现问题:

$permission = new Permission();

$user->getPermissions()->add( $permission );

$em->persist( $user );
$em->flush();

这是我的堆栈跟踪的最后一点:

PHP  11. Doctrine\ORM\UnitOfWork->persist() vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:565
PHP  12. Doctrine\ORM\UnitOfWork->doPersist() vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1555
PHP  13. Doctrine\ORM\UnitOfWork->cascadePersist() vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1615
PHP  14. Doctrine\ORM\UnitOfWork->doPersist() vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:2169
PHP  15. Doctrine\ORM\UnitOfWork->persistNew() vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1597
PHP  16. Doctrine\ORM\UnitOfWork->scheduleForInsert() doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:836
PHP  17. Doctrine\ORM\UnitOfWork->addToIdentityMap() vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1157
PHP  18. implode() vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1337

任何见解将不胜感激。

【问题讨论】:

  • 只是检查一下,你记得运行doctrine:schema:update 吗? :)
  • add方法代码是什么?
  • @IgorPantović:很遗憾我做不到。我正在将 Doctrine 应用于已经存在的数据库。抱歉,应该提到这一点。
  • @shad:add 方法来自 Doctrine 的ArrayCollection,即getPermissions() 返回一个ArrayCollection。不过,我已经用我的持久代码更新了我的问题..

标签: php doctrine-orm entity-relationship


【解决方案1】:

好的。我已经成功了。

我还没有完全弄清楚原因,但是当我将以下内容添加到我的 User 实体时,它可以工作:

class User {    

   public function __toString()
   {
      return strval( $this->getId() );
   }

}

如果我发现更多,我会在这里发布。

【讨论】:

    【解决方案2】:

    您的解决方案让我知道发生了什么。

    即使你有实体和注释,Doctrine 也无法理解实体之间的关系。当学说理解实体之间的关系时,它知道要调用什么方法(即 User::getId()),否则,它会尝试将您发送的任何内容转换为可用于查询数据库的标量值。这就是它调用用户的 __toString 函数的原因,这就是为什么如果你在 toString 中返回 id,一切都从这里开始。

    这没关系,但它是一个补丁,如果我们能找到更好的解决方案,你可能不想保留它,因为随着应用程序的增长,它可能更难维护。

    我可以看到,在您拥有的权限中:

    /**
    * @ORM\Column(name="user_id", type="integer")
    * @ORM\ManyToOne(targetEntity="User", inversedBy="permissions")
    */
     protected $user;
    

    你应该删除@ORM\Column(type="integer")

    关于连接列,这不是强制性的,但您必须确保默认值是您想要的。我们可以读到here

    在我们详细介绍所有关联映射之前,您应该 请注意,@JoinColumn 和 @JoinTable 定义通常是 可选并具有合理的默认值。连接的默认值 一对一/多对一关联中的列如下:

    name: "<fieldname>_id"
    referencedColumnName: "id"
    

    所以,它们将与显式相同:

    /**
     * @ORM\ManyToOne(targetEntity="User", inversedBy="permissions", cascade={"persist"})
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="user_id", referencedColumnName="id")
     * })
     */
      protected $user;
    

    所以它应该在Permissions 表中查找user_id 列,并将其与User 表的id 列连接。我们认为这没问题。

    如果这是真的,那么在你的用户中,id 不应该是 user_id,而是 id:

     /**
        * @ORM\Column(name="id", type="integer", nullable=false)
        * @ORM\Id
        * @ORM\GeneratedValue(strategy="IDENTITY")
        */
       protected $id;
    

    或者如果列名实际上是user_id,那么User类是可以的,但是你必须将连接列更改为@ORM\JoinColumn(name="user_id", referencedColumnName="user_id")

    我能说的就这么多了。我无法尝试知道,但如果你能再试一试,我会很高兴。

    【讨论】:

      【解决方案3】:

      我认为权限实体中用户属性的映射存在问题。试试这个:

      /**
       * @ORM\ManyToOne(targetEntity="User", inversedBy="permissions")
       * @JoinColumn(name="user_id", referencedColumnName="id")
       */
      protected $user;
      

      【讨论】:

      • 我试过这个。清除了我的缓存,但我得到了完全相同的错误。
      • 检查两个实体上的 getter 以查看是否返回了一个对象而不是变量,例如。 return $this; 而不是 return $this-&gt;id;
      • 我已将我的 getter 和 setter 添加到问题中。我看不出他们有什么问题……
      【解决方案4】:

      您是否在 OneToMany 端初始化集合? 还有,从集合中添加和删除的方法?

      class User {
         /**
          * @ORM\OneToMany(targetEntity="Permission", mappedBy="user", cascade={"persist"})
          */
         protected $permissions;
      
         public function getPermissions()
         {
            return $this->permissions;
         }
      
          public function __construct()
          {
              $this->permissions = new \Doctrine\Common\Collections\ArrayCollection();
          }
      
      
      
          public function addPermissions (Permission $permissions)
          {
              $this->permissions[] = $permissions;
      
                  return $this;
           }
      
      
           public function removePermissions(Permission $permissions)
           {
              $this->permissions->removeElement($permissions);
            }
      
             //...
      

      【讨论】:

      • 嗨。是的,我的 $permissions 被初始化为 ArrayCollection。不确定实体上的 addremove 方法如何解决问题。
      • 实际上我唯一关心的是构造函数。其他方法可能很方便,但我喜欢这样做,因为我喜欢实体具有一致的接口,而不取决于其数据类型的实现。另外,我所知道的是,如果您通过数据库的逆向工程创建实体,使用教义工具创建这些方法,我不知道这是否意味着某些 hydrator 期望它们存在。
      • 不用担心。得分。
      猜你喜欢
      • 2018-11-27
      • 1970-01-01
      • 2022-01-05
      • 2015-07-27
      • 2012-04-29
      • 2011-04-06
      • 2011-11-30
      • 2011-08-30
      相关资源
      最近更新 更多