Doctrine鉴别器如何知道从地图中使用哪个实体

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Doctrine鉴别器如何知道从地图中使用哪个实体相关的知识,希望对你有一定的参考价值。

今天我接到了编写鉴别器的任务,这是我第一次了解Doctrine鉴别器的工作原理。在阅读了这里的文档后,我已经完成了。

我需要创建一个命令来更改博客/帖子作者,然后还更新有关该事件的动作实体。

行动实体:

/**
 * @ORM\Table(name="action")
 * @ORM\Entity()
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="discriminator", type="string")
 * @ORM\DiscriminatorMap({"action" = "Action", "blog" = "Blog", "post" = "Post"})
 */
class Action
{ ...

在eventCommand的某个地方:

...
$action = new Action();
$action->setType('author_change');

$this->em->persist($action);

这一切都在运行命令后工作。唯一的问题是动作鉴别器每次都会保存“动作”,而不是“博客”或“发布”。

即使我像这样强制它,列也不会改变:

$action->setDiscriminator('blog');

所以我认为我的问题是Action如何知道以及我应该如何从地图中触发使用哪个鉴别器?

答案

要检查的事项:

  • 你的父实体是Action,确保BlogPost都扩展它
  • 如果您希望子类能够访问它们,则应保护Action类中的所有属性(包括id)

我尝试使用以下类进行设置:

行动:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\ActionRepository")
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="discriminator", type="string")
 * @ORM\DiscriminatorMap({"action" = "Action", "blog" = "Blog", "post" = "Post"})
 */
class Action
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    protected $name;

    // ... getters and setters for $id and $name (notice they are also protected, not private !!!)
}

博客:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\BlogRepository")
 */
class Blog extends Action
{
    /**
     * @var string
     * @ORM\Column(name="blog_prop", length=255, nullable=true)
     */
    private $blogProp;

    // ... getters and setters for $blogProp
}

帖子:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\PostRepository")
 */
class Post extends Action
{
    /**
     * @var string
     * @ORM\Column(name="post_prop", length=255, nullable=true)
     */
    private $postProp;

    // .... getters and setters for $postProp
}

Doctrine将为您的每个实体创建一个单独的表。存储子实体时,还会在父实体中添加一行,并填充公共(继承)字段。子实体独有的属性将插入其各自的表中。这导致以下数据库结构:

mysql> describe action;
+---------------+--------------+------+-----+---------+----------------+
| Field         | Type         | Null | Key | Default | Extra          |
+---------------+--------------+------+-----+---------+----------------+
| id            | int(11)      | NO   | PRI | NULL    | auto_increment |
| name          | varchar(255) | YES  |     | NULL    |                |
| discriminator | varchar(255) | NO   |     | NULL    |                |
+---------------+--------------+------+-----+---------+----------------+


mysql> describe blog;
+-----------+--------------+------+-----+---------+-------+
| Field     | Type         | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| id        | int(11)      | NO   | PRI | NULL    |       |
| blog_prop | varchar(255) | YES  |     | NULL    |       |
+-----------+--------------+------+-----+---------+-------+


mysql> describe post;
+-----------+--------------+------+-----+---------+-------+
| Field     | Type         | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| id        | int(11)      | NO   | PRI | NULL    |       |
| post_prop | varchar(255) | YES  |     | NULL    |       |
+-----------+--------------+------+-----+---------+-------+

和控制器:

/**
 * @Route("/test", name="test")
 */
public function test()
{
    $manager = $this->getDoctrine()->getManager();

    $action = new Action();
    $action->setName('my action');

    $blog = new Blog();
    $blog
        ->setName('my blog')
        ->setBlogProp('my blog prop');

    $post = new Post();
    $post
        ->setName('my post')
        ->setPostProp('my post prop');



    $manager->persist($action);
    $manager->persist($blog);
    $manager->persist($post);

    $manager->flush();

}

运行控制器代码后:

mysql> select * from action;
+----+-----------+---------------+
| id | name      | discriminator |
+----+-----------+---------------+
|  1 | my post   | post          |
|  2 | my blog   | blog          |
|  3 | my action | action        |
+----+-----------+---------------+
3 rows in set (0.00 sec)

mysql> select * from blog;
+----+--------------+
| id | blog_prop    |
+----+--------------+
|  2 | my blog prop |
+----+--------------+
1 row in set (0.00 sec)

mysql> select * from post;
+----+--------------+
| id | post_prop    |
+----+--------------+
|  1 | my post prop |
+----+--------------+
1 row in set (0.00 sec)

以上是关于Doctrine鉴别器如何知道从地图中使用哪个实体的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Symfony 2.1 从内部控制器获取 Doctrine 实体的实体管理器

Doctrine2 中的条件关联

PHP Doctrine 使用鉴别器映射查询继承的类

使用Doctrine2加入表中的鉴别器

Symfony2/Doctrine:如何从实体类中持久化一个实体?

Doctrine2:任意连接和单表继承