Laravel雄辩-设置双向关系后加载?



让我们考虑下面的例子:一个线程有帖子,而这些帖子也有一个"线程"关系。每篇文章的标题必须包含父线程的标题。

class Thread extends Model
{
public function posts()
{
return $this->hasMany(Post::class);
}
}
class Post extends Model
{
public function thread()
{
return $this->belongsTo(Thread::class);
}
public function getTitleAttribute(string $title): string
{
return $this->thread->title . ': ' . $title;
}
}

我想要达到的目标:

//when we load the posts using the thread...
$posts = $thread->posts;
//...I want the "thread" relation of each post to be automatically set to $thread, so that:
$posts->first()->thread === $thread //true

默认不为真。如果我们这样做:

$array = $thread->posts->toArray();

这将导致每个帖子一个接一个地从DB加载线程,这是超级非最佳的。是否有一些优雅的Laravel技术来建立刚刚加载的模型之间的关系?

您可以像这样延迟加载它们

$posts = $thread->posts()->with('thread')->get();

如果你不想要额外的查询,你可以使用map()

$thread->posts->map(function($post) use ($thread) {
return $post->setRelation('thread', $thread);
});

这将导致相同数量的对象,但也将导致引用循环。

//this is defined and doesn't use more object or launch other queries
$thread->posts->first()->thread->posts()->first()->thread; 

如果你想自动化它,我建议你在Thread模型上创建一个函数来让帖子线程化。

public function loadThreadedPosts()
{
$this->posts->map(function($post) {
return $post->setRelation('thread', $this);
});
return $this;
}
//then you can
$thread->loadThreadedPosts()->posts;

如果你想在调用"post "关系时自动完成在Thread::class模型上,将此方法添加到您的Thread::class中以覆盖特性HasAttributes中存在的功能,风险由您自己承担

/**
* Get a relationship value from a method.
*
* @param  string  $method
* @return mixed
*
* @throws LogicException
*/
protected function getRelationshipFromMethod($method)
{
$relation = $this->$method();
if (! $relation instanceof Relation) {
if (is_null($relation)) {
throw new LogicException(sprintf(
'%s::%s must return a relationship instance, but "null" was returned. Was the "return" keyword used?', static::class, $method
));
}
throw new LogicException(sprintf(
'%s::%s must return a relationship instance.', static::class, $method
));
}
return tap($relation->getResults(), function ($results) use ($method) {
if ($method == "posts") {
$results->map(function($post) {
return $post->setRelation('thread', $this);
});
}
$this->setRelation($method, $results);
});
}

希望你明白,这覆盖了一个供应商的方法,并可能导致未来的问题,我也不认为这一个方法工作与急切加载(例如:Thread::with('posts')->get()),我不知道还有什么可能会被打破/有意外的行为。

正如我所说,风险由你自己承担(打赌/希望->loadThreadedPosts()现在看起来更有趣)

相关内容

  • 没有找到相关文章

最新更新