Modelos inteligentes autovalidados para Eloquent ORM do Laravel Framework 5.
Baseado no pacote Aware para Laravel 3 de Colby Rabideau.
Copyright (C) 2013-2015 Max Ehsan & Igor Santos
Visite nossa lista de lançamentos. O changelog é feito lá :)
Adicione laravelbook/ardent
como um requisito ao composer.json
(veja nossa versão estável mais recente nos emblemas!):
{"require": {"laravelbook/ardent": "3.*"}}
Atualize seus pacotes com composer update
ou instale com composer install
.
Você também pode adicionar o pacote usando composer require laravelbook/ardent
e posteriormente especificando a versão desejada (por enquanto, dev-master
é sua melhor aposta).
Se você deseja usar o Ardent como um pacote ORM independente, você está convidado a fazê-lo usando a seguinte configuração no arquivo de inicialização/inicialização do seu projeto (alterando as propriedades de acordo com o seu banco de dados, obviamente):
LaravelArdentArdentArdent::configureAsExternal(array( 'driver' => 'mysql', 'host' => 'localhost', 'port' => 3306, 'database' => 'my_system', 'username' => 'myself', 'senha' => 'h4ckr', 'charset' => 'utf8', 'agrupamento' => 'utf8_unicode_ci'), 'pt'); //Inglês é o idioma padrão das mensagens, pode ser deixado em branco
Introdução
Começando
Validação sem esforço com Ardent
Recuperando Erros de Validação
Substituindo validação
Mensagens de erro de validação personalizadas
Regras de validação personalizadas
Ganchos modelo
Definição mais limpa de relacionamentos
Hidratar automaticamente entidades ardentes
Limpar automaticamente dados de formulário redundantes
Transformar automaticamente atributos de texto seguro
Atualizações com regras exclusivas
Com que frequência você recria o mesmo código padrão nos aplicativos que cria? Esse código típico de processamento de formulário parece muito familiar para você?
Route::post('register', function() {$rules = array('name' => 'required|between:3,80|alpha_dash','email' => 'required|between:5,64|email |único:usuários','senha' => 'obrigatório|min:6|confirmado','senha_confirmação' => 'required|min:6');$validator = Validator::make(Input::all(), $rules);if ($validator->passes()) { User::create(array('name' => Input::get('name'),'email' => Input::get('email'),'password' => Hash::make(Input:: obter('senha')) ));return Redirect::to('/')->with('message', 'Obrigado por se registrar!'); } else {return Redirect::to('/')->withErrors($validator->getMessages()); } } );
Implementar isso sozinho geralmente resulta em muitos códigos clichê repetidos. Como um bônus adicional, seus controladores (ou manipuladores de rota) engordam prematuramente e seu código fica confuso, feio e difícil de entender.
E se outra pessoa fizesse todo o trabalho pesado por você? E se, em vez de regurgitar a bagunça acima, tudo o que você precisasse digitar fossem essas poucas linhas?...
Route::post('register', function() {$user = new User;if ($user->save()) {return Redirect::to('/')->with('message', 'Obrigado para se registrar!'); } else {return Redirect::to('/')->withErrors($user->errors()); } } );
Entre Ardente!
Ardent - a solução completa, movida a pó mágico e fácil de usar para todos os seus monótonos padrões de higienização de entrada!
Trocadilhos à parte, a funcionalidade de validação de entrada pode rapidamente se tornar tediosa de escrever e manter. Ardent lida com essas complexidades fornecendo ajudantes para automatizar muitas tarefas repetitivas.
No entanto, o Ardent não é ótimo apenas para validação de entrada - ele o ajudará a reduzir significativamente o código do modelo de dados do Eloquent. Ardent é particularmente útil se você estiver cansado de escrever códigos muito semelhantes repetidamente em vários aplicativos individuais.
Por exemplo, o registro do usuário ou o envio de postagem no blog é um requisito de codificação comum que você pode querer implementar em um aplicativo e reutilizar novamente em outros aplicativos. Com Ardent, você pode escrever seus modelos inteligentes e autoconscientes apenas uma vez e depois reutilizá-los (com nenhuma ou muito pouca modificação) em outros projetos. Depois de se acostumar com essa maneira de fazer as coisas, você honestamente se perguntará como conseguiu lidar com a situação sem o Ardent.
Chega de lesões cerebrais repetitivas para você!
Ardent
pretende estender a classe base Eloquent
sem alterar sua funcionalidade principal. Como o próprio Ardent
é descendente de IlluminateDatabaseEloquentModel
, todos os seus modelos Ardent
são totalmente compatíveis com Eloquent
e podem aproveitar todo o poder do incrível OR/M do Laravel.
Para criar um novo modelo Ardent, simplesmente faça com que sua classe de modelo derive da classe base Ardent
. Nos próximos exemplos usaremos a classe completa com namespace para deixar os exemplos mais limpos, mas você é encorajado a fazer uso de use
em todas as suas classes:
use LaravelArdentArdentArdent;class O usuário estende Ardent {}
Nota: Você pode misturar livremente seus modelos Eloquent simples com descendentes Ardent. Se um objeto modelo não depende do conteúdo enviado pelo usuário e, portanto, não requer validação - você pode deixar a classe modelo Eloquent como está.
Os modelos Ardent usam a classe Validator integrada do Laravel. Definir regras de validação para um modelo é simples e normalmente é feito na classe do modelo como uma variável estática:
class Usuário estende LaravelArdentArdentArdent { public static $rules = array('name' => 'required|between:3,80|alpha_dash','email' => 'required|between:5,64|email|unique:users', 'senha' => 'obrigatório|min:6|confirmado','password_confirmation' => 'obrigatório | min: 6', ); }
Nota : você também pode usar a sintaxe de array para regras de validação. Espero que você não se importe com o antigo link de documentos do Laravel, mas por melhor que seja a documentação do Laravel, a referência clara às sintaxes de pipe/array para regras de validação infelizmente desapareceu desde a versão 5.1.
Os modelos Ardent se validam automaticamente quando Ardent->save()
é chamado.
$user = novo usuário;$user->name = 'John doe';$user->email = '[email protected]';$user->password = 'test';$success = $user->save( ); // retorna falso se o modelo for inválido
Nota: Você também pode validar um modelo a qualquer momento usando o método
Ardent->validate()
.
Quando um modelo Ardent falha na validação, um objeto IlluminateSupportMessageBag
é anexado ao objeto Ardent que contém mensagens de falha de validação.
Recupere a instância de coleta de mensagens de erros de validação com o método Ardent->errors()
ou a propriedade Ardent->validationErrors
.
Recupere todos os erros de validação com Ardent->errors()->all()
. Recupere erros para um atributo específico usando Ardent->validationErrors->get('attribute')
.
Nota: Ardent aproveita o objeto MessagesBag do Laravel, que possui um método simples e elegante de erros de formatação.
Existem duas maneiras de substituir a validação do Ardent:
forceSave()
valida o modelo, mas salva independentemente de haver ou não erros de validação.
ambos Ardent->save($rules, $customMessages)
e Ardent->validate($rules, $customMessages)
usam dois parâmetros:
$rules
é uma matriz de regras do Validador da mesma forma que Ardent::$rules
.
O mesmo se aplica ao parâmetro $customMessages
(igual a Ardent::$customMessages
)
Uma matriz que não esteja vazia substituirá as regras ou mensagens de erro personalizadas especificadas pela classe apenas para aquela instância do método.
Nota: o valor padrão para
$rules
e$customMessages
éarray()
vazio; portanto, se você passar umarray()
nada será substituído.
Assim como o Laravel Validator, o Ardent permite definir mensagens de erro personalizadas usando a mesma sintaxe.
class User estende LaravelArdentArdentArdent { public static $customMessages = array('required' => 'O campo :attribute é obrigatório.', ... ); }
Você pode criar regras de validação personalizadas da mesma forma que faria para o Laravel Validator.
Ardent fornece um pouco de açúcar sintático sobre os eventos de modelo do Eloquent: ganchos de modelo tradicionais. Eles são uma maneira fácil de conectar operações adicionais a diferentes momentos da vida de seu modelo. Eles podem ser usados para fazer trabalho de limpeza adicional antes de excluir uma entrada, fazer correções automáticas após a validação ou atualizar modelos relacionados após uma atualização.
Todos os ganchos before
, ao retornar false
(especificamente valores booleanos, não simplesmente "falsos") interromperão a operação. Então, por exemplo, se você quiser parar de salvar se algo der errado em um método beforeSave
, apenas return false
e o salvamento não acontecerá - e obviamente afterSave
também não será chamado.
Aqui está a lista completa de ganchos disponíveis:
before
/ afterCreate()
before
/ afterSave()
before
/ afterUpdate()
before
/ afterDelete()
before
/ afterValidate()
- ao retornar false interromperá a validação, fazendo com que as operações save()
também falhem, já que a validação foi uma falha.
Por exemplo, você pode usar beforeSave
para fazer o hash da senha de um usuário (na verdade, seria uma ideia melhor usar o hash automático!):
class User estende LaravelArdentArdentArdent { public function beforeSave() {// se houver uma nova senha, hash itif($this->isDirty('password')) { $this->password = Hash::make($this->password ); } return true;//ou não retorna nada, pois apenas um booleano false interromperá a operação } }
beforeSave
e afterSave
podem ser incluídos em tempo de execução. Simplesmente passe os encerramentos com o modelo como argumento para o método save()
(ou forceSave()
).
$user->save(array(), array(), array(), function ($model) { // fechamento para beforeSaveecho "salvando o objeto modelo...";return true; }, function ($model) { // fechamento para afterSaveecho "done!"; } );
Nota: os encerramentos devem ter um parâmetro, pois será passada uma referência ao modelo que está sendo salvo.
Você já escreveu um modelo do Eloquent com um monte de relações, só para perceber como sua classe é desordenada, com todas aquelas frases simples que têm quase o mesmo conteúdo do próprio nome do método?
No Ardent você pode definir claramente seus relacionamentos em um array com suas informações, e eles funcionarão como se você os tivesse definido em métodos. Aqui está um exemplo:
class Usuário estende LaravelArdentArdentArdent { public static $relationsData = array('address' => array(self::HAS_ONE, 'Address'),'orders' => array(self::HAS_MANY, 'Order'),'groups' = > array(self::BELONGS_TO_MANY, 'Grupo', 'tabela' => 'grupos_têm_usuários') ); }$usuário = Usuário::find($id);echo "{$usuário->endereço->rua}, {$usuário->endereço->cidade} - {$usuário->endereço->estado}";
A sintaxe da matriz é a seguinte:
Primeiro valor indexado: nome da relação, sendo um de hasOne
, hasMany
, belongsTo
, belongsToMany
, morphTo
, morphOne
, morphMany
, ou uma das constantes relacionadas ( Ardent::HAS_MANY
ou Ardent::MORPH_ONE
por exemplo).
Segundo indexado: nome da classe, com namespace completo. A exceção são as relações morphTo
, que não aceitam argumentos adicionais.
argumentos nomeados, seguindo aqueles definidos para os métodos originais do Eloquent:
foreignKey
[opcional], válido para hasOne
, hasMany
, belongsTo
e belongsToMany
table
, otherKey
[opcional], timestamps
[booleano, opcional] e pivotKeys
[matriz, opcional], válido para belongsToMany
name
, type
e id
, usados por morphTo
, morphOne
e morphMany
(os dois últimos requerem name
seja definido)
Nota: Este recurso foi baseado nas relações fáceis do Yii 1.1 ActiveRecord.
Ardent é capaz de hidratar automaticamente sua classe de modelo de entidade a partir do envio de entrada do formulário!
Vamos ver isso em ação. Considere este trecho de código:
$usuário = novo usuário;$usuário->nome = Input::get('nome');$usuário->email = Input::get('email');$usuário->senha = Hash::make(Input ::get('senha'));$usuario->save();
Vamos invocar a magia do Ardente e reescrever o trecho anterior:
$usuário = novo usuário;$usuário->salvar();
É isso! Tudo o que fizemos foi remover as coisas chatas.
Acredite ou não, o código acima executa essencialmente a mesma tarefa que seu irmão mais antigo, embora bastante detalhado. Ardent preenche o objeto modelo com atributos de dados de formulário enviados pelo usuário. Chega de puxar o cabelo tentando descobrir qual propriedade do Eloquent você esqueceu de preencher. Deixe Ardent cuidar das coisas chatas, enquanto você continua com as coisas divertidas!
Ele segue internamente as mesmas regras de atribuição em massa, dependendo das propriedades $fillable
/ $guarded
.
Para ativar o recurso de hidratação automática, basta definir a variável de instância $autoHydrateEntityFromInput
como true
em sua classe de modelo. No entanto, para evitar o preenchimento de propriedades pré-existentes, se você quiser a auto-hidratação também para cenários de atualização, você deve usar $forceEntityHydrationFromInput
:
class Usuário estende LaravelArdentArdentArdent { public $autoHydrateEntityFromInput = true; // hidrata na validação de novas entradas public $forceEntityHydrationFromInput = verdadeiro; // hidrata sempre que a validação é chamada}
Os modelos Ardent podem limpar automaticamente dados de entrada redundantes (como confirmação de senha , _token
CSRF oculto ou campos _method
HTTP personalizados) - para que os dados extras nunca sejam salvos no banco de dados. Ardent usará os campos de confirmação para validar a entrada do formulário e, em seguida, descartará esses atributos com prudência antes de salvar a instância do modelo no banco de dados!
Para ativar esse recurso, basta definir a variável de instância $autoPurgeRedundantAttributes
como true
em sua classe de modelo:
class Usuário estende LaravelArdentArdentArdent { public $autoPurgeRedundantAttributes = true; }
Você também pode limpar campos adicionais. O atributo Ardent::$purgeFilters
é uma matriz de encerramentos aos quais você pode adicionar suas regras personalizadas. Esses encerramentos recebem a chave do atributo como argumento e devem retornar false
para atributos que devem ser eliminados. Assim:
function __construct($atributos = array()) { pai::__construct($atributos); $this->purgeFilters[] = function($key) {$purge = array('tempData', 'myAttribute');return ! in_array($chave, $purga); }; }
Suponha que você tenha um atributo chamado password
em sua classe de modelo, mas não queira armazenar a versão em texto simples no banco de dados. A coisa pragmática a fazer seria armazenar o hash do conteúdo original. Não se preocupe, Ardent é totalmente capaz de transmogrificar qualquer número de campos seguros automaticamente para você!
Para fazer isso, adicione o nome do atributo à variável de matriz estática Ardent::$passwordAttributes
em sua classe de modelo e defina a variável de instância $autoHashPasswordAttributes
como true
:
class Usuário estende LaravelArdentArdentArdent { public static $passwordAttributes = array('senha'); public $autoHashPasswordAttributes = verdadeiro; }
Ardent substituirá automaticamente o atributo de senha de texto simples por uma soma de verificação de hash segura e o salvará no banco de dados. Ele usa o método Laravel Hash::make()
internamente para gerar hash. Nota: É aconselhável usar o atributo $hidden
do Eloquent para que a senha, mesmo com hash, não saia tão facilmente se você estiver construindo uma API ou similar :)
Caso esteja usando o Ardent autônomo, você pode usar Ardent::$hasher
para verificar o valor do campo, usando algo como User::$hasher->check($given_password, $user->password)
.
Ardent pode ajudá-lo com atualizações exclusivas. De acordo com a documentação do Laravel, ao atualizar (e portanto validar) um campo com uma regra única, você deve passar o ID exclusivo do registro que está atualizando. Sem passar este ID, a validação falhará porque o Validador do Laravel pensará que este registro é duplicado.
Da documentação do Laravel:
'e-mail' => 'único:usuários,e-mail,10'
No passado, os programadores tinham que gerenciar manualmente a passagem do ID e a alteração do conjunto de regras para incluir o ID em tempo de execução. Não é assim com Ardente. Basta configurar suas regras com a função de chamada unique
updateUniques
e Ardent cuidará do resto.
Em seu modelo estendido defina suas regras
public static $rules = array( 'email' => 'required|email|unique', 'password' => 'required|between:4,20|confirmed', 'password_confirmation' => 'between:4,20', );
No seu controlador, quando precisar atualizar, basta ligar
$model->updateUniques();
Se necessário, você pode passar regras em tempo de execução para updateUniques
, caso contrário, ele usará as regras estáticas fornecidas pelo seu modelo.
Observe que no exemplo de regras acima, não informamos ao Validador qual tabela ou mesmo qual campo usar conforme descrito na documentação do Laravel (ou seja unique:users,email,10
). Ardent é inteligente o suficiente para descobrir isso. (Obrigado ao usuário do github @Sylph)