Here's simplified view of Models and according columns from DB
Route
id
City
id
name
RouteCityPivot
id
city_id
route_id
One Route can have only two related Cities. Let's say they are Berlin and Munich.
How can I find a route by the City names?
This code can find several routes which has at least one of the Cities:
$route = Route::whereHas('cities', function ($q) use ($from, $to){
q->whereIn('name', [$from, $to]);
})->get();
How can I find the route which has exactly 2 of the given Cities? Thanks!
According to the same issue
The solution is
$route = Route::whereHas('cities', function ($q) use ($cities){
$q->whereIn('name', $cities);
}, '=', count($cities))->get();
Related
I'm using Larave 9 to build a complicated web application.
I'm trying to get foreign key already set in relationship of a model to make another dynamic join query for some other data.
This is an example to make a dynamic query after getting foreign keys from many models:
foreach ($joinFunc as $table => $jQ){
$relTbl = $jQ['related'];
$k = $jQ['oKey'];
$fk = $jQ['fKey'];
$q->leftJoin($table, $table. '.' . $k, $relTbl. '.' .$fk);
}
My relationship in model is:
public function autopays()
{
return $this->hasMany(ClientAutoPay::class, 'client_id', 'id');
}
I want to get client_id set in the relationship
$q = Client::query()->with('autopays');
dump(
$q->first()->autopays()->getRelated()->getKeyName(),
$q->first()->autopays()->getRelated()->getForeignKey(),
);
but the result id:
"id"
"client_auto_pay_id"
what I need is to get client_id instead of client_auto_pay_id. Any help :(
I found a solution to check if the relationship has an instance ($q->whereHas()) which gave me the table name and if no instance found then I didn't pass it to dynamic joining query loop.
One thing I had to pass manually from the controller to my function and that is array of each table joining ownKeys and foreignKeys.
Now my dynamic dataTable by Livewire component is working awesome 👍
Assume I have the follow hasMany() models:
Country > State > City > Street > Person
And I want to retrieve person "John", but also know what country he belongs to:
$person = Person::with(['country'], ['state'], ['city'], ['street'],
['person'] = function ($query) {
$query->where('name', '=', 'John')
});
This generates a separate query for each model which does not seem efficient. Should I use join instead?
From my experience with MySQL 8+, there is not much difference, and I wouldn't use joins.
You can also use this package for nested relations
https://github.com/staudenmeir/eloquent-has-many-deep
I have 3 columns in my database. 2 columns is connected with one column by using a hybrid relationship.
here is my query.
$data=Client::with('product','department')->select(['product.product_name','product.product_description']);
how to select row from another table?
in your product or department relation method do the selection with all the forging keys if you have any other relation for product for later use is you want them like
public function product()
{
return $this->hasMany(department::class)->select(['id', 'another_relation_to_product_id', 'product_name', 'product_description']);
}
You can do it this way
$data = Client::with(['product:id,product_name,product_description','department'])->get();
see docs https://laravel.com/docs/5.7/eloquent-relationships#constraining-eager-loads in Eager Loading Specific Columns section. Or you can do it
App\User::with([
'product' => function ($query) {
$query->select('id', 'product_name', 'product_description');
},
'department'
])->get();
My two table Member and Deposit there has one to many relationship one member has multiple deposit in Deposit table i want to search by multiple column both table which will have to match.
This is my Member Table
1.id,
2.branch_id,
3.village_id,
4.user_id,
5.name,
6.phone,
7.email,
8........
My Deposit Table
1.meber_id,
2.user_id
3.deposit_date,
4.deposit_amount,
5.total_amount,
6..........
My Controller Code
$depo = Deposit::with(['member'=>function($query){$query->where('branch_id',$request->branch_id)->where('status','running')->get();}])->where('user_id',$request->user_id)->whereDate('deposit-date','>=',$from_date)->whereDate('deposit-date','<=',$to_date)->get();
if i do that then ....$query->where('branch_id',$request->branch_id)->get()..... section is not working please help me any one
Try this:
$depo = Deposit::whereHas('member', function($query) use ($request){
$query->where([
['branch_id' => $request->branch_id],
['status'=> 'running']
])
})
->where('user_id',$request->user_id)
->whereDate([
['deposit-date','>=',$from_date],
['deposit-date','<=',$to_date]
])->get();
Your question is quite ambiguous, but looks like you need to use the $request in the with function.
$deposits = Deposit::with(['member' => function ($query) use ($request) {
$query->where('branch_id', $request->branch_id)
->where('status', 'running')->get();
}])->where('user_id', $request->user_id)
->whereDate('deposit-date', '>=', $from_date)
->whereDate('deposit-date', '<=', $to_date)
->get();
But the with method wont filter down your query it will simply limit the number of members returned with all the deposits. It's not searching in the member table.
UPDATE 04/12/2018
Without checking the docs at all, and completely off the top of my head.
Deposit::with('member', function($query) use($request){
$query->where('branch_id', $request->branch_id)
->orWhere('village_id', $request->village_id)
})->where(function($query) use($request) {
$query->where('user_id', $request->user_id)
->whereDate('deposit-date', '>=', $from_date)
->whereDate('deposit-date', '<=', $to_date)
})->orWhereHas('member', function($query) use($request){
$query->where('branch_id', $request->branch_id)
->orWhere('village_id', $request->village_id)
})->get();
This is a followup post to: Laravel 4 and Eloquent: retrieving all records and all related records
The solution given works great:
$artists = Artist::with('instruments')->get();
return \View::make('artists')->withArtists($artists);
It also works with just:
$artists = Artist::get();
Now I'm trying to specify the exact columns to return for both tables. I've tried using select() in both the statement above and in my Class, like this:
ArtistController.php
$artists = Artist::select('firstname', 'lastname', 'instruments.name')->get();
or:
$artists = Artist::with(array('instruments' => function($query) {
$query->select('name');
}))->get();
(as suggested here and while this doesn't throw an error, it also doesn't limit the columns to only those specified)
or in Artist.php:
return $this->belongsToMany('App\Models\Instrument')->select(['name']);
How would I go about getting just the firstname and lastname column from the artists table and the name column from instruments table?
Not sure what I was thinking. I think working on this so long got me cross-eyed.
Anyhow, I looked into this a lot more and searched for answers and finally posted an issue on GitHub.
The bottom line is this is not possible as of Laravel v4.1.
https://github.com/laravel/laravel/issues/2679
This solved it:
Artists.php
public function instruments() {
return $this->hasMany('App\Models\Instrument', 'id');
}
Note that I changed this to a hasMany from a belongsToMany which makes more sense to me as a musicians (or Artist) would have many Instruments they play and an Instrument could belong to many Artists (which I also alluded to in my previous questions referenced above). I also had to specify 'id' column in my model which tells the ORM that instrument.id matches artist_instrument.id. That part confuses me a bit because I thought the order for hasMany was foreign_key, primary_key, but maybe I'm thinking about it backwards. If someone can explain that a bit more I'd appreciate it.
Anyhow, the second part of the solution...
In ArtistsController.php, I did this:
$artists = Artist::with(array(
'instruments' => function($q) {
$q->select('instruments.id', 'name');
})
)->get(array('id', 'firstname', 'lastname'));
That gives me exactly what I want which is a collection of Artists that contains only the firstname and lastname columns from the artists table and the name column for each of the instruments they play from the instruments.
$artists = Artist::with(array('instruments' => function ($query) {
$query->select('id', 'name');
}))->get('id', 'firstname', 'lastname');