How to access model hasMany Relation with where condition?

前端 未结 8 1340
迷失自我
迷失自我 2020-12-08 00:02

I created a model Game using a condition / constraint for a relation as follows:

class Game extends Eloquent {
             


        
相关标签:
8条回答
  • 2020-12-08 00:29

    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();
    
    0 讨论(0)
  • 2020-12-08 00:36

    //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);
    }
    
    0 讨论(0)
  • 2020-12-08 00:36

    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;
        }
    
    0 讨论(0)
  • 2020-12-08 00:46

    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.

    0 讨论(0)
  • 2020-12-08 00:50

    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().

    You can easily find out investigating the Laravel source:

    // 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.

    Anyway, my example works perfectly okay now, and $model->availableVideos always returns a Collection.

    0 讨论(0)
  • 2020-12-08 00:52

    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() );
    
    0 讨论(0)
提交回复
热议问题