【问题标题】:Reverse model relationships in LaravelLaravel 中的反向模型关系
【发布时间】:2014-05-24 06:01:31
【问题描述】:

我正在尝试根据标签获取帖子的相关帖子。

我的帖子 (id 1) 附加了几个标签,即标签 (id 1-3) 这意味着我的帖子有 3 个标签。根据这些标签,我想显示其他具有此标签的帖子。

我的标签模型:

<?php namespace Digitus\Base\Model;

class Tag extends \Eloquent{

    protected $table = 'tags';
    protected $guarded = ['id'];
    protected $fillable = ['name'];

    public function posts()
    {
        $this->belongsToMany('Digitus\Base\Model\Post');
    }

}

我的帖子模型:

    <?php namespace Digitus\Base\Model;

class Post extends \Eloquent {

    protected $fillable = array('title','body', 'author','slug');

    public function user()
    {
        return $this->belongsTo('Digitus\Base\Model\User', 'author');
    }

    public function tags()
    {
        return $this->belongsToMany('Digitus\Base\Model\Tag');
    }

    public function comments()
    {
        return $this->belongsToMany('Digitus\Base\Model\Comment');
    }

    public function categories()
    {
        return $this->belongsToMany('Digitus\Base\Model\Categorie');
    }
}

在我看来,我目前有:

<div class="col-xs-8 col-sm-8 col-md-8 col-lg-8 panel panel-info">
    <p>Gerelateerde berichten:</p>

            <?php 
            $posts = Digitus\Base\Model\Post::all();
            $tags = Digitus\Base\Model\Tag::all(); ?>
            @foreach($posts as $post)   
                @foreach($post->tags as $tag)
                    <div class="col-xs-6 col-sm-6 col-md-6 col-lg-6">{{ $post->title }}</div>
                @endforeach
            @endforeach


</div>

但它并没有真正显示具有相同标签的帖子,它只是将我所有的帖子都扔掉了。另外,我尝试向它添加某种过滤器,因此不会有任何重复的帖子(相同的帖子出现 2 次以上),但这也失败了。

我不是在寻找直接的答案,而是在寻找方向和建议等。

【问题讨论】:

  • 你能不能比“doesn'þ doesn'þ doesn'þdoesn'þdoesn'þdoesn'þdoesn'þdoesn'þdoesn'þdoesn'þdoesn'þdoesn'þdoesn'þdoesn'þdoesn'þdoesn'þdoesn'þdoesn'þdoesn'þdoesn'þdoesn'þ更明确?
  • 对不起@TomMacdonald,我编辑了
  • 要做你想做的事,你需要一个嵌套的 foreach,虽然这不是解决方案,因为它会导致 n+1 问题(许多数据库查询)。您必须阅读有关预加载的内容laravel.com/docs/eloquent#eager-loading

标签: php model laravel relationship


【解决方案1】:

在这段代码中:

@foreach($posts as $post)   
     @foreach($post->tags as $tag)
         <div class="col-xs-6 col-sm-6 col-md-6 col-lg-6">{{ $post->title }}</div>
     @endforeach
@endforeach

您正在遍历所有帖子的所有标签,并输出帖子标题。

所以对于一个有 3 个标签的帖子,你会输出帖子标题 3 次。

你可能会这样做:

<?php $posts = Digitus\Base\Model\Post::with('Tags.Posts')->get(); ?>
@foreach ($posts as $post)
    @foreach ($post->tags as $tag)
        @foreach ($tag->posts as $relatedPost)
            <div class="col-xs-6 col-sm-6 col-md-6 col-lg-6">{{ $relatedPost->title }}</div>
        @endforeach
    @endforeach
@endforeach

未测试,但据我了解 Eloquent 急切加载的工作原理,它应该可以工作。

编辑:

上面实际上会输出所有帖子,所以如果你想要单个帖子的相关帖子,这是要走的路:

以下应该输出一个包含单个帖子的数组:

<?php $posts = Digitus\Base\Model\Post::with('tags.posts')->where('id', $id)->get(); ?>

然后你“迭代”:

@foreach ($posts as $post)
    @foreach ($post->tags as $tag)
        @foreach ($tag->posts as $relatedPost)
            <div class="col-xs-6 col-sm-6 col-md-6 col-lg-6">{{ $relatedPost->title }}</div>
        @endforeach
    @endforeach
@endforeach

【讨论】:

  • 如果我手动添加一个id,它也会返回这个错误:Call to a member function addEagerConstraints() on a non-object
  • 尝试在 with() 和 find() 之间添加 get()。
  • 为了清楚起见,'->find($id)' 正在搜索帖子 ID,对吗?如果是这种情况,它仍然会返回相同的错误。我还在 with() 和 find() 之间添加了 ->get()
  • 嗯,研究建议以不同的方式执行此操作。请稍后检查我的编辑。
  • 另外,我使用的是“Tag.Post”而不是“Tags.Posts”或“tags.posts”。我的错。
【解决方案2】:

这可以,但请注意将运行 3 个数据库查询,所以也许你想要一些连接

<?php 
// don't do this in the view, better in controller, service or whatever and just pass $posts to the view
$posts = Digitus\Base\Model\Post::with('tags.posts')->get();
?>
@foreach($posts as $parentPost)
    @foreach($parentPost->tags as $tag)
        @foreach($tag->posts as $post)
            <?php if($post->id == $parentPost->id) continue; ?>
            <div class="col-xs-6 col-sm-6 col-md-6 col-lg-6">{{ $post->title }}</div>
        @endforeach
    @endforeach
@endforeach

----- 编辑: 在您的 Tag 模型中,您不会从关系中返回任何内容,因此只需添加 return:

public function posts()
{
   return $this->belongsToMany('Digitus\Base\Model\Post');
}

【讨论】:

  • 我认为 'tags.posts' 需要是 'Tags.Posts'
  • 你错了 ;) 在 with() 你称之为关系,而不是模型。
  • 嗯,我在这样的生产应用程序中使用它并且它正在工作,所以也许两者都工作?
  • 这里肯定不行,但你可能有名为 Tag 和 Post 的关系,那么它会起作用。
  • 经过测试。两者都有效。 :-) 我收回我之前的评论!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-08
  • 2018-12-20
  • 2014-08-17
  • 2015-12-09
  • 2020-04-24
  • 2017-02-25
  • 2019-04-04
相关资源
最近更新 更多