Laravel 4: selection many to many relation - php

I work on a blog project, which have relation many to many between "posts" and "cats" tables (with pivote table)
posts:
id
title
topic
cats:
id
name
cat_post:
post_id
cat_id
I prepare models correctly,
so, how to select all posts in specific category? I tried:
Cat::with('post')->where('id', '=', '3')->get();
and
Post::with('cat')->whereId('3')->get();
but nothing yet,

This is better/shorter:
$cats = Cat::with('post')->find(3);
Update:
$cats = Cat::with(array('post' => function($q) { // make sure posts not post
$q->orderBy('id', 'desc'); // order the posts
}))->find(3); // No need to order a single model

just found the answer
$cats = Cat::with('post')->whereId(3)->first();
then retrive it in blade:
#foreach($cats->post as $post)
{{$post->title}}
#endforeach
thanks,

Related

Laravel multiple select filter for categories, only get one select as output

In laravel 8, I am filtering blog articles by category. However when I select multiple categories in my select menu. I do get the proper request . for example: articles/category/?category_ids=3,4
But it will only output one selected filter. If I select 2 filters it just selects that next filter as if I only selected that one. (I also use Axios but the request is done proper, so its in my Controller)
Here is my code I tried:
$data['articles'] = Article::whereHas('categories', function ($query) use($category_ids){
$query->whereHas('category_id', '=', $category_ids)->where('premium',0);
;})->get();
I also tried:
$data['articles'] = Article::whereHas('categories', function ($query) use($category_ids){
$query->whereIn('category_id', [$category_ids])->where('premium',0);
;})->get();
So how do I get to query both or more category id's ?
I am using a pivot table:
Articles can have many Categories
Categories can have many Articles
I use article_category as a pivot table
When checking for relationship existence in many-to-many relations, the check is still to be done against the id in the categories table.
Try this
$category_ids = collect(explode(',', $request->category_ids))
->map(fn($i) => trim($i))
->all();
$data['articles'] => Article::whereHas('category', fn($query) =>
$query->whereIn('categories.id', $category_ids)
->where('categories.premium', 0)
)->get();
You can explode the categories and then make the query like this.
$categories = explode(',',$request->categories);
$data['articles'] = Article::whereHas('categories', function ($query) use($categories){
$query->whereIn('category_id', $categories)->where('premium',0);
})->get();

Laravel gather data by relational id

In my application, I have a posts table, categories tables and category_post table as a post and category have a many to many relationship.
I want to get all posts with their attached categories, but also group them together as on my frontend I want to be a loop over an object and show a list like this,
Cooking
Post Number 1
Post Number 3
Post Number 4
Music
Post Number 2
Post Number 5
Languages
Post Number 6
Post Number 7
I know in my controller I can do this,
$posts = Post::with('categories')->get();
But I don't how to groupBy a relational attribute or if I can structure the returned data in such a way that I can loop over it to form the list below.
you can get the data from db and then group them the way you want:
$posts = Post::with('categories')->get();
$result = $posts->groupBy([
'categories',
function ($item) {
return $item['category_name'];
},
], $preserveKeys = true);
more details about grouping by relation fields in:
https://laravel.com/docs/7.x/collections#method-groupby
As per given your table: posts and categories tables are the main tables and category_post table is a pivot table which contains the relation between posts and categories table :
So, Your relation should be posts->category_post->categories
$posts = Posts::with('category_post')->get();
$grouped = $posts->groupBy('category_post.category_id');
The category_post also related to the categories table for categories data.
In category model you cam setup and belongsToMany relation like the following
function posts()
{
return $this->beongsToMany(Post::class, 'category_post', 'category_id', 'post_id');
}
Then do as Arun A S suggested.

Get the quantity and name of an object between related tables

I'm taking data from my Animals table, which has a relationship with the Categories table. My problem is that I need to count how many products per category are registered.
Doing a search here on Stackoverflow, I started using the code below that is returning the quantity of animals per category ([Animal, quantity]).
$data = DB::table('animals')
->select(
DB::raw('category_id as category'),
DB::raw('count(*) as number'))
->groupBy('category')
->get();
$array[] = ['Name', 'Quantity'];
foreach($data as $key => $value)
{
$array[++$key] = [$value->category, $value->number];
}
$cat = json_encode($array);
dd($cat);
Using "dd", I see that the data below is correct, but the category_id is coming, I am not sure how to get this id and put the category name for that id.
"[["Category","Quantity"],[1,10],[2,14],[3,30],[4,26],[5,1]]"
Example: [2,14] this refers to category_id 2 which has the name: mammal. So I would have 14 animals registered in the mammal category.
I would like the result to be like this:
"[["Category","Quantity"],[birds,10],[mammals,14],[reptiles,30],[amphibians ,26],[fish,1]]"
How can I handle this id related to the category name?
Join your category table and get name from there, I suppose it should look like:
$data = DB::table('animals')
->join('category', 'animals.category_id', '=', 'category.id')
->select(
DB::raw('category.id as category_id'),
DB::raw('category.name as category_name'),
DB::raw('count(*) as number'))
->groupBy('category')
->get();
More about joins
You can use the method "withCount" from the model, it helps you to count the number of results from a relationship
$posts = App\Post::withCount('comments')->get();
foreach ($posts as $post) {
echo $post->comments_count;
}
See the documentation https://laravel.com/docs/7.x/eloquent-relationships#counting-related-models

Laravel group by foreign key

I have three models
Project
Category
Drawing
The relationship between them is as follows
Drawing belongs to a category
Drawing also belongs to a project
Drawing table:
id
name
project_id
category_id
Project Table :
id
name
Category Table :
id
name
I want to print all the drawings of a particular project grouped by category name like so :
CATEGORY X
* Drawing 1
* Drawing 2
CATEGORY Y
* Drawing 3
* Drawing 4
I do not want to print a category if there is no drawing for this particular project in it.
this is what im stuck at :
Project->drawings()->groupBy('category_id');
Thank you in advance
To get the output you want, it'd be easier to come at the problem from the direction of categories.
The following will find all categories, with drawings belonging to the specified $projectId, but only those categories that actually have one or more drawings.
$projectId = 123;
$projectScope = function ($query) use ($projectId) {
return $query->where('project_id', $projectId)
});
$categories = Category::with(['drawings' => $projectScope])
->whereHas('drawings', $projectScope)
->get();
You can do it like
$categories = Category::whereIn('id',$project->drawings()
->groupBy('category_id')
->pluck('category_id')
)->get();
Now, Iterate over $categories like
#foreach($categories as $category)
// display category name as {{$category->name}}
#foreach($category->drawings() as $drawing)
// display drawings as {{$drawing->name}}
#endforeach
#endfoeach
Hope you understand.

Laravel eager loading - relationship query

Say I have this 3 tables Blog, Post, Comment which has corresponding models Blog, Post, Comment.
No here is the relation between them:
Blog has many Post, posts()
Post belongs to Blog, blog()
Post has many Comment, comments()
Comment belongs to Post post()
Now I want to execute some query like this:
Blog::with(array('posts.comments' => function($q)
{
//query Post columns
})->find(1);
As I know the $q is corresponding to the Comment table. Is there any way to query the Post table?
Query nested relation like this:
$blog = Blog::with(['posts' => function ($q) {
$q->where('column','value'); // query posts table
}, 'posts.comments' => function ($q) {
$q->where('commentsColumn','anotherValue'); // query comments table
}])->find(1);
Eloquent will load posts accordingly, only then will it fetch the comments for those posts.

Categories