2014-11-30 2 views
0

Для управления параллелизмом - это обеспечение того, что данные, сохраненные в базе данных, не устарели или уже отредактированы каким-либо другим пользователем - в моем приложении CakePHP я использую атрибут modified в моих функциях редактирования. Ниже приведен фрагмент кода, который находится в моем контроллере.Управление параллелизмом данных в CakePHP - Поведение/Контроллер/Модель?

$this->MyModel->recursive = -1; 
$event = $this->MyModel->findById($id); 
$requestTimeStamp = new DateTime($this->request->data['MyModel']['modified']); 
$dbTimeStamp = new DateTime($event['MyModel']['modified']); 
if ($requestTimeStamp < $dbTimeStamp) { 
    $response = array(
     'success' => false, 
     'id' => $id, 
     'message' => 'A concurrency error occurred while trying to save. Please try again'); 
    echo json_encode($response); 
    exit; 
} else { 
    //... continue processing 
} 

Этот код работает отлично - но, как я стараюсь, чтобы оптимизировать его по моей заявке, я пытаюсь выяснить, где лучше разместить. Является ли это лучше всего в моем классе AppModel или лучше создать Behavior для того же самого или он лучше всего останется в контроллере? Я полагаю, что идеальным вариантом будет рассмотрение производительности и минимизация затрат на загрузку класса, а также накладные расходы на доступ к базам данных.

Кто-нибудь сталкивался с этой проблемой раньше? Мысли/предложения оценили.

ответ

0

Таким образом, я решил это, сделав параллелизм проверкой части моего метода AppModel->beforeSave(). Ниже приведен код для справки других пользователей

/* 
* Incorporated concurrency check in the beforeSave callback method to ensure that data is not stale before user saves. 
* The function checks if the model has a `modified` field, before it proceeds. If the model does not have such a method 
* then concurrency does not apply to this data structure. Upon proceeding, the method checks to see if the value of modified 
* data is the same in the database as well as the request that invokes this method. If they are not same then the save is 
* aborted 
* This method requires the view or controller to pass a variable called data[ModelName][modified]. 
* This variable must contain the value of the modified field when the record was read and it must be passed back as such. 
* I usually set a hidden form field in my view like below - 
* <input type="hidden" name="data[Model][modified]" value="<?php echo $model['modifed']; ?>" /> 
*/ 
    public function beforeSave($options = array()) { 
     if ($this->hasField('modified') && isset($this->data[$this->name]['id']) && isset($this->data[$this->name]['modified'])) { 
      CakeLog::debug('AppModel: beforeSave - inside concurrency check'); 
      CakeLog::debug($this->data); 
      $this->recursive = -1; 

      // run a select statement to ensure the modified date in the database has not changed. If it has changed then 
      // the below find query will return 0 rows 
      $row = $this->find('first', array(
       'fields' => array(
        'id', 'modified' 
       ), 
       'conditions' => array(
        'id' => $this->data[$this->name]['id'], 
        'modified' => $this->data[$this->name]['modified'] 
       ) 
      )); 

      // if no row is returned then error out and return - basically a concurrency error has occurred 
      if (!$row) { 
       CakeLog::error($this->name.':Concurrency error - [row-id:'.$this->data[$this->name]['id'].']'); 
       return false; 
      } 

      // if a row was retrned then there is no concurrency error, so proceed but change the modified date 
      // to current timestamp to reflect accuracy 
      $this->data[$this->name]['modified'] = date('Y-m-d H:i:s'); 
      return true; 
     } 
    }