artificertech/laravel-relationship-events

Laravel缺少关系事件

v0.2.1 2023-03-29 04:41 UTC

This package is auto-updated.

Last update: 2024-08-29 07:26:44 UTC


README

Laravel缺少关系事件

此包最初是从https://github.com/chelout/laravel-relationship-events 分支的代码派生而来,该分支不再积极开发。此包对原始想法进行了不同的实现,允许基于每个关系创建关系事件监听器

此包仍在开发中。欢迎通过提交拉取请求进行贡献

Build Status Total Downloads Latest Stable Version License

安装

  1. 使用composer安装包

最新版本

由于该项目仍在开发中,因此目前没有发布版本。

composer require artificertech/laravel-relationship-events

开发分支

composer require artificertech/laravel-relationship-events:dev-master
  1. 将HasRelationshipEvents特性添加到您的模型中
use Artificertech\RelationshipEvents\Concerns\HasRelationshipEvents;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    use HasRelationshipEvents;

    public static function boot()
    {
        parent::boot();

        /**
         * hasOne
         */
        static::hasOneSaved('profile', function ($user, $profile) {
            dump('hasOneSaved', $user, $profile);
        });
    }

    public function profile()
    {
        return $this->hasOne(Profile::class)->withEvents();
    }

}

对于所有在操作执行之前触发的保存、附加、创建等事件,您可以从不从事件监听器返回false以取消操作

use Artificertech\RelationshipEvents\Concerns\HasRelationshipEvents;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    use HasRelationshipEvents;

    public static function boot()
    {
        parent::boot();

        /**
         * hasMany
         */
        static::hasManyCreating('posts', function ($user, $post) {
            if ($post->name == 'badName') return false;
        });
    }

    public function posts()
    {
        return $this->hasMany(Post::class)->withEvents();
    }

}
  1. 可分发的关联事件。可以通过$dispatchesEvents属性来通过事件类触发事件
use Artificertech\RelationshipEvents\Concerns\HasRelationshipEvents;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    use HasRelationshipEvents;

    protected $dispatchesEvents = [
        'postsCreating' => UserPostsCreating::class,
        'postsCreated' => UserPostsCreated::class,
        'postsSaving' => UserPostsSaving::class,
        'postsSaved' => UserPostsSaved::class,
    ];

    public function posts()
    {
        return $this->hasMany(Post::class)->withEvents();
    }

}

观察者

您可以在Laravel观察者类中使用关系事件。使用非常简单。定义观察者类

namespace App\Observer;

class UserObserver
{
    /**
     * Handle the User "postsCreating" event.
     *
     * @param \App\Models\User $user
     * @param \App\Models\Post $post
     *
     * @return void
     */
    public function postsCreating(User $user, Post $post)
    {
        Log::info("Creating post: {$post->name} for user {$user->name}.");
    }

    /**
     * Handle the User "postsCreated" event.
     *
     * @param \App\Models\User $user
     * @param \App\Models\Post $post
     *
     * @return void
     */
    public function postsCreated(User $user, Post $post)
    {
        Log::info("Post: {$post->name} for user: {$user->name} has been created.");
    }

    /**
     * Handle the User "postsCreating" event.
     *
     * @param \App\Models\User $user
     * @param \App\Models\Post $post
     *
     * @return void
     */
    public function postsSaving(User $user, Post $post)
    {
        Log::info("Saving post: {$post->name} for user {$user->name}.");
    }

    /**
     * Handle the User "postsCreated" event.
     *
     * @param \App\Models\User $user
     * @param \App\Models\Post $post
     *
     * @return void
     */
    public function postsSaved(User $user, Post $post)
    {
        Log::info("Post: {$post->name} for user: {$user->name} has been saved.");
    }
}

检测可观察事件

laravel-relationship-events包不能自动检测您想要观察的关系事件。请像这样在您的模型类中定义它们

class User extends Model
{
    use HasRelationshipEvents;

    /**
     * User exposed observable events.
     *
     * These are extra user-defined events observers may subscribe to.
     *
     * @var array
     */
    protected $observables = [
        'postsCreating',
        'postsCreated',
        'postsSaving',
        'postsSaved',
    ];

    public function posts()
    {
        return $this->hasMany(Post::class)->withEvents();
    }

}

别忘了在AppServiceProvider的boot方法中注册观察者

namespace App\Providers;

use App\Models\User;
use App\Observers\UserObserver;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
// ...
    public function boot()
    {
        User::observe(UserObserver::class);
    }
// ...
}

现在只需为用户创建配置文件

// ...
$user = factory(User::class)->create([
    'name' => 'John Smith',
]);

// Create profile and assosiate it with user
// This will fire two events hasOneCreating, hasOneCreated
$user->post()->create([
    'name' => 'My first post!',
]);
// ...

自定义事件名称

默认情况下,关系事件名称等于关系函数名称,动作以驼峰式表示。例如,如果您有一个HasOne关系"profile",则事件名称将是"profileCreating"、"profileCreated"、"profileSaving"、"profileSaved"。

您可以通过将关系名称作为字符串传递给withEvents()函数来自定义事件名称。例如

class User extends Model
{
    use HasRelationshipEvents;

    public function posts()
    {
        return $this->hasMany(Post::class)->withEvents('userPost');
    }

}

将触发"userPostCreating"、"userPostCreated"、"userPostSaving"、"userPostSaved"事件

关系特定信息

每个关系都有稍微不同的事件。例如,belongsTo关系触发{relationship}Associating、{relationship}Associated、{relationship}Dissociating和{relationship}Dissociated事件

待办事项

  • 修复自动测试
  • 添加ManyToMany类型事件的文档(这些事件可以通过内置的pivot模型处理,不需要此包)
  • 非默认事件名称测试
  • 事件调度器测试
  • 事件监听器异常测试
  • HasOneThrough & HasManyThrough
  • 新HasOneOfMany关系?