2012-08-15 28 views
5

Tôi không thể tìm thấy quá nhiều tài liệu về việc áp dụng phạm vi mặc định cho mô hình trong yii, tôi tự hỏi liệu có ai đó có thể giải thích hoặc chỉ cho tôi đúng hướng không.áp dụng phạm vi mặc định với tham chiếu đến mối quan hệ trong yii

Phiên bản nhanh chóng của câu hỏi của tôi:

Có thể thêm một liên quan đến một phạm vi mặc định, hoặc để thêm một 'với' tiêu chuẩn theo mặc định cho tất cả các tìm kiếm AR trên một mô hình?

Phiên bản dài của câu hỏi của tôi:

Một bản tóm tắt nhanh chóng của ứng dụng của tôi:

Tôi có hai mô hình, provideritem. Trong đó có một mối quan hệ m: 1, nơi một nhà cung cấp có thể có nhiều mặt hàng, nhưng mỗi mục chỉ có thể có một nhà cung cấp.

Cho đến nay tôi có những mối quan hệ:

class Provider extends CActiveRecord 
{ 
    ... 
    public function relations() 
    { 
     return array(
      'items' => array(self::HAS_MANY, 'Item', 'id_provider', 'order'=>'rank DESC'), 
     ); 
    } 
    ... 
} 

class Item extends CActiveRecord 
{ 
    ... 
    public function relations() 
    { 
     return array(
      'provider' => array(self::BELONGS_TO, 'Provider', 'id_provider'), 
     ); 
    } 
    ... 
} 

Trong mô hình các mặt hàng của tôi, tôi đã có một defaultScope đó lọc ra tất cả các mục ẩn (tức là chỉ hiển thị các mặt hàng được thiết lập để offline = false):

public function defaultScope() 
{ 
    $alias = $this->getTableAlias(false,false); 
    return array(
     'condition'=>"`$alias`.`offline` = false", 
    ); 
} 

Điều tôi muốn làm bây giờ, cũng lọc ra các mục mà nhà cung cấp của họ được đặt thành ngoại tuyến (tức là chỉ hiển thị các mục ở đây provider.offline = false cùng với item.offline = false hiện tại).

tôi đã cố gắng tham gia vào bảng các nhà cung cấp trong defaultScope:

public function defaultScope() 
{ 
    $alias = $this->getTableAlias(false,false); 
    return array(
     'join'=>"JOIN `provider` AS `provider` ON `provider`.`id` = `$alias`.`id_provider`", 
     'condition'=>"`$alias`.`offline` = false AND `provider`.`offline` = false", 
    ); 
} 

Tuy nhiên JOIN áp dụng sau khi câu lệnh ON, và causese một lỗi (CDbCommand failed to execute the SQL statement: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'provider.offline' in 'on clause').

Tôi cũng đã thử thêm một với tiêu chí để các defaultScope:

public function defaultScope() 
{ 
    $alias = $this->getTableAlias(false,false); 
    return array(
     'with'=>"provider", 
     'condition'=>"`$alias`.`offline` = false AND `provider`.`offline` = false", 
    ); 
} 

Nhưng tôi nhận được lỗi tương tự: SQLSTATE [42S22]: Cột không tìm thấy: 1054 Unknown column 'provider.offline' trong ' trên mệnh đề'`).

Mọi đề xuất?

Trả lời

6

Có một vài điều tôi sẽ cố gắng:

Thứ nhất, thay đổi tình trạng của bạn để áp dụng cho toàn bộ điều (và đừng quên rằng nếu không có mục cho một nhà cung cấp, nó sẽ không trả lại nhà cung cấp)

public function defaultScope() 
{ 
    return array(
     'with'=> array("provider" => array(
      'condition'=> "t.offline = false AND provider.offline = false", 
     ) 
    ); 
} 

thứ hai, hãy thử thêm phạm vi để mô hình của bạn và sau đó tham khảo chúng trong phạm vi mặc định như vậy:

public function defaultScope() 
{ 
    return array(
     'scopes'=> array('default'), 
    ); 
} 

class Provider extends CActiveRecord 
{ 
    ... 
    public function scopes() 
    { 
     ... 
    } 
    ... 
} 

class Item extends CActiveRecord 
{ 
    ... 
    public function scopes() 
    { 
     ... 
    } 
    ... 
} 
+0

Dĩ nhiên ! Tôi đã đặt điều kiện trong tuyên bố 'điều kiện' chính, không phải trong 'với'. Đề xuất đầu tiên của bạn hoạt động hoàn hảo, cảm ơn! – Stu

0

Chỉ có một vấn đề tương tự. Trong khi lời đề nghị đầu tiên của Benjamin đã chỉ cho tôi đúng hướng (được đánh giá cao!), Tôi đã gặp phải một vấn đề không mong muốn bằng cách sử dụng 'điều kiện' và 'với', điều có thể hữu ích nếu bạn biết.

Nếu bảng bạn đang tham gia ('nhà cung cấp' trong ví dụ) có mặc địnhScope của nó, nó xuất hiện được áp dụng như một phần của mệnh đề SQL ON khi bạn sử dụng 'with', hạn chế các hàng trả về.

Vì kết nối bên ngoài được sử dụng, bạn vẫn nhận được bản ghi cho mỗi hàng trong bảng chính ('mục'), nhưng trường 'nhà cung cấp' có thể không có giá trị cho một số hàng. trả lại.

Điều này không gây ra vấn đề cho đến khi bạn cố gắng áp dụng 'điều kiện' liên quan đến một trong các trường của nhà cung cấp đó. Điều này được thực hiện như một phần của mệnh đề WHERE được xử lý sau khi kết nối, nhưng vì trường đó là null, điều kiện sẽ thất bại và bản ghi sẽ không được trả về.

Trong một số trường hợp này có thể là hành vi mà bạn muốn, nhưng trong những trường hợp khác mà bạn có thể muốn di chuyển các bài kiểm tra trên các lĩnh vực 'cung cấp' để trong tham gia bằng công on tùy chọn:

public function defaultScope() 
{ 
return array(
    'with'=> array("provider" => array(
     'condition'=> "t.offline = false", 
     'on'=>"provider.offline = false", 
    ) 
); 
} 
Các vấn đề liên quan