Saving or killing non validation in validators?


(Alexander Makarov) #1

Currently there are non-validation validators in Yii:

  • default that is setting default value if there’s no value.
  • filter that converts value from one format to another.
  • url can auto-prefix http:// or https:// if it’s missing.

Common sense tells us that validation should not modify data but check it for errors so these above do not quite match the concept. Still, they proved to be handy in both Yii 1 and Yii 2.

We have multiple options:

  1. Keep these as is i.e. allow validators to modify values validated.
  2. Remove these.
  3. Move these to a conceptually different mechanism. That is likely to complicate configuration but may not.

What do you think?


(Mehdi Achour) #2

3 sounds like a good option. They seem to be related to Sanitization.


(Tom) #3

3 unless it turns out to cause too many complications, then 2. But definitely agree that validators should validate and not mutate!


(Fabrizio Caldarelli) #4

I think that filter and url can be replaced with custom getter, I never used them. I have used sometimes default to fill property values, but we can init them in constructor.

So I’m for solution 2.


(Tecnologiaterabyte) #5

The most reasonable option is 3, followed by 2.


(Schmunk) #6

I think all are (kind of) filters, I’d also say 3. followed by 2.

How about preValidation and postValidation filters for ie. models?


(Fabrizio Caldarelli) #7

Have not we already beforeValidate and afterValidate?


(Schmunk) #8

Yeah, I meant a standardized way to use filters in these use-cases.


(Yusup Hambali) #9

move these implementation as behavior


(SohelAhmed) #10

I would go with option 3. I think that would be more professional


(Alexander Makarov) #11

I forgot to tell about models… New validation would not be tied to them and will be able to work with any object implementing an interface (if it provides rules itself) or any object (if rules are defined elsewhere). This way it will be possible to validate plain objects, ARs, Doctrine entities etc.


(Viktor) #12

I like option 3. It is a frequently used mechanism, but it is not validation. And sometimes it should be used in other time than validation:

  • before validation
  • after validation
  • after getting values from DB (e.g. “presenters”)
  • etc.

(Razon Yang) #13

I’d go with option 2, followed by 3.


(Isidoro) #14

IMHO, 3, followed by 2


(Ramin Farmani) #15

definitely option 3 :slightly_smiling_face:


(Leo) #16

I’m think Option 3 will fit best choice.
A good example IMHO would be localized date and number transformations in beforeValidation and beforeSearch and afterSearch (looking at yii1, no real exp with newer). Events based would be my best bet.


(Fabrizio Caldarelli) #17

@Piemol I usually add custom getters and setters directly inside the model (or its subclass) to handle date localization, without passing through event and validation, in model subclass.

This avoid to add extra code in search or validation functions, and automatically date model properties are filled from localized version

This is the model:

namespace backend\models;

use common\models\MyModel;

class MyModelForm extends MyModel
{
    /**
     * Rules
     */
    public function rules()
    {
        return array_merge(parent::rules(), [
            [['startTimeLocalized'], 'required'],
        ]);
    }

    /**
     * Start Time
     */
    public function getStartTimeLocalized()
    {
    	$retOut = null;
		if($this->start_time!=null)
		{
			$dt = new \DateTime($this-> start_time);
			$retOut = $dt->format('d/m/Y H:i');
		}
        return $retOut;
    }

	public function setStartTimeLocalized($v)
	{
		$this-> start_time = null;
		if($v!=null)
		{
			$dt = date_create_from_format('d/m/Y H:i', $v);
			$this->start_time = $dt->format('Y-m-d H:i');
	}
}

This is the form:

<?= $form->field($model, 'startTimeLocalized')->widget(\kartik\datetime\DateTimePicker::classname(), [
    'language' => 'it',
    'options' => ['placeholder' => 'Insert the date ...'],
    'type' => \kartik\datetime\DateTimePicker::TYPE_INPUT,
    'pluginOptions' => [
        'autoclose' => true,
        'format' => 'dd/mm/yyyy hh:ii'
    ]

    ]) ?>

The only thing to change inside the controller is the reference of model class, from MyModel to MyModelForm.


(Tomasz Kane) #18

3 (best architecture solution) , then 1 (non BC solution).


(Alexander Makarov) #19

Decided to prevent validators mutating data.