How to get relation of relation Count in laravel? - php

i have laravel models
Category: id,name
public function posts(){
return $this->hasMany(PostCategory::class,'category_id','id');
}
PostCategory : post_id, category_id
public function post(){
return $this->belongsTo(Post::class,'post_id');
}
POST: id, ..so on
public function solutions(){
return $this->hasMany(PostSolution::class,'post_id','id');
}
I need to get count of all posts fall under a category and also solutions under one category.. there is no direct relation of category and solution so how to get count of solutions in one category.
$categories = Category::withCount('posts')->get();

I think use hasManyThrough relation
// Category Class
public function solutions()
{
return $this->hasManyThrough(PostSolution::class, Post::class);
}
// Then get the data in the same old manner
$categories = Category::->withCount('posts')->get();
I hope this will help

Related

Eloquent: filter only rows which has related “children” rows

I want to filter only those categories which have at least one product. I write Category::with('products')->… but how do I filter out those empty categories? Those with no product?
app\Category.php:
class Category extends Model {
// ...
public function products() {
return $this->hasMany('App\Product');
}
// ...
}
app\Http\Controller\CategoriesController.php:
function getIndex() {
$categories = Category::with('products')->get();
return view('categories.index', compact('categories'));
}
You can use has in it
$users = Category::has('products')->get();
// only Categories that have at least one product are contained in the collection
has() is to filter the selecting model based on a relationship. So it acts very similarly to a normal WHERE condition. If you just use has('relation') that means you only want to get the models that have at least one related model in this relation.
I have found solution..
There’s an app function for that: has().
app\Http\Controller\CategoriesController.php:
function getIndex() {
$categories = Category::with('products')->has('products')->get();
return view('categories.index', compact('categories'));
}

Sending posts with a specific category to the view in Laravel

I am making a blog in Laravel Framework. I want to send posts to the frontend view that have a specific category. How can i do this when i have a separate category table that is connected to the posts table?
For example, my posts table has a category_id that is connected to the category table.
Post model:
public function category(){
return $this->belongsTo('App\Category');
}
Category model:
public function posts(){
return $this->hasMany('App\Post');
}
Now, how can i send posts to the view, but only posts that have a specific category, for example "Archive"?
I know it should be something like:
public function index()
{
$rows = Post::notdeleted()->get();
return view('admin.posts.index', compact('rows'));
}
but i dont know how to get the category since it is a category_id 1 in posts table and "archive" in category table.
I think you want to filter the post by category name.
public function index(){
// For example Archive
$categoryName= request()->get('category_name');
$posts = Post::whereHas('category',function($query) use ($categoryName){
$query->where('name','like',"%{$categoryName}%");
});
return view('admin.posts.index', compact('posts'));
}
You can do something like this:
public function index()
{
$rows = Post::whereHas('category',function($q){
$q->where('category_name','archive');
})->get();
return view('admin.posts.index', compact('rows'));
}

Retrieving data by other field than id in has many relations

I have a has many relation between models: post and category in laravel application. I've defined these relations as:
public function category() {
return $this->belongsTo('artSite\category');
}
public function posts() {
return $this->hasMany('artSite\post');
}
Now I'm trying retrieve posts belonging to the particular category which are derived in http request:
Route::get('posts/categories/{categoryName}','postsViewController#showPostGivenCategory')
Below I show my controller function (it does work fine!):
public function showPostGivenCategory($categoryName) {
$category = category::where('category_name','=',$categoryName)-first();
$posts = category::find($category->id)->posts;
return view('pages.homePage')->with('categories',$categories)with('posts',$posts);
}
In this solution I'm creating 2 queries. Is any possible way to create 1 query to retrieve posts of particular category in has many relation?
Something like that doesn't work:
$posts = category::where('category_name','=',$categoryName)->posts;
Could someone help me with this problem? I would be very grateful, greetings.
we can get rid of the second line :
$posts = Category::find($category->id)->posts;
So You can say :
$posts = Category::where('category_name','=',$categoryName)->first()->posts;

Calling a list of posts based on category

Im trying to call a list os posts based on a category, but it isnt working, is giving me the error:Non-static method App\Category::posts() should not be called statically, assuming $this from incompatible context.
I already tried calling from both sides, going threw the post model methdos or categories, but same error message. Can figure out what im doing wrong.
Database:
Posts:
-id;
-title;
-text;
Categories:
-id;
-name;
-internal_name;
category_post:
-id;
-post_id;
-category_id
Controller:
public function categoryPostList($category)
{
$category = Category::posts()->where('internal_name',$category)->first();
$posts = Post::categories()->where('category_id',$category->id)->get();
dd($posts)
}
Model Post:
class Post extends Model
{
public function categories()
{
return $this->belongsToMany(Category::class);
}
}
Model Category:
class Category extends Model
{
public function posts()
{
return $this->belongsTo('App\Post');
}
}
First of all if relationship is many to many (you're using pivot table) your relation should be belongsToMany(), but not belongsTo().
To load relation You should use with() method. For example, if you want to load one category with all it's posts:
Post::where('category_id', $category->id)->with('categories')->first();
You can use whereHas as:
$category = Category::where('internal_name',$category)->first();
$posts = Post::whereHas('categories', function($q) use($category) {
$q->where('category_id',$category->id);
})->get();
Or
$category = Category::where('internal_name',$category)->first();
$posts = $category->posts;
The whereHas method is used to put "where" conditions on your has
queries.

Laravel relations

I am creating a basic forum just so I have something meaningful to do while learning Laravel.
So just like every forum is organized, on the main page i would like to have a list of categories and their subcategories, a total count of posts in every subcategory while also a link to latest post
So relationship is nested hasMany:
Category -> has Subcategories -> has Threads -> has Posts.
In controller method I have
$cat = Category::with('subcategory')->get();
return View::make('forum.index', compact('cat'));
and this works for basic list of categories and subcategories but I can't figure out the rest.
This sure doesnt work
Category::with('subcategory')->with('threads')->with('posts')->get();
since relation between them is not set. Looking at Laravel docs, there is hasManyThrough relation. Is that a solution?
class Category extends Eloquent {
public function subcategory() {
return $this->hasMany('Subcategory');
}
public function posts() { // not sure about this cause it doesnt work
return $this->hasManyThrough('Post', 'Thread');
}
}
And on top of that how do I get posts->count() for every subcategory? Is it possible to have it split? Chaining could get complicated..
EDIT
Table columns are
Categories
id | title
Subcategory
id | title | category_id
Threads
id | title | subcategory_id | user_id
Posts
id | title | body | thread_id | user_id
EDIT 2
What would be the code for grabing only latest post? This doesnt work
$data = Category::with('subcategories.threads')->with(array('posts' => function($query)
{
$query->take(1);
}))->get();
You have setup only one relation that works and that is:
class Category extends Eloquent {
public function subcategory() {
return $this->hasMany('Subcategory');
}
}
Declare other relationships in other models:
class Subcategory extends Eloquent {
public function threads() {
return $this->hasMany('Thread');
}
}
class Thread extends Eloquent {
public function posts() {
return $this->hasMany('Post');
}
}
Once you have declared relationships then you may use:
$categories = Category::with('subcategory.threads.posts')->get();
Since the one Category has many subcategories so use the plural name for subcategories instead of subcategory in your Category model, so for example, you may use:
class Category extends Eloquent {
public function subcategories() {
return $this->hasMany('Subcategory');
}
}
Then also:
$categories = Category::with('subcategories.threads.posts')->get();
All relationships will be retrieved as nested object collections. For example:
$categories->subcategories; // Will be a collection of Subcategory models
$categories->subcategories->threads // Will be a collection of Thread models
$categories->subcategories->threads->posts // Will be a collection of Post models
You may declare a hasManyThrough relationship between Subcategory and Post using something like this:
class Subcategory extends Eloquent {
public function threads() {
return $this->hasMany('Thread');
}
public function posts() {
return $this->hasManyThrough('Post', 'Thread');
}
}
Also, you may build a relationship between Category and Thread through Subcategory.
I have
QuestionCategory and Questions['category_id'] and ItemsOfQuestion['question_id']
This Code has Work for my I hope that is useful for you
$categories=ExamCategory::with(['question' => function ($query) use($exam){$query->where('exam_id','=',$exam->id)->with('Items');}])->get();

Categories