I'm not sure how to explain my problem but i'll give it a try.
I'm using Laravel 5 and i have 3 tables:
pages
languages
language_page
This is what my models look like:
Page model:
public function languages()
{
return $this->belongsToMany('App\Language', 'language_page')
->withPivot('title', 'content', 'slug', 'meta_title', 'meta_description')
->orderBy('main', 'desc');
}
Language Model:
public function pages()
{
return $this->belongsToMany('App\Page')
->withPivot('title', 'content', 'slug', 'meta_title', 'meta_description');
}
What i want to do return a record from the page table where language_id is a certain id, and where slug is a certain text.
This is what i got so far: EDIT:
Page::with(['languages' => function($q) use($language_id, $slug) {
$q->where('language_id', $language_id);
$q->wherePivot('slug', $slug);
}])
->first();
My problem: how can i add a where clause with the column slug (from the pivot table language_page) ?
i hope this makes any sense at all..
Eloquent's BelongsToMany class has a
wherePivot()
method that allows you applying WHERE clauses to pivot table directly, see:
https://github.com/laravel/framework/blob/5.1/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php#L111
Related
I have 2 tables that are named Resort and booking. in the booking table, there is a field named amount. I want to join these tables using with hasMany relation and get sum of the amount field in the booking table using with groupBy. can you please help me to solve this problem?
Thanks in Advance
Laravel Eloquent has the own withSum() method for avoiding "groupBy()" method.
For your case you can use something like this (you can modify for your needs):
// resorts with bookings and their summary prices
$data = Resort::select([
'id',
'name',
'image',
])
// ->orderBy('some_field', 'ASC')
->with(['bookings' => function($query) {
return $query->select([
'id',
'booking_id',
'price',
]);
}])
->withSum('bookings', 'price')
// ->where('resorts.some_field', '<=', 123)
->get();
// ->toArray();
But don't forget to have appropriate relation defined in your parent (Resort) model:
public function bookings() {
return $this->hasMany(Booking::class, 'resort_id', 'id');
}
Also you need to have "resort_id" foreign key defined in child's (Booking) migration:
$table->unsignedTinyInteger('resort_id')->nullable();
$table->foreign('resort_id')->references('id')
->on('resorts'); // ->onUpdate('cascade')->onDelete('cascade');
I use this hasOneThrough to get user through post to display result inf file:
Controller
File::where('agent_id', $user->id)
->with(['user' => function ($q) {
$q->select('name','phone');
}])->get(['post_id', 'status']);
Model
// __________________________ related__|__through_|_1key_|_2key_|_lkey_|_seclkey
return $this->hasOneThrough('App\User', 'App\Post', 'id', 'id', 'post_id', 'user_id');
// ___________________________________________^ > want to get `hash` from `post`
This work good, but now I need one item from post called hash in this result, is it possible to get any data from through (Post table). Already able to get any data from file and user but how can I get data from through (Post table) ?
I don't know how can do this, so I searched and nothing found, so I couldn't try anything.
You should use hasOne in your model:
public function post(){
return $this->hasOne('App\Post', 'id', 'post_id');
}
And in your controller you can use eager loading but I noticed you get null, in order for this to work, you also have to select the id:
$files = File::where('agent_id', $user->id)->with('user:phone,name', 'post:id,hash')->get(['post_id', 'status']);
If your File table has a post_id, and between posts and files table there is a One to Many relation, just declare a new relation:
public function post(){
return $this->belongsTo('App\Post', 'post_id', 'id');
}
Also keep in mind that if inside a with you want to select only specific fields, you can just do ->with('user:phone,name')
I am try to made Eloquent: Relationships for three model. Please have a look on my code.
$account = Account::select(['id', 'is_sign_contract', 'restaurant_name', 'state', 'phone_no', 'email', 'one_time_pick_up', 'sign_contract_date', 'created_at', 'oil_on_hand', 'binsize'])
->with(['completedservice' => function($c) {
//$c->select('id');
}])
->with(['accountService' => function($q) {
$q->with(['serviceProvider' => function($qs) {
$qs->select('id', 'company_name');
}])->select('account_id', 'service_provider_id', 'service_id');
}])
->whereRaw($where)
->orderBy('id', 'ASC')->offset(54)->limit(1)->get();
if i remove that //$c->select('id'); select form above relation then i get data if i am using it display blank relationship block.
below image for response in last image whole function there
In short without select it works fine, but if I am using select then not working.
Laravel loads the relations after the first query is run. In order for it to attach the related model to the parent you need to select the foreign key on the related table so Laravel knows which model to attach the child to after the query is run.
The accountService works because ytou are selecting account_id on that model to attach it to Account and serviceProvider works because you are selecting id on serviceProvider as well as service_provider_id on accountService so after all queries are run Laravel knows which models get attached where.
Your query is not working because you are not selecting the account_id on the child model.
The following will work:
$account = Account::select(['id', 'is_sign_contract', 'restaurant_name', 'state', 'phone_no', 'email', 'one_time_pick_up', 'sign_contract_date', 'created_at', 'oil_on_hand', 'binsize'])
->with(['completedservice' => function($c) {
$c->select('id', 'account_id');
}])
->with(['accountService' => function($q) {
$q->with(['serviceProvider' => function($qs) {
$qs->select('id', 'company_name');
}])
->select('account_id', 'service_provider_id', 'service_id');
}])
->whereRaw($where)
->orderBy('id', 'ASC')->offset(54)->limit(1)->get();
You need to have the foreign key selected along with any other fields you wish to select. Without which you'll get an empty relationship. So it should be something similar to $c->select('id', 'account_id');
I am using laravel 5.1 for my new project smart search.
My problem is to get data from foreign key using like query for search of that table.
My database tables are:
category->id, name
search->id, category_id (foreign_key), question, answer, tags
My model code is:
category model
public function helpcenter() {
return $this->belongsTo('App\HelpCenter');
}
helpcenter model
public function category() {
return $this->hasOne('App\HelpCenterCategory', 'id', 'category_id');
}
My controller function for search query is
$queries = HelpCenter::has('category')
->where('questions', 'LIKE', '%'.$term.'%')
->orwhere('category_id.name','LIKE','%'.$term.'%')
->take(5)->get();
You will want to use whereHas() to subquery a relationship:
$queries = HelpCenter::whereHas('category', function($category) use ($term)
{
$category->where('name','LIKE','%'.$term.'%');
})
->orWhere('questions', 'LIKE', '%'.$term.'%')
->take(5)->get();
whereHas() is documented here: http://laravel.com/docs/5.1/eloquent-relationships#querying-relations
In the documentation of Eloquent it is said that I can pass the keys of a desired relationship to hasManyThrough.
Lets say I have Models named Country, User, Post. A Country model might have many Posts through a Users model. That said I simply could call:
$this->hasManyThrough('Post', 'User', 'country_id', 'user_id');
This is fine so far! But how can I get these posts only for the user with the id of 3 ?
Can anybody help here?
So here it goes:
models: Country has many User has many Post
This allows us to use hasManyThrough like in your question:
// Country model
public function posts()
{
return $this->hasManyThrough('Post', 'User', 'country_id', 'user_id');
}
You want to get posts of a given user for this relation, so:
$country = Country::first();
$country->load(['posts' => function ($q) {
$q->where('user_id', '=', 3);
}]);
// or
$country->load(['posts' => function ($q) {
$q->has('user', function ($q) {
$q->where('users.id', '=', 3);
});
})
$country->posts; // collection of posts related to user with id 3
BUT it will be easier, more readable and more eloquent if you use this instead:
(since it has nothing to do with country when you are looking for the posts of user with id 3)
// User model
public function posts()
{
return $this->hasMany('Post');
}
// then
$user = User::find(3);
// lazy load
$user->load('posts');
// or use dynamic property
$user->posts; // it will load the posts automatically
// or eager load
$user = User::with('posts')->find(3);
$user->posts; // collection of posts for given user
To sum up: hasManyThrough is a way to get nested relation directly, ie. all the posts for given country, but rather not to search for specific through model.
$user_id = 3;
$country = Country::find($country_id);
$country->posts()->where('users.id', '=', $user_id)->get();
$this->hasManyThrough('Post', 'User', 'country_id', 'user_id')->where(column,x);
What happen here is you get the collection in return you can put any condition you want at the end.