Doctrine 鉴别器如何从地图中知道要使用哪个实体
How does Doctrine discriminator know which entity to use from the map
今天接到一个写判别器的任务,第一次了解Doctrine判别器的工作原理。阅读文档后,这就是我所做的。
我需要创建一个命令来更改 blog/post 作者,然后还要更新有关事件的操作实体。
动作实体:
/**
* @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
{ ...
事件中某处命令:
...
$action = new Action();
$action->setType('author_change');
$this->em->persist($action);
这一切都在 运行 命令之后起作用。唯一的问题是 Action discriminator 每次都保存 'action',而不是 'blog' 或 'post'。
即使我这样强制列也不会改变:
$action->setDiscriminator('blog');
所以我想我的问题是 Action 是如何知道的以及我应该如何触发从地图中使用哪个鉴别器?
要检查的事项:
- 您的父实体是
Action
,确保 Blog
和 Post
都扩展它
- 如果您希望您的子class能够访问您的
Action
class 中的所有属性(包括 ID)
我用以下 class 尝试了您的设置:
操作:
<?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
}
Post:
<?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 将为您的每个实体创建一个单独的 table。存储子实体时,还会在父实体中添加一行,并填充公共(继承)字段。子实体特有的属性将插入到它们各自的 table 中。这导致以下数据库结构:
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判别器的工作原理。阅读文档后,这就是我所做的。
我需要创建一个命令来更改 blog/post 作者,然后还要更新有关事件的操作实体。
动作实体:
/**
* @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
{ ...
事件中某处命令:
...
$action = new Action();
$action->setType('author_change');
$this->em->persist($action);
这一切都在 运行 命令之后起作用。唯一的问题是 Action discriminator 每次都保存 'action',而不是 'blog' 或 'post'。
即使我这样强制列也不会改变:
$action->setDiscriminator('blog');
所以我想我的问题是 Action 是如何知道的以及我应该如何触发从地图中使用哪个鉴别器?
要检查的事项:
- 您的父实体是
Action
,确保Blog
和Post
都扩展它 - 如果您希望您的子class能够访问您的
Action
class 中的所有属性(包括 ID)
我用以下 class 尝试了您的设置:
操作:
<?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
}
Post:
<?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 将为您的每个实体创建一个单独的 table。存储子实体时,还会在父实体中添加一行,并填充公共(继承)字段。子实体特有的属性将插入到它们各自的 table 中。这导致以下数据库结构:
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)