web-dev-qa-db-fra.com

Yii2: comment utiliser la fonction de validation personnalisée pour activeform?

Dans le modèle de mon formulaire, j'ai une fonction de validation personnalisée pour un champ défini de cette manière.

class SignupForm extends Model
{
    public function rules()
    {
        return [
            ['birth_date', 'checkDateFormat'],

            // other rules
        ];
    }

    public function checkDateFormat($attribute, $params)
    {
        // no real check at the moment to be sure that the error is triggered
        $this->addError($attribute, Yii::t('user', 'You entered an invalid date format.'));
    }
}

Le message d'erreur n'apparaît pas sous le champ dans la vue formulaire lorsque j'appuie sur le bouton d'envoi, tandis que d'autres règles, telles que l'adresse électronique et le mot de passe requis, apparaissent.

Je travaille sur le formulaire natif de Signup, alors pour être sûr qu'il ne s'agit pas d'un problème classé, j'ai défini la règle

['username', 'checkDateFormat']

et supprimé toutes les autres règles liées au champ nom d'utilisateur, mais le message n'apparaît pas non plus.

J'ai essayé de ne rien transmettre en tant que paramètres à checkDateFormat, j'ai explicitement passé le nom du champ à addError()

$this->addError('username', '....');

mais rien n'apparait.

Quelle est la bonne façon de définir une fonction de validation personnalisée? 

20
Alhazred

Avez-vous lu la documentation?

Selon les étapes de validation ci-dessus, un attribut sera validé si et seulement s'il s'agit d'un attribut actif déclaré dans scénarios () et est associé à une ou plusieurs règles actives déclarée dans les règles ().

Donc, votre code devrait ressembler à:

class SignupForm extends Model
{
    public function rules()
    {
        return [
            ['birth_date', 'checkDateFormat'],

            // other rules
        ];
    }

    public function scenarios()
    {
        $scenarios = [
            'some_scenario' => ['birth_date'],
        ];

        return array_merge(parent::scenarios(), $scenarios);
    }

    public function checkDateFormat($attribute, $params)
    {
        // no real check at the moment to be sure that the error is triggered
        $this->addError($attribute, Yii::t('user', 'You entered an invalid date format.'));
    }
}

Et dans le scénario de jeu de contrôleurs, exemple:

$signupForm = new SignupForm(['scenario' => 'some_scenario']);
10
TomaszKane

Essayez de forcer la validation sur un champ vide

['birth_date', 'checkDateFormat', 'skipOnEmpty' => false, 'skipOnError' => false],

Assurez-vous également que vous n'attribuez pas d'identifiant à votre champ birth_date dans votre vue. 

Si vous avez un identifiant pour votre birth_date, vous devez spécifier la selectors

<?= $form->field($model, 'birth_date', ['selectors' => ['input' => '#myBirthDate']])->textInput(['id' => 'myBirthDate']) ?>
5
Michael Nguyen

Vous devez déclencher $model->validate() quelque part si vous sortez de la classe Model.

5
Josue Mota

Pour effectuer des validations personnalisées dans yii 2, vous pouvez écrire une fonction personnalisée dans le modèle et l’affecter à la règle ..__ pour, par exemple. Je dois appliquer les critères de mot de passe dans le champ password, puis j'écrirai comme ceci dans le modèle.

public function rules()
{
    return [
        ['new_password','passwordCriteria'],
    ];
}

public function passwordCriteria()
{
    if(!empty($this->new_password)){
        if(strlen($this->new_password)<8){
            $this->addError('new_password','Password must contains eight letters one digit and one character.');
        }
        else{
            if(!preg_match('/[0-9]/',$this->new_password)){
                $this->addError('new_password','Password must contain one digit.');
            }
            if(!preg_match('/[a-zA-Z]/', $this->new_password)){
                $this->addError('new_password','Password must contain one character.');
            }
        }
    }
}

Références: - validation du formulaire dans yii 2

5
Sudhanshu sharma

Je suis tombé sur cela en utilisant le générateur CRUD. La fonction actionCreate () générée n'incluant pas d'appel de validation de modèle, les validateurs personnalisés ne sont jamais appelés. En outre, le formulaire n'inclut pas et résumé d'erreur.

Ajoutez donc le résumé de l'erreur au _form.

<?= $form->errorSummary($model); ?>

... et ajoutez l'appel de validation - $ model-> validate () - à l'action du contrôleur

public function actionCreate()
{
    $model = new YourModel();

    if ($model->load(Yii::$app->request->post()) && $model->validate()) {...
2
Steven McElveen

Vous devez rendre le modèle à partir du contrôleur. Sans initialiser le modèle en vue. Et dans le contrôleur, vous devez appeler la fonction de validation

1
Betson

Bien que ce soit un ancien post, je pensais devoir répondre. 

Vous devez créer une classe de validateur personnalisé et pour créer un validateur prenant en charge la validation côté client, vous devez implémenter la méthode yii\validators\Validator::clientValidateAttribute() qui renvoie un morceau de code JavaScript qui effectue la validation du côté client. Dans le code JavaScript.

Vous pouvez utiliser les variables prédéfinies suivantes:

attribute: le nom de l'attribut en cours de validation.

value: la valeur en cours de validation.

messages: un tableau utilisé pour contenir les messages d'erreur de validation pour l'attribut.

deferred: un tableau dans lequel des objets différés peuvent être insérés dans (expliqué dans la sous-section suivante).

Cela signifie donc que vous pouvez utiliser le tableau messages pour pousser vos messages vers le client et le moment de l'exécution au sein du bloc de code javascript de cette méthode.

Je vais créer une classe qui inclut des contrôles factices qui pourraient être remplacés comme vous le souhaitez. et changez la namespace en fonction de votre yii2 advanced ou basic.

Custom Client-side Validator

namespace common\components;
use yii\validators\Validator;

class DateFormatValidator extends Validator{
public function init() {
        parent::init ();
        $this->message = 'You entered an invalid date format.';
    }

    public function validateAttribute( $model , $attribute ) {

        if ( /*SOME CONDITION TO CHECK*/) {
            $model->addError ( $attribute , $this->message );
        }
    }

    public function clientValidateAttribute( $model , $attribute , $view ) {

        $message = json_encode ( $this->message , JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
        return <<<JS
if ($("#DATE-1").val()=="" || $("#DATE-2").val() =="") {
    messages.Push($message);
}
JS;
    }
}

et ensuite dans votre modèle SigupForm, ajoutez la rule

['birth_date', 'common\components\DateFormatValidator'],

Deferred Validation

Vous pouvez même ajouter des appels ajax dans la fonction clientValidateAttribute et sur la base du résultat de cet appel ajax, vous pouvez envoyer un message au client, mais vous pouvez utiliser l'objet deferred fourni par yii, qui est un tableau d'objets différés. des appels à l'intérieur de ce tableau ou créez explicitement l'objet différé et appelez sa méthode resolve().

Default Yii's deferred Object

public function clientValidateAttribute($model, $attribute, $view)
{
    return <<<JS
        deferred.Push($.get("/check", {value: value}).done(function(data) {
            if ('' !== data) {
                messages.Push(data);
            }
        }));
JS;
}

En savoir plus sur Deferred Validation

1

Etes-vous sûr que le premier paramètre de addError ne devrait pas être comme ça

$this->addError(**'attribute'**, Yii::t('user', 'You entered an invalid date format.'));
1
Pino Wackers

J'ai eu un problème commun.

Dans votre fonction de validation:

public function checkDateFormat($attribute, $params)
    {
        // no real check at the moment to be sure that the error is triggered
        $this->addError($attribute, Yii::t('user', 'You entered an invalid date format.'));
    }

$ params n'obtient aucune valeur. En fait, cela équivaut toujours à Null. Vous devez vérifier la valeur de votre attribut dans function:

public function checkDateFormat($attribute, $params)
{
    if($this->birth_date == False)
    {
        $this->addError($attribute, Yii::t('user', 'You entered an invalid date format.'));
    }
}

c'est comme ça que ça a marché pour moi.

1
Максим

Si vous n'utilisez pas de scénarios pour votre modèle, vous devez marquer votre attribut comme étant "sans danger":

    ['birth_date','safe'],
    ['birth_date', 'checkDateFormat'],

Et, d'autre part, vous pouvez l'utiliser pour la validation de la date:

    ['birth_date','safe'],
    [['birth_date'],'date', 'format'=>'php:Y-m-d'],

Vous pouvez changer le format que vous voulez. 

0
hesselek