步骤13:管理Doctrine对象的生命周期

5.2版本
维护 没有维护的
5.0

管理学说对象的生命周期

创建新评论时,如果是很棒createdAt日期将自动设置为当前日期和时间。

Doctrine有不同的方法来操作对象及其生命周期中的属性(在数据库中创建行之前,行更新之后,…)。

定义生命周期回调

当行为不需要任何服务并且应该仅应用于一种实体时,在实体类中定义回调:

patch_file.
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
——/ src /实体/ Comment.php+ + + b / src /实体/ Comment.php@@ -7,6 +7,7 @@使用Doctrine ORM映射为ORM;/ ** * * @orm \实体(repositoryClass = CommentRepository :: class)+ * @ORM \ HasLifecycleCallbacks ()*/类注释{@@ -106,6 +107,14 @@类注释返回这个美元;}+ / * *+ * @orm \ prepersist+ * /+ public function setCreatedAtValue()+ {+ $this->createdAt = new \DateTime();+}+公共功能getConference():?会议{返回$以下 - >会议;

@ORM \ PrePersist事件当对象第一次存储在数据库中时触发。当这种情况发生时,setCreatedAtValue ()方法的值使用当前日期和时间createdAt财产。

在会议中添加鼻涕虫

会议的URL并不有意义:/会议/ 1。更重要的是,它们依赖于实现细节(数据库中的主键泄漏)。

使用像这样的url怎么样- 2020 /会议/巴黎反而?这看起来要好得多。巴黎- 2020这就是我们所说的会议吗鼻涕虫

添加一个新的鼻涕虫会议的财产(A 255个字符的不可空字符串):

1
$ ob娱乐下载symfony console make:实体会议

创建一个迁移文件来添加新列:

1
$ ob娱乐下载symfony控制台制作:迁移

并执行新的迁移:

1
主机ob娱乐下载信条:迁移:迁移

有一个错误吗?这是预期。为什么?因为我们要求子弹不是但会议数据库中现有的条目将得到一个迁移时的值为RAN。让我们通过调整迁移来解决:

patch_file.
1 2 3 4 5 6 7 8 9 10 11 12 13
——/迁移/ Version00000000000000.php+ + + b /迁移/ Version00000000000000.php@@ -20,7 +20,9 @@最终类版本20200714152808扩展了抽象迁移public function up(Schema $ Schema): void{//这个up()迁移是自动生成的,请根据需要修改它- $this->addSql('ALTER TABLE conference ADD slug VARCHAR(255) NOT NULL'); / /删除表+ $以下 - > ADDSQL('ALTER TABLE会议添加SLUG VARCHAR(255)');+ $this->addSql("UPDATE conference SET slug=CONCAT(LOWER(city), '-', year)");+ $以下 - > ADDSQL('ALTER TABLE会议ALTER列SLUS SLUS LET NOT NULL');} public function down(Schema $ Schema): void

这里的诀窍是添加列并允许它成为,则将弹头设置为not值,最后,更改SLUS列以不允许

请注意

对于一个真实的项目,使用CONCAT(低(市),“-”,年)可能还不够。在这种情况下,我们需要使用“真实”的甩口。

现在迁移应该可以正常运行:

1
主机ob娱乐下载信条:迁移:迁移

由于应用程序即将使用SLUS查找每个会议,因此让我们调整会议实体,以确保SLUS值在数据库中是唯一的:

patch_file.
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
--- a / src /实体/会议.php+++ B / SRC / ENTITY / CONELTS.PHP@@ -6,9 +6,111 @@使用app \ repository \ conferencerepository;使用Doctrine \ Common \ Collections \ ArrayCollection;使用原则\常见\集合\集合;使用Doctrine \ ORM \映射为ORM;+使用Syob娱乐下载mfony \桥\学说\验证器\ \ UniqueEntity约束;/ * * * @ORM \实体(repositoryClass = ConferenceRepository::类)+ * @UniqueEntity(“鼻涕虫”)*/类会议{@@ -40,7 +42,7 @@班级会议私人美元评论;/ * *- * @ORM\列(type="string", length=255)+ * @ORM\列(type="string", length=255, unique=true)* /私人美元弹头;

因为我们正在使用一个验证器来确保鼻涕虫的唯一性,所以我们需要添加Symfony验证器组件:ob娱乐下载

1
$ ob娱乐下载Symfony Composer REQ验证器

正如您可能猜到的那样,我们需要执行迁移舞蹈:

1
$ ob娱乐下载symfony控制台制作:迁移
1
主机ob娱乐下载信条:迁移:迁移

生成蛞蝓

生成在URL中读得良好的slu(除了应编码ASCII字符之外的任何内容)是一个具有挑战性的任务,尤其是英语以外的语言。你如何转换É.e例如?

让我们使用symfony而不是重新发明轮子ob娱乐下载字符串组件,它简化了字符串的操作,并提供了一个重击者:

1
$ ob娱乐下载symfony composer请求字符串

添加A.computeSlug ()方法会议基于会议数据计算SLUI的类:

patch_file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 18 19 20 21 22 23 23 24
--- a / src /实体/会议.php+++ B / SRC / ENTITY / CONELTS.PHP@@ -7,6 +7,7 @@使用doctrine \ common \ collections \ arraycollection;使用原则\常见\集合\集合;使用Doctrine ORM映射作为ORM;使用Syob娱乐下载mfony \桥\学说\验证器\ \ UniqueEntity约束;+使用syob娱乐下载mfony \ component \ string \ slugger \ sluggerinterface;/ * * * @ORM \实体(repositoryClass = ConferenceRepository::类)@@ -61,6 + 62,13 @ @类会议返回$ this - > id;}+公共功能ComputesLug(SLUGGERINTERFACE $ SLUGGER)+ {+如果(!$ this-> slug ||' - '=== $ this-> slug){+ $ this-> slug =(string)$ slugger-> slug((字符串)$以下) - > leough();+}+}+公共函数getcity():?字符串{返回$ this-> city;

computeSlug ()方法仅在当前弹头为空或设置为特殊弹头时计算弹头-价值。为什么我们需要-特价?因为在后端添加会议时,需要SLUG。因此,我们需要一个非空值,该值告诉我们希望将自动生成SLUS的应用程序。

定义一个复杂的生命周期回调

至于createdAt财产,呢鼻涕虫只要通过调用会议即可自动设置一个computeSlug ()方法。

但由于这种方法取决于一个SluggerInterface实现时,我们不能添加一个prePersist事件和以前一样(我们没有办法注射强击球)。

相反,创建一个Doctrine实体监听器:

src / EntityListener / ConferenceEntityListener.php
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
名称空间App \ EntityListener;使用应用实体\ \会议;使用学说\ ORM \ \ LifecycleEventArgs事件;使用ob娱乐下载Symfony \组件\ \重击者\ SluggerInterface字符串;班级ConferenceEntityListener{私人的美元重击者;公共函数__构造(SluggerInterface美元重击者){$这一点->重击者=美元重击者;}公共函数prePersist(会议美元的会议,LifecycleEventArgs美元的事件){美元的会议->computeslug.($这一点->重击者);}公共函数预伪(会议美元的会议,LifecycleEventArgs美元的事件){美元的会议->computeslug.($这一点->重击者);}}

请注意,创建新会议时,SLU将更新(预备主义者())每当它更新时(Preupdate())。

在容器中配置服务

到目前为止,我们没有谈论Symfony的一个关键组成部分,ob娱乐下载依赖注入容器。容器负责管理服务:创建它们并在需要时注入它们。

一个服务一个提供特性的“全局”对象(如邮件发送器、日志记录器、重击器等)与之不同吗数据对象(例如:教条实体实例)。

你很少直接与容器交互,因为它会在你需要的时候自动注入服务对象:容器会在你输入-提示时注入控制器参数对象。

如果您想知道在前面的步骤中事件侦听器是如何注册的,那么现在您有了答案:容器。当一个类实现了一些特定的接口时,容器知道这个类需要以某种方式注册。

不幸的是,没有为一切提供自动化,特别是对于第三方包装。我们刚写的实体听众是这样的例子;它无法自动管理Symfony Service Conttob娱乐下载e,因为它不实现任何接口,并且它不会扩展“知名类”。

我们需要在容器中部分声明侦听器。可以省略依赖连接,因为它仍然可以由容器猜测,但是我们需要手动添加一些标签向Doctrine事件调度程序注册侦听器:

patch_file.
1 2 3 4 5 6 7 8 9 10
--- a / config / services.yaml+++ b / config / services.yaml@@ -29,3 +29,7 @@服务:#在需要显式配置时添加更多的服务定义#请注意最后一个定义总是*替换*之前的定义+应用\ EntityListener \ ConferenceEntityListener:+标签:+  -  {名:'doctrine.ortity_listener',事件:'prepersist',实体:'app \ entity \ conference'}+  -  {name:'doctrine.ortity_listener',事件:'preupdate',实体:'app \ entity \ conference'}

请注意

不要混淆教条事件的听众和交响乐的听众。ob娱乐下载即使它们看起来非常相似,但它们实际上并没有使用相同的基础设施。

在应用程序中使用鼻涕虫

尝试在后台添加更多的会议,并更改现有会议的城市或年份;蛞蝓不会更新,除非你使用特殊-价值。

最后一个变化是更新控制器和模板来使用会议鼻涕虫而不是会议ID路线:

patch_file.
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@@类ConferenceController扩展了AbstractController]));}- #[路线('/ conference / {id}',名称:'会议')]+ #[路线(“/会议/{蛞蝓}”,名字:“会议”))public function show(Request $ Request, Conference $ Conference, CommentRepository $ CommentRepository): Response {$offset = max(0, $ Request ->query->getInt('offset', 0));——/模板/ base.html.twig+ + + b /模板/ base.html.twig@@ -12,7 +12,7 @@

Guestbook

访问会议页面现在应该通过它的slug完成:


该工作,包括代码示例,根据anc - sa知识共享4.0许可证。