2010-01-11 17 views
5

Tengo una tabla de proyectos y una tabla de usuarios que están vinculados por una relación HABTM. En la página "agregar" nuevo proyecto, tengo una sección de casilla de verificación múltiple para seleccionar Usuarios para el nuevo proyecto. Quiero tener al menos un Usuario para el Proyecto. ¿Cuál es la mejor manera de abordar esto en CakePHP?Validación de formulario HABTM en CakePHP

Respuesta

19

Prueba esto:

// 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

perfecto! Gracias Neil. – Sabourinov

+0

Esto funciona para validar, pero cuando la página se recarga, perdí algunos datos y recibí errores debido a la falta de datos. ¿Alguna idea? – Dave

2

El blog de teknoid tiene una solución bastante profunda a su problema aquí. La forma más fácil de hacer esto de Cakey sería agregar una validación personalizada a su modelo, como menciona en su comentario anterior. Salida http://teknoid.wordpress.com/2008/10/16/how-to-validate-habtm-data/

Desde el artículo, donde la etiqueta HABTM Post (:: usuarios del proyecto HABTM):

En primer lugar, se valida el modelo de etiqueta, por utilizando los datos de la forma de asegurar que al al menos una etiqueta fue seleccionada. Si guardamos la publicación y las etiquetas relevantes .

6

He estado mirando a su problema por mí mismo en un proyecto y se encontró con una solución ligeramente más elegante, siempre y cuando sólo se está tratando con una relación HABTM y debe asegurarse de que se haya seleccionado al menos una casilla de verificación.

así que por ejemplo se está editando un proyecto y desea que sea asociado con al menos un usuario

Añadir esto a beforeValidate()

// comprobar HABTM modelo y añadir a los datos

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

En las reglas de validación añadir lo siguiente:

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

Esto funciona bien en su mayor parte, pero el div que contiene el error no aparece. ¿Algunas ideas? – Joseph

12

I st Se lanzó sobre el mismo problema, pero ahora - 3 años después - con CakePHP 2.3.

Para ser claro; Group tiene y pertenece a User. He tenido un formulario como el siguiente:

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

Con la regla de validación como en la respuesta de user448164:

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

que no funcionó, después de buscar en Google para ello, me encontré con esta pregunta, que no podía' todavía ser la mejor solución. Luego he intentado varias cosas, y descubrió que esto funcione bien: Solución

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

demasiado fácil, pero tuvo que cavar en ella para descubrir que funciona de esta manera.

Esperemos que ayude a alguien un día.

Actualización para CakePHP 2.4.x (2.3.x posiblemente también)

Cuando escribí esta respuesta, yo estaba usando CakePHP 2.3.x. En aquel entonces, funcionó perfectamente tanto para validar como para guardar los datos.Ahora, al aplicar el mismo código en un nuevo proyecto, usando CakePHP 2.4.x, ya no funcionaba.

he creado un caso de prueba, usando el siguiente código:

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

Mi primer pensamiento fue: Ahorro de todos los medios de ahorro de todos los modelos de "raíz", lo que realmente tiene sentido para mí. Para ahorrar más profundo que solo los "raíz", tendrá que agregar la opción deep. Así que terminé con el siguiente código:

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

¡Funciona como un encanto! Feliz codificación. :)

actualización (2014/03/06)

La lucha con el mismo problema de nuevo, en este caso con hasMany en lugar de habtm. Parece que se comporta de la misma manera. Pero me encontré buscando esta respuesta nuevamente, y me confundí.

Me gustaría aclarar que es clave usar Group.User en lugar de User en su entrada. De lo contrario, no usará la validación del modelo User.

+3

Esta es la respuesta correcta para Cake 2.3 – Steven

+1

Realicé este cambio en mi código por un problema similar. La validación funciona correctamente, pero la tabla de la base de datos vinculada a través de HABTM ya no guarda automáticamente los datos nuevos. ¿Qué falta? – Blazemonger

+0

@Blazemonger Cuando lo escribí, funcionó bien tanto para validar como para guardar. Pero de alguna manera está roto en la última versión de CakePHP. Vamos a hacer un poco más de excavación ... --- Ver la actualización de respuesta para más información! –

1

Si está utilizando CakePHP 2.3.x, puede ser necesario añadir este código a su modelo, además del código que proporciona GuidoH, de lo contrario los datos del modelo HABTM pueden no guardar:

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

Según mi comentario en la respuesta anterior de Guido, uso la respuesta de Guido exactamente, sin embargo modifico los datos con la devolución de llamada beforeSave antes de que se guarde en la base de datos.

que tienen este problema en la torta 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 actualización para CakePHP 2.7

respuesta completa aquí: 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; 
} 

En el modelo principal de su HABTM:

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