Posted on: December 03, 2021 09:54 AM
Posted by: Renato
Views: 2761
20 dicas e truques do Laravel Eloquent
O Eloquent ORM parece um mecanismo simples, mas por baixo do capô, há muitas funções semi-ocultas e maneiras menos conhecidas de conseguir mais com ele. Neste artigo, vou mostrar alguns truques.
1. Incrementos e decrementos
Em vez disso:
1$article = Article::find($article_id);
2$article->read_count++;
3$article->save();
Você consegue fazer isso:
1$article = Article::find($article_id);
2$article->increment('read_count');
Também funcionarão:
1Article::find($article_id)->increment('read_count');
2Article::find($article_id)->increment('read_count', 10); // +10
3Product::find($produce_id)->decrement('stock'); // -1
2. Métodos XorY
O Eloquent tem algumas funções que combinam dois métodos, como “por favor, faça X, caso contrário, faça Y”.
Exemplo 1 - findOrFail()
:
Ao invés de:
1$user = User::find($id);
2if (!$user) { abort (404); }
Fazem isto:
1$user = User::findOrFail($id);
Exemplo 2 - firstOrCreate()
:
Ao invés de:
1$user = User::where('email', $email)->first();
2if (!$user) {
3 User::create([
4 'email' => $email
5 ]);
6}
Faça apenas isto:
1$user = User::firstOrCreate(['email' => $email]);
3. Método model boot ()
Existe um lugar mágico chamado boot()
em um modelo do Eloquent onde você pode substituir o comportamento padrão:
1class User extends Model
2{
3 public static function boot()
4 {
5 parent::boot();
6 static::updating(function($model)
7 {
8 // do some logging
9 // override some property like $model->something = transform($something);
10 });
11 }
12}
Provavelmente, um dos exemplos mais populares é definir algum valor de campo no momento da criação do objeto de modelo. Digamos que você queira gerar o campo UUID naquele momento.
1public static function boot()
2{
3 parent::boot();
4 self::creating(function ($model) {
5 $model->uuid = (string)Uuid::generate();
6 });
7}
4. Relacionamento com condições e pedidos
Esta é uma maneira típica de definir relacionamento:
1public function users() {
2 return $this->hasMany('App\User');
3}
Mas você sabia que neste momento já podemos adicionar where
ou orderBy
?
Por exemplo, se você deseja um relacionamento específico para algum tipo de usuário, também solicitado por e-mail, você pode fazer o seguinte:
1public function approvedUsers() {
2 return $this->hasMany('App\User')->where('approved', 1)->orderBy('email');
3}
5. Propriedades do modelo: carimbos de data / hora, anexos etc.
Existem alguns “parâmetros” de um modelo do Eloquent, na forma de propriedades dessa classe. Os mais populares são provavelmente estes:
1class User extends Model {
2 protected $table = 'users';
3 protected $fillable = ['email', 'password']; // which fields can be filled with User::create()
4 protected $dates = ['created_at', 'deleted_at']; // which fields will be Carbon-ized
5 protected $appends = ['field1', 'field2']; // additional values returned in JSON
6}
Mas espere, tem mais:
1protected $primaryKey = 'uuid'; // it doesn't have to be "id"
2public $incrementing = false; // and it doesn't even have to be auto-incrementing!
3protected $perPage = 25; // Yes, you can override pagination count PER MODEL (default 15)
4const CREATED_AT = 'created_at';
5const UPDATED_AT = 'updated_at'; // Yes, even those names can be overridden
6public $timestamps = false; // or even not used at all
E tem ainda mais, eu listei os mais interessantes, para mais por favor verifique o código da classe de modelo abstrato padrão e verifique todas as características usadas.
6. Encontre várias entradas
Todo mundo conhece o find()
método, certo?
1$user = User::find(1);
Estou bastante surpreso como poucas pessoas sabem que ele pode aceitar vários IDs como uma matriz:
1$users = User::find([1,2,3]);
7. WhereX
Há uma maneira elegante de transformar isso:
1$users = User::where('approved', 1)->get();
Nisso:
1$users = User::whereApproved(1)->get();
Sim, você pode alterar o nome de qualquer campo e anexá-lo como um sufixo a “onde” e ele funcionará como um passe de mágica.
Além disso, existem alguns métodos predefinidos no Eloquent, relacionados a data / hora:
1User::whereDate('created_at', date('Y-m-d'));
2User::whereDay('created_at', date('d'));
3User::whereMonth('created_at', date('m'));
4User::whereYear('created_at', date('Y'));
8. Ordem por relacionamento
Um “truque” um pouco mais complicado. E se você tiver tópicos de fórum, mas quiser ordená-los pela última postagem ? Requisito bastante comum em fóruns com os últimos tópicos atualizados no topo, certo?
Primeiro, descreva um relacionamento separado para a última postagem sobre o tópico:
1public function latestPost()
2{
3 return $this->hasOne(\App\Post::class)->latest();
4}
E então, em nosso controlador, podemos fazer esta “mágica”:
1$users = Topic::with('latestPost')->get()->sortByDesc('latestPost.created_at');
9. Eloquent :: when () - não há mais if-else's
Muitos de nós escrevemos consultas condicionais com "if-else", algo assim:
1if (request('filter_by') == 'likes') {
2 $query->where('likes', '>', request('likes_amount', 0));
3}
4if (request('filter_by') == 'date') {
5 $query->orderBy('created_at', request('ordering_rule', 'desc'));
6}
Mas há uma maneira melhor - de usar when()
:
1$query = Author::query();
2$query->when(request('filter_by') == 'likes', function ($q) {
3 return $q->where('likes', '>', request('likes_amount', 0));
4});
5$query->when(request('filter_by') == 'date', function ($q) {
6 return $q->orderBy('created_at', request('ordering_rule', 'desc'));
7});
Pode não parecer mais curto ou mais elegante, mas o mais poderoso é passar dos parâmetros:
1$query = User::query();
2$query->when(request('role', false), function ($q, $role) {
3 return $q->where('role_id', $role);
4});
5$authors = $query->get();
10. Pertence a modelos padrão
Digamos que você tenha uma postagem pertencente ao autor e, em seguida, ao código Blade:
1{{ $post->author->name }}
Mas e se o autor for excluído ou não for definido por algum motivo? Você obterá um erro, algo como “propriedade do não objeto”.
Claro, você pode evitá-lo assim:
1{{ $post->author->name ?? '' }}
Mas você pode fazer isso no nível de relacionamento do Eloquent:
1public function author()
2{
3 return $this->belongsTo('App\Author')->withDefault();
4}
Neste exemplo, a author()
relação retornará um App\Author
modelo vazio se nenhum autor estiver anexado à postagem.
Além disso, podemos atribuir valores de propriedade padrão a esse modelo padrão.
1public function author()
2{
3 return $this->belongsTo('App\Author')->withDefault([
4 'name' => 'Guest Author'
5 ]);
6}
11. Pedido por Mutator
Imagine que você tem isso:
1function getFullNameAttribute()
2{
3 return $this->attributes['first_name'] . ' ' . $this->attributes['last_name'];
4}
Agora, você quer ordenar por isso full_name
? Isso não vai funcionar:
1$clients = Client::orderBy('full_name')->get(); // doesn't work
A solução é bastante simples. Precisamos ordenar os resultados depois de obtê-los.
1$clients = Client::get()->sortBy('full_name'); // works!
Observe que o nome da função é diferente - não é orderBy , é sortBy .
12. Ordenação padrão no escopo global
E se você quiser que User::all()
sempre seja ordenado por name
campo? Você pode atribuir um escopo global. Vamos voltar ao boot()
método, que já mencionamos acima.
1protected static function boot()
2{
3 parent::boot();
4
5 // Order by name ASC
6 static::addGlobalScope('order', function (Builder $builder) {
7 $builder->orderBy('name', 'asc');
8 });
9}
Leia mais sobre Query Scopes aqui .
13. Métodos de consulta bruta
Às vezes, precisamos adicionar consultas brutas às nossas instruções do Eloquent. Felizmente, existem funções para isso.
1// whereRaw
2$orders = DB::table('orders')
3 ->whereRaw('price > IF(state = "TX", ?, 100)', [200])
4 ->get();
5
6// havingRaw
7Product::groupBy('category_id')->havingRaw('COUNT(*) > 1')->get();
8
9// orderByRaw
10User::where('created_at', '>', '2016-01-01')
11 ->orderByRaw('(updated_at - created_at) desc')
12 ->get();
14. Replicar: faça uma cópia de uma linha
Um curto. Sem explicações profundas, esta é a melhor maneira de fazer uma cópia da entrada do banco de dados:
1$task = Tasks::find(1);
2$newTask = $task->replicate();
3$newTask->save();
15. Método Chunk () para tabelas grandes
Não exatamente relacionado ao Eloquent, é mais sobre Coleção, mas ainda poderoso - para processar conjuntos de dados maiores, você pode dividi-los em pedaços.
Ao invés de:
1$users = User::all();
2foreach ($users as $user) {
3 // ...
Você pode fazer:
1User::chunk(100, function ($users) {
2 foreach ($users as $user) {
3 // ...
4 }
5});
16. Crie coisas adicionais ao criar um modelo
Todos nós conhecemos este comando do Artisan:
1php artisan make:model Company
Mas você sabia que existem três sinalizadores úteis para gerar arquivos relacionados ao modelo?
1php artisan make:model Company -mcr
- -m irá criar um arquivo de migração
- -c criará um controlador
- -r irá indicar que o controlador deve ser engenhoso
17. Substituir updated_at ao salvar
Você sabia que esse ->save()
método pode aceitar parâmetros? Como resultado, podemos dizer a ele para “ignorar” a updated_at
funcionalidade padrão a ser preenchida com o carimbo de data / hora atual. Veja isso:
1$product = Product::find($id);
2$product->updated_at = '2019-01-01 10:00:00';
3$product->save(['timestamps' => false]);
Aqui estamos substituindo o padrão updated_at
pelo pré-definido.
18. Qual é o resultado de uma atualização ()?
Você já se perguntou o que esse código realmente retorna?
1$result = $products->whereNull('category_id')->update(['category_id' => 2]);
Quer dizer, a atualização é realizada no banco de dados, mas o que isso $result
conteria?
A resposta é linhas afetadas . Portanto, se você precisar verificar quantas linhas foram afetadas, não precisa chamar mais nada - o update()
método retornará esse número para você.
19. Transforme os colchetes em uma consulta do Eloquent
E se você tiver e / ou misturar sua consulta SQL, assim:
1... WHERE (gender = 'Male' and age >= 18) or (gender = 'Female' and age >= 65)
Como traduzir para o Eloquent? Este é o caminho errado :
1$q->where('gender', 'Male');
2$q->orWhere('age', '>=', 18);
3$q->where('gender', 'Female');
4$q->orWhere('age', '>=', 65);
O pedido estará incorreto. O caminho certo é um pouco mais complicado, usando funções de encerramento como subconsultas:
1$q->where(function ($query) {
2 $query->where('gender', 'Male')
3 ->where('age', '>=', 18);
4})->orWhere(function($query) {
5 $query->where('gender', 'Female')
6 ->where('age', '>=', 65);
7})
20. ou Onde com vários parâmetros
Finalmente, você pode passar uma série de parâmetros para orWhere()
.
Forma “usual”:
1$q->where('a', 1);
2$q->orWhere('b', 2);
3$q->orWhere('c', 3);
Você pode fazer assim:
1$q->where('a', 1);
2$q->orWhere(['b' => 2, 'c' => 3]);
Fonte: https://laravel-news.com/eloquent-tips-tricks
Donate to Site
Renato
Developer