2012-04-08 14 views
3

Ich habe ein Basismodell, von dem ich erweitere. Darin habe ich zwei Validierungsfilter definiert. Einer prüft, ob ein Datensatz eindeutig ist, der andere prüft, ob ein Datensatz existiert. Sie funktionieren genau so, außer dass der Rückgabewert das Gegenteil von dem anderen ist.Lithium: So rufen Sie einen Validierungsfilter von innen heraus

Es klingt also nicht richtig, denselben Code zweimal zu schreiben, um nur einen anderen Wert zurückzugeben. Ich würde gerne wissen, wie ich einen benutzerdefinierten Validator von einem anderen aufrufen kann.

Hier mein Code ist für den unique Validator:

<?php 
Validator::add('unique', function($value, $rule, $options) { 
    $model = $options['model']; 
    $primary = $model::meta('key'); 

    foreach ($options['conditions'] as $field => $check) { 
     if (!is_numeric($field)) { 
      if (is_array($check)) { 
       /** 
       * array(
       * 'exists', 
       * 'message' => 'You are too old.', 
       * 'conditions' => array(
       *  
       *  'Users.age' => array('>' => '18') 
       * ) 
       *) 
       */ 
       $conditions[$field] = $check; 
      } 
     } else { 
      /** 
      * Regular lithium conditions array: 
      * array(
      * 'exists', 
      * 'message' => 'This email already exists.', 
      * 'conditions' => array(
      *  'Users.email' //no key ($field) defined 
      * ) 
      *) 
      */ 
      $conditions[$check] = $value; 
     } 
    } 

    /** 
    * Checking to see if the entity exists. 
    * If it exists, record exists. 
    * If record exists, we make sure the record is not checked 
    * against itself by matching with the primary key. 
    */ 
    if (isset($options['values'][$primary])) { 
     //primary key value exists so it's probably an update 
     $conditions[$primary] = array('!=' => $options['values'][$primary]); 
    } 

    $exists = $model::count($conditions); 
    return ($exists) ? false : true; 
}); 
?> 

exists soll wie folgt funktionieren:

<?php 
Validator::add('exists', function($value, $rule, $options) { 
    $model = $options['model']; 
    return !$model::unique($value, $rule, $options); 
}); 
?> 

Aber natürlich kann es nicht auf diese Weise durchgeführt werden. Müsste ich die Validierungsfunktion als eine anonyme Funktion definieren, sie einer Variablen zuweisen und diese anstelle des Abschlusses übergeben? Oder gibt es eine Möglichkeit, unique innerhalb von exists anrufen?

Antwort

2

Die anonyme Funktionsmethode würde funktionieren. Und dann könnten Sie diese Variable in einer anderen anonymen Funktion verwenden, die Sie für den Validierer "exists" definieren. Hier ist eine andere Idee, die es in Ihre Basismodell-Klasse einbaut:

<?php 

namespace app\data\Model; 

use lithium\util\Validator; 

class Model extends \lithium\data\Model { 

    public static function __init() { 
     static::_isBase(__CLASS__, true); 
     Validator::add('unique', function($value, $rule, $options) { 
      $model = $options['model']; 
      return $model::unique(compact('value') + $options); 
     }); 
     Validator::add('exists', function($value, $rule, $options) { 
      $model = $options['model']; 
      return !$model::unique(compact('value') + $options); 
     }); 
     parent::__init(); 
    } 

    // ... code ... 

    public static function unique($options) { 
     $primary = static::meta('key'); 

     foreach ($options['conditions'] as $field => $check) { 
      if (!is_numeric($field)) { 
       if (is_array($check)) { 
        /** 
        * array(
        * 'exists', 
        * 'message' => 'You are too old.', 
        * 'conditions' => array(
        * 
        *  'Users.age' => array('>' => '18') 
        * ) 
        *) 
        */ 
        $conditions[$field] = $check; 
       } 
      } else { 
       /** 
       * Regular lithium conditions array: 
       * array(
       * 'exists', 
       * 'message' => 'This email already exists.', 
       * 'conditions' => array(
       *  'Users.email' //no key ($field) defined 
       * ) 
       *) 
       */ 
       $conditions[$check] = $options['value']; 
      } 
     } 

     /** 
     * Checking to see if the entity exists. 
     * If it exists, record exists. 
     * If record exists, we make sure the record is not checked 
     * against itself by matching with the primary key. 
     */ 
     if (isset($options['values'][$primary])) { 
      //primary key value exists so it's probably an update 
      $conditions[$primary] = array('!=' => $options['values'][$primary]); 
     } 

     $exists = $model::count($conditions); 
     return ($exists) ? false : true; 
    } 

} 

?> 
+0

Danke @rmarscher. Ich sehe, Sie haben die Rückleitung gekürzt, alberne mich, ich hätte das tun sollen :) Aber warum stellen Sie '$ self' dort ein? – Housni

+0

Außerdem müssen Sie $ value in die 'unique' Methode übergeben, da sie dort benötigt wird. – Housni

+1

Ah ja, ich denke ich kopiere und füge versehentlich '$ self' ein, weil ich das in einigen meiner Filter machen muss, um das aktuelle Objekt innerhalb des Callbacks verfügbar zu machen ('$ self' wird dann über' 'übergeben) Verwenden Sie die Klausel der Funktionsdefinition. Und ich reparierte den '$ value' Teil. Aber ja, nette Lösung von Ihrer Seite. Ich hätte meinen nicht gepostet, wenn ich die Seite aktualisiert hätte, bevor ich auf "Submit" geklickt habe. – rmarscher

1

Ich habe am Ende eine separate Methode erstellt, die die Funktionalität enthält, die ich brauche, und dann von meinem Validierungsfilter aufrufen. Ich habe mein Basismodell getrimmt, um nur die relevanten Daten darin zu speichern. Hoffe es hilft jemandem, der ein ähnliches Problem hat.

<?php 
namespace app\extensions\data; 
class Model extends \lithium\data\Model { 

    public static function __init() { 
     parent::__init(); 

     Validator::add('unique', function($value, $rule, $options) { 
      $model = $options['model']; 
      return ($model::exists($value, $rule, $options, $model)) ? false : true; 
     }); 

     Validator::add('exists', function($value, $rule, $options) { 
      $model = $options['model']; 
      return ($model::exists($value, $rule, $options, $model)) ? true : false; 
     }); 
    } 


    public static function exists($value, $rule, $options, $model) { 
     $field = $options['field']; 
     $primary = $model::meta('key'); 

     if (isset($options['conditions']) && !empty($options['conditions'])) { 
      //go here only of `conditions` are given 
      foreach ($options['conditions'] as $field => $check) { 
       if (!is_numeric($field)) { 
        if (is_array($check)) { 
         /** 
         * 'conditions' => array(
         *  'Users.age' => array('>' => 18) //condition with custom operator 
         * ) 
         */ 
         $conditions[$field] = $check; 
        } 
       } else { 
        /** 
        * Regular lithium conditions array: 
        * 'conditions' => array(
        *  'Users.email' //no key ($field) defined 
        * ) 
        */ 
        $conditions[$check] = $value; 
       } 
      } 
     } else { 
      //since `conditions` is not set, we assume 
      $modelName = $model::meta('name'); 
      $conditions["$modelName.$field"] = $value; 
     } 

     /** 
     * Checking to see if the entity exists. 
     * If it exists, record exists. 
     * If record exists, we make sure the record is not checked 
     * against itself by matching with the primary key. 
     */ 
     if (isset($options['values'][$primary])) { 
      //primary key value exists so it's probably an update 
      $conditions[$primary] = array('!=' => $options['values'][$primary]); 
     } 

     return $model::count($conditions); 
    } 
} 
?> 
+0

Ha ... Ich schrieb die obige Antwort letzte Nacht, aber vergessen zu treffen, zu senden. Ich drücke einfach submit und jetzt sehe ich deine Antwort. Aber ja, dasselbe. – rmarscher