I'm trying to fetch data from my DB based on the value in my pivot table.
These are my tables:
uploads
-> id
-> name
-> type
emails
-> id
-> email
upload_emails
-> id
-> upload_id
-> email_id
-> url
Now for example I have the following url: 1234
How can I select the upload that is attached to the pivot table 'upload_email'
where the url value in the pivot table matches 1234
I had the following
Upload::emails()->wherePivot('url', $key)->get();
But that's not working at all. I do have the relations set up in my model etc...
EDIT:
After the suggested answer I'm pretty close. This is what I have now:
return Upload::with(array('emails' => function($query) use ($key) {
$query->wherePivot('url', $key);
}))->get();
I have 9 uploads in my database. When I use the query above, it returns all uploads, but the emails are only included on the matching pivot url. But that's not what I want, I only want 1 upload. The one where the pivot url matches my value.
According to your tables all you need is to fix this:
Upload::emails()->wherePivot('url', $key)->get(); // no url field on that table!
// change to:
Upload::find($id)->emails()->wherePivot('key', $key)->get();
// or if you want a collection then:
Upload::with(array('emails'=> function ($q) use ($key) {
$qwherePivot('key', $key);
}))->get();
// to fetch only those Upload models that have related email matching given 'key'
Upload::whereHas('emails', function ($q) use ($key) {
$q->where('upload_emails.key', $key);
})->get(); // add the above with(...) method to also load those emails
Eager loading constraints using the with method could be what you need:
Upload::with('email', function($q) use($key) {
$q->where('url', $key);
})->get();
check the docs for more info.
Try this:
$upload = Upload::with(array('email' => function($query) use ($key) {
// where is URL in the table? shouldn't it be 'key'?
$query->where('key', $key);
}))->get();
notes
As wherePivot and orWherePivot has become available, see here.
You have to add the additional column to your relationship like this:
public function emails(){
return $this->belongsToMany(...)->withPivot("key");
}
Supposedly with Laravel 4.1 you can add another method to your model:
$upload = Upload::emails()->wherePivot('key', $key)->get();
Related
I have posts table that has related table where I store different translations based on post_id now when I want to return translation data based on user selected locale it says:
mb_strpos(): Argument #1 ($haystack) must be of type string, Closure given
Here is my function
$posts = Post::with('translations', function($q) {
$q->where('translate_code', app()->getLocale());
})->get();
dd($posts); // returning error above
But if I do this
$posts = Post::with('translations')->get();
dd($posts);
I will get following results
Here is translations data details:
My question is:
How can I return the one translation that has current locale name only?
If you using callback in with then use array of relations like below. Older version of laravel was working which you mentioned but latest version need array of relations when using callback.
$posts = Post::with(['translations'=> function($q) {
$q->where('translate_code', app()->getLocale());
}])->get();
using conditional eager loading should be like this:
$posts = Post::with(['translations'=> function($q) {
$q->where('translate_code', app()->getLocale());
}])->get();
while the relation name is the key, a closer to get data should be the value for the associative array for 'with' statement.
You can query your relation by using whereHas().
Docs: Laravel Docs Relationships
For example:
$posts = Post::whereHas('translations', function ($query) {
$query->where('translate_code', 'en');
})->get();
Maybe try to put the app()->getLocale() into a variable first. (after trying this out in tinker, this does seem te return a string, so may passing it by reference might help).
I have a hasOne(Many) relation function like this:
return $this->hasOne('App\Models\ProductTranslation','product_id','id')->where('language_id', $language_id['id']);
Also, I tried to use
return $this->hasOne('App\Models\ProductTranslation','product_id','id')->select('product_translations.name')->where('language_id', '1');
In Controller use this
$value=Product::with('translation:name')->find(1);
I try to receive only one specific column from the table, but it returned an empty array. In debug bar I see the query when I use it in PHPMyAdmin it return only one column as I want.
Is this possible?
P.S (use Laravel 5.8.34)
Updating
I choose 'Entity Layers for Translated Fields and Non-Translated Fields' approach for translation in the project and have a database like this Database picture
If you want to get only that language_id type of translation then you might do like this.
$language_id = 1;
$products = Product::with(array('translation'=>function($query) use($language_id){
$query->where('language_id',$language_id);
}))->get();
and if you want to select name then like this
make sure you've to select id,name id is a must.
$language_id = 1;
$products = Product::with(array('translation'=>function($query) use($language_id){
$query->where('language_id',$language_id)->select('id','name');
}))->get();
Remove where conditions from models.
As per your DB structure in Language it's belongsToMany with role
Languages.php model
public function role(){
returh $this->belongsToMany('App\Models\Role','role_translations','language_id','role_id')
}
$language_id = 1;
$products = Product::with(array('translation.role'=>function($query) use($language_id){
$query->where('role_translations.language_id',$language_id)->select('languages.id','languages.name');
}))->get();
I have the following relationships:
TheEpisodeJob hasOne TheEpisode
TheEpisodeJob hasMany TheJobs
I am successfuly retrieving all TheEpisodesJobs and TheSeriesEpisodes with all the fields in database (including sensitive information) using this command:
$jobs = TheEpisodeJob::with('TheEpisode')->get();
I would like to limit TheEpisode fields shown only for this case (public $hidden will not work)
EDIT
Let's say I need only title and description field from TheEpisode.
How can I achieve that?
As #Buglinjo pointed out you can scope the relationship when eager loading, however, if you're going to be doing this to only select specific columns you must included the related column in the select so that Eloquent knows which Model to attach the related data to.
This should give you what you want:
$jobs = TheEpisodeJob::with(['TheEpisode' => function ($query) {
$query->select('jobID', 'title', 'description');
}])->get();
Furthermore, if you then wanted to to get rid of the jobID as well you could do something like:
$jobs->transform(function ($job) {
$job->TheEpisode->transform(function ($item) {
unset($item->jobID);
return $item;
});
return $job;
});
Hope this helps!
As far as I understood you, you want to limit the results according to some more parameters. If I am right, you should add more queries, like:
->where, ->orwhere, ->select, ->whereNull
Here is the link for more queries. Hope it will help )
I saw an update, so then you need
->pluck('title', 'description');
for more information, go to the link above
You should do like this:
$jobs = TheEpisodeJob::with(['TheEpisode' => function($q){
$q->get(['title', 'description']);
//or
$q->pluck('title', 'description');
}])->get();
Note: pluck is getting as array not as Eloquent Object.
I'm querying a table, which finds all tasks assigned to a given user (the one signed in).
I have a pivot table for the tasks/users relation, as more than one user can be assigned to a task. The function below successfully grabs all the tasks the user is assigned too. No issue there.
However, I also want to include tasks that NO users have been assigned to in the function below (in my platform, no users assigned to a task means it's for "everyone").
$user_tasks = Team::currentTeam()->tasks()->with('user', 'comments')->whereHas('user', function($query) {
$query->where('user_id', Auth::user()->id);
})->get();
Probably something like this should work:
$user_tasks = Team::currentTeam()->tasks()->with('user', 'comments')->whereHas('user', function($query) {
$query->where('user_id', Auth::user()->id);
})->doesntHave('user','or')->get();
because there is no function orDoesntHave. There's only:
public function doesntHave($relation, $boolean = 'and', Closure $callback = null)
{
return $this->has($relation, '<', 1, $boolean, $callback);
}
defined, so you need to use doesntHave and specify operator as 2nd argument.
You can get the unassigned tasks separately:
$unassigned_tasks = Task::unassigned()->get(); // Uses a scope that says where user_id is null
And then something like:
$user_tasks->tasks->push($unassigned_tasks);
I have a number of models and I have the relationships set up correctly I believe.
I want to retrieve all of the models from a table if and only if the active column of a foreign key table is true.
I have tried a number of variations but to no avail.
Below is the set up.
The table is question is called device, which points to a table called dep.
The DEVICE model has the following relationship to DEP
public function dep() {
return $this->belongsTo('App\Dep');
}
The DEP model has a column called active, which is set to true or false.
What eloquent command should I use to return all Devices where the active field of the DEP table is true?
At the moment I am having to get all the DEP models and then only get the devices if the active field is set to true but I am sure there must be a more elegant approach.
Thanks.
If you want to limit the results based on the existence of a field in a related model, you want to take a look at the whereHas method.
$devices = Device::whereHas('dep', function($query) {
$query->where('active', '=', true); // Replace true with 1 if you aren't using casts
})->get();
This will get all devices that have a dep with the active field of true. This will not fetch dep along with the Device though. If you want that, then just use whereHas with eager loading as you normally would do like this:
$devices = Device::with('dep')->whereHas('dep', function($query) {
$query->where('active', '=', true);
})->get();
You can simply add a filter to your relationship:
public function dep() {
return $this->belongsTo('App\Dep')->where('active', true);
}
Or, if you prefer to keep the dep relation unaltered, you can consider to add another relation to retrieve only the active models:
public function depActive() {
return $this->belongsTo('App\Dep')->where('active', true);
}
This will return all the DEP models related to a Device, having active = 1.
You can use the relation as follow:
$depActives = $device->depActive;
or
$depActives = $device->depActive()->get();
boh of them will do the same