76

次のように、リレーションの条件/制約を使用してモデル ゲームを作成しました。

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);
    }
}

どういうわけか次のように使用する場合:

$game = Game::with('available_videos')->find(1);
$game->available_videos->count();

ロールは結果のコレクションであるため、すべてが正常に機能します。

私の問題:

熱心な読み込みなしでアクセスしようとすると

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

「非オブジェクトでのメンバー関数 count() の呼び出し」というように、例外がスローされます。

使用する

$game = Game::find(1);
$game->load('available_videos');
$game->available_videos->count();

正常に動作しますが、関係内で条件を使用しない場合、関連モデルをロードする必要がないため、かなり複雑に思えます。

私は何かを逃しましたか?熱心な読み込みを使用せずに available_videos にアクセスできるようにするにはどうすればよいですか?

興味のある方のために、この問題をhttp://forums.laravel.io/viewtopic.php?id=10470にも投稿しました。

4

8 に答える 8

36

これがあなたが探しているものだと思います(Laravel 4、http://laravel.com/docs/eloquent#querying-relationsを参照)

$games = Game::whereHas('video', function($q)
{
    $q->where('available','=', 1);

})->get();
于 2014-07-15T21:42:54.257 に答える
33

// getQuery() を使用して条件を追加します

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

// 単純に

public function videos() {
    return $this->hasMany('Video')->where('available','=', 1);
}
于 2016-04-14T03:09:44.333 に答える
16

他の誰かが同じ問題に遭遇した場合に備えて。

リレーションはキャメルケースである必要があることに注意してください。したがって、私の場合、available_videos() は availableVideos() である必要があります。

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 は常に Collection を返します。

于 2014-04-22T19:30:12.157 に答える
13

リレーショナル テーブルに条件を適用する場合は、他のソリューションも使用できます。このソリューションは私の側で機能しています。

public static function getAllAvailableVideos() {
        $result = self::with(['videos' => function($q) {
                        $q->select('id', 'name');
                        $q->where('available', '=', 1);
                    }])                    
                ->get();
        return $result;
    }
于 2016-10-05T08:01:51.847 に答える