Cuando los datos de entrada son enviados desde formularios HTML, a menudo necesitas asignar algunos valores por defecto a las entradas
si estas están vacías. Puedes hacerlo utilizando el validador [default](tutorial-core-validators.md#default). Por ejemplo,
```php
return [
// convierte "username" y "email" en null si estos están vacíos
[['username', 'email'], 'default'],
// convierte "level" a 1 si está vacío
['level', 'default', 'value' => 1],
];
```
Por defecto, una entrada se considera vacía si su valor es un string vacío, un array vacío o null.
Puedes personalizar la lógica de detección de valores vacíos configurando la propiedad [[yii\validators\Validator::isEmpty]]
con una función PHP invocable. Por ejemplo,
```php
['agree', 'required', 'isEmpty' => function ($value) {
return empty($value);
}]
```
> Note: La mayoría de los validadores no manejan entradas vacías si su propiedad [[yii\validators\Validator::skipOnEmpty]] toma
el valor por defecto true. Estas serán simplemente salteadas durante la validación si sus atributos asociados reciben una entrada vacía.
Entre los [validadores del framework](tutorial-core-validators.md), sólo `captcha`, `default`, `filter`,
`required`, y `trim` manejarán entradas vacías.
## Validación Ad Hoc <span id="ad-hoc-validation"></span>
A veces necesitas realizar *validación ad hoc* para valores que no están ligados a ningún modelo.
Si sólo necesitas realizar un tipo de validación (por ej: validar direcciones de email), podrías llamar
al método [[yii\validators\Validator::validate()|validate()]] de los validadores deseados, como a continuación:
```php
$email = 'test@example.com';
$validator = new yii\validators\EmailValidator();
if ($validator->validate($email, $error)) {
echo 'Email válido.';
} else {
echo $error;
}
```
> Note: No todos los validadores soportan este tipo de validación. Un ejemplo es el validador del framework [unique](tutorial-core-validators.md#unique),
que está diseñado para trabajar sólo con un modelo.
Si necesitas realizar varias validaciones contro varios valores, puedes utilizar [[yii\base\DynamicModel]],
que soporta declarar tanto los atributos como las reglas sobre la marcha. Su uso es como a continuación:
Un validador independiente es una clase que extiende de [[yii\validators\Validator]] o sus sub clases. Puedes implementar
su lógica de validación sobrescribiendo el método [[yii\validators\Validator::validateAttribute()]]. Si falla la validación
de un atributo, llama a [[yii\base\Model::addError()]] para guardar el mensaje de error en el modelo, tal como haces
con los [validadores en línea](#inline-validators).
Por ejemplo, el validador en línea de arriba podría ser movida a una nueva clase [[components/validators/CountryValidator]].
```php
namespace app\components;
use yii\validators\Validator;
class CountryValidator extends Validator
{
public function validateAttribute($model, $attribute)
{
if (!in_array($model->$attribute, ['USA', 'Web'])) {
$this->addError($model, $attribute, 'El país debe ser "USA" o "Web".');
}
}
}
```
Si quieres que tu validador soporte la validación de un valor sin modelo, deberías también sobrescribir
el método[[yii\validators\Validator::validate()]]. Puedes también sobrescribir [[yii\validators\Validator::validateValue()]]
en vez de `validateAttribute()` y `validate()` porque por defecto los últimos dos métodos son implementados
llamando a `validateValue()`.
Debajo hay un ejemplo de cómo podrías utilizar la clase del validador de arriba dentro de tu modelo.
```php
namespace app\models;
use Yii;
use yii\base\Model;
use app\components\validators\CountryValidator;
class EntryForm extends Model
{
public $name;
public $email;
public $country;
public function rules()
{
return [
[['name', 'email'], 'required'],
['country', CountryValidator::className()],
['email', 'email'],
];
}
}
```
## Validación del Lado del Cliente <span id="client-side-validation"></span>
La validación del lado del cliente basada en JavaScript es deseable cuando la entrada del usuario proviene de formularios HTML, dado que
permite a los usuarios encontrar errores más rápido y por lo tanto provee una mejor experiencia. Puedes utilizar o implementar
un validador que soporte validación del lado del cliente *en adición a* validación del lado del servidor.
> Info: Si bien la validación del lado del cliente es deseable, no es una necesidad. Su principal propósito es proveer al usuario una mejor
experiencia. Al igual que datos de entrada que vienen del los usuarios finales, nunca deberías confiar en la validación del lado del cliente. Por esta razón,
deberías realizar siempre la validación del lado del servidor llamando a [[yii\base\Model::validate()]], como
se describió en las subsecciones previas.
### Utilizar Validación del Lado del Cliente <span id="using-client-side-validation"></span>
Varios [validadores del framework](tutorial-core-validators.md) incluyen validación del lado del cliente. Todo lo que necesitas hacer
es solamente utilizar [[yii\widgets\ActiveForm]] para construir tus formularios HTML. Por ejemplo, `LoginForm` mostrado abajo declara dos
reglas: una utiliza el validador del framework [required](tutorial-core-validators.md#required), el cual es soportado tanto en
lado del cliente como del servidor; y el otro usa el validador en línea `validatePassword`, que es sólo soportado de lado
del servidor.
```php
namespace app\models;
use yii\base\Model;
use app\models\User;
class LoginForm extends Model
{
public $username;
public $password;
public function rules()
{
return [
// username y password son ambos requeridos
[['username', 'password'], 'required'],
// password es validado por validatePassword()
['password', 'validatePassword'],
];
}
public function validatePassword()
{
$user = User::findByUsername($this->username);
if (!$user || !$user->validatePassword($this->password)) {
$this->addError('password', 'Username o password incorrecto.');
}
}
}
```
El formulario HTML creado en el siguiente código contiene dos campos de entrada: `username` y `password`.
Si envias el formulario sin escribir nada, encontrarás que los mensajes de error requiriendo que
escribas algo aparecen sin que haya comunicación alguna con el servidor.
> Tip: Si necesitas trabajar con validación del lado del cliente manualmente, por ejemplo, agregar campos dinámicamente o realizar alguna lógica de UI,
> consulta [Trabajar con ActiveForm vía JavaScript](https://github.com/samdark/yii2-cookbook/blob/master/book/forms-activeform-js.md)
Algunas validaciones sólo pueden realizarse del lado del servidor, debido a que sólo el servidor tiene la información necesaria.
Por ejemplo, para validar si un nombre de usuario es único o no, es necesario revisar la tabla de usuarios del lado del servidor.
Puedes utilizar validación basada en AJAX en este caso. Esta lanzará una petición AJAX de fondo para validar
la entrada mientras se mantiene la misma experiencia de usuario como en una validación del lado del cliente regular.
Para habilitar la validación AJAX individualmente un campo de entrada, configura la propiedad [[yii\widgets\ActiveField::enableAjaxValidation|enableAjaxValidation]]
de ese campo como true y especifica un único `id` de formulario: