Доктрина: объект класса User не может быть преобразован в строку

Я продолжаю получать эту ошибку с доктриной:

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

в моей системе пользователи могут иметь много разрешений в отношениях один ко многим. Я установил User и Permission сущности. Они выглядят так (я удалил некоторые аннотации, геттеры и сеттеры, чтобы уменьшить беспорядок):

class User {

   /**
    * @ORMColumn(name="user_id", type="integer", nullable=false)
    * @ORMId
    * @ORMGeneratedValue(strategy="IDENTITY")
    */
   protected $id;

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

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

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

}

class Permission {

   /**
    * @ORMColumn(name="user_id", type="integer")
    * @ORMManyToOne(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. DoctrineORMUnitOfWork->persist() vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:565
PHP  12. DoctrineORMUnitOfWork->doPersist() vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1555
PHP  13. DoctrineORMUnitOfWork->cascadePersist() vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1615
PHP  14. DoctrineORMUnitOfWork->doPersist() vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:2169
PHP  15. DoctrineORMUnitOfWork->persistNew() vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1597
PHP  16. DoctrineORMUnitOfWork->scheduleForInsert() doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:836
PHP  17. DoctrineORMUnitOfWork->addToIdentityMap() vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1157
PHP  18. implode() vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1337

любое понимание было бы очень признателен.

4 ответов


ваше решение дало мне ключ к пониманию того, что происходит.

даже если у вас есть сущности и анотации, доктрина не в состоянии понять отношения между сущностями. Когда doctrine понимает связь между сущностями, он знает, какие методы вызывать (например, User::getId ()), но в противном случае он пытается преобразовать все, что вы отправляете, в скалярное значение, которое он может использовать для запроса базы данных. Вот почему он вызывает функцию __toString пользователя и вот почему, если вы возвращаете идентификатор в toString, все работает отсюда.

это нормально, но это патч, и, вероятно, вы не хотите держать его, если мы сможем найти лучшее решение, так как это может быть сложнее поддерживать по мере роста вашего приложения.

что я вижу, это то, что в разрешениях у вас есть:

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

вы должны удалить @ORM\Column(type="integer")

о соединения колонок, это не является обязательным, но вы должны быть уверены, что defauts, являются что ты хочешь. Как мы можем читать здесь

прежде чем мы представим все сопоставления ассоциаций подробно, вы должны обратите внимание, что определения @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;

таким образом, он должен искать колонка user_id на Permissions таблица, и присоединиться к нему с на User таблица. Мы полагаем, что это нормально.

если это правда, то в вашем пользователе id не должен быть user_id, но id:

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

или если имя столбца на самом деле user_id, то класс пользователя в порядке, но вы должны изменить столбец соединения на @ORM\JoinColumn(name="user_id", referencedColumnName="user_id")

что я могу сказать. Я не могу попробовать, знаю, но я буду. рад, если вы можете дать ему вторую.


OK. У меня все работает.

Я еще не полностью разработал причину, но когда я добавляю следующее К моему User организация работ:

class User {    

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

}

Если я узнаю больше, я опубликую здесь.


Я думаю, что есть проблема с отображением свойств пользователя в сущности разрешение. Попробуйте вот это:

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

вы инициализируете коллекцию на своей стороне 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);
      }

       //...