Bogey's avatar
Level 1

Eloquent relationship is not working

I have the following in my index function of my controller

public function index()
{
    $posts = Blog::inRandomOrder()
        ->with(['tags'])
        ->limit(3)
        ->get(['post_title','post_context','post_slug']);

    return view('welcome', [
        'posts' => $posts,
        'home' => true
    ]);
}

My Blog model has the following relationship set up

public function tags()
{
    return $this->belongsToMany(Tags::class, 'tags_posts');
}

And my tags model has the following relationship set up

function blog()
{
    return $this->belongsToMany(Blog::class, 'tags_posts');
}

And everything works in the show function of my controller

public function show($post_slug)
{
    $blog = Blog::where('post_slug', $post_slug)->firstOrFail();
    
    return view('blog.post', [
        'post'              => $blog,
        'tags'              => $blog->tags()->get(['tag_name']),
        'extendPageTitle'   => $blog->post_title,
        'blog'              => true
    ]);
}

In the blog/post-slug-1 the tags are displayed, but when I try to combine the tags with eloquent in my index function of my controller, the tags collection is added to the object, but it's empty, even though each post has 2 tags associated with it.

Than in my view I've put the following code inside the foreach loop

<pre>{{  print_r($post->tags) }}</pre>

And that is giving me the following for each blog post

Illuminate\Database\Eloquent\Collection Object
(
    [items:protected] => Array
        (
        )

    [escapeWhenCastingToString:protected] => 
)
1
0 likes
3 replies
Bogey's avatar
Level 1

The issue is with the column names...

public function index()
{
    $posts = Blog::inRandomOrder()
        ->with(['tags'])
        ->limit(3)
        ->get();

    return view('welcome', [
        'posts' => $posts,
        'home' => true
    ]);
}

Removing the ['post_title','post_context','post_slug'] from the get() function seems to have fixed it. Now I wish it was just an array with the two tags rather than an object...

So my next question, is there a way to get just the tags in an array rather then the entire collection?

DhPandya's avatar
DhPandya
Best Answer
Level 12

@bogey While using the select statement, you must provide the column name with which the relationship is connected with tables.

->get(['post_title','post_context','post_slug','blog_id'])

To convert the collection to an array, you can use

$blog->tags->toArray()
1 like
Bogey's avatar
Level 1

@DhPandya Thank you, all that did the trick. I've also added the following into the view

The index function in my controller now looks like the following

public function index()
{
    $posts = Blog::inRandomOrder()
        ->with(['tags' => function ($query) {
            $query->select('tag_name');
        }])
        ->limit(3)
        ->get(['id', 'post_title', 'post_context', 'post_slug', 'post_image']);

    return view('welcome', [
        'posts'     => $posts,
        'home'      => true
    ]);
}

And in my view I'm doing the following to get the array that I want

$tags = array_column($post->tags->toArray(), 'tag_name');

And that gives me a nice workable array for my use-case.

Array
(
    [0] => testing
    [1] => blog
)

Please or to participate in this conversation.