Reputation: 7715
Laravel 5.7. I have a model Audio
, with the fields id
and title
. An Audio
can have many AudioVersion
s, where AudioVersion
has id
, audio_id
(referring to Audio
) and url
.
Now, I have two parent models, Foo
and Bar
, which can have many Audio
models.
Audio:
class Audio extends Model
{
public function versions()
{
return $this->hasMany('App\AudioVersion', 'audio_id');
}
}
AudioVersion:
class AudioVersion extends Model
{
public function audio()
{
return $this->belongsTo('App\AudioContent');
}
}
Foo:
class Foo extends Model
{
public function audioContents()
{
return $this->morphToMany('App\Audio', 'audio_contentable', 'audio_contentable');
}
}
I have an Eloquent API resource, FooResource
, which returns its Audio
objects:
FooResource:
class FooResource extends JsonResource
{
public function toArray($request)
{
return [
'audio' => AudioResource::collection($this->audioContents),
];
}
}
AudioResource:
class AudioResource extends JsonResource
{
public function toArray($request)
{
return [
'urls' => $this->versions,
];
}
}
My problem is that in the audio
key of my FooResource
I only want to return Audio
s which have AudioVersions
related to them. I.e. if I have an Audio
with no AudioVersions
, I do not want that Audio
included in the Foo
's audio
key. I can't find a way to do this deep conditional logic in Eloquent / Resources.
Upvotes: 0
Views: 954
Reputation: 7715
In the end I added a scope to Audio
:
public function scopeHasVersions($query)
{
return $query->whereHas('versions');
}
Then in FooResource
:
return [
'audio' => AudioResource::collection($this->audioContents()->hasVersions()->get()),
];
Upvotes: 0
Reputation: 4202
In the FooResource
class, you could filter()
the collection before passing it to the collection method.
class FooResource extends JsonResource
{
public function toArray($request)
{
$audioContents = $this->audioContents()->filter(function($audio, $key) {
return $audio->versions->count();
}
return [
'audio' => AudioResource::collection($audioContents),
];
}
}
Upvotes: 1
Reputation: 517
You need to do something like this. This is the example, you only need to add join inside with
so that only those audios
will be fetched which have audio versions
.
$audioContents = AudioContents::with([
'audio' => function ($query) use ($SpecificID) {
return $query->join("audio_versions")
->on("audio_versions.audio_id", "=", "audios.id");
}
])->get();
Try this and let me know if you are facing any issue.
Upvotes: 0