Validación - comparación entre enteros


(Ley) #1

Hola a todos:

Quisiera si alguien supiera que me ayudara con el siguiente problema. En un modelo tengo la siguiente validación:

public function rules()
{
return [
[[‘fecha_inicio’, ‘fecha_fin’], ‘safe’],
[[‘cant_min’, ‘cant_max’], ‘default’, ‘value’ => null],
[[‘cant_min’, ‘cant_max’], ‘integer’],
[‘cant_max’, ‘compare’, ‘compareAttribute’=>‘cant_min’, ‘operator’=> ‘>=’, ‘message’=>‘La matrícula máxima no puede ser inferior a la mínima.’ ],
[‘fecha_fin’, ‘compare’, ‘compareAttribute’=>‘fecha_inicio’, ‘operator’=> ‘>=’, ‘message’=>‘La fecha de culminación no puede ser antes de la fecha de inicio.’ ],

    ];
}

En el caso que cant_min=2 y cant_max= 10 se muestra el mensaje de error de la validación, es como si interpretara el valor 10 como 1. Esto sucede siempre
cant_max sea igual a un valor que contenga ceros a la derecha y el número que acompaña a los ceros sea menor que la cant_min. Para el resto de los casos
funciona bien.

Algo similar me sucede con las fechas, mientras las fecha_inicio y fecha_fin se encuentran en el mismo mes y año la validación funciona perfectamente, pero
cuando la fecha_fin se encuentra en otro mes y año, muestra el mensaje de error de validación. Por ejemplo, fecha_inicio=12/19/2019 y fecha_fin=01/02/2020.


(Rafaelt88) #2

Siempre que tengas una duda busca la documentación o inspecciona tus clases involucradas:
https://www.yiiframework.com/doc/api/2.0/yii-validators-comparevalidator

Para comparar números tienes que definir el tipo TYPE_NUMBER, para tu fecha recomendaría hagas un casting beforeValidate donde los valores se lleven a TIMESTAMP, posterior haces la regresión de este casting afterValidate.

Puedes crear tu validador particular, que extienda de yii\validators\CompareValidator y aplicas la comparación manualmente, contrario recuerda que por defecto te comprará siempre cadenas de texto (String)


(Ley) #3

Muchas gracias, seguiré tu consejo, saludos


(Ley) #4

Hola
Gracias a tu ayuda resolví el tema de la comparación de enteros, pero la comparación entre fechas sigue sin funcionar. Hice lo que me recomendaste en cuanto a los casting de fechas, pero sigo sin ver resultados


(Rafaelt88) #5

Sube el código que tienes de la fecha, para saber q camino tomaste o la idea que llevas, como te dije las fechas son un caso particular q podrías hacer tu propia clase y luego reutilizarla.


(Ley) #6

Intenté esto y no funcionó

public function rules()
{
return [
[[‘fecha_inicio’, ‘fecha_fin’], ‘safe’],
[‘fecha_fin’,‘validateDates’],
];
}

public function validateDates(){

    if(strtotime($this->fecha_fin) < strtotime($this->fecha_inicio)){
        $this->addError('fecha_fin','La fecha de culminación no puede ser antes de la fecha de inicio.');
    }
}

Hice esto otro y tampoco

public function rules()
{
return [
[[‘fecha_inicio’, ‘fecha_fin’], ‘safe’],
[‘fecha_inicio’, ‘date’,‘timestampAttribute’=>‘fecha_inicio’],
[‘fecha_fin’, ‘date’,‘timestampAttribute’=>‘fecha_fin’],
[‘fecha_inicio’, ‘compare’, ‘compareAttribute’=>‘fecha_fin’,‘operator’=>’<’,‘enableClientValidation’=>false]
];
}

Esto otro y tampoco

public function rules()
{
return [
[[‘fecha_inicio’, ‘fecha_fin’], ‘safe’],
];
}

public function beforeValidate(){

    if(strtotime($this->fecha_fin) < strtotime($this->fecha_inicio)){
        $this->addError('fecha_fin','La fecha de culminación no puede ser antes de la fecha de inicio.');
        return parent::beforeValidate();
    }
}

Crees que me pudieras poner un ejemplo de lo que me comentas con el CompareValidator.


(Rafaelt88) #7

@Ley la lógica que aplicas esta bien, estoy casi seguro que el problema ahora es tu entrada.

No es lo mismo strtotime("20/02/2020") a strtotime("02/20/2020") y estoy casi seguro la entrada está de la segunda forma lo que te retornará NULL.

Por defecto PHP utiliza el sistema internacional y reconoce como fecha YYYY-MM-DD o YYYY/MM/DD, te anexo un ejemplo para que notes la diferencia de tu entrada y como seria interpretada la cadena que ingresas, si estas capturando el dato desde un widget verifica el envio de tus parámetros.

20/11/2020: 1970-Jan-01 *** 20-11-2020: 2020-Nov-20 11/20/2020: 2020-Nov-20 11-20-2020: 1970-Jan-01 *** 2020-08-20: 2020-Aug-20 2020/08/20: 2020-Aug-20

Si tu lógica esta bien siempre revisa la entrada ;).


(Ley) #8

Tomé tu consejo y en el actionCreate antes de validar el modelo hice un casting de las fechas a AAAA-MM-DD (para cambiar la entrada de los datos) y luego pasa por la función validateDates, lo cual hace bien, pero nunca muestra el mensaje de error en fecha_fin. Cuando traceo el código sale un mensaje que “fecha_fin can’t get property”.


(Rafaelt88) #9

Vale entonces el error va por otro lado viste, a veces uno se enfrasca y el error es otro…


(Ley) #10

Ya lo resolví, gracias por toda la ayuda


(Eloy Gonzalez) #11

@Ley;

Gracias al usuario @rafaelt88 por su aporte, damos el tema por solucionado!