laravel 5 Search related models - laravel

I have two related model.
class Girl extends Model
{
public function target()
{
//return $this->hasOne('App\Target');
return $this->belongsToMany('App\Target', 'girl_target', 'girl_id',
'target_id');
}
}
And
class Target extends Model
{
public function girl()
{
return $this->belongsToMany('App\Girl', 'girl_target');
}
}
How I can find girl model by related target id?
$girls = Girl::where('banned', 0)
->with('target');
$targets=$seachSettings->target()->get();
if($targets!=null){
foreach ($targets as $item) {
// $girls->target()->array_where();
$girls->target()->where('girl_target','target_id',$item->id);
}
}
I want get only models where related targets with id from my $targets array.

You need to use whereHas() method
$girls = Girl::whereHas('target', function ($query) use($item) {
$query->where('id', $item->id);
})->where('banned', 0)->with('target');

define the relationship between Girl and Target
class Girl extends Model
{
public function target(): HasMany
{
return $this->hasMany('App\Target', 'foreign_key', 'local_key');
}
}
class Target extends Model
{
public function girl(): BelongsTo
{
return $this->belongsTo('App\Girl', 'foreign_key', 'local_key');
}
}
and then if u want to get girl targets, just call
$targets = Girl::find(1)->target;
or if u want to get girl by target
$girl = Target::find(1)->girl;

Related

laravel relation data to search for other models

Client model has relations to Invoice. I need to get the amounts from the Invoice relationship and find the matching transactions from the Transaction model.
I do it like this:
class Client extends Model
{
public function invoices()
{
return $this->hasMany(Invoice::class);
}
public function priceInvoices()
{
return $this->hasMany(Invoice::class)->select('gross_price');
}
}
foreach (Client::find($id)->priceInvoices->toArray() as $item) {
$prices[] = $item['gross_price'];
}
$transactions_for_prices = Transaction::whereIn('price', $prices)->get();
Will it be possible to make it more elegant?
If your Invoice.php Model has a relationship with a Transaction.php Model,
Example:
class Invoice extends Model
{
public function trasnactions()
{
return $this->hasMany(Transaction::class);
}
}
You could do something like this in a controller. (example)
public function show($id) {
$client = Client::findOrFail($id);
return view('view_name', [
'client' => $client,
'transactions => $client->invoices->transactions
]);
}

Laravel/Eloquent - How to query a for a relation that depends on another relation

The query I want to write:
I have three models:
A Chef hasMany FoodItems.
A FoodItem hasMany FoodItemAvailabilityDays.
In my query I want to look up a chef by a given slug. I want to return all of the chef's food items that are available on a specific date.
Example:
Imagine the Chef with slug "bob-smith" sells three food items: Lasagne, Burger and Burrito.
The Lasagne is available on 2022-01-01 and 2022-01-02
The Burger is available on 2022-01-02
The Burrito is available on 2022-01-03
IF I pass in the slug "bob-smith" and the date "2022-01-02"
THEN the query should return the "bob-smith" chef with the Lasange and Burger food items.
Model relationships:
// Chef.php
class Chef extends Model
{
public function foodItems()
{
return $this->hasMany(FoodItem::class);
}
}
// FoodItem.php
class FoodItem extends Model
{
public function availabilityDays()
{
return $this->hasMany(FoodItemAvailabilityDay::class);
}
}
I found an/the answer
$chef = Chef::where('slug', $slug)
->with(['foodItems' => function ($food_item_query) use ($selected_date) {
$food_item_query->whereHas('availabilityDays', function ($day_query) use ($selected_date) {
$day_query->where('date', $selected_date);
});
}])
->firstOrFail();
You should define a HasManyThrough relationship between Chef and FoodItemAvailabilityDays like this:
class Chef extends Model
{
public function foodItems()
{
return $this->hasMany(FoodItem::class);
}
public function foodItemAvailabilityDays()
{
return $this->hasManyThrough(FoodItemAvailabilityDays::class, Chef::class);
}
}
class FoodItem extends Model
{
public function chef()
{
return $this->belongsTo(Chef::class);
}
public function availabilityDays()
{
return $this->hasMany(FoodItemAvailabilityDay::class);
}
}
class FoodItemAvailabilityDay extends Model
{
public function foodItems()
{
return $this->belongsTo(FoodItem::class);
}
}
Now you can query the relationship directly:
$chef = Chef::whereSlug($slug)
->with(['foodItemAvailabilityDays' => fn($q) => $q->where('date', $selectedDate)])
->firstOrFail();

Get parent relation of an object dynamically in Laravel / Eloquent

I have three models
Product, Variant and Option.
class Product {
public $id;
public function variants(): HasMany
{
return $this->hasMany(Variant::class);
}
}
class Variant {
public $id;
public $product_id;
public function product(): BelongsTo
{
return $this->belongsTo(Product::class);
}
public function options(): HasMany
{
return $this->hasMany(Option::class);
}
}
class Option {
public $id;
public $variant_id;
public function variant(): BelongsTo
{
return $this->belongsTo(Variant::class);
}
}
I want to know if there is a way for an instance of Variant to get parent (Product) relationship and for Option
the parent (Variant) relationship with one line of code. Is there anything like the below?
$instance->parent();
I want to avoid writing
If (get_class($instance) === 'Variant' ) {
$instance->product();
} else if (get_class($instance) === 'Option' ) {
$instance->variant();
}
You can get the relation model easily. Like-
$variants = \App\Models\Variant::latest()->get();
foreach($variants as $variant)
{
$product_name = $variant->product->name; // this will be the product name that that related with this variant
}
It will be also work for single collection
$variant = \App\Models\Variant::find(1)>-first();
$variant->product;// this is product model instance that related to variant

How to get data from table related through pivot table?

I have 4 tables: countries, activities, country_activities and packages.
countries and activities are related through pivot table country_activity, and packages is related to country_activity.
Now, How do I eager load all packages related to each activity in a country?
class Country extends Model
{
public function activities() {
return $this->belongsToMany('App\Models\Activity','country_activities')->using('App\Models\CountryActivity')->as('country_activities');
}
}
class Activity extends Model
{
public function countries() {
return $this->belongsToMany('App\Models\Country','country_activities')->using('App\Models\CountryActivity')->as('country_activities');
}
}
class Package extends Model
{
public function country_activities() {
return $this->belongsToMany('App\Models\CountryActivity');
}
}
class CountryActivity extends Pivot
{
protected $table = 'country_activities';
public function packages() {
return $this->hasMany('App\Models\Package');
}
}
So, this worked for me.
class Country extends Model
{
public function activities() {
return $this->belongsToMany('App\Models\Activity','country_activities')->using('App\Models\CountryActivity')->withPivot(['id'])->as('country_activities');
}
Now, In my controller, I do this
$country = Country::with(['activities'=> function($q) {$q->where('name','Trekking');}])->where('name','Nepal')->first(['id','name']);
$country->activities->map(function ($i){
$i->country_activities->load('packages');
return $i;
});
I did something similar in a project i worked on. I'm not sure it will work but it's worth the shot:
$country = Country::find(1);
$country->activities = $contry->activities()->get()->each(function ($i, $k){
$i->packages = $i->pivot->packages;
//$i->makeHidden('pivot'); -> This is useful if you want to hide the pivot table
});
var_dump($country);

join table in laravel

I have 3 table in laravel:
class General extends Mode
{
public function populars()
{
return this->hasMany('App\Popular');
}
}
enter code here
and
class Popular extends Model
{
public function general()
{
return this->belongsTo('App\General');
}
}
and
class Specific extends Model
{
public function popular(){
return this->belongsTo('App\Popular');
}
}
...
how to join tables and return this list result:
1. generals
2.popular
3.Specific
I assume Popular has many Specific, you could add another mapping in Popular model as
class Popular extends Model
{
public function general()
{
return this->belongsTo('App\General');
}
public function specific()
{
return this->hasMany('App\Specific');
}
}
Doing with eloquent way you could write it as
$generals = General::with('populars.specific')->get();
Using query builder you could join them as
DB::table('general as g')
->join('popular as p', 'g.id','=','p.general_id')
->join('specific as s', 'p.id','=','p.popular_id')
->get();

Resources