首页 > 解决方案 > 覆盖 Eloquent 关系创建方法

问题描述

我想覆盖 create 方法,但是对于关系,它没有触及 create 方法。

有两种型号:

class User extends Model
{
    public function user_detail()
    {
        return $this->hasOne(UserDetail::class);
    }
}


class UserDetail extends Model
{
    public static function create(array $attributes = [])
    {
        //I was trying to do something like
        /*
        if(isset($attributes['last_name']) && isset($attributes['first_name']))
        {
            $attributes['full_name']=$attributes['first_name'].' '.$attributes['last_name'];
        }
        unset($attributes['first_name'],$attributes['last_name']);
        */

        Log::debug('create:',$attributes);
        $model = static::query()->create($attributes);
        return $model;
    }
}

当我使用UserDetail::create($validated)时,laravel.log 中有一个日志,所以我知道代码触及了我的自定义创建方法。

但是如果我使用

$user = User::create($validated);
$user->user_detail()->create($validated);

laravel.log 中没有日志,说明 laravel 没有接触 create 方法,那么在这种情况下我应该如何覆盖 create 方法呢?(我使用的是 laravel 5.7)

标签: laravel-5eloquent

解决方案


谢谢@Jonas Staudenmeir,在我阅读了文档之后,这是我的解决方案。

如果 $属性不在受保护的 $fillable array中,那么我在 __construct 方法中执行此操作。

class UserDetail extends Model
{
    protected $fillable=['full_name','updated_ip','created_ip'];

    public function __construct(array $attributes = [])
    {
        if (isset($attributes['first_name']) && isset($attributes['last_name'])) {
            $attributes['full_name'] = $attributes['first_name'].' '.$attributes['last_name'];
        }

        parent::__construct($attributes);
    }
}

否则,我会在 Observer 中进行。

namespace App\Observers;

use App\Models\UserDetail;

class UserDetailObserver
{
    public function creating(UserDetail $userDetail)
    {
        $userDetail->created_ip = request()->ip();
    }

    public function updating(UserDetail $userDetail)
    {
        $userDetail->updated_ip = request()->ip();
    }

}

在 AppServiceProvider 中注册观察者。

namespace App\Providers;

use App\Models\UserDetail;

use App\Observers\UserDetailObserver;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        UserDetail::observe(UserDetailObserver::class);
    }
}

我选择 Observer 而不是 Event&Listener 是为了便于维护。


推荐阅读