过滤Doctrine Entity中的子项作为属性和mutate / hydrate表单输入

时间:2017-01-24 14:56:28

标签: doctrine symfony entity-relationship symfony-forms

我正在使用Symfony 3.2和Doctrine 2.5开发一个带有API端点的文章数据库。在请求正文中,我有一个作者:

{
   "article": {
       "title": "Some article",
       "author": {
           "email": "someone@something.com",
           "name": "Howard Wedothis"
       }
   }
}

我想存储一个带有日期时间,文章ID和作者ID的更新实体。为了做到这一点,我必须发布以下内容:

{
    "article": {
        "title": "Some article",
        "updates": [{
            "author": {
                "email": "someone@something.com",
                "name": "Howard Wedothis"
            }
        }]
    }
}

这不是优雅的IMO。

第一个问题:对于简单的作者字段进行变异/补充以及针对文章和作者存储更新的最佳方法是什么?作者和文章很多很多,但我想避免发布一个数组,主要是出于可读性原因。

第二个问题:是否可以为createdlastUpdated的文章实体添加属性,以便在不注入存储库的情况下分别显示文章的第一个和最后一个更新进入实体?

$article->getCreated() // returns first Update
$article->getLastUpdated() // returns last Update

2 个答案:

答案 0 :(得分:0)

回答第二个问题 - 使用生命周期回调

<?php

use Doctrine\ORM\Mapping as ORM;

/** 
 * @ORM\HasLifecycleCallbacks
 */
class Author
{
    ...

    /**
     * @ORM\Column(type="datetime")
     */
    protected $createdAt;

    /**
     * @ORM\Column(type="datetime")
     */
    protected $updatedAt;

    /**
     * Get id.
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set createdAt.
     *
     * @param \DateTime $createdAt
     *
     * @return this
     */
    public function setCreatedAt($createdAt)
    {
        $this->createdAt = $createdAt;

        return $this;
    }

    /**
     * Get createdAt.
     *
     * @return \DateTime
     */
    public function getCreatedAt()
    {
        return $this->createdAt;
    }

    /**
     * Set modifiedAt.
     *
     * @param \DateTime $updatedAt
     *
     * @return Article
     */
    public function setUpdatedAt($updatedAt)
    {
        $this->updatedAt = $updatedAt;

        return $this;
    }

    /**
     * Get updatedAt.
     *
     * @return \DateTime
     */
    public function getUpdatedAt()
    {
        return $this->updatedAt;
    }

    ...

    /**
     * @ORM\PrePersist
     * @ORM\PreUpdate
     */
    public function updatedTimestamps()
    {
        $this->setUpdatedAt(new \DateTime(date('Y-m-d H:i:s')));

        if ($this->getCreatedAt() == null) {
            $this->setCreatedAt(new \DateTime(date('Y-m-d H:i:s')));
        }
    }
}

http://symfony.com/doc/current/doctrine/lifecycle_callbacks.html http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#lifecycle-events

关于您的请求示例,插入请求和更新请求应具有相同的格式。您通过更新键使您的生活更加复杂。

使用POST方法插入文章和PUT(您发送完整的文章对象)或PATCH(您只发送要更新的字段)。

https://knpuniversity.com/screencast/rest/put-versus-post

https://knpuniversity.com/screencast/symfony-rest/patch-programmer

答案 1 :(得分:0)

最后,我通过添加作者并在更新时覆盖作者并使用生命周期事件在PrePersist上创建新的更新实体并按照@Matko的建议在PreUpdated上解决了这个问题。

请求数据:

{
   "article": {
       "title": "Some article",
       "author": {
           "email": "someone@something.com",
           "name": "Howard Wedothis"
       }
   }
}

Article.php:

/**
 * @ORM\Entity
 * @ORM\Table(name="articles")
 * @ORM\HasLifecycleCallbacks
 */
class Article
{
    /**
     * @return Update
     */
    public function getCreated(): Update
    {
        return $this->updates->first();
    }

    /**
     * @return Update
     */
    public function getLastUpdated(): Update
    {
        return $this->updates->last();
    }

    /**
     * @ORM\PrePersist
     * @ORM\PreUpdate
     */
    public function addUpdate(): void
    {
        $update = new Update();
        $update->setAuthor($this->getAuthor());
        $update->setArticle($this);
        $this->updates->add($update);
    }
}

此方法会使实体的作者无效,但保留文章历史记录。