Validando campos de data e hora no model do Laravel.

Neste post irei mostrar como validar campos de formulários com valores que contenham uma data e hora no framework Laravel, por exemplo, “04/03/2012 13:00:00″.

O PHP leva em conta sua definição da variável date.timezone do arquivo php.ini ou então o valor da definição do método date_default_timezone_set() para as funções de data do sistema, no caso do Brasil ficaria assim:

date_default_timezone_set('America/Sao_Paulo');

Primeiro devemos adicionar um método a classe “Validator” do Laravel em nome_do_seu_projeto/laravel/validator.php (recomendo adicionar após o método validate_required).

EDIT: O método usando o strtotime() do PHP parece não funcionar em alguns casos para nosso formato de data/hora, estou usando o método a seguir para validação:

// nao alterar o nome do metodo pois senao nao
// sera encontrado pelo validator do laravel.
protected function validate_datetime($attribute, $value)
{
	// separa data e hora
	$pieces = explode(' ', $value);
	if ( count($pieces) == 2 ) {
		$date_piece = $pieces[0];
		$time_piece = $pieces[1];
		// lista os dados de data e hora
		list($day, $month, $year) = explode('/', $date_piece);
		list($hour, $minute) = explode(':', $time_piece);
		// data eh valida?
		$date_is_valid = checkdate($month, $day, $year);
		// hora eh valida?
		$time_is_valid = false;
		if ( ($hour > -1 && $hour < 24) && ($minute > -1 && $minute < 60) ) {
			$time_is_valid = true;
		}
		// data e hora sao validos?
		if ( $date_is_valid && $time_is_valid ) return true;
	}
	return false;
}
// ### NAO RECOMENDADO ###
protected function validate_datetime($attribute, $value)
{
    if ( ! strtotime($value) ) return false;
    return true;
}

Desta forma podemos dentro do model do Laravel adicionar a validação da seguinte maneira.

$rules = array(
    'start_at'  => array('required', 'datetime'),
    'end_at'    => array('required', 'datetime'),
);
 
// mensagens personalizadas para os erros (opcional)
$messages = array(
    'start_at_required' => 'O campo "Data início" é obrigatório.',
    'start_at_datetime' => 'A data informada em "Data início" é inválida.',
    'end_at_required'   => 'O campo "Data fim" é obrigatório.',
    'end_at_datetime'   => 'A data informada em "Data fim" é inválida.',
);
 
$validator = Validator::make( Input::get(), $rules, $messages );
if ( $validator->valid() ) {
    // salvar dados da model!
}

Ainda é possível criar outros métodos de validação por exemplo para validar um CPF, telefone, etc.

Até mais!!

4 thoughts on “Validando campos de data e hora no model do Laravel.

  1. Bem legal o tutorial, já desenvolvi um site de e-commerce de notícias para faculdade, mas foi apenas um protótipo e não usei muita coisa.
    Aprendi muito coisa sobre o Laravel e gosto muito dele. Além dele, indico o FuelPHP. Sobre validação, o meu maior problema é mostrar os erros. Por exemplo: Em um controlador, eu verifico os dados e caso de erro, gostaria de redirecionar para outro controlador (até ai tudo bem), mas não consigo ver os erros.
    E queria saber se tem como, retornar os dados que estiverem correto. Por exemplo: O formulário tem 3 dados Login, Nome e Senha e apenas o nome está errado, logo gostaria de fazer um redirecionamento novamente para o formulário, deixa preenchido o resto e do lado de nome, informar o erro.

    Grato.

  2. Olá Felipo!
    Geralmente eu faço um método validateAndSave() dentro do model e no retorno eu faço algo tipo assim:

    public static function validateAndSave($promo=null)
    {
    	$rules = array(
    		// aqui as regras
    	);
     
    	$messages = array(
    		// aqui vai as mensagens
    	);
     
    	$validator = Validator::make( Input::get(), $rules, $messages );
    	if ( $validator->valid() )
    	{
    		if (empty($promo)) {
    			$promo = new self;
    			$promo->user_id = Auth::user()->id;
    		}
     
    		$promo->store_id    = Input::get('store');
    		$promo->product_id  = Input::get('product');
    		$promo->name        = Input::get('name');
    		$promo->save();
    	}
     
    	return $validator->errors->all();
    }

    Na controller eu verifico:

    $errors = Promo::validateAndSave();
    if ( count($errors) > 0 )
    {
    	return Redirect::to('/promo/add')
    				   ->with('message.errors', $errors);
    }

    Isso ira redirecionar os dados para a view com a lista de erros encontrados, ai na view é só mostrar:

    <?php if (Session::has('message.errors')): ?>
    	<?php foreach (Session::get('message.errors') as $message): ?>
    		<div class="alert-message error">
    			<p><?php echo $message; ?></p>
    		</div>
    	<?php endforeach; ?>
    <?php endif; ?>

    Espero que lhe ajude.
    Qualquer dúvida só chamar.

  3. Oi, agradeço a ajuda, eu já havia conseguido, estava com problema para receber os erros, só conseguia receber individualmente coloquei o $validator -> errors -> all(); , igual você fez e tinha dado certo. As vezes acho que a documentação do Laravel tem alguns erros e algumas coisas deixo de usar, como o Compositor, pois perco tempo demais fazendo funcionar (se funcionar) e o uso é desnecessário, logo opto por não usar.
    No meu caso estou colocando a validação junto com o método que cadastra o cliente, mas creio que do seu modo fica mais organizado.

  4. Oi, deu certo o jeito que você fez, apenas modifiquei um pouco para meu uso. O legal que deixa o Controlador mais limpo e fica mais organizado, pois podemos por funções no modelo, no qual ela representa.
    Por exemplo um CRUD de usuários, no Model usuário e o Controller foca mais em chamar as Views e usar os métodos do Model.

Deixe uma resposta

O seu endereço de email não será publicado Campos obrigatórios são marcados *

*

Você pode usar estas tags e atributos de HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">