I have categories related to each other in a tree. Each category hasMany children. Each end category hasMany products.
The products also belongsToMany different types.
I want to eager load the categories with their children and with the products but I also want to put a condition that the products are of a certain type.
This is how my categories Model looks like
public function children()
{
return $this->hasMany('Category', 'parent_id', 'id');
}
public function products()
{
return $this->hasMany('Product', 'category_id', 'id');
}
The Product Model
public function types()
{
return $this->belongsToMany(type::class, 'product_type');
}
In my database I have four tables:
category, product, type, and product_type
I've tried eager loading like so but it loads all the products and not just the ones that fulfil the condition:
$parentLineCategories = ProductCategory::with('children')->with(['products'=> function ($query) {
$query->join('product_type', 'product_type.product_id', '=', 'product.id')
->where('product_type.type_id', '=', $SpecificID);
}]])->get();
Instead of the current query, try if this fits your needs.
(I modified my answer as follows with your comment)
$parentLineCategories = ProductCategory::with([
'children' => function ($child) use ($SpecificID) {
return $child->with([
'products' => function ($product) use ($SpecificID) {
return $product->with([
'types' => function ($type) use ($SpecificID) {
return $type->where('id', $SpecificID);
}
]);
}
]);
}
])->get();
You can use whereHas to limit your results based on the existence of a relationship as:
ProductCategory::with('children')
->with(['products' => function ($q) use($SpecificID) {
$q->whereHas('types', function($q) use($SpecificID) {
$q->where('types.id', $SpecificID)
});
}])
->get();
Related
I have products which have also comments. This comments can be voted and comments can also have child comments.
Now I want to sort these comments by date, amount of likes and amount of child comments.
Before I show you my tries I will show you my code:
Product.php (Model)
namespace App;
class Product extends Model
{
/**
* #Protected_variables
*/
protected $with = ['comments', 'user'];
/**
* #Relationships
*/
public function user()
{
return $this->belongsTo('App\User');
}
public function comments()
{
return $this->morphMany('App\Comment', 'commentable');
}
}
As you can see, I already tell Laravel with the variable $with to load comments and user always when loading a product.
ProductController.php
public function show(Product $product, Request $request)
{
if($request->has('sorting') && in_array($request->sorting, ['Beliebtesten', 'Diskutiertesten', 'Neusten'])){
if($request->sorting == 'Neusten'){
$product->load(['comments' => function ($query) {
$query->orderBy('created_at', 'desc');
}]);
}else if($request->sorting == 'Diskutiertesten'){
$product->load(['comments.children' => function ($query) {
$query->orderBy('published_date', 'asc');
}]);
}else{
$product->load('comments')->get()->sortByDesc(function($product)
{
return $product->likes->count();
});
}
return response()->json([
'product' => $product
]);
}else{
$product->load('comments');
return response()->json([
'product' => $product
]);
}
}
So, I have two questions now:
Do I even need $product->load('comments')? - Because I have figured out when I just pass the $product without executing $product->load('comments') I also have the comments loaded... Looks like I don't need it. Is that right?
How can I sort the comments by amount of likes (rows, because you can only upvote) and by amount of child comments (rows)?
This is what I have tried so far (all not working for me):
1.
$product->load('comments')
->withCount('likes')
->orderBy('likes_count','DESC')
->get();
$product->loadCount('comments');
$product->orderBy('comments_count', 'desc');
1:
$comments = $product->comments;
$comments->loadCount('likes');
$comments->sortByDesc('likes_count');
2:
$product->loadCount('comments');
$product->sortByDesc('comments_count');
I have a model customer and it has many projects. I want to find projects count without including its object.
Customer model includes:
public function numberOfProjects()
{
return $this->hasMany(Project::class)->count();
}
Query in my controller:
$customers = Customer::where(['is_active'=>1])
->with(['customerContactInformation'=> function ($query) {
$query->where('is_active',1);
}, 'numberOfProjects'])
->skip($skip)->take(10)
->get();
Its giving me error:Call to a member function addEagerConstraints() on integer
Try this
Customer Model
public function numberOfProjects()
{
return $this->hasMany(Project::class);
}
Controller
$customers = Customer::where(['is_active'=>1])
->with(['customerContactInformation'=> function ($query) {
$query->where('is_active',1);
}])
->withCount('numberOfProjects') //you can get count using this
->skip($skip)
->take(10)
->get();
That should be work
$customers = Customer::withCount('numberOfProjects')->get();
WithCount on the particular status
$customers = Customer::withCount([
'numberOfProjects',
'numberOfProjects as approved_count' => function ($query) {
$query->where('approved', true);
}
])
->get();
class Tutorial extends Model
{
function chapters()
{
return $this->hasMany('App\Chapter');
}
function videos()
{
return $this->hasManyThrough('App\Video', 'App\Chapter');
}
}
And then you can do:
Tutorial::withCount(['chapters', 'videos'])
Counting Related Models
If you want to count the number of results from a relationship without actually loading them you may use the withCount method, which will place a {relation}_count column on your resulting models. For example:
$posts = App\Post::withCount('comments')->get();
foreach ($posts as $post) {
echo $post->comments_count;
}
You may add the "counts" for multiple relations as well as add constraints to the queries:
$posts = App\Post::withCount(['votes', 'comments' => function ($query) {
$query->where('content', 'like', 'foo%');
}])->get();
echo $posts[0]->votes_count;
echo $posts[0]->comments_count;
You may also alias the relationship count result, allowing multiple counts on the same relationship:
$posts = App\Post::withCount([
'comments',
'comments as pending_comments_count' => function ($query) {
$query->where('approved', false);
}
])->get();
echo $posts[0]->comments_count;
echo $posts[0]->pending_comments_count;
If you're combining withCount with a select statement, ensure that you call withCount after the select method:
$posts = App\Post::select(['title', 'body'])->withCount('comments');
echo $posts[0]->title;
echo $posts[0]->body;
echo $posts[0]->comments_count;
I am using Lumen and it's Models with model's relationships. What I am trying to do is to get all Categories and count how many posts every category has, which is working fine. However, I do not want it to count those which creator_id == $current_user_id, how should I do it?
This is in my Post class:
public function user(){
return $this->belongsTo(User::class);
}
public function category(){
return $this->belongsTo(Category::class);
}
And this is in my Category class:
public function posts(){
return $this->hasMany(Post::class);
}
And this is my query:
public function getCategories($user_id){
$categories = Category::withCount('posts')->get();
return new JsonResponse(['categories' => $categories]);
}
So I do not want to count posts that the current user has created.
So the output should be something like this:
{
"categories": [
{
"name": "All",
"posts_count": 0
}]
}
This what I also tried without success:
$categories = Category::where('creator_id', '!=', $user_id)->withCount('posts')->get();
Try using the following line:
$categories = Category::withCount(['posts' => function($query) use($user_id){
$query->where('creator_id', '!=', $user_id);
}])->get();
I have a little query in which I need your help, Please have a look below.
I want to fetch all the data from the products table with some conditions like city, price, Type, category.
I can fetch all the data but I can't fetch the category data from the product model with all other conditions.
Below is my tables and Eloquent relations. I am using Laravel 5.2.
products ->foreign_key('subcategory_id')
subcategories ->foreign_key('category_id')
category
users: ->foreign_key('product_id')
users table columns: ->city, price, product_id
Relations:
User Model:
public function product(){
return $this->hasMany('App\Product');
}
Product Model:
public function subcategory(){
return $this->belongsTo('App\Subcategory', 'subcategory_id');
}
Subcategory Model:
public function product(){
return $this->hasMany('App\Product', 'subcategory_id');
}
public function category(){
return $this->belongsTo('App\Category');
}
Category Model:
public function subCategory(){
return $this->hasMany('App\Subcategory');
}
public function product(){
return $this->hasManyThrough('App\Product', 'App\Subcategory');
}
Here is my query(in ProductsController.php).
$city_id, $category_id, $min_price, $max_price : demo data passed
//fetching city data
$products = Product::whereHas('user', function($query) use($city_id) {
$query->where('city_id', $city_id);
});
//fetching category data (I am not sure about this part)
$products = $products->whereHas('category', function($query) use($category_id) {
$query->where('id', $category_id);
});
//fetching price data
$products = $products->where('price', '>=', $min_price)->where('price', '<=', $max_price);
//sub category filtering
$products = $products->where('subcategory_id', 1);
$products = $products->get()->toArray();
return $products;
Any help would be appreciated. Thanks in Advance.
I think you can use with() method:
Product Model:Add the following method
public function subcategory($category_id){
return $this->belongsTo('App\Subcategory', 'subcategory_id')->with(`category`)->where('category_id',$category_id);
}
Now in Controller, you can check if the product belongs to that category,
$products = $products->subcategory($category_id);
This will get you category data also.
I have a polymorphic model, named FeedItem which is has polymorphic relationships to an Alert and Publication model.
There is also another model, named Category, which the Alert and Publication models have a hasMany relationship to.
FeedItem
public function feedable()
{
return $this->morphTo();
}
Publication
public function feedItem()
{
return $this->morphOne('FeedItem', 'feedable');
}
public function categories()
{
return $this->hasMany(Category::class);
}
Alert
public function feedItem()
{
return $this->morphOne('FeedItem', 'feedable');
}
public function categories()
{
return $this->hasMany(Category::class);
}
I want to be able to get all FeedItems where the feedable models have a given category.
I've tried:
$items = FeedItem::with(['feedable.categories' => function($item) {
$item->whereHas('feedable.categories', function ($q) {
$q->where('categories.name', 'my-category');
})->orderBy('id', 'desc')
->paginate();
However, the issue is that the feedable relation never gets eager loaded, which prevents the categories relationship scoping from being performed.
For example, if I do this:
$items = FeedItem::with(['feedable.categories' => function($item) {
dd('This should be displayed');
$item->whereHas('feedable.categories', function ($q) {
$q->where('categories.name', 'my-category');
})->orderBy('id', 'desc')
->paginate();
The dd() statement is never called.
Can anyone provide a way of doing this sort of query?