Laravel relations doesn't return anything - php

i have problem in laravel eloquent relationships.
there is 2 model in my application: article and category.
article model:
public function category()
{
return $this->belongsToMany('App\Category');
}
category model:
public function article()
{
return $this->hasMany('App\Article');
}
the relation between this tow is hasMany (Category -> article) & belongsToMany (Article -> category).
category will fetch by requested slug using this method at categoryController:
$category = Category::where('slug', '=', $slug)->get();
problem will be shown in view when i want to fetch articles from category and nothhing will return back:
#foreach ($category->article->all() as $article)
{{ $article->name }}
#endforeach
and from #dd($category->article) we will get empty collection:
Collection {#323 ▼
#items: []
}

As #lagbox tried to highlight in a comment, for pivot tables, both relationships should be belongsToMany. Inverse of hasMany is belongsTo.
If one article belongs to many categories, and one category can have many articles, then, ideally, there it should be a many-to-many relationship. Category model should have a belongsToMany relationship with Article model and vice versa. Additionally, there should be a pivot table, article_category. And as many have suggested, you can get articles the belongs to a category by using #foreach($category->articles as $articles)
You can read more about many to many here:
https://laravel.com/docs/5.8/eloquent-relationships#many-to-many

You can use #forelse blade directive like
#forelse ($category->article as $article)
<li>{{ $article->name }}</li>
#empty
<p>No articles</p>
#endforelse
You can check that here

You dont need to write $category->article->all() . $category->article itself will return all articles.
So just use like,
#foreach ($category->article->all() as $article)
{{ $article->name }}
#endforeach
For eager loading articles, you can use
with keyword
$category = Category::with('article')->where('slug', '=', $slug)->get();

Related

i cant display posts' category with manyToMany relationship

i cant display posts' category with manyToMany relationship. i build relationship but can't display it.
// here is my post model
public function getCategory(){
return $this->belongsToMany(Category::class,
'post_categories','id','post_id');
}
// here is my controller
public function Allindex(){
$posts=Post::all();
return view('allposts',compact('posts'));
}
//here is my allposts blade
<div class="media-body">
<h4 class="media-heading">{{$post->pivot['name']}}</h4>
{{$post->created_at}}
</div>
You are passing the wrong param in a model relationship.
public function getCategory(){
return $this->belongsToMany(Category::class,'post_categories','post_id','category_id');
}
Now you can access it as below.
#foreach($post->getCategory as $category)
{{ $category->name }}
#endforeach
Or
{{ $post->getCategory->pluck('name')->implode(',') }}
Laravel is not automatically loading your relationship, the keyword you are looking for is eager loading.
You can eager load relationships with the with method like so:
$posts = Post::with('getCategory')->get();

Pulling all categories and grouping them by parent id

I am working with Laravel data querying and I need a query that is going to group all the children of a parent when I take the categories.
the categories table has a name and a parent_id, the routes of the categories have the parent_id set as null, the query should return every category grouped by parent id and the parent should be the first node of every group.
If you only want to display the categories as parent child somewhere, you do not need to collect them like that, you can make a relationship within the model like
class Category {
public function children()
{
return $this->hasMany(self::class, 'parent_id');
}
public function parent()
{
return $this->hasMany(self::class, 'id', 'parent_id');
}
}
may be it will be one-to-many relationship instead of many-to-many depending on your requirement.
Now you can just get all the parents like
Category::whereNull('parent_id')->get();
or using a scope
Category::parent()->get(); and define the scope in the model
and loop through the parent category like
#foreach ( $categories as $category )
{{ $category->name }}
#foreach ( $category->children as $subCategory )
{{ $subCategory->name }}
#endforeach
#endofreach
and to retrieve parent with children you can use
Category::whereNull('parent_id')->with('children')->get();
or
Category::parent()->with('children')->get();
I have not tested the code, but roughly it will be like this.
contoller
$locations = OurLocation::groupBy('country_id')->with('children')->get();
model
public function children()
{
return $this->hasMany(OurLocation::class, 'country_id','country_id');
}
blade
#foreach($locations as $index=>$location)
#foreach($location->children as $children)
{{ $children->company_name }} <br>
#endforeach
#endforeach
When you get the returned collection from the query, you are able to use the ->groupBy() method where you can specify the field which the results should be grouped by.
Assuming your categories model is Category:
$categories = Category::all()->groupBy('parent_id')->toArray();

How to use eloquent to retrieve a column from another table

I have two tables
product: id|category ...
category: id|name ...
product.category is a foreign key linked to category.id . I am building a basic CRUD and I would like to display all Products in the the product table as well as the name of the category they belong to rather than their category ID. TO do this, while searching the laravel documentation I came across the query builder and I achieved my goal.
public function index()
{
$products = \DB::table('products')
->join('categories', 'products.category', '=', 'categories.id')
->select('*')
->get();
return view('product' ,compact('products'));
}
Under my models for product and category I have created the appropriate relationships.
product.php :
public function category()
{
return $this->belongsTo('App\Category');
}
category.php :
public function products()
{
return $this->hasMany('App\Product');
}
I keep hearing about the power of Eloquent and was wondering how I could achieve a similar result with eloquent and if eloquent is designed for such operations or if the query builder is the right way to go.
Every tutorial online seems to only use the post and comments scenario of getting all comments belonging to a post.
You can use this code
public function index()
{
$products = Product::with('category')->get();
return view('product' ,compact('products'));
}
In blade
#foreach($products as $product)
{{$product->name}}
{{$product->category->name ?? ''}}
//or
#if ($product->category)
$product->category->name
#endif
#endforeach
Also if in project table foreign key is not equal category_id. In your case
public function category()
{
return $this->belongsTo('App\Category', 'category');
}

Laravel 5 - Count the number of posts that are assigned to each category in a blog

I was wondering what the cleanest way was to count the number of posts that are connected to a category in my blog.
Here is how the table relationship is set up.
What I have is a hasMany relationship from the Category to the Post models like this:
In Categories Model
public function blog_posts()
{
return $this->hasMany('App\Http\Models\Blog_Post', 'category_id');
}
And in the Blog_Post Model
public function blog_categories()
{
return $this->belongsTo('App\Http\Models\BlogCategories', 'category_id');
}
In effect all I want to do is be able to return to my view the total number of posts that each category has as shown below. Where x is the number of posts within each category.
cat1 (x)
cat2 (x)
cat3 (x)
It's not hard to count I know however as I only want a count I do not want to also retrieve the records as they are not required and I also do not want to create more queries than is necessary.
I have not completed the view as yet but probably a start would be to pass through the categories in a loop to display each and add the count at the same time?
#foreach ($categories as $category)
{!! $category->name !!} - {!! Count of posts here !!}
#endforeach
Hopefully that is clear(ish)!
Eager load the relation in your controller:
public function index()
{
$categories = Category::with('blog_posts')->get();
return view('categories.index', compact('categories'));
}
You can then use the count() method on the blog_posts relation when looping over categories in your view:
#foreach ($categories as $category)
<li>{{ $category->name }} ({{ $category->blog_posts->count() }})</li>
#endforeach
EDIT: Since Laravel 5.3, you can use withCount() to load counts of relations, i.e.
$categories = Category::withCount('blog_posts')->get();
This will make the count available via a property:
foreach ($categories as $category) {
$blog_posts_count = $category->blog_posts_count;
}
The nicest way to do it with eager loading support I know is to create a separate relation with the post count. Check this out:
public function blog_posts_count() {
return $this->hasOne('App\Http\Models\Blog_Post', 'category_id')
->selectRaw('category_id, count(*) as aggregate')
->groupBy('category_id');
}
public function getBlogPostsCountAttribute() {
if(!array_key_exists('blog_posts_count', $this->relations))
$this->load('blog_posts_count');
$related = $this->getRelation('blog_posts_count');
return $related ? (int) $related->aggregate : 0;
}
Usage is simple:
{{ $category->blog_posts_count }}

Laravel eloquent - One to many relationships (Trying to get property of non-object)

I have "posts" table that has many-to-one relationship with "categories" table. The goal is to show all of posts and their categories.
Tables:
Posts: id, content, category_id, etc
Categories: id,name
Here's my code
Models:
class Posts extends Eloquent
{
public static $table = 'posts';
public function categories()
{
return $this->belongs_to('Categories');
}
}
class Categories extends Eloquent
{
public static $table = 'categories';
public function posts()
{
return $this->has_many('posts');
}
}
My controller
public function get_posts()
{
$posts = Posts::with('categories')->all();
return View::make('admin.posts')
->with('title', 'Posts')
->with('posts', $posts);
}
My view
#foreach($posts as $post)
<tr>
<td>{{ $post->title }}</td>
<td>{{ $post->categories->name }}</td>
<td><small> {{$post->updated_at}} </small></td>
<td>
<button>
{{HTML::link_to_route('edit_post','Edit',array($post->id))}}
</button>
{{Form::open('admin/delete','Delete')}}
{{Form::hidden('id', $post->id)}}
<input type="submit" name="edit_post" value="Delete"/>
{{Form::close()}}
</td>
</tr>
#endforeach
ERROR:
Error rendering view: [admin.posts]
Trying to get property of non-object
I am a newbie, please help me solve this issues
{{ $post->categories->name }} before test is categories exists
Example:
#if( ! empty($post->categories))
<td>{{ $post->categories->name }}</td>
#else
#end if
Aesis.
Just use ::all() instead of ::with(..)->all()
categories is an array as you are using a has_many relationship. There are many categories, hence an array is returned, so to access it you have to index it like an array
the correct solution would be
$post->categories[0]->name
Are you using Laravel 4? First the syntax for declaring relationship is hasMany and belongsTo, in camel case. Check it out in Laravel documentation
In view, check if categories are empty collection, ie., whether post has its category:
#if($post->categories->count())
<td>{{ $post->categories->name }}</td>
...
#endif
By the way, I would use singular form as model class name, like Post and Category instead of plural forms. And in Post class I would define inverse one-to-many relationship with singular form, to show there's only one entry in category table for this given Post.
public function category()
{
return $this->belongsTo('Category');
}

Categories