Alan Godoi
Alan Godoi

Reputation: 667

Laravel Collection get one of values by key

I'm new to Laravel and I'm trying to get one of the values in one collection by one ID retrieved from another collection.

My function returns 2 Collections:

public function index()
{
    $category = BlogCategory::all(['id', 'name']);        
    $post = BlogPost::orderBy('id', 'desc')->take(14)->get();
    return view('blog.index', ['posts' => $post],  ['categories' => $category]);
}

In a foreach loop I'm getting values from collections:

    @foreach($posts as $post)
     @if($loop->iteration > 2)
        <div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
          <a href="#">
             <img src="#" alt="">
             <p class="post-category">{{ $categories->get($post->category_id) }}</p>
             <h5 class="post-title">{{ $post->title }}</h5>                        
          </a>
         </div>
      @endif
     @endforeach

I'm partially getting the result as you can see in the image below, but I want to get only the name.

Example Result

Here is the code that I'm trying to figure out {{ $categories->get($post->category_id) }}

If there is a better or correct way to do it, let me know.

Blog Posts migration:

public function up()
{
    Schema::create('blog_posts', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('title');
        $table->longText('content');
        $table->mediumText('slug');
        $table->bigInteger('author_id')->unsigned();
        $table->bigInteger('category_id')->unsigned();
        $table->timestamps();
        $table->foreign('author_id')->references('id')->on('blog_authors');
        $table->foreign('category_id')->references('id')->on('blog_categories');
    });
}

Upvotes: 1

Views: 842

Answers (4)

Joseph
Joseph

Reputation: 6269

It could be optimized, first, you need to make relation one to many from categories to posts

first: make sure that you have in posts migrations category_id column

Second: Open Category Model and write this method this will allow you to fetch posts that belong to the category

public function posts(){
   return $this->hasMany(\App\Post::class);
}

Third: open shop model and write this method this will allow you to fetch category that belongs to the post

public function catgeory(){
   return $this->belongsTo(\App\Category::class);
}

Finally: you will edit your view like this one

@foreach($posts as $post)
    <div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
      <a href="#">
         <img src="#" alt="">
         <p class="post-category">{{ $post->category->title }}</p>
         <h5 class="post-title">{{ $post->title }}</h5>                        
      </a>
     </div>
 @endforeach

and of course, you wouldn't call categories in your controller anymore

public function index()
{        
  $post = BlogPost::orderBy('id', 'desc')->take(14)
          ->with('category')->get();
  return view('blog.index', ['posts' => $post]);
}

Upvotes: 1

dparoli
dparoli

Reputation: 9161

You should put in place the relationships between BlogPost and BlogCategory models, seen that you already have a category_id field in BlogPost model, i.e.:

in BlogPost Model:

public function category(){
   return $this->belongsTo(\App\BlogCategory::class);
}

in BlogCategory Model:

public function posts(){
   return $this->hasMany(\App\BlogPost::class);
}

Next you can eager load categories with the $posts in your controller with only two queries:

public function index()
{        
    $posts = BlogPost::with('category')->orderBy('id', 'desc')->take(14)->get();
    return view('blog.index', compact('posts'));
}

Then in your view you can access each $post->category object directly because eager loaded in the controller:

@foreach($posts as $post)
 @if($loop->iteration > 2)
    <div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
      <a href="#">
         <img src="#" alt="">
         <p class="post-category">{{ $post->category->name }}</p>
         <h5 class="post-title">{{ $post->title }}</h5>                        
      </a>
     </div>
  @endif
 @endforeach

Upvotes: 1

Thamer
Thamer

Reputation: 1954

this line $categories->get($post->category_id) return for you an array of category, so the solution for you here is just like bellow:

{{ $categories->get($post->category_id)['name'] }}

Upvotes: 0

Luis jorquera
Luis jorquera

Reputation: 59

Maybe it better use a relation to drive this situation. You can load in the controller the data in this way.

In the Model Post:

function categories(){
return $this->belongsToMany('App\BlogCategory')->select(array('id', 'name');
}

Maybe is hasOne -> the relationship if you don't have a table pivot...

In the Controller:

    public function index()
{     
    $data['posts'] = BlogPost::orderBy('id', 'desc')->take(14)->with('categories')->get();
    return view('blog.index', $data);
}

In the View:

@foreach($posts as $post)
     @if($loop->iteration > 2)
        <div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
          <a href="#">
             <img src="#" alt="">
             <p class="post-category">{{ $post->categories->name }}</p>
             <h5 class="post-title">{{ $post->title }}</h5>                        
          </a>
         </div>
      @endif
     @endforeach

Upvotes: 0

Related Questions