Symfony2 OneToMany 关系

Posted

技术标签:

【中文标题】Symfony2 OneToMany 关系【英文标题】:Symfony2 OneToMany relation 【发布时间】:2018-02-10 08:58:21 【问题描述】:

我正在使用 Symfony 2.5 和 php 5.3 做一个 AdvertPlatform。

我想添加一个功能:当用户看到(通过点击)广告时,我们可以看到文字"Seen by : username"

我开始添加一个名为 AdvertReader 的新实体,在 AdvertAdvertReader 之间具有 OneToMany 关系:

广告.php:

    /**
     * Advert
     *
     * @ORM\Table()
     * @ORM\Entity(repositoryClass="Society\PerfclientBundle\Entity\AdvertRepository")
     * @ORM\HasLifecycleCallbacks()
     * @UniqueEntity(fields="title", message="Une annonce existe déjà avec ce titre.")
     */        
    class Advert
    
        public function __construct()
        
            $this->date = new \Datetime();
        

    /**
     *
     * @ORM\OneToMany(targetEntity="Society\PerfclientBundle\Entity\AdvertReader", mappedBy="advert", cascade="persist")
     */
    private $readers;


    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="date", type="datetime")
     */
    private $date;

    /**
 * @var string
 *
 * @ORM\Column(name="title", type="string", length=255, unique=true)
 *
 * @Assert\Length(min=10, minMessage="Le titre de l'annonce doit faire au moins  limit  caractères.")
 */
    private $title;

    /**
     * @var string
     *
     * @ORM\Column(name="category", type="string", length=255)
     */
    private $category;

    /**
     * @var string
     *
     * @ORM\Column(name="author", type="string", length=255)
     */
    private $author;

    /**
     * @var string
     *
     * @ORM\Column(name="content", type="text")
     * @Assert\Length(min=10, minMessage="Le contenu de l'annonce doit faire au moins  limit  caractères.")
     */
    private $content;

    /**
     * @ORM\Column(name="updated_at", type="datetime", nullable=true)
     */
    private $updatedAt;`

AdvertReader.php:

/**
 * AdvertReader
 *
 * @ORM\Table()
 * @ORM\Entity
 */
class AdvertReader

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="Society\PerfclientBundle\Entity\Advert", inversedBy="readers")
     * @ORM\JoinColumn(name="advert_id", referencedColumnName="id")
     */
    private $advert;

    /**
     * @var string
     *
     * @ORM\Column(name="username", type="string", length=255)
     */
    private $username;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="created_at", type="datetime")
     */
    private $createdAt;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="updated_at", type="datetime")
     */
    private $updatedAt;


    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    
        return $this->id;
    

    /**
     * Set advert
     *
     * @param integer $advert
     * @return AdvertReader
     */
    public function setAdvert($advert)
    
        $this->advert = $advert;

        return $this;
    

    /**
     * Get advert
     *
     * @return integer 
     */
    public function getAdvert()
    
        return $this->advert;
    

    /**
     * Set username
     *
     * @param string $username
     * @return AdvertReader
     */
    public function setUsername($username)
    
        $this->username = $username;

        return $this;
    

    /**
     * Get username
     *
     * @return string 
     */
    public function getUsername()
    
        return $this->username;
    

还有我的 viewAction()

    /**
     * @param $id
     * @return Response
     */
    public function viewAction($id)
    
        // On récupère le repository
        $repository = $this->getDoctrine()
            ->getManager()
            ->getRepository('SocietyPerfclientBundle:Advert')
        ;
        $advert = $repository->find($id);

        if (null === $advert) 
            throw new NotFoundHttpException("L'annonce d'id ".$id." n'existe pas.");
        

        $securityContext = $this->container->get('security.context');
        $user = $securityContext->getToken()->getUser();

        if ($securityContext->isGranted('IS_AUTHENTICATED_FULLY')) 
            $em = $this->getDoctrine()->getManager();
            $queryBuilder = $em->createQueryBuilder();

            $query = $queryBuilder->select('count(ar.id)')
                ->from('SocietyPerfclientBundle:AdvertReader', 'ar')
                ->where('ar.advert = :advert')
                ->andWhere('ar.username = :username')
                ->setParameter('advert', $advert->getId())
                ->setParameter('username', $user->getUsername())
                ->getQuery();

            $advertReaderCount = $query->getSingleScalarResult();

            if ($advertReaderCount <= 0) 
// l'utilisateur lis pour la 1er fois
                $advertReader = new AdvertReader;
                $advertReader->setAdvert($advert->getId());
                $advertReader->setUpdatedAt(new \DateTime);
                $advertReader->setUsername($user->getUsername());
                $advertReader->setCreatedAt(new \DateTime);

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

        return $this->render('SocietyPerfclientBundle:Default:view.html.twig', array(
            'advert' => $advert,
        ));
    

doctrine:schema:validate -> [映射] OK [数据库] OK

Error500 ORM 异常:在关联 Society\PerfclientBundle\Entity\AdvertReader#advert 上找到类型的实体,但期望 Society\PerfclientBundle\Entity\Advert

堆栈跟踪分析器: UnitOfWork ->computeAssociationChanges (array('fieldName' => 'advert', 'joinColumns' => array(array('name' => 'advert_id', 'unique' => false, 'nullable' => true, 'onDelete ' => null, 'columnDefinition' => null, 'referencedColumnName' => 'id')), 'cascade' => array(), 'inversedBy' => 'readers', 'targetEntity' => 'Society\PerfclientBundle \Entity\Advert', 'fetch' => '2', 'type' => '2', 'mappedBy' => null, 'isOwningSide' => true, 'sourceEntity' => 'Society\PerfclientBundle\Entity\ AdvertReader', 'isCascadeRemove' => false, 'isCascadePersist' => false, 'isCascadeRefresh' => false, 'isCascadeMerge' => false, 'isCascadeDetach' => false, 'sourceToTargetKeyColumns' => array('advert_id' => 'id'), 'joinColumnFieldNames' => 数组('advert_id' => 'advert_id'), 'targetToSourceKeyColumns' => 数组('id' => 'advert_id'), 'orphanRemoval' => false), '26' )

我的实体关系有什么问题? 请帮帮我:)

【问题讨论】:

如果可能,尝试迁移到新版本。这不是太难而且非常有益。 【参考方案1】:

我认为问题出在这段代码

$advertReader->setAdvert($advert->getId());

试试这个:

$advertReader->setAdvert($advert);

Doctrine 期望该关系上有一个对象,而您传递了一些整数。

希望这会有所帮助。快乐编码

亚历山德鲁·科索伊

【讨论】:

以上是关于Symfony2 OneToMany 关系的主要内容,如果未能解决你的问题,请参考以下文章

symfony2 构建表单实体 oneToMany

Symfony2 项目中的 Doctrine2 映射问题

Symfony2 3 个实体之间的映射

Symfony2:PrePersist/PreUpdate 生命周期事件未触发

Sonata Admin Bundle 一对多关系不保存外国 ID

Symfony 2.1 Sonata 管理包 OneToMany