2010-01-11 2 views
5

У меня есть таблица проектов и таблица Users, которые связаны отношением HABTM. На странице «Добавить» нового проекта у меня есть несколько флажков, чтобы выбрать «Пользователи для нового проекта». Я хочу иметь хотя бы одного пользователя для проекта. Каков наилучший способ приблизиться к этому в CakePHP?Проверка формы HABTM в CakePHP

ответ

19

Попробуйте это:

// app/models/project.php 
/** 
* An additional validation check to ensure at least one User is 
* selected. Spoofs Cake into thinking that there are validation 
* errors on the Project model by invalidating a non-existent field 
* on the Project model, then also invalidates the habtm field as 
* well, so when the form is re-displayed, the error is displayed 
* on the User field. 
**/ 
function beforeValidate() { 
    if (!isset($this->data['User']['User']) 
    || empty($this->data['User']['User'])) { 
    $this->invalidate('non_existent_field'); // fake validation error on Project 
    $this->User->invalidate('User', 'Please select at least one user'); 
    } 
    return true; 
} 
+0

Отлично! Спасибо Нейлу. – Sabourinov

+0

Это работает, чтобы проверить, но когда страница перезагружается, я потерял некоторые данные и получаю ошибки из-за отсутствия данных. Есть предположения? – Dave

2

Блог teknoid имеет довольно глубокое решение вашей проблемы здесь. Самый простой способ сделать это - добавить пользовательскую проверку в вашу модель, как вы упомянули в своем комментарии выше. Проверьте http://teknoid.wordpress.com/2008/10/16/how-to-validate-habtm-data/

Из статьи, где Tag HABTM Post (:: Проект HABTM Пользователи):

Во-первых, мы утверждаем модель тегов, с помощью , используя данные из формы, чтобы гарантировать, что в был выбран хотя бы один тег. Если так, мы сохраняем сообщение и соответствующие теги.

6

Я просто смотрел на свою проблему сам по проекту и наткнулся на несколько более элегантное решение, до тех пор, пока вы только имеете дело с отношения HABTM и вам нужно убедиться, что выбран хотя бы один флажок.

так, например, вы редактируете проект, и вы хотите, чтобы это было связано с, по меньшей мере, один пользователь

Добавить это beforeValidate()

// проверить HABTM модель и добавить к данным

foreach($this->hasAndBelongsToMany as $k=>$v) { 
    if(isset($this->data[$k][$k])) 
    { 
    $this->data[$this->alias][$k] = $this->data[$k][$k]; 
    } 
    } 

В правилах проверки добавьте следующее:

'User' => array(
    'rule' => array('multiple', array('min' => 1)), 
    'message' => 'Please select one or more users' 
) 
+1

Это работает по большей части, но div, содержащий ошибку, не появляется. Есть идеи? – Joseph

12

I-й пошатнулся по той же проблеме, но теперь - через 3 года - с CakePHP 2.3.

Должно быть ясно; Group имеет и принадлежит User. Я имел форму, как это:

// View/Groups/add.ctp 
echo $this->Form->input('name'); 
echo $this->Form->input('User'); 

С правила проверки, как в ответ user448164 в:

// Model/Group.php 
public $validate = array(
    'User' => array(
     'rule' => array('multiple', array('min' => 1)), 
     'message' => 'Please select one or more users' 
    ) 
); 

Это не сработало, после погуглить его, я нашел этот вопрос, который не мог» t остается лучшим решением. Тогда я попробовал несколько вещей, и обнаружил, что это работает просто отлично:

// View/Groups/add.ctp 
echo $this->Form->input('name'); 
echo $this->Form->input('Group.User'); 

Слишком простое решение, но пришлось копаться в ней, чтобы узнать, что это работает таким образом.

Надеюсь, кому-то это поможет.

Обновление для CakePHP 2.4.x (возможно, 2.3.x, а)

Когда я писал этот ответ, я использовал CakePHP 2.3.х. В то время он отлично работал для проверки и сохранения данных.Теперь, применяя тот же код в новом проекте, используя CakePHP 2.4.x, он больше не работает.

Я создал тестовый пример, используя следующий код:

$data = array(
    'User' => array(
     'Client' => array(8) 
    ), 
); 
$this->User->create(); 
$this->User->saveAll($data); 

Моя первая мысль была: Сохранение всех спасательных средств все модели «корень», что на самом деле имеет смысл для меня. Чтобы сохранить глубже, чем просто «корневые», вам нужно добавить опцию deep. Итак, у меня закончился следующий код:

$data = array(
    'User' => array(
     'Client' => array(8) 
    ), 
); 
$this->User->create(); 
$this->User->saveAll($data, array('deep' => true)); 

Работает как очарование! Счастливое кодирование. :)

Обновление (2014/03/06)

снова Борьба с той же проблемой, в данном случае с hasMany вместо habtm. Похоже, он ведет себя одинаково. Но я снова нашел этот ответ и смутился.

Я хотел бы уточнить, что это ключ к использованию Group.User вместо User на вашем входе. Иначе он не будет использовать проверку модели User.

+3

Это правильный ответ для Cake 2.3 – Steven

+1

Я сделал это изменение для моего кода для аналогичной проблемы. Валидация работает правильно, но таблица базы данных, связанная с помощью HABTM, больше не автоматически сохраняет новые данные. Чего не хватает? – Blazemonger

+0

@Blazemonger Когда я написал его, он отлично работал как для проверки, так и для сохранения. Но как-то он сломан в последней версии CakePHP. Давайте сделаем еще больше копания ... --- См. Обновление ответа для получения дополнительной информации! –

1

Если вы используете CakePHP 2.3.x, возможно, потребуется добавить этот код в вашей модели в дополнение к коду, который GuidoH при условии, в противном случае ваши данные HABTM модель не может сохранить:

public function beforeSave($options = array()){ 
    foreach (array_keys($this->hasAndBelongsToMany) as $model){ 
    if(isset($this->data[$this->name][$model])){ 
     $this->data[$model][$model] = $this->data[$this->name][$model]; 
     unset($this->data[$this->name][$model]); 
    } 
    } 
    return true; 
} 
0

Согласно моему комментарию к ответу Guido выше, я использую ответ Guido точно, однако я изменяю данные с обратным вызовом beforeSave, прежде чем он сохраняет базу данных.

У меня есть этот вопрос на торт 2.4.5+

public function beforeSave($options = array()) { 
    $temp = $this->data['Group']['User']; 
    unset($this->data['Group']['User']); 
    $this->data['User']['User'] = $temp; 

    return true; 
} 
2

2016 обновление для CakePHP 2.7

Полный ответ здесь: HABTM form validation with CakePHP 2.x


TL; DR;

AppModel.php

public function beforeValidate($options = array()){ 
    foreach (array_keys($this->hasAndBelongsToMany) as $model){ 
    if(isset($this->data[$model][$model])) 
     $this->data[$this->name][$model] = $this->data[$model][$model]; 
    } 
    return true; 
} 

public function afterValidate($options = array()){ 
    foreach (array_keys($this->hasAndBelongsToMany) as $model){ 
    unset($this->data[$this->name][$model]); 
    if(isset($this->validationErrors[$model])) 
     $this->$model->validationErrors[$model] = $this->validationErrors[$model]; 
    } 
    return true; 
} 

В основной модели вашего HABTM:

public $validate = array(
    'Tag' => array(
     'rule' => array('multiple', array('min' => 1)), 
     'required' => true, 
     'message' => 'Please select at least one Tag for this Post.' 
     ) 
    );