php 在laravel中将模型关联到一个关系时启用类型检查

ws51t4hk  于 12个月前  发布在  PHP
关注(0)|答案(2)|浏览(183)

假设我有三个模型UserPostComment,并像这样链接:

class User extends Model
{
    public function posts(): HasMany
    {
        return $this->hasMany(Post::class);
    }
}
class Comment extends Model
{
    public function post(): BelongsTo
    {
        return $this->belongsTo(Post::class);
    }
}
class Post extends Model
{
    /**
     * Get the comments for the blog post.
     */
    public function comments(): HasMany
    {
        return $this->hasMany(Comment::class);
    }
}

我想把一个帖子和评论联系起来,我会这样做:

$comment->post()->associate($post);


但如果我错误地将不同的模型传递给关联函数:

$comment->post()->associate($user);


那么它仍然会工作,它会关联具有传递用户的相同ID的帖子,这是错误的。
基本上,associate函数在关联之前不会检查传递的模型的类型,有没有什么东西可以启用,以便laravel在关联之前检查模型的类型?

w8f9ii69

w8f9ii691#

Laravel associate本身不会检查关联模型的类型。
通过扩展关系方法,可以动态地检查相关模型,从而解决了这个问题.

use Illuminate\Database\Eloquent\Relations\BelongsTo;
use InvalidArgumentException;

class TypedBelongsTo extends BelongsTo
{
    public function associate($model)
    {
        $relatedModelClass = $this->getRelated()::class;

        if (! $model instanceof $relatedModelClass) {
            throw new InvalidArgumentException("Expected instance of $relatedModelClass.");
        }

        return parent::associate($model);
    }
}

字符串
例如,您的Comment模型可以具有以下关系。

public function post(): TypedBelongsTo
{
    return new TypedBelongsTo(Post::query, $this, 'post_id', 'id', 'post');
}

pbgvytdp

pbgvytdp2#

associate方法不检查类型,也不进行参数类型提示,它需要Model示例、string、int或null,如图所示:

/**
 * Associate the model instance to the given parent.
 *
 * @param  \Illuminate\Database\Eloquent\Model|int|string|null  $model
 * @return \Illuminate\Database\Eloquent\Model
 */
public function associate($model)

字符串
基本上,你必须自己处理这个问题,因为这不是用户输入,所以很容易确保你传递的参数是正确的。
否则,你将需要做一个多余的工作-IMO-来处理这个问题。
首先,您将覆盖模型中返回新BelongsTo类的belongsTo方法(在下一步中)。
其次,您需要创建BelongsTo关注点的 shadow 版本,很可能您将继承Illuminate\Database\Eloquent\Relations\BelongsTo并重写associate方法以键入hint参数,给予一个适当的名称,比如CommentsBelongsTo或其他名称。
最后一个类类似于:

use Illuminate\Database\Eloquent\Relations\BelongsTo;
use App\Models\Post;

class CommentsBelongsTo extends BelongsTo
{
    ...
    public function associate(Post $model)
    ...
}

相关问题