2013-08-27 26 views
6

Tôi đang tăng sự kiện Yii trên beforeSave của mô hình, chỉ được kích hoạt nếu một thuộc tính cụ thể của mô hình được thay đổi. Cách duy nhất tôi có thể nghĩ về cách thực hiện điều này tại thời điểm này là tạo một đối tượng AR mới và truy vấn DB cho mô hình cũ bằng PK hiện tại, nhưng điều này không được tối ưu hóa rất tốt.Yii khi cập nhật, phát hiện xem một thuộc tính AR cụ thể đã được thay đổi trên beforeSave()

Dưới đây là những gì tôi có ngay bây giờ (lưu ý rằng bảng của tôi không có một PK, đó là lý do tại sao tôi truy vấn bởi tất cả các thuộc tính, bên cạnh những người tôi đang so sánh với - vì thế unset chức năng):

public function beforeSave() 
{ 
    if(!$this->isNewRecord){ // only when a record is modified 
     $newAttributes = $this->attributes; 
     unset($newAttributes['level']); 
     $oldModel = self::model()->findByAttributes($newAttributes); 

     if($oldModel->level != $this->level) 
      // Raising event here 
    } 
    return parent::beforeSave(); 
} 

Có cách tiếp cận nào tốt hơn không? Có thể lưu trữ các thuộc tính cũ trong thuộc tính cục bộ mới trong afterFind()?

Trả lời

12

Bạn cần lưu trữ các thuộc tính cũ trong thuộc tính cục bộ trong lớp AR để có thể so sánh các thuộc tính hiện tại với các thuộc tính cũ bất kỳ lúc nào.

Bước 1. Thêm thuộc tính mới vào lớp AR:

// Stores old attributes on afterFind() so we can compare 
// against them before/after save 
protected $oldAttributes; 

Bước 2. Ghi đè lên số afterFind() của Yii và lưu trữ các thuộc tính ban đầu ngay sau khi chúng được truy lục.

public function afterFind(){ 
    $this->oldAttributes = $this->attributes; 
    return parent::afterFind(); 
} 

Bước 3. So sánh các thuộc tính cũ và mới trong beforeSave/afterSave hoặc bất kỳ nơi nào khác bạn thích bên trong lớp AR. Trong ví dụ bên dưới, chúng tôi đang kiểm tra xem thuộc tính có tên 'level' đã được thay đổi chưa.

public function beforeSave() 
{ 
    if(isset($this->oldAttributes['level']) && $this->level != $this->oldAttributes['level']){ 

      // The attribute is changed. Do something here... 

    } 

    return parent::beforeSave(); 
} 
+1

Đây thực sự là chỉ "sạch" cách để làm điều đó trong Yii. Những gì tôi đã làm là triển khai một ActiveRecord có nguồn gốc có chức năng được tích hợp sẵn và làm cho nó có sẵn cho tất cả các mô hình của tôi. Dễ dàng hơn rất nhiều so với làm lại lần nữa. Tôi cũng đưa ra các phương thức như "getIsChanged()" và "getChangedProperties()", v.v. – Blizz

0

Bạn có thể lưu trữ các thuộc tính cũ với các trường ẩn bên trong biểu mẫu cập nhật thay vì tải lại mô hình.

0

Chỉ trong một dòng

$ changedArray = array_diff_assoc ($ this-> thuộc tính, $ this-> oldAttributes);

foreach($changedArray as $key => $value){ 

    //What ever you want 
    //For attribute use $key 
    //For value use $value 

} 

Trong trường hợp của bạn, bạn muốn sử dụng if ($ key == 'độ') bên trong foreach

Các vấn đề liên quan