2013-08-29 22 views
17

Tôi tạo ra một mô hình trò chơi sử dụng một điều kiện/hạn chế cho một mối quan hệ như sau:Cách truy cập mô hình hasMany Relation với điều kiện ở đâu?

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

Khi sử dụng nó bằng cách nào đó như thế này:

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

tất cả mọi thứ hoạt động tốt, như vai trò là kết quả bộ sưu tập.

vấn đề của tôi:

khi tôi cố gắng truy cập vào nó mà không bốc háo hức

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

một ngoại lệ được ném như nó nói "Gọi đến một số chức năng thành viên() trên một phi đối tượng ".

Sử dụng

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

hoạt động tốt, nhưng nó có vẻ khá phức tạp đối với tôi, như tôi không cần phải tải mô hình liên quan, nếu tôi không sử dụng điều kiện trong mối quan hệ của tôi.

Tôi đã bỏ lỡ điều gì chưa? Làm thế nào tôi có thể đảm bảo rằng, có thể truy cập vào available_videos mà không cần sử dụng tải háo hức?

Đối với bất cứ ai quan tâm, tôi cũng đăng tải vấn đề này trên http://forums.laravel.io/viewtopic.php?id=10470

+0

Cách tốt nhất để triển khai quản lý người dùng dựa trên vai trò trong laravel là sử dụng gói sentry. Hãy thử một lần đi. – harishannam

+0

Như tôi đã nói trong mô tả ở trên, các tên Mẫu chỉ là một ví dụ, vấn đề của tôi không liên quan gì đến quản lý người dùng. Tôi sẽ chỉnh sửa câu hỏi của mình và đăng ví dụ wordl thực sự của mình. – Remluben

Trả lời

6

Chỉ trong trường hợp bất cứ ai khác gặp những vấn đề tương tự.

Lưu ý rằng mối quan hệ đó bắt buộc phải là camelcase. Vì vậy, trong trường hợp của tôi available_videos() nên đã có sẵnVideo().

Bạn có thể dễ dàng tìm ra điều tra nguồn gốc 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); 
    } 
} 

này cũng giải thích lý do tại sao mã của tôi làm việc, bất cứ khi nào tôi nạp dữ liệu bằng cách sử dụng phương pháp load() trước đó.

Dù sao, ví dụ của tôi hoạt động hoàn toàn ổn, và $ model-> availableVideos luôn trả về Bộ sưu tập.

+0

Không có lý do nào chắc chắn . Bạn nên luôn luôn sử dụng tên hàm với dấu gạch dưới '_' bởi vì, trong MVC nên luôn luôn trở thành một cấu trúc URL như'/controller/function_name'. Nếu bạn không thiết lập định tuyến thích hợp cho hàm, bạn sẽ nhận được tên hàm lạc đà trong URL, không thân thiện với SEO. – Vineet

+3

@Vineet xin lỗi, không. MVC không liên quan gì đến cấu trúc URL. Tệp routes.php định nghĩa ánh xạ từ url thành bộ điều khiển. – Greg

0

Bạn đã tạo ra một mô hình cho "Vai trò". Kiểm tra xem sự cố có tồn tại ngay cả sau khi tạo mô hình cho Vai trò hay không.

+0

Cảm ơn lời khuyên của bạn, nhưng tôi đã tạo ra mô hình liên quan. Như bạn có thể thấy trong câu hỏi đã chỉnh sửa của tôi: theo ý kiến ​​của tôi, không có gì liên quan đến mô hình khác như $ game-> video hoạt động, nhưng $ game-> available_videos không – Remluben

35

Tôi nghĩ rằng đây là cách chính xác:

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

Và sau đó bạn sẽ phải

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

Cảm ơn bạn đã trả lời, ví dụ của bạn hoàn toàn hoạt động, nhưng hiện tôi khi gọi $ game-> available_videos() -> get(). Vấn đề là, tôi muốn sử dụng $ game-> available_videos vì tôi cũng có thể sử dụng $ game-> video mà không gặp sự cố. Theo như tôi biết Eloquent nên tải các mô hình liên quan nếu không háo hức nạp trước, hoặc tôi sai? – Remluben

+0

tên hàm cập nhật thành 'availableVideos'. Nếu bạn chỉ cần video để trả lại các video có sẵn, bạn có thể làm: 'return $ this-> hasMany ('Video') -> trong đó ('available', '=', 1); ' –

5

// thấp hơn đối với một số phiên bản v4

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

// v5

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

Ý tưởng tuyệt vời nhưng cũng giống như vậy bởi vì Relation gọi phương thức đó trên trình tạo truy vấn cho bạn – peter

+0

có, không cần phải gọi cho getQuery ngay bây giờ. thấp hơn phiên bản cần thiết –

+0

Đối với v5 bạn có thể làm: 'return $ this-> hasMany ('Video') -> where ('available', '=', 1);' để làm cho nó sạch hơn –

0

Nếu bạn muốn áp dụng điều kiện trên bảng quan hệ, bạn cũng có thể sử dụng các giải pháp khác .. Giải pháp này đang hoạt động từ đầu của tôi.

public static function getAllAvailableVideos() { 
     $result = self::with(['videos' => function($q) { 
         $q->select('id', 'name'); 
         $q->where('available', '=', 1); 
        }])      
       ->get(); 
     return $result; 
    } 
Các vấn đề liên quan