Laravel - get all items in a parent-category - laravel

I have the following table, called recipe_subcategories:
each recipe can be assigned to one parent category and multiple subcategories.
Currently, I have the following code to get the all recipes within a parent category:
public function recipes(Request $request) {
$id = explode('-', $request->idName)[0];
return Category::where('id',$id)->first()->recipes;
}
The issue is, that if the same recipe belongs to different sub categories in the same parent category, it will return it multiple times.
What's the ideal solution for this issue? The goal is to return all recipes within one parent category (category_id) without duplicates.

You could start on the pivot table, like so:
public function recipes(Request $request)
{
$categoryId = explode('-', $request->idName)[0];
$recipeIds = DB::table('recipe_subcategories')
->where('category_id', $categoryId)
->groupBy('recipe_id')
->pluck('recipe_id');
return Recipe::whereIn('id', $recipeIds)
->get();
}
I'm not sure how to join these as one query.

You can try :
$category = Category::find('id', $categoryId);
$recipes = $category->recipes->unique('category_id');
Note : This will get all recipes and then filter then on collection level, not on DB query level.

Related

Laravel eloquent order by custom attribute

I have a total_views attribute added to my Product model like this
public function getTotalViewsAttribute(){
return (int)$this->views()->sum('count');
}
views() is a relationship on Product like this
public function views()
{
return $this->morphMany(View::class, 'viewable');
}
What I would like to do is order my Product by the total_views. Or in other words to order by the sum of the views() relationship.
I have tries to ->orderBy('total_views') on the query but it doesn't seem to work as expected.
Any help will be highly appreciated.
Eloquent getter can only work, when the query has been executed, therefor your current code is not working. I would always use withCount(), on the query;
$products = Product ::withCount(['views'])->get();
The count would be on a property named views_count;.
foreach ($products as $product) {
$product->views_count; // get view count
}
And also possible to order by the column, as it will be present in the SQL returned by the query.
Product ::withCount(['views'])->orderBy('views_count', 'desc')->get();

Looking up model in Laravel after returning array of objects in Controller

I am trying to do something I've never done before in Laravel and cannot figure out how to do it.
I have the following code in my Controller:
public function show($id)
{
//Get application for drug
$application = PharmaApplication::where('ApplNo', $id)->first();
//Get all products for given application (i.e. the different quantities and forms drug comes in)
$product = PharmaProduct::where('ApplNo', $id)->get();
foreach($product as $product){
$product->ProductNo;
}
//Get Marketing Status for drug
$marketingStatus = DB::table('pharma_marketing_statuses')
->where('ApplNo', $id)
->where('ProductNo', $product->ProductNo)
->get();
//Lookup marketing status Description
$marketingStatusDescription = PharmaMarketingSatusLookup::where('MarketingStatusID', $marketingStatus->MarketingStatusID);
return view('profiles.drug', compact('application', 'product', 'marketingStatus', 'marketingStatusDescription'));
}
I am trying to accomplish the following:
Get the application for a drug - this part of my code works
Return an array of objects for the products (i.e. 7 products that belong to one application). I can do this but get stuck going to the next part.
Next, I have to use the array of objects and search a table with the following columns: MarketingStatusID, ApplNo, ProductNo. I know how to query this table and get one row, but the problem is I have an array that I need to search. I imagine I have to use a loop but don't know where.
Finally, I use the MarketingStatusID to retrieve the MarketingStatusDescription which I will know how to do.
I am also getting an error message that says:
Class 'App\Http\Controllers\profiles\PharmaMarketingSatusLookup' not found
In my Controller, I have use App\PharmaMarketingStatusLookup; so I am not sure why it is searching the Controllers folder
You have a typo in your class
From PharmaMarketingSatusLookup change to PharmaMarketingStatusLookup
App\Http\Controllers\profiles\PharmaMarketingStatusLookup
USE whereIn
use App\PharmaApplication;
use App\PharmaProduct;
use App\PharmaMarketingSatusLookup;
public function show($id)
{
$application = PharmaApplication::where('ApplNo', $id)->first();
$products = PharmaProduct::where('ApplNo', $id)->get();
$productid = array();
foreach($products as $product){
$productid[] = $product->ProductNo;
}
$marketingStatus = DB::table('pharma_marketing_statuses')
->where('ApplNo', $id)
->whereIn('ProductNo', $productid)
->get();
$marketingStatusDescription = PharmaMarketingSatusLookup::where('MarketingStatusID', $marketingStatus->MarketingStatusID);
return view('profiles.drug', compact('application', 'product', 'marketingStatus', 'marketingStatusDescription'));
}

Laravel where condition not working on query WITH relation

i have a simple query that looks like this:
$category = Category::with('translation')
->with(['childCategories' => function ($query) {
$query->active();
}])
->where('id', $id)->first();
Scope and relation:
public function scopeActive($query)
{
return $query->where('active', 1);
}
public function childCategories()
{
return $this->hasManyThrough('App\SupremeShop\Models\Category',
'App\SupremeShop\Models\CategoryToCategory',
'id_parent_category', //category_to_categories
'id', //categories
'id',
'id_category'); // category_to_categories.
}
So i am looking for category, some translations and child categories of given "main" category. And query returns 15 child categories. But in query is scope that should only take active ones and it's not working correctly. When i use dd it shows inactive child categories also. I've tried to remove scope and write simple WHERE but result was the same.
Have somebody any ides why condition is not working properly?
I believe the problem is the column is ambiguous since Category and its relation childCategories are both the same model and share the same table.
The active() scope is getting applied to the parent Category instead of the child Categories.
Try and see if this works
$category = Category::from('categories as c')
->with(['childCategories' => function ($query) {
$query->active();
}])
->where('id', $id)->first();

Filter many to many relationship based on child existence and column value

I've been searching for a while and couldn't find an answer, here's what I have:
1- ShowCategory (id & title)
class ShowCategory extends Model
{
public function shows()
{
return $this->belongsToMany(Show::class, 'category_show');
}
}
2- Show (id, title & active)
class Show extends Model
{
public function categories()
{
return $this->belongsToMany(ShowCategory::class, 'category_show');
}
}
So there's a many to many relationship, what I need is retrieving all ShowCategory elements that has at least one Show related to it, and to filter each ShowCategory->shows by show.active, only return shows that are active
Here's what I'm trying to do:
$categories = ShowCategory::whereHas('shows', function($query) {
$query->where('shows.active', '=', true);
})->get();
It only filters ShowCategory that includes shows and if only one of those shows are active, it returns the category with all shows inside, even if others are not active, I need to filter those who are not active.
What should I do? Thanks in advance
This requires a combination of whereHas() and with(). First, whereHas() will filter the ShowCategory model to those that have an active Show, while the with() clause will limit the results of the relationship to only return active ones:
$categories = ShowCategory::whereHas("shows", function($subQuery) {
$subQuery->where("shows.active", "=", true); // See note
})->with(["shows" => function($subQuery){
$subQuery->where("shows.active", "=", true);
}])->get();'
Note: You should be able to use active instead of shows.active, but depends on if that column is on multiple tables.
Using this query, you will get a Collection of ShowCategory models, each with their active Show models already loaded and available via ->shows:
foreach($categories AS $category){
dd($category->shows); // List of `active` Shows
}
This is what you need.
$categories = ShowCategory::whereHas('shows', function($query) {
$query->whereActive(true);
})->get();
Try, this can be a possible way to retreive related results.
// This will only return ShowCategory which will have active shows.
/* 1: */ \ShowCategory::has('shows.active')->get();
// So, logically this will only have active shows -__-
$showCategory->shows
Laravel allows to extends foreign relation by using this . notation as a condition for retreival.
Update
You should update the \ShowCategory model as
public function shows(){
return $this->belongsToMany(Show::class, 'category_show')->where('active', true);
}

Laravel Eloquent model with counter

I'm trying to count all the files within a category, and I have these two relationships:
public function files() {
return $this->hasMany('App\File', 'category_id','category_id');
}
public function fileCount() {
return $this->files()->selectRaw("category_id, count(*) AS count")
->groupBy('category_id');
}
This gives me a collection of items, where the count attribute could be accessed like this:
$my_category = Category::where("category_id", category_id)->with('fileCount')->get();
$file_counter = $my_category->first()->fileCount->first()->count;
Is it possible to directly attach the count attribute to the $my_category variable? Any suggestions will be appreciated.
You can use withCount() method:
$my_category = Category::where("category_id", category_id)
->withCount(['files' => function($q) {
$q->groupBy('category_id');
})
->get();
This will put files_count attribute into results.
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

Resources