2010-03-17 22 views
7

J'ai un formulaire d'inscription dans lequel les utilisateurs peuvent remplir deux adresses e-mail (email1 & email2). L'exigence du marketing est qu'ils doivent être uniques (uniques comme si nous avions 10 utilisateurs, alors il y aurait 10 * 2 = 20 adresse e-mail unique).cakephp estUnique pour 2 champs?

Le système est déjà construit sur cakephp, ce que j'aimerais savoir, est-ce qu'il y a quelque chose de similaire à la fonction isUnique (unique dans un domaine) qui peut le faire dès la sortie de la boîte? Ou suis-je condamné à coder ceci moi-même? Merci d'avance.

EDIT: construit sur l'exemple de Richard, cela a fonctionné pour moi:

function checkUnique($data, $fields) { 
    if (!is_array($fields)) { 
     $fields = array($fields); 
    } 
    foreach($data as $key) { 
     $checks = $key; 
    } 
    if (empty($checks)) { 
     return true; //allow null 
    } 
    foreach($fields as $key) { 
     $tmp[$key] = $checks; 
    } 
    if (isset($this->data[$this->name][$this->primaryKey])) { 
     $tmp[$this->primaryKey] = "<>".$this->data[$this->name][$this->primaryKey]; 
    } 
    return $this->isUnique($tmp); 
} 
+1

Notez que les nouvelles versions de CakePHP2.x supportent un tableau pour http://book.cakephp.org/2.0/fr/models/data-validation.html#Model::Validation::isUnique pour autoriser plusieurs champs par défaut à présent. – mark

Répondre

12

J'ai posté une solution à ce sur le CakePHP Google Groupe:

http://groups.google.com/group/cake-php/browse_frm/thread/b3a1e4ae3eeb6091/e168f54bac27c163?lnk=gst&q=checkUnique#e168f54bac27c163

Ajoutez ce qui suit à votre AppModel:

 /** 
     * checks is the field value is unqiue in the table 
     * note: we are overriding the default cakephp isUnique test as the 
original appears to be broken 
     * 
     * @param string $data Unused ($this->data is used instead) 
     * @param mnixed $fields field name (or array of field names) to 
validate 
     * @return boolean true if combination of fields is unique 
     */ 
     function checkUnique($data, $fields) { 
       if (!is_array($fields)) { 
         $fields = array($fields); 
       } 
       foreach($fields as $key) { 
         $tmp[$key] = $this->data[$this->name][$key]; 
       } 
       if (isset($this->data[$this->name][$this->primaryKey])) { 
         $tmp[$this->primaryKey] = "<>".$this->data[$this->name][$this- 
>primaryKey]; 

       } 
       return $this->isUnique($tmp, false); 
     } 
} 

et est utilisé dans votre modèle valider:

 var $validate = array( 
       "name"=>array( 
         "unique"=>array( 
           "rule"=>array("checkUnique", array("name", "institution_id")), 
           "message"=>"A contact with that name already exists for that 
institution" 
         ) 
       ) 
     ); 
+0

Merci pour le starter! J'ai dû le modifier un peu pour le faire fonctionner pour ma situation cependant. Éditera la question originale avec le code final. Le – jodeci

+0

'if (isset ($ this-> data [$ this-> nom] [$ this-> primaryKey])) { $ tmp [$ this-> primaryKey] = "<>". $ This-> données [$ this-> name] [$ this- > primaryKey]; 'devrait être supprimé, car Cake 2.x effectue cette vérification par lui-même dans la méthode' isUnique'. Pire, cela rend le retour isUnique incorrect pour moi. – OlivierH

-2

Pour autant que je me rappelle, vous avez à ce type d'application en utilisant la méthode beforeSave dans le modèle. J'avais l'exigence qu'un objet ait au moins un ensemble de N, et je ne pouvais le faire que de cette façon.

Editer: essayez this thread pour voir si quelque chose là résout votre problème.

-1

Oui et non. Oui, vous devrez le coder vous-même, mais dans le composant de validation de CakePHP.

Le composant de validation dispose d'un mécanisme permettant des règles de validation personnalisées. Essentiellement, vous mettez un nom de fonction dans $ validate (comme vous le feriez normalement). Vous devez définir la fonction; dans ce cas, c'est assez simple (il suffit d'appliquer votre double exigence isUnique).

http://book.cakephp.org/2.0/en/models/data-validation.html#custom-validation-rules

11

checkUnique pourrait simplement être écrit comme un wrapper pour isUnique.

class AppModel extends Model { 
    public function checkUnique($ignoredData, $fields, $or = true) { 
     return $this->isUnique($fields, $or); 
    } 
} 

et est utilisé dans votre modèle validate:

public $validate = array(
    'name' => array(
     'unique' => array(
      'rule' => array('checkUnique', array('name', 'institution_id'), false), 
      'message' => 'A contact with that name already exists for that 
institution' 
     ) 
    ) 
); 
+0

Ceci est une réponse beaucoup plus simple que celle initialement acceptée. –

+1

@KimStacks Cette fonctionnalité n'était pas disponible dans CakePHP lorsque j'ai écrit ma réponse originale – RichardAtHome

+0

Got it. Merci de me dire @RichardAtHome –

-1

Au risque d'être frappé à la tête et les épaules pour offrir une solution non CakePHP, laissez-moi vous présenter ce qui suit.

Créez un index unique dans votre base de données, quel que soit le nombre de colonnes dont vous avez besoin.

syntaxe SQL standard pour cela est:

create unique index {IndexName} on {Table} ({Column}, {Column}, ...) 

Placez votre commande "$ this-> Model-> save()" à l'intérieur d'un bloc "try/catch". Dans le bloc "catch", testez l'exception pour le code d'erreur. En MySQL, une violation de clé unique est le code d'erreur 23000, mais vous devez également être préparé pour d'autres erreurs possibles.

C'est rapide et simple et n'implique pas de compter les parenthèses de tableau.

Vous devez toujours placer le code d'accès à la base de données dans un bloc "try/catch" de toute façon. Une partie de votre gestion des exceptions devrait inclure la consignation des messages d'erreur inattendus. Vous ne pouvez pas attendre que CakePHP fasse tout pour vous.

+0

Je vois que ma réponse a été rejetée. Peu importe. Je soutiens que ma solution est plus simple, probablement plus rapide, et implique certainement beaucoup moins de codage que la réponse «correcte» désignée. – UncaAlby

2

From cakePHP 2.0 documentation:

Vous pouvez confirmer qu'un ensemble de champs sont uniques en leur fournissant plusieurs champs et définissez $ ou faux:

public $validate = array(
    'email' => array(
     'rule' => array('isUnique', array('email', 'username'), false), 
     'message' => 'This username & email combination has already been used.' 
    ) 
); 

Assurez-vous d'inclure le champ d'origine dans la liste des champs lorsque faire une règle unique à travers plusieurs champs.

Si un champ répertorié n'est pas inclus dans les données du modèle, il est traité comme une valeur nulle. Vous pouvez envisager de marquer les champs listés comme requis.