Model Observer
The Model Observer component registers classes that handle Hyperf model events. An observer can be bound from the observer class or from the model class.
Installation
composer require friendsofhyperf/model-observerThe component is registered automatically through its ConfigProvider. It requires hyperf/database when used with Hyperf models:
composer require hyperf/databaseGenerate an Observer
Pass a model class to gen:observer to generate an observer in the default App\Observer namespace:
php bin/hyperf.php gen:observer UserObserver --model="App\\Model\\User"The command also supports:
php bin/hyperf.php gen:observer UserObserver \
--model="App\\Model\\User" \
--namespace="App\\ModelObserver" \
--force--model,-M: model class used in the generated attribute and method signatures.--namespace,-N: namespace of the generated observer.--force,-f: overwrite an existing observer file.
You can change the default namespace or stub in config/autoload/devtool.php:
return [
'generator' => [
'observer' => [
'namespace' => 'App\\ModelObserver',
'stub' => BASE_PATH . '/stubs/observer.stub',
],
],
];Bind from an Observer
Use #[Observer] on an observer class. The model argument accepts one model class or an array of model classes:
namespace App\Observer;
use App\Model\User;
use FriendsOfHyperf\ModelObserver\Annotation\Observer;
#[Observer(model: User::class)]
class UserObserver
{
public function creating(User $model): void
{
// Runs when a user is being created.
}
public function created(User $model): void
{
// Runs after a user has been created.
}
}namespace App\Observer;
use App\Model\Post;
use App\Model\User;
use FriendsOfHyperf\ModelObserver\Annotation\Observer;
use Hyperf\Database\Model\Model;
#[Observer(model: [User::class, Post::class])]
class SearchIndexObserver
{
public function saved(Model $model): void
{
// Update the search index.
}
}#[Observer] is repeatable. You can use priority to run higher-priority observers first:
#[Observer(model: User::class, priority: 100)]
#[Observer(model: Post::class, priority: 50)]
class AuditObserver
{
// ...
}Bind from a Model
Use #[ObservedBy] to declare observers on a model. Its classes argument accepts one observer class or an array of observer classes, and the attribute is repeatable:
namespace App\Model;
use App\Observer\AuditObserver;
use App\Observer\UserObserver;
use FriendsOfHyperf\ModelObserver\Annotation\ObservedBy;
use Hyperf\Database\Model\Model;
#[ObservedBy([UserObserver::class, AuditObserver::class], priority: 100)]
class User extends Model
{
// ...
}Bindings from #[Observer] and #[ObservedBy] are combined. Duplicate observer classes for the same model are called only once.
Run an Observer in a Coroutine
Implement ShouldCoroutine when all callable event methods on an observer should run in newly created coroutines:
namespace App\Observer;
use App\Model\User;
use FriendsOfHyperf\ModelObserver\Annotation\Observer;
use FriendsOfHyperf\ModelObserver\Contract\ShouldCoroutine;
#[Observer(model: User::class)]
class UserObserver implements ShouldCoroutine
{
public function created(User $model): void
{
// Runs in a newly created coroutine.
}
}Coroutine observers run asynchronously. Do not rely on them completing before the model operation returns.
Supported Events
Define only the methods needed by an observer. Each callable method receives the model instance:
bootingbootedretrievedcreatingcreatedupdatingupdatedsavingsavedrestoringrestoreddeletingdeletedforceDeleted
The component dispatches these methods through Hyperf events. Return values from observer methods are ignored and cannot cancel a model operation.