CakePHP 3 - 有条件地为关联表

时间:2017-04-06 13:26:37

标签: php mysql cakephp cakephp-3.0

我有这三个表:

  • 预订(hasOne Sessions)
  • 会话(hasOne文件),外键booking_id链接到预订
  • 文件(belongsTo Sessions),其中外键session_id链接到Sessions

在BookingsController中,我有两个功能:

  • 新功能(功能与添加功能相同)
  • 确认(编辑功能等功能)

当用户首次提交新的预订数据条目时,在为预订和会话创建并保存newEntity时,不会为文件创建和保存newEntity。但是,当正在更新和确认预订/会话时,即第一次创建文件中的newEntity时。由于Confirm函数可以多次使用,因此我使用条件if语句来确定是否存在关联的Files条目 - 如果存在,则创建newEntity for Files,修补然后保存。如果没有,它只是修补并保存。

在我的确认功能中:

public function confirm($id = null)
{
    $booking = $this->Bookings->get($id,[
        'contain' => ['Sessions']
    ]);
    if ($this->request->is(['patch', 'post', 'put'])) {
        $booking = $this->Bookings->patchEntity($booking, $this->request->data,[
            'contain' => ['Sessions']
        ]);
        $fileTable = TableRegistry::get('Files');
        $findFiles = $fileTable->find()->where([
            'session_id' => $session['id']
        ])->first();
        if($findFiles == null){
            $findFiles = $fileTable->newEntity();
            $findFiles = $fileTable->patchEntity($findFiles, $data);
            $findFiles->session_id = $booking['session']['id'];
            if($fileTable->save($findFiles)){

            } else {

            }
        } else {
            $findFiles = $filesTable->patchEntity($findFiles, $data);
            if($filesTable->save($findFiles)){

            } else {

            }
        }
        if ($this->Bookings->save($booking)) {
            $this->Flash->success(__('The booking has been saved.'));
            return $this->redirect(['action' => 'index']);
        } else {
            $this->Flash->error(__('The booking could not be saved. Please, try again.'));
        }
        $this->set(compact('booking'));
        $this->set('_serialize', ['booking']);
    }
}

但是,在尝试使用Confirm功能时,我会在Sessions表中获得有关booking_id外键的完整性约束违规。我已经确定通过删除有关Files表的所有条件保存代码,该函数工作正常,但这意味着在需要时都不会创建newEntity for Files。

更简单的方法是我认为只包含新功能中的文件,但由于某些预订可能被取消,可能会有很多空的文件数据条目。

更新:包括模型和确认功能的视图和表单输入。

以下是BookingsController中的Confirm功能视图:

<?= $this->Form->create($booking) ?>
<fieldset>
    <legend><?= __('Confirm Booking') ?></legend>
            <?php
        echo $this->Form->input('session.startdate', ['class'=>'form-control']);
        echo $this->Form->input('session.enddate', ['class'=>'form-control']);
        echo $this->Form->input('session.no_people', ['class'=>'form-control']);
    ?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>

各个表的模型。

预订:

public function initialize(array $config)
{
    parent::initialize($config);

    $this->table('bookings');
    $this->displayField('id');
    $this->primaryKey('id');

    $this->addBehavior('Timestamp');

    $this->hasOne('Sessions', [
        'foreignKey' => 'booking_id'
    ]);
}
public function validationDefault(Validator $validator)
{
    $validator
        ->integer('id')
        ->allowEmpty('id', 'create');

    return $validator;
}

会话:

public function initialize(array $config)
{
    parent::initialize($config);

    $this->table('sessions');
    $this->displayField('id');
    $this->primaryKey('id');

    $this->addBehavior('Timestamp');

    $this->belongsTo('Bookings', [
        'foreignKey' => 'booking_id',
        'joinType' => 'INNER'
    ]);
    $this->hasOne('Templates', [
        'foreignKey' => 'session_id'
    ]);
}

public function validationDefault(Validator $validator)
{
    $validator
        ->integer('id')
        ->allowEmpty('id', 'create');

    $validator
        ->date('startdate')
        ->requirePresence('startdate', 'create')
        ->notEmpty('startdate');

    $validator
        ->date('enddate')
        ->requirePresence('enddate', 'create')
        ->notEmpty('enddate');
    $validator
        ->integer('no_people')
        ->requirePresence('no_people', 'create')
        ->notEmpty('no_people');

    return $validator;
}

public function buildRules(RulesChecker $rules)
{
    $rules->add($rules->existsIn(['booking_id'], 'Bookings'));
    return $rules;
}

文件:

public function initialize(array $config)
{
    parent::initialize($config);

    $this->table('files');
    $this->displayField('id');
    $this->primaryKey('id');

    $this->addBehavior('Timestamp');

    $this->belongsTo('Sessions', [
        'foreignKey' => 'session_id',
        'joinType' => 'INNER'
    ]);
}

public function validationDefault(Validator $validator)
{
    $validator
        ->integer('id')
        ->allowEmpty('id', 'create');

    $validator
        ->allowEmpty('link');

    $validator
        ->allowEmpty('name');

    return $validator;
}

public function buildRules(RulesChecker $rules)
{
    $rules->add($rules->existsIn(['session_id'], 'Sessions'));

    return $rules;
}

2 个答案:

答案 0 :(得分:1)

外键session_id是必需属性(这就是文件无法保存的原因)。我已将功能更改为以下内容:

public function confirm($id = null)
{
    $booking = $this->Bookings->get($id,[
        'contain' => ['Sessions', 'Sessions.Files']
    ]);
    if ($this->request->is(['patch', 'post', 'put'])) {
        if($booking->session->file == null){ //checks for existing Files array
            $template = $this->Bookings->Sessions->Files->newEntity(); //creates new Files entity if one doesn't exist for the associated session
            $template->session_id = $booking->session->id; //fills in the foreign key with the currently active session primary key.
            if($this->Bookings->Sessions->Templates->save($template)){ //saves the File entity

            } else {

            }
        }
        $booking = $this->Bookings->patchEntity($booking, $this->request->data,[
            'contain' => ['Sessions', 'Sessions.Files']
        ]);
        $fileTable = TableRegistry::get('Files');
        $file = $fileTable->find('all',[
            'contain' => ['Sessions'],
            'conditions' => ['Sessions.booking_id' => $booking->id, 'Files.session_id' => $booking->session->id]
        ])->first();
        if($file->session_id != $data['session']['id']){ //checks for any changes in session_id
            $file->engineer_id = $data['session']['id']; //changes value to match if there isn't a match 
            $fileTable->save($template);
        }
        if ($this->Bookings->save($booking)) {
            $this->Flash->success(__('The booking has been saved.'));
            return $this->redirect(['action' => 'index']);
        } else {
            $this->Flash->error(__('The booking could not be saved. Please, try again.'));
        }
        $this->set(compact('booking'));
        $this->set('_serialize', ['booking']);
    }
}

答案 1 :(得分:0)

这样的事情应该有效。如果存在id,Cake会将查询更改为UPDATE,否则使用INSERT。

public function confirm($id = null)
{
    $booking = $this->Bookings->get($id, [
        'contain' => ['Sessions' => ['Files']]
    ]);
    if ($this->request->is(['patch', 'post', 'put'])) {
        $booking = $this->Bookings->patchEntity($booking, $this->request->data, [
            'associated' => ['Sessions' => ['associated' => ['Files']]]
        ]);

        if ($this->Bookings->save($booking)) {
            $this->Flash->success(__('The booking has been saved.'));
            return $this->redirect(['action' => 'index']);
        } else {
            $this->Flash->error(__('The booking could not be saved. Please, try again.'));
        }
        $this->set(compact('booking'));
        $this->set('_serialize', ['booking']);
    }
}
相关问题