Laravel 获取构建器而不是关系

Posted

技术标签:

【中文标题】Laravel 获取构建器而不是关系【英文标题】:Laravel getting builder instead of relation 【发布时间】:2016-01-31 07:11:34 【问题描述】:

我正在尝试在保存模型之前对其进行验证。显然,如果模型无效,则不应将其保存到数据库中。当验证失败时,它会抛出异常并且不会继续保存。下面的工作:

$question = new Question([...]);
$question->validate();
$question->save();

我对 answers() hasMany 关系有疑问。根据this answer,我应该可以在关系对象上调用add()

$question = new Question([...]);
$question->answers()->add(new Answer([...]));
$question->validate();
$question->save();

以上失败:

Call to undefined method Illuminate\Database\Query\Builder::add()

我认为 answers() 函数会返回一个 HasMany 关系对象,但看起来我正在获得一个构建器。为什么?

【问题讨论】:

如果 answers 是一个关系,你会想要调用 $question->answers 而不是 $question->answers() (不要调用函数)。确保使用定义关系的函数的名称,而不是模型名称本身(如果它们相同就可以)。 【参考方案1】:

answers() 确实返回了一个 HasMany 对象。但是,由于 HasMany 对象上没有 add 方法,Laravel 求助于 php__call 魔术方法。

public function __call($method, $parameters)

    $result = call_user_func_array([$this->query, $method], $parameters);

    if ($result === $this->query) 
        return $this;
    

    return $result;

__call 方法获取查询实例并尝试对其调用add 方法。但是,查询生成器上没有 add 方法,这就是您收到该消息的原因。

最后,add 方法是 Laravel 的 Eloquent Collection 的一部分,而不是 HasMany 的一部分。为了获得 Collection 类,您需要删除括号(如链接中提供的答案所示)并改为这样做:

$question->answers->add(new Answer([...]));

【讨论】:

谢谢!我错过了不带括号的部分。 将答案添加到集合中不会在保存问题时将其保存到数据库中。【参考方案2】:

没有add 方法。使用save 方法:

$question->answers()->save(new Answer([]));

【讨论】:

在执行验证之前我无法将对象保存到数据库中,因此我无法在集合上销售 save()。

以上是关于Laravel 获取构建器而不是关系的主要内容,如果未能解决你的问题,请参考以下文章

如何在 laravel 5.4 orm 中执行多个 has() /orHas()

laravel 查询构建器计数关系

具有计数关系的 Laravel 查询构建器

Laravel 通过属性获得雄辩的查询构建器关系

Laravel 查询构建器与雄辩的关系

laravel 7.14 在使用关系搜索数据表后为产品构建链接