I created a model Game using a condition / constraint for a relation as follows:
class Game extends Eloquent {
// many more stuff here
// relation without any constraints ...works fine
public function videos() {
return $this->hasMany('Video');
}
// results in a "problem", se examples below
public function available_videos() {
return $this->hasMany('Video')->where('available','=', 1);
}
}
When using it somehow like this:
$game = Game::with('available_videos')->find(1);
$game->available_videos->count();
everything works fine, as roles is the resulting collection.
MY PROBLEM:
when I try to access it without eager loading
$game = Game::find(1);
$game->available_videos->count();
an Exception is thrown as it says "Call to a member function count() on a non-object".
Using
$game = Game::find(1);
$game->load('available_videos');
$game->available_videos->count();
works fine, but it seems quite complicated to me, as I do not need to load related models, if I do not use conditions within my relation.
Have I missed something? How can I ensure, that available_videos are accessible without using eager loading?
For anyone interested, I have also posted this issue on http://forums.laravel.io/viewtopic.php?id=10470
I think this is what you're looking for (Laravel 4, see http://laravel.com/docs/eloquent#querying-relations)
$games = Game::whereHas('video', function($q)
{
$q->where('available','=', 1);
})->get();
//lower for v4 some version
public function videos() {
$instance =$this->hasMany('Video');
$instance->getQuery()->where('available','=', 1);
return $instance
}
//v5
public function videos() {
return $this->hasMany('Video')->where('available','=', 1);
}
I think that this is the correct way:
class Game extends Eloquent {
// many more stuff here
// relation without any constraints ...works fine
public function videos() {
return $this->hasMany('Video');
}
// results in a "problem", se examples below
public function available_videos() {
return $this->videos()->where('available','=', 1);
}
}
And then you'll have to
$game = Game::find(1);
var_dump( $game->available_videos()->get() );
Model (App\Post.php):
/**
* Get all comments for this post.
*/
public function comments($published = false)
{
$comments = $this->hasMany('App\Comment');
if($published) $comments->where('published', 1);
return $comments;
}
Controller (App\Http\Controllers\PostController.php):
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function post($id)
{
$post = Post::with('comments')
->find($id);
return view('posts')->with('post', $post);
}
Blade template (posts.blade.php):
{{-- Get all comments--}}
@foreach ($post->comments as $comment)
code...
@endforeach
{{-- Get only published comments--}}
@foreach ($post->comments(true)->get() as $comment)
code...
@endforeach
If you want to apply condition on the relational table you may use other solutions as well.. This solution is working from my end.
public static function getAllAvailableVideos() {
$result = self::with(['videos' => function($q) {
$q->select('id', 'name');
$q->where('available', '=', 1);
}])
->get();
return $result;
}
I have fixed the similar issue by passing associative array as the first argument inside Builder::with
method.
Imagine you want to include child relations by some dynamic parameters but don't want to filter parent results.
Model.php
public function child ()
{
return $this->hasMany(ChildModel::class);
}
Then, in other place, when your logic is placed you can do something like filtering relation by HasMany
class. For example (very similar to my case):
$search = 'Some search string';
$result = Model::query()->with(
[
'child' => function (HasMany $query) use ($search) {
$query->where('name', 'like', "%{$search}%");
}
]
);
Then you will filter all the child results but parent models will not filter. Thank you for attention.
public function outletAmenities()
{
return $this->hasMany(OutletAmenities::class,'outlet_id','id')
->join('amenity_master','amenity_icon_url','=','image_url')
->where('amenity_master.status',1)
->where('outlet_amenities.status',1);
}
Source: Stackoverflow.com