Laravel 如何访问与where条件有很多关系的模型?

Laravel 如何访问与where条件有很多关系的模型?,laravel,laravel-4,eloquent,Laravel,Laravel 4,Eloquent,我使用关系的条件/约束创建了一个模型游戏,如下所示: 类游戏扩展了口才{ //这里还有很多东西 //没有任何约束的关系…工作正常 公共活动视频(){ 返回$this->hasMany('Video'); } //导致“问题”,请参见下面的示例 公共功能可用\u视频(){ 返回$this->hasMany('Video')->where('available','=',1); } } 当以这样的方式使用它时: $game=game::with('available_videos')->查找(1)

我使用关系的条件/约束创建了一个模型游戏,如下所示:

类游戏扩展了口才{
//这里还有很多东西
//没有任何约束的关系…工作正常
公共活动视频(){
返回$this->hasMany('Video');
}
//导致“问题”,请参见下面的示例
公共功能可用\u视频(){
返回$this->hasMany('Video')->where('available','=',1);
}
}
当以这样的方式使用它时:

$game=game::with('available_videos')->查找(1);
$game->available_videos->count();
一切正常,因为角色是最终的集合

我的问题:

当我试图访问它而不急于加载时

$game=game::find(1);
$game->available_videos->count();
抛出一个异常,因为它表示“调用非对象上的成员函数count()”

使用

$game=game::find(1);
$game->load(“可用的_视频”);
$game->available_videos->count();
工作正常,但对我来说似乎相当复杂,因为如果不在关系中使用条件,我不需要加载相关模型

我错过什么了吗?我如何确保无需使用即时加载即可访问可用的_视频


对于任何感兴趣的人,我也在

上发布了这个问题。我认为这是正确的方式:

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);
    }
}
然后你就必须

$game = Game::find(1);
var_dump( $game->available_videos()->get() );

以防其他人遇到同样的问题

请注意,关系必须是完全一致的。因此,在我的例子中,available_videos()应该是available videos()

您可以通过调查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);
    }
}
这也解释了我的代码在以前使用load()方法加载数据时工作的原因


无论如何,我的示例现在运行得非常好,$model->availableVideos总是返回一个集合。

我认为这就是您要寻找的(Laravel 4,请参阅)


//对于v4某些版本,请降低

public function videos() {
    $instance =$this->hasMany('Video');
    $instance->getQuery()->where('available','=', 1);
    return $instance
}
//v5


如果要对关系表应用条件,还可以使用其他解决方案。。这个解决方案在我这边起作用

public static function getAllAvailableVideos() {
        $result = self::with(['videos' => function($q) {
                        $q->select('id', 'name');
                        $q->where('available', '=', 1);
                    }])                    
                ->get();
        return $result;
    }
模型(App\Post.php):

控制器(App\Http\Controllers\PostController.php):

刀片模板(posts.Blade.php):


通过将关联数组作为
Builder::with
方法中的第一个参数传递,我解决了类似的问题

假设您希望通过一些动态参数包含子关系,但不希望筛选父结果

Model.php

公共函数子项()
{
返回$this->hasMany(ChildModel::class);
}
然后,在另一个地方,当您的逻辑被放置时,您可以通过
HasMany
类过滤关系。例如(与我的情况非常相似):

$search='Some search string';
$result=Model::query()->with(
[
'child'=>函数(有许多$query)使用($search){
$query->where('name','like',“%{$search}%”);
}
]
);
然后,您将过滤所有子结果,但父模型不会过滤。
感谢您的关注。

在laravel中实现基于角色的用户管理的最佳方法是使用sentry软件包。所以试一下。正如我在上面的描述中所说,模型名称只是一个例子,我的问题与用户管理无关。我将编辑我的问题并发布我的真实wordl示例。感谢您的回复,您的示例非常有效,但在调用$game->available\u videos()->get()时,我的示例也非常有效。关键是,我想使用$game->available\u videos,因为我也可以使用$game->videos而不会遇到麻烦。据我所知,如果之前没有加载,Elount应该加载相关模型,还是我错了?将函数名更新为
availableVideos
。如果您只需要这些视频来返回可用的视频,您可以这样做:
return$this->hasMany('Video')->where('available','=',1)不,这绝对不是原因。您应该始终使用带下划线的函数名
,因为在MVC中,应该始终有一个类似
/controller/function\u name
的URL结构。如果您没有为函数设置正确的路由,您将在URL中获得驼峰大小写的函数名,这不利于SEO。@Vinet抱歉,不是。MVC与URL结构无关。php文件定义了从url到控制器的映射。更不用说这是在模型中,而不是在控制器中。它与URL绝对没有对应关系。好主意,但这是一样的,因为Relation在查询生成器上为您调用该方法是的,现在不需要调用getQuery。v5需要较低的版本,您可以这样做:
return$this->hasMany('Video')->where('available','=',1)为了让它更干净,这些设施突然从哪里来?这和答案还不太接近。你能解释一下你的答案吗?
 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);
}
public static function getAllAvailableVideos() {
        $result = self::with(['videos' => function($q) {
                        $q->select('id', 'name');
                        $q->where('available', '=', 1);
                    }])                    
                ->get();
        return $result;
    }
/**
 * Get all comments for this post.
 */
public function comments($published = false)
{
    $comments = $this->hasMany('App\Comment');
    if($published) $comments->where('published', 1);

    return $comments;
}
/**
 * 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);
}
{{-- Get all comments--}}
@foreach ($post->comments as $comment)
    code...
@endforeach

{{-- Get only published comments--}}
@foreach ($post->comments(true)->get() as $comment)
    code...
@endforeach
 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);
}