hasMany와 belongsTo

이 게시물 정보
기본적인 사용법을 써 보았습니다.

하고 싶은 일
상위 테이블의 한 레코드에 대해 하위 테이블의 여러 레코드를 연결하고 싶습니다.
예: 사용자가 여러 개의 취미를 가지고 있음
상위 테이블: 사용자
아이 테이블: 취미

등장하는 MVC
  • /Controller/UsersController.php
  • /Template/Users/edit.ctp
  • /Table/UsersTable.php
  • /Table/UserHobbiesTable.php
  • /Entity/UserHhobby.php

  • 테이블
        users
          id integer not null
    
        user_hobbies
          id integer not null
          user_id integer not null
          hobby_id integer not null
    

    /Table/UsersTable.php
        public function initialize(array $config)
        {
            $this->setTable('users');
            $this->setDisplayField('id');
            $this->setPrimaryKey('id');
    
            $this->hasMany('UserHobbies', [
                'foreignKey' => 'user_id',
                'saveStrategy' => 'replace',
                'dependent' => true,
            ]);
        }
        public function beforeMarshal(\Cake\Event\Event $event, $data, $options)
        {
            // リクエストデータを操作します。
            if (!empty($data['user_hobbies']['hobby_id'])) {
                foreach ($data['user_hobbies']['hobby_id'] as $value) {
                    $hobbies[] = ['hobby_id' => $value];
                }
                $data['user_hobbies'] = $hobbies;
            }
        }
        public function beforeSave(\Cake\Event\Event $event, $entity)
        {
            // 更新の場合、userbeforeSaveuser_idに紐付く、UserHobbiesテーブルを全削除します。
            if (!$entity->isNew()) {
                $this->UserHobbies->deleteAll(['user_id' => $entity->id]);
            }
        }
    

    /Table/UserHobbiesTable.php
        public function initialize(array $config)
        {
            $this->setTable('user_hobbies');
            $this->setDisplayField('id');
            $this->setPrimaryKey('id');
    
            $this->belongsTo('Users', [
                'foreignKey' => 'user_id',
                'joinType' => 'LEFT'
            ]);
        }
    
        public function buildRules(RulesChecker $rules)
        {
            $rules->add($rules->existsIn(['user_id'], 'users'));
    
            return $rules;
        }
        public function beforeSave(\Cake\Event\Event $event, $entity)
        {
            // 趣味がひとつも選択されていない場合、イベントを中止します。
            if (!$entity->hobby_id) {
                $event->stopPropagation();
            }
        }
    

    /Entity/UserHobby.php
        protected $_accessible = [
            'user_id' => true,
            'hobby_id' => true
        ];
    

    /Controller/UsersController.php
        public function edit($id = null)
        {
            try {
                $entity = $this->Users->get($id, ['contain' => ['UserHobbies']]);
            } catch (\Exception $e) {
                return $this->redirect('index');
            }
            if ($entity->user_hobbies) {
                $entity->user_hobbies = [
                    'hobby_id' => Hash::extract($entity->user_hobbies, '{n}.hobby_id'),
                ];
            }
            $this->set(compact('entity'));
        }
    

    이렇게하면 업데이트 화면 (edit)에서
    user_hobbies (array)
     hobby_id (array)
      0 1
     1 3
    에서 ctp에 값을 전달할 수 있습니다.

    /Template/Users/edit.ctp
    <?php
        $hobby = array(
            1=>"音楽鑑賞",
            2=>"映画鑑賞",
            3=>"読書",
            4=>"ジョギング"
        );
    ?>
    <?= $this->Form->input('user_hobbies.hobby_id', [
        'type' => 'select',
        'options' => $hobby,
        'multiple' => 'checkbox',
        'label' => false,
        'required' => false,
    ]) ?>
    

    음악 감상과 독서를 선택하고 올바르게 저장되면 아래와 같이 됩니다.

    user_hobbies 테이블
        id  user_id  hobby_id 
        1         1         1
        2         1         3
    

    좋은 웹페이지 즐겨찾기