2017-08-29 61 views
1

我學會了here在CakePHP 3.x中添加或編輯student時,如何將數據保存到連接表CoursesMemberships的字段。爲了增加grades許多courses我可以在我的addedit形式做到這一點:使用CakePHP 3.x中的控制選項將數據保存到連接表

echo $this->Form->control('courses.0.id', ['type' => 'select', 'options' => $courses]); 
echo $this->Form->control('courses.0._joinData.grade'); 

echo $this->Form->control('courses.1.id', ['type' => 'select', 'options' => $courses]); 
echo $this->Form->control('courses.1._joinData.grade'); 

echo $this->Form->control('courses.2.id', ['type' => 'select', 'options' => $courses]); 
echo $this->Form->control('courses.2._joinData.grade'); 
... 

但這種形式:

  1. 對於每個student固定數量的courses;
  2. 要求從列表中選擇course id'type' => 'select');
  3. 即使不參加,也會將所有課程添加到學生記錄中(嗯,相應的grade字段可以保留爲空,但仍然是)。

有沒有辦法有一個簡單的形式,所有courses列和一個只能複選框course出席並進入相應的grade?我發現使用control它非常具有挑戰性......

編輯:下面提出了一個很不錯的方法@ndm,我實現了它在add.ctp

foreach ($courses as $key => $course) { 

echo $this->Form->control('courses.'.$key.'.id', ['type' => 'checkbox', 'hiddenField' => false, 'value' => $key, 
    'label' => $key]); 
echo $this->Form->control('courses.'.$key.'._joinData.grades'); 
} 

,並相應糾正StudentsTable.php。它運行沒有問題。

但是,如果我做同樣的edit.ctp,先前保存的記錄(例如1,3,5和7 courses現在列爲1,2和3顯示grades爲前3日第5和第7 courses和我知道第一個記錄消失了,因爲我的coursesid=1(循環中的$鍵也是這樣)開頭,因此'courses.0.id'缺失,但一般問題是通過beforeMarshal函數刪除空字段edit.ctp形式不再是公認的,我無法找到一個合理的方式來編輯student's記錄。

回答

0

沒有構建支持你想要實現的內容,你必須想出一個自定義解決方案,這可能需要混合使用表單和編組邏輯或JavaScript。

您可以創建例如一個複選框列表,並使用id值(至極將是零的情況下,該複選框未選中,或在情況下,它的ID是檢查)除去從選中的條目編組之前提交的數據,這樣的事情:

echo $this->Form->control('courses.0.id', [ 
    'type' => 'checkbox', 
    'value' => $courses[0]->id, 
    'label' => $courses[0]->title 
]); 
echo $this->Form->control('courses.0._joinData.grade'); 

echo $this->Form->control('courses.1.id', [ 
    'type' => 'checkbox', 
    'value' => $courses[1]->id, 
    'label' => $courses[1]->title 
]); 
echo $this->Form->control('courses.1._joinData.grade'); 

// ... 
// in the `StudentsTable` class 

public function beforeMarshal(\Cake\Event\Event $event, \ArrayObject $data, \ArrayObject $options) 
{ 
    forach ($data['courses'] as $key => $course) { 
     if (empty($course['id'])) { 
      unset($data['courses'][$key]) 
     } 
    } 
} 

另外,您可以使用JavaScript來禁用有關,使他們沒有被擺在首位提交的複選框的控件。爲了正常工作,您需要確保您禁用默認情況下爲複選框生成的隱藏字段(請參閱hiddenField選項),否則將發送零未選中複選框。

這裏有一個快速的,未經檢驗的jQuery的例子來說明這個原則:

echo $this->Form->control('courses.0.id', [ 
    'class' => 'course-checkbox', 
    'data-join-data-input' => '#course-join-data-0', 
    'type' => 'checkbox', 
    'hiddenField' => false, // no fallback, unchecked boxes aren't being submitted 
    'value' => $courses[0]->id, 
    'label' => $courses[0]->title 
]); 
echo $this->Form->control('courses.0._joinData.grade', [ 
    'id' => 'course-join-data-0', 
    'disabled' => true 
]); 

// ... 
$('.course-checkbox').each(function() { 
    var $checkbox = $(this); 
    var $joinDataInput = $($checkbox.data('join-data-input')); 

    $checkbox.on('change', function() { 
     $joinDataInput.prop('disabled', !$checkbox.prop('checked')); 
    }); 
}); 

又見

+0

我非常感謝你的優雅的解決方案和詳細的解釋!我開始實現第一個並得到這個錯誤消息:不能使用Cake \ ORM \ Query類型的對象作爲數組(行'value'=> $ courses [0] - > id) –

+0

您必須將其轉換首先使用'$ courses-> toArray()'來創建一個數組,而'$ courses'需要是一個常規查詢(而不是一個列表)。我假設你想給你的示例代碼片段生成特定數量的課程。或者,您可以遍歷'$ courses',並且在'$ courses'是列表查找器查詢的情況下使用鍵/值而不是訪問屬性。 – ndm

+0

令人驚歎!一切正如你所解釋的那樣。一如既往。非常感謝! –

相關問題