laravel 如何访问模型 hasMany 与 where 条件的关系?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18520209/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to access model hasMany Relation with where condition?
提问by Remluben
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".
抛出异常,因为它说“调用非对象上的成员函数 count()”。
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?
我错过了什么吗?如何确保在不使用预先加载的情况下可以访问 available_videos?
For anyone interested, I have also posted this issue on http://forums.laravel.io/viewtopic.php?id=10470
对于任何感兴趣的人,我也在http://forums.laravel.io/viewtopic.php?id=10470上发布了这个问题
采纳答案by Remluben
Just in case anyone else encounters the same problems.
以防万一其他人遇到同样的问题。
Note, that relations are required to be camelcase. So in my case available_videos() should have been availableVideos().
请注意,关系必须是驼峰式的。所以在我的情况下,available_videos() 应该是 availableVideos()。
You can easily find out investigating the Laravel source:
你可以很容易地找到调查 Laravel 源代码的方法:
// Illuminate\Database\Eloquent\Model.php
...
/**
* Get an attribute from the model.
*
* @param string $key
* @return mixed
*/
public function getAttribute($key)
{
$inAttributes = array_key_exists($key, $this->attributes);
// If the key references an attribute, we can just go ahead and return the
// plain attribute value from the model. This allows every attribute to
// be dynamically accessed through the _get method without accessors.
if ($inAttributes || $this->hasGetMutator($key))
{
return $this->getAttributeValue($key);
}
// If the key already exists in the relationships array, it just means the
// relationship has already been loaded, so we'll just return it out of
// here because there is no need to query within the relations twice.
if (array_key_exists($key, $this->relations))
{
return $this->relations[$key];
}
// If the "attribute" exists as a method on the model, we will just assume
// it is a relationship and will load and return results from the query
// and hydrate the relationship's value on the "relationships" array.
$camelKey = camel_case($key);
if (method_exists($this, $camelKey))
{
return $this->getRelationshipFromMethod($key, $camelKey);
}
}
This also explains why my code worked, whenever I loaded the data using the load() method before.
这也解释了为什么我的代码在之前使用 load() 方法加载数据时有效。
Anyway, my example works perfectly okay now, and $model->availableVideos always returns a Collection.
无论如何,我的示例现在可以正常工作,并且 $model->availableVideos 总是返回一个集合。
回答by Antonio Carlos Ribeiro
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() );
回答by Sabrina Leggett
I think this is what you're looking for (Laravel 4, see http://laravel.com/docs/eloquent#querying-relations)
我认为这就是您要寻找的(Laravel 4,请参阅http://laravel.com/docs/eloquent#querying-relations)
$games = Game::whereHas('video', function($q)
{
$q->where('available','=', 1);
})->get();
回答by xsilen T
//lower for v4 some version
//较低的v4某些版本
public function videos() {
$instance =$this->hasMany('Video');
$instance->getQuery()->where('available','=', 1);
return $instance
}
//v5
//v5
public function videos() {
return $this->hasMany('Video')->where('available','=', 1);
}
回答by Nikunj K.
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;
}
回答by kush
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);
}
回答by Vitalii
I have fixed the similar issue by passing associative array as the first argument inside Builder::with
method.
我通过将关联数组作为Builder::with
方法内部的第一个参数来解决类似的问题。
Imagine you want to include child relations by some dynamic parameters but don't want to filter parent results.
想象一下,您想通过一些动态参数包含子关系,但又不想过滤父结果。
Model.php
模型.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):
然后,在其他地方,当您放置逻辑时,您可以执行诸如按HasMany
类过滤关系之类的操作。例如(与我的情况非常相似):
$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.
然后您将过滤所有子结果,但父模型不会过滤。感谢您的关注。
回答by Santo Boldi?ar
Model (App\Post.php):
模型(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):
控制器(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):
刀片模板(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
回答by Sreedhar M B
Have you created a model for "Role". Check whether the problem exists even after creating model for Role.
您是否为“角色”创建了模型。为角色创建模型后,检查是否存在问题。
回答by ahmad_mhm
I have User
model and its Relation
is:
我有User
模型,它Relation
是:
class User extends Model
{
public function Orders()
{
return $this->hasMany(Order::class, 'user_id', 'id');
}
}
And in controller I wanna to get the user
order with order_id
that passed from url:
在控制器中,我想获取从 url 传递的user
订单order_id
:
public function orderDetails($orderID){
$userOrder = Auth::user()->Orders()->where('id', $orderID)->first();
dd($userOrder);
}