2011-07-03 3 views
1

HABTM과 관련된 두 가지 모델 : 부재 및 사용자가 있습니다. 문맥을 위해, 사용자는 결석을 신청합니다 (따라서, 사용자는 신청자에게 별칭이 부여되며 결석은 부재자에게 적용됩니다). HABTM 레코드를 추가하고 HABTM 레코드를 각각 제거하는 '적용'및 '취소'에 대한 컨트롤러 기능을 만들려고합니다. 하나의 레코드를 저장할 지점까지 코드를 가져 왔지만 그 이상은 아닙니다. 지금 '적용'에 대한 내 컨트롤러 코드는 두 개의 레코드를 추가하기 위해 하드 코드되어 있지만 마지막으로 요청한 코드 만 추가합니다. 여기 내 컨트롤러 코드입니다 :CakePHP는 saveAll에서 다른 HABTM 레코드를 삭제합니다.

function apply($id = null) { 
      if (!$id) { 
        $this->Session->setFlash(__('Invalid id for absence', true)); 
        $this->redirect(array('action'=>'index')); 
      } 

      $this->Absence->recursive = 1; 
      $user = $this->Session->read('User'); 
      $absence = $this->Absence->read(null, $id); 
      $data = array(
        array(
          'Applicant' => array('id' => 1), 
          'Absence' => array('id' => 4) 
        ), 
        array(
          'Applicant' => array('id' => 2), 
          'Absence' => array('id' => 4) 
        ) 
      ); 

      //$data = array_unique($data); 
      if ($this->Absence->saveAll($data)) { 
        $this->Session->setFlash('Application was successful'); 
      } else { 
        $this->Session->setFlash('Application failed'); 
      } 
      $this->set(compact('data')); 
    } 

내가 디버그 쿼리에서 처리되는 $ 데이터의 두 항목을 볼 수 있지만 어떤 이유 중 하나가 삭제됩니다. 왜 그런지 알아? 여기에 해당 컨트롤러 코드에 의해 실행되는 쿼리의 일부가 (19 주, 25을, 26) :

11 START TRANSACTION  0  0 
12 SELECT COUNT(*) AS `count` FROM `absences` AS `Absence` WHERE `Absence`.`id` = 4  1 1 0 
13 SELECT COUNT(*) AS `count` FROM `absences` AS `Absence` WHERE `Absence`.`id` = 4  1 1 0 
14 SELECT COUNT(*) AS `count` FROM `absences` AS `Absence` WHERE `Absence`.`id` = 4  1 1 0 
15 SELECT COUNT(*) AS `count` FROM `absences` AS `Absence` WHERE `Absence`.`id` = 4  1 1 0 
16 SELECT COUNT(*) AS `count` FROM `absences` AS `Absence` WHERE `Absence`.`id` = 4  1 1 0 
17 UPDATE `absences` SET `id` = 4, `modified` = '2011-07-03 00:28:39' WHERE `absences`.`id` = 4  1  0 
18 SELECT `AbsencesUser`.`user_id` FROM `absences_users` AS `AbsencesUser` WHERE `AbsencesUser`.`absence_id` = 4  0 0 0 
19 INSERT INTO `absences_users` (`absence_id`,`user_id`) VALUES (4,1)  1  0 
20 SELECT COUNT(*) AS `count` FROM `absences` AS `Absence` WHERE `Absence`.`id` = 4  1 1 0 
21 SELECT COUNT(*) AS `count` FROM `absences` AS `Absence` WHERE `Absence`.`id` = 4  1 1 0 
22 SELECT COUNT(*) AS `count` FROM `absences` AS `Absence` WHERE `Absence`.`id` = 4  1 1 0 
23 UPDATE `absences` SET `id` = 4, `modified` = '2011-07-03 00:28:39' WHERE `absences`.`id` = 4  0  0 
24 SELECT `AbsencesUser`.`user_id` FROM `absences_users` AS `AbsencesUser` WHERE `AbsencesUser`.`absence_id` = 4  1 1 0 
25 DELETE `AbsencesUser` FROM `absences_users` AS `AbsencesUser` WHERE `AbsencesUser`.`absence_id` = 4 AND `AbsencesUser`.`user_id` = (1)   1  1 
26 INSERT INTO `absences_users` (`absence_id`,`user_id`) VALUES (4,2)  1  0 
27 COMMIT  0  123 

답변

1

내가 디버그 쿼리에서 처리되는 $ 데이터의 두 항목을 볼 수 있지만, 웬일인지 사람은 삭제된다. 왜 그런지 알아?

확실한 이유는 이것이 Cake의 기본 동작이기 때문입니다. Read this section about saving data with HABTM.

이 섹션에서는 조인 테이블에 대해 별도의 모델을 만드는 방법에 대해 간단하게 이야기하지만 그 의미 또는 수행 방식을 정확하게 설명하는 것은 충분하지 않다고 생각합니다. 이 방법이 귀하의 접근 방식이어야한다고 제안하는 것은 아니며 정보를 조사하고 귀하의 앱을 기반으로 결정을 내려야합니다! 데이터 회로도는 가장 중요한 측면 중 하나입니다.

저는 Ruby on Rails에 익숙하지 않지만 본질적으로 RoR's has_many :through 모델 연관을 복제하려고합니다. 간단히 말해서 다른 모델과 마찬가지로 HABTM join 테이블을 사용하여 작업 할 수 있기를 원합니다.

그래서 우리는

class Absence extends AppModel { 

    public $belongsTo = array('AbsentUser'); 
    ... 

귀하의 User 모델 ... ...이

귀하의 Absence 모델처럼 우리의 새로운 모델 연결을 설정하는 것

class User extends AppModel { 
    public $belongsTo = array('AbsentUser'); 
    ... 

귀하의 새로운AbsentUser 모델 ...

class AbsentUser extends AppModel { 
    public $hasMany = array('Absence', 'User'); 
    ... 

이제 AbsentUser을 자체 모델로 사용하여 Cake의 기본 HABTM 동작을 우회 할 수 있습니다. 또한 선택하면 추가 필드를 통합하기 위해 AbsentUser 데이터를 쉽게 확장 할 수 있습니다. 예를 들어, 특정 부재에 대한 특정 정보를 저장할 수 있습니다.

나는 또한 fat models and skinny controllers.을 가지고 있는지 확인하는 것이 좋습니다. 당신은 나중에 자신을 사랑하게 될 것입니다.

+0

나는 조인을위한 별도의 모델에 대한 섹션을 보았지만, 내가 필요로하는 것을 조합하지 않았다. 확고한 접근 방식처럼 보입니다. 감사! – Jay

+0

감사합니다. 이것이 당신을 위해 작동하지 않으면 알려주십시오. 내 대답이 실제로 뭔가를 해결할 때가 마음에 듭니다. – cspray

0

는 버전 2.1 이후로 당신은 지금 저장 작업시 별도의 데이터 손실을 회피 keepExisting독특한 설정을 설정할 수 있습니다.

var $hasAndBelongsToMany = array(
     'User' => array(
      'unique' => 'keepExisting', 
      ), 
    ); 
관련 문제