Doctrine 事件
Doctrine 是一組 Symfony 用於操作資料庫的 PHP 函式庫,提供輕量級的事件系統,以便在應用程式執行期間更新實體。這些事件稱為生命週期事件,允許執行諸如「在持久化此類型的實體之前自動更新 createdAt 屬性」之類的任務。
Doctrine 在執行最常見的實體操作(例如 prePersist/postPersist
、preUpdate/postUpdate
)之前/之後觸發事件,也在其他常見任務(例如 loadClassMetadata
、onClear
)上觸發事件。
有不同的方式來監聽這些 Doctrine 事件
- 生命週期回呼,它們被定義為實體類別上的公開方法。它們不能使用服務,因此它們適用於與單一實體相關的非常簡單的邏輯;
- 實體監聽器,它們被定義為具有回呼方法的類別,用於您想要回應的事件。它們可以使用服務,但它們僅針對特定類別的實體調用,因此它們非常適合與單一實體相關的複雜事件邏輯;
- 生命週期監聽器,它們與實體監聽器類似,但它們的事件方法針對所有實體調用,而不僅僅是特定類型的實體。它們非常適合在實體之間共享事件邏輯。
每種監聽器的效能取決於它應用於多少實體:生命週期回呼比實體監聽器快,而實體監聽器又比生命週期監聽器快。
本文僅說明在 Symfony 應用程式中使用 Doctrine 事件的基本知識。請閱讀 Doctrine 事件的官方文件,以了解有關它們的所有資訊。
另請參閱
本文涵蓋 Doctrine ORM 的監聽器。如果您使用 ODM for MongoDB,請閱讀DoctrineMongoDBBundle 文件。
Doctrine 生命週期回呼
生命週期回呼被定義為您想要修改的實體內的公開方法。例如,假設您想要將 createdAt
日期欄位設定為目前日期,但僅在首次持久化實體(即插入)時才設定。為此,請為 prePersist
Doctrine 事件定義回呼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
// src/Entity/Product.php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
// When using attributes, don't forget to add #[ORM\HasLifecycleCallbacks]
// to the class of the entity where you define the callback
#[ORM\Entity]
#[ORM\HasLifecycleCallbacks]
class Product
{
// ...
#[ORM\PrePersist]
public function setCreatedAtValue(): void
{
$this->createdAt = new \DateTimeImmutable();
}
}
注意
某些生命週期回呼會接收一個參數,該參數提供對有用資訊的存取,例如目前的實體管理器(例如,preUpdate
回呼接收 PreUpdateEventArgs $event
參數)。
Doctrine 實體監聽器
實體監聽器被定義為 PHP 類別,它們監聽單一實體類別上的單一 Doctrine 事件。例如,假設您想要在資料庫中修改 User
實體時傳送一些通知。
首先,定義一個處理 postUpdate
Doctrine 事件的 PHP 類別
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// src/EventListener/UserChangedNotifier.php
namespace App\EventListener;
use App\Entity\User;
use Doctrine\ORM\Event\PostUpdateEventArgs;
class UserChangedNotifier
{
// the entity listener methods receive two arguments:
// the entity instance and the lifecycle event
public function postUpdate(User $user, PostUpdateEventArgs $event): void
{
// ... do something to notify the changes
}
}
然後,將 #[AsEntityListener]
屬性新增到類別,以在您的應用程式中將其啟用為 Doctrine 實體監聽器
1 2 3 4 5 6 7 8 9 10 11 12 13
// src/EventListener/UserChangedNotifier.php
namespace App\EventListener;
// ...
use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsEntityListener;
use Doctrine\ORM\Events;
#[AsEntityListener(event: Events::postUpdate, method: 'postUpdate', entity: User::class)]
class UserChangedNotifier
{
// ...
}
或者,如果您不想使用 PHP 屬性,則必須為實體監聽器設定服務,並依照以下方式使用 doctrine.orm.entity_listener
標籤標記它
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
# config/services.yaml
services:
# ...
App\EventListener\UserChangedNotifier:
tags:
-
# these are the options required to define the entity listener
name: 'doctrine.orm.entity_listener'
event: 'postUpdate'
entity: 'App\Entity\User'
# these are other options that you may define if needed
# set the 'lazy' option to TRUE to only instantiate listeners when they are used
# lazy: true
# set the 'entity_manager' option if the listener is not associated to the default manager
# entity_manager: 'custom'
# by default, Symfony looks for a method called after the event (e.g. postUpdate())
# if it doesn't exist, it tries to execute the '__invoke()' method, but you can
# configure a custom method name with the 'method' option
# method: 'checkUserChanges'
Doctrine 生命週期監聽器
生命週期監聽器被定義為 PHP 類別,它們監聽應用程式中所有實體上的單一 Doctrine 事件。例如,假設您想要在資料庫中持久化新實體時更新一些搜尋索引。為此,請為 postPersist
Doctrine 事件定義一個監聽器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// src/EventListener/SearchIndexer.php
namespace App\EventListener;
use App\Entity\Product;
use Doctrine\ORM\Event\PostPersistEventArgs;
class SearchIndexer
{
// the listener methods receive an argument which gives you access to
// both the entity object of the event and the entity manager itself
public function postPersist(PostPersistEventArgs $args): void
{
$entity = $args->getObject();
// if this listener only applies to certain entity types,
// add some code to check the entity type as early as possible
if (!$entity instanceof Product) {
return;
}
$entityManager = $args->getObjectManager();
// ... do something with the Product entity
}
}
注意
在先前的 Doctrine 版本中,您必須使用 LifecycleEventArgs
而不是 PostPersistEventArgs
,LifecycleEventArgs
在 Doctrine ORM 2.14 中已被棄用。
然後,將 #[AsDoctrineListener]
屬性新增到類別,以在您的應用程式中將其啟用為 Doctrine 監聽器
1 2 3 4 5 6 7 8 9 10 11
// src/EventListener/SearchIndexer.php
namespace App\EventListener;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\ORM\Events;
#[AsDoctrineListener(event: Events::postPersist, priority: 500, connection: 'default')]
class SearchIndexer
{
// ...
}
或者,如果您不想使用 PHP 屬性,則必須在 Symfony 應用程式中啟用監聽器,方法是為其建立新服務,並使用 doctrine.event_listener
標籤標記它
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// src/EventListener/SearchIndexer.php
namespace App\EventListener;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\ORM\Event\PostPersistEventArgs;
#[AsDoctrineListener('postPersist'/*, 500, 'default'*/)]
class SearchIndexer
{
public function postPersist(PostPersistEventArgs $event): void
{
// ...
}
}
2.8.0
AsDoctrineListener 屬性是在 DoctrineBundle 2.8.0 中引入的。
提示
connection
選項的值也可以是組態參數。