Distinct pivot results with Eloquent - laravel

Inside my Laravel project, I'm printing out all the business cards of my contacts.
In the contact model I have:
public function organizations()
{
return $this->belongsToMany('Organization')->withPivot('ContractStatus')->withTimestamps();
}
So in that way, I can show all the companies the contact is still working for.
In the footer of my contacts overview page, I want to print out all the associated companies logo's for that particular search query.
But something like this:
#foreach($contacts as $key => $value)
#foreach($value->organizations as $organization)
#endforeach
#endforeach
Will print duplicated company logo's as soon as the search results contains 2 contacts that both work for the same company.

If you want to list a distinct collection of a collection of contacts, then don't use relation, but whereHas:
$contactsIds = $contacts->modelKeys();
$organizations = Organization::whereHas('contacts', function ($q) use ($contactsIds) {
$q->whereIn('contacts.id', $contactsIds);
})->get();
Another way would be this trick, in case you in fact need to load the relation:
$organizations = null;
$contacts = Contact::with(['organizations' => function ($q) use (&$organizations) {
$organizations = $q->get();
}])->get();
$organizations = $organizations->unique();
This will load the relation as usually and also run additional query and assign its result to $organizations.

In the controller action generate a new Collection with the organizations:
$uniqueOrganizations = new Collection();
foreach($contacts as $contact)
$uniqueOrganizations->merge($contact->organizations);
Then pass it to the view, to show all the different organizations
#foreach($uniqueOrganizations as $org)
//show org logo
#endforeach

Related

API filtering with pivot table

I'm using laravel 7 and i've made an API to fetch data with a VUE component.
I want to filter restaurants based on their type of food. So if i query "pizza" i want to show only restaurants that make pizza.
getTypes is a many to many relation.
public function restaurants(Request $request)
{
$ricerca = $request->input('query');
$users = Restaurant::with(array('getTypes' => function ($query) use ($ricerca) {
$query->where('name', "LIKE", "%" . $ricerca . "%");
}))->get();
return response()->json($users);
}
I tried this, but this way i don't have access to other genres, if a restaurant make pizza and meat, i don't see meat anymore.
Any advice?
create a many to many relation with restaurant and pizza.
get an array which restaurant make pize,
$array = [];
or simple var
$array = $request('query');
and put this array in query.
$data = Project::whereHas('restorant_pizza', function ($q) use ($array) {
$q->whereIn('restorant_pizza.pizza_id', $array);
})->get();
I think this idea will help you

Join tables in Laravel Eloquent method

How to write this code in eloquent method ?
$product = DB::table('products')
->join('purchase', 'products.id', '=', 'purchase.id')
->join('sales', 'purchase.id', '=', 'sales.id')
->select('sales.*', 'purchase.*','products.*')
->get();
Create model Product and add one to many relationship with Purchase in Product model.
public function purchases()
{
return $this->hasMany('App\Models\Purchase');
}
Create model Purchase and add one to many relationship with Sale in Purchase model.
public function sales()
{
return $this->hasMany('App\Models\Sale');
}
Create model Sale.
You can retrieve data using following statement.
$products = Product::with('purchases.sales')->get();
Note: I am assuming the relationship as one to many you can also declare as per your data, also you can define one to many inverse relationship, please refer to laravel docs https://laravel.com/docs/8.x/eloquent-relationships#one-to-many.
You will get purchases and sales data in different key so you can use below syntax to loop over it.
foreach ($products as $product) {
foreach ($product->purchases as $purchase) {
//Purchase data for current product
foreach($purchase->sales as $sale){
//Sale data for current purchase
}
}
}

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'));
}

Access relation in forelse on the same model - laravel

i have a question about accessing relation in laravel model. I have category model which has relation to translation model and category model(same model/itself - one category can be displayed in other categories using pivot table CategoryToCategory):
category model:
public function childCategories(){
return $this->hasManyThrough('App\Models\Category',
'App\Models\CategoryToCategory',
'id_parent_category',
'id',
'id',
'id_category');
}
public function translation($locale = null)
{
if ($locale == null) {
$locale = \App::getLocale();
}
return $this->hasOne('App\Models\CategoryLanguage', 'id_category', 'id')->where('locale', '=', $locale);
}
Now i take current category + translation + child categories:
$category = Category::with('translation', 'childCategories')->active()->where('id', $id)->first();
And display all childs names:
#forelse($category->childCategories as $category)
{{ $category->translation->name }}
#endforelse
I works but each child category makes another query to get translation(it's not loaded for elements in forelse). So how to load relation "translation" in category model which is foreaching loaded relation?
I could query model CategoryToCategory to get all child categories + load translation for that model and result be the same:
$categories = CategoryToCategory::with('translation')->where('id_parent_category', $id)->get();
And there will be one query for translations. Still i'm curious about using first solution instead query categoryToCategory.
Any ideas?
Have a nice day!
To eager load a distant relationship you can use the dot notation like so:
$category = Category::with('translation', 'childCategories.translations')
->active()
->where('id', $id)
->first();
This is known as "nested eager loading" and is referenced in the docs here:
https://laravel.com/docs/5.8/eloquent-relationships#eager-loading

Laravel: Filter query based on many-to-many relationship

I have two objects, say Post and Tag with a many-to-many relationship.
Based on a collection of tags, I want to select all posts that match either (1) any tag or (2) all tags in the collection.
Is there a simple way to perform these queries in Laravel (preferably using Eloquent)?
You query the tags you want, then you can loop through each tags posts with
$tags = Tag::where('name','=','Laravel 4')->get();
foreach($tags as $tag)
{
foreach($tag->posts as $post)
{
echo $post->name;
}
}
This is assuming you have your relationship and your pivot table setup appropriately.
You can also eager load certain tags based on certain posts...
$posts = Post::where('name','=','Some post name')
->with(array('tags' => function($query)
{
$query = $query->where('tag_name','=','Laravel');
}))->get();
foreach($posts as $post)
{
foreach($post->tags as $tag)
{
echo $tag->tag_name;
}
}

Resources