最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

php - How can I use a many-to-many relationship to display articles by tag in Laravel? - Stack Overflow

programmeradmin1浏览0评论

I am working on a blogging application in Laravel 8.

I am trying to display articles by tag at the following route:

Route::get('/tag/{tag_id}', [ArticlesController::class, 'tag'])->name('tag');

In the ArticlesController controller, I have the tag() method, which is supposed to display all posts that contain a certain tag:

public function tag($tag_id)
{
    $tag   = Tag::firstWhere('id', $tag_id);
    $articles = Article::where('id', $tag->id)->orderBy('id', 'desc')->paginate($this->per_page);

    return view(
      'themes/' . $this->theme_directory . '/templates/index',
      array_merge($this->data, [
        'tag'   => $tag,
        'articles' => $articles
      ])
    );
}

There is a many-to-many relationship between articles and tags. I have an article_tag pivot table:

In the Tag model I have:

class Tag extends Model
{
   use HasFactory;

   protected $fillable = ['name'];

   public function article()
   {
       return $this->belongsToMany(Article::class);
   } 
}

To the Article model I have added the tags() method

public function tags()
{
    return $this->belongsToMany(Tag::class)->as('tags');
}

The problem

The /tag/1 displays only one article and that article does not contain a tag with the id of 1.

Questions:

  1. Where is my mistake?
  2. What working solution requires minimal change in the current code?

I am working on a blogging application in Laravel 8.

I am trying to display articles by tag at the following route:

Route::get('/tag/{tag_id}', [ArticlesController::class, 'tag'])->name('tag');

In the ArticlesController controller, I have the tag() method, which is supposed to display all posts that contain a certain tag:

public function tag($tag_id)
{
    $tag   = Tag::firstWhere('id', $tag_id);
    $articles = Article::where('id', $tag->id)->orderBy('id', 'desc')->paginate($this->per_page);

    return view(
      'themes/' . $this->theme_directory . '/templates/index',
      array_merge($this->data, [
        'tag'   => $tag,
        'articles' => $articles
      ])
    );
}

There is a many-to-many relationship between articles and tags. I have an article_tag pivot table:

In the Tag model I have:

class Tag extends Model
{
   use HasFactory;

   protected $fillable = ['name'];

   public function article()
   {
       return $this->belongsToMany(Article::class);
   } 
}

To the Article model I have added the tags() method

public function tags()
{
    return $this->belongsToMany(Tag::class)->as('tags');
}

The problem

The /tag/1 displays only one article and that article does not contain a tag with the id of 1.

Questions:

  1. Where is my mistake?
  2. What working solution requires minimal change in the current code?
Share Improve this question edited 2 days ago Shadow 34.2k10 gold badges63 silver badges74 bronze badges asked 2 days ago Razvan ZamfirRazvan Zamfir 4,6167 gold badges47 silver badges282 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 4

It seems that the problem is that you take the article using the tag id, and do not check whether this tag is attached to the article where('id', $tag->id)

Try using whereHas in the articles query:

$articles = Article::whereHas('tags', function (Builder $query) use ($tag) {
  $query->where('id', $tag->id);
})->orderBy('id', 'desc')->paginate($this->per_page);

https://laravel.com/docs/8.x/eloquent-relationships

Where is my mistake?

Your issue is with this this line -->

$articles = Article::where('id', $tag->id)->orderBy('id', 'desc')->paginate($this->per_page);

Here you are retrieving the articles where article id is same as tag id.

Solution:

Use the many-to-many relationship that you have defined on the Tag model. You can retrieve the articles using the relationship like this like this: $tag->article.

So your full code for the tag method in the ArticleController:

public function tag($tag_id)
{
    $tag   = Tag::firstWhere('id', $tag_id);
    $articles = $tag->article->orderBy('id', 'desc')->paginate($this->per_page);

    return view(
      'themes/' . $this->theme_directory . '/templates/index',
      array_merge($this->data, [
        'tag'   => $tag,
        'articles' => $articles
      ])
    );
}
发布评论

评论列表(0)

  1. 暂无评论