管理Doctrine对象的生命周期
管理Doctrine对象的生命周期
在创建一个新的注释时,如果createdAt
Date将自动设置为当前日期和时间。
Doctrine有不同的方法在对象的生命周期中(在数据库中创建行之前,更新行之后,……)操作对象及其属性。
定义生命周期回调
当行为不需要任何服务并且应该只应用于一种实体时,在实体类中定义一个回调:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
——/ src /实体/ Comment.php+ + + b / src /实体/ Comment.php@@ -7,6 +7,7 @@ use Doctrine\DBAL\Types\Types;使用Doctrine\ORM\Mapping作为ORM;# (ORM \实体(repositoryClass: CommentRepository::类))+ # (ORM \ HasLifecycleCallbacks)class注释{#[ORM\Id] @@ -91,6 +92,12 @@ class注释返回$this;}+ # (ORM \ PrePersist)+公共函数setCreatedAtValue+ {+ $this->createdAt = new \DateTimeImmutable();+}+公共函数getConference(): ?会议{返回$this->会议;
的ORM \ PrePersist
事件当对象第一次存储在数据库中时触发。当这种情况发生时setCreatedAtValue ()
方法的值将使用当前日期和时间createdAt
财产。
在会议中添加蛞蝓
会议的url没有意义:/会议/ 1
.更重要的是,它们依赖于实现细节(数据库中的主键被泄露)。
使用url像- 2020 /会议/巴黎
而不是?那样看起来会好很多。巴黎- 2020
这次会议叫什么名字鼻涕虫.
添加一个新的鼻涕虫
属性(255个字符的非空字符串):
1
$ob娱乐下载symfony控制台make:实体会议
创建一个迁移文件来添加新列:
1
$ob娱乐下载Symfony控制台make:迁移
并执行新的迁移:
1
$ob娱乐下载Symfony控制台原则:迁移:迁移
有错误吗?这是意料之中的。为什么?因为我们要求子弹不是零
但是会议数据库中的现有条目将得到一个零
值。让我们通过调整迁移来解决这个问题:
12 3 4 5 6 7 8 9 10 11 12 13
——/迁移/ Version00000000000000.php+ + + b /迁移/ Version00000000000000.php@@ -20,7 +20,9 @@ final类Version00000000000000 extends AbstractMigration公共函数up(Schema $ Schema): void{//这个up()迁移是自动生成的,请根据您的需要修改它- $this->addSql('ALTER TABLE conference ADD slug VARCHAR(255) NOT NULL');+ $this->addSql('ALTER TABLE conference ADD slug VARCHAR(255)');+ $this->addSql("UPDATE conference SET slug=CONCAT(LOWER(city), '-', year)");+ $this->addSql('ALTER TABLE conference ALTER COLUMN slug SET NOT NULL');}公共函数关闭(Schema $ Schema):无效
这里的技巧是添加列并允许它存在零
,然后将弹头设置为not零
值,最后,将slug列更改为不允许零
.
请注意
对于一个真实的项目,使用CONCAT(LOWER(城市),'-',年)
可能还不够。在这种情况下,我们需要使用“真正的”重击器。
迁移现在应该运行正常:
1
$ob娱乐下载Symfony控制台原则:迁移:迁移
因为应用程序很快将使用鼻涕虫来查找每个会议,让我们调整conference实体,以确保鼻涕虫值在数据库中是唯一的:
12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20 21 22
——/ src /实体/ Conference.php+ + + b / src /实体/ Conference.php@@ -6,8 +6,10 @@使用App\Repository\ConferenceRepository;使用原则\常见\ \ ArrayCollection集合;使用原则\常见\集合\集合;使用Doctrine\ORM\Mapping作为ORM;+使用Syob娱乐下载mfony \桥\学说\验证器\ \ UniqueEntity约束;# (ORM \实体(repositoryClass: ConferenceRepository::类))+ #【UniqueEntity(“鼻涕虫”)]class Conference {#[ORM\Id] @@ -27,7 +29,7 @@ class Conference #[ORM\OneToMany(mappedBy: ' Conference ', targetEntity: Comment::class, orphanRemoval: true)] private Collection $comments;#[ORM\列(长度:255)]+ #[ORM\列(类型:'string',长度:255,唯一:true)]字符串$slug = null;公共函数__construct()
你可能已经猜到了,我们需要表演迁徙舞蹈:
1
$ob娱乐下载Symfony控制台make:迁移
1
$ob娱乐下载Symfony控制台原则:迁移:迁移
生成蛞蝓
生成一个在URL(应该对ASCII字符以外的任何字符进行编码)中读取良好的段代码是一项具有挑战性的任务,特别是对于英语以外的语言。如何进行转换e
来e
例如呢?
让我们使用Symfony,而不是重新发明轮子ob娱乐下载字符串
组件,该组件简化了字符串的操作,并提供了重击者.
添加一个computeSlug ()
方法。会议
根据会议数据计算段的类:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
——/ src /实体/ Conference.php+ + + b / src /实体/ Conference.php@@ -7,6 +7,7 @@使用Doctrine\Common\Collections\ArrayCollection;使用原则\常见\集合\集合;使用Doctrine\ORM\Mapping作为ORM;使用Syob娱乐下载mfony \桥\学说\验证器\ \ UniqueEntity约束;+使用Syob娱乐下载mfony轰\组件\字符串\ \ SluggerInterface;#[ORM\Entity(repositoryClass: ConferenceRepository::class)] #[UniqueEntity('slug')] @@ -47,6 +48,13 @@ class Conference return $this->id;}+公共函数computeSlug+ {+ if (!$这->鼻涕虫|| '-' === $this->slug) {+ $ this - >蛞蝓=(字符串)重击者- >蛞蝓((字符串)这个美元)- >低();+}+}+公共函数getCity(): ?string{返回$this->city;
的computeSlug ()
方法仅在当前段塞为空或设置为特殊时计算段塞-
价值。为什么我们需要-
特殊的价值?因为在后端添加会议时,需要使用段塞。因此,我们需要一个非空值,它告诉应用程序我们希望自动生成这个段代码。
定义复杂生命周期回调
至于createdAt
财产,鼻涕虫
方法更新会议时,应该自动设置computeSlug ()
方法。
但是这个方法依赖于aSluggerInterface
实现时,不能添加prePersist
事件和之前一样(我们没有办法注入重击器)。
相反,创建Doctrine实体监听器:
请注意,当创建一个新的会议时,该段代码将被更新(prePersist ()
),每当更新时(preUpdate ()
).
在容器中配置服务
到目前为止,我们还没有讨论Symfony的一个关键组件ob娱乐下载依赖注入容器.容器负责管理服务:创建它们并在需要时注入它们。
一个服务一个“全局”对象提供的特性(例如,邮件,日志记录器,击打器等)不同吗数据对象(例如,学说实体实例)。
你很少直接与容器交互,因为当你需要服务对象时,它会自动注入服务对象:例如,当你输入提示时,容器会注入控制器参数对象。
如果您想知道在前面的步骤中事件侦听器是如何注册的,那么现在就有了答案:容器。当一个类实现一些特定的接口时,容器知道该类需要以某种方式注册。
在这里,因为我们的类没有实现任何接口,也没有扩展任何基类,Symfony不知道如何自动配置它。ob娱乐下载相反,我们可以使用一个属性来告诉Symfony容器如何连接它:ob娱乐下载
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16
——/ src / EntityListener / ConferenceEntityListener.php+ + + b / src / EntityListener / ConferenceEntityListener.php@@ -3,9 +3,13 @@名称空间的应用程序\ EntityListener;使用App \实体\会议;+使用原则\包\ DoctrineBundle \ \ AsEntityListener属性;使用原则\ ORM \ \ LifecycleEventArgs事件;+使用原则\ ORM \事件;使用Syob娱乐下载mfony轰\组件\字符串\ \ SluggerInterface;+#[AsEntityListener(event: Events::prePersist, entity: Conference::class)]+#[AsEntityListener(event: Events::preUpdate, entity: Conference::class)]类ConferenceEntityListener{公共函数__construct(
请注意
不要混淆Doctrine事件监听器和Symfony事件监听器。ob娱乐下载即使它们看起来非常相似,但实际上它们并没有使用相同的基础设施。
在应用程序中使用段塞
尝试在后端添加更多会议,并更改现有会议的城市或年份;除非你使用了特殊功能,否则弹头不会更新-
价值。
最后一个更改是更新控制器和使用会议的模板鼻涕虫
而不是会议id
路线:
12 34 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
——/ src /控制器/ ConferenceController.php+ + + b / src /控制器/ ConferenceController.php@@ -20,7 +20,7 @@类ConferenceController扩展AbstractController]);}- #[路线(“/会议/ {id}”,名字:“会议”))+ #[路线(“/会议/{蛞蝓}”,名字:“会议”))公共函数show(Request $ Request, Conference $ Conference, CommentRepository $ CommentRepository): Response {$offset = max(0, $ Request ->query->getInt('offset', 0));——/模板/ base.html.twig+ + + b /模板/ base.html.twig@@ -18,7 +18,7 @@Guestbook
{% for conference in conferences %}- - {{conference}}
. Id})}}">{{conference}}+ - {{conference}}
.{% endfor %}
. {% endfor %}
.——/模板/会议/ index.html.twig+ + + b /模板/会议/ index.html.twig@@ -8,7 +8,7 @@{% for conference in meetings %} {{conference}}
. {% for conference in meetings %}
{{conference}- 查看 . id})}}+ 查看 . slug})}} {% endfor %} {% endblock %}——/模板/会议/ show.html.twig+ + + b /模板/会议/ show.html.twig@@ -22,10 +22,10 @@{% endfor %} {% if previous >= 0 %}- > . id, offset: previous})}}"> previous . id, offset: previous}+ < / >{% endif %} {% if next < comments|length %}- 下一个 . id, offset: next})}}+ 下一个 . > . > . >{% endif %} {% else %} 本次会议尚未发布任何评论
访问会议页面现在应该通过它的鼻涕虫完成:
要进一步
- 的主义事件系统(生命周期回调和监听器,实体监听器和生命周期订阅者);
- 的字符串组件文档;
- 的服务容器;
- 的ob娱乐下载Symfony服务备忘单.