Back-End

Back-End

Um pouco mais sobre criação de models com Eloquent

19 dez, 2017
Publicidade

E aí, pessoal?! Nos últimos meses eu iniciei um estudo sobre desenvolvimento com Laravel aqui na DialHost. Então, resolvi compartilhar todos os aprendizados por aqui. No artigo anterior, eu falei sobre o Eloquent e a criação de models no Laravel. Como o artigo estava ficando muito amplo, deixei algumas funções que achei realmente diferenciadas para aprofundar neste segundo artigo.

Nesta segunda parte, focarei no Eloquent com as funções findOrFail, firstOrFail,  chunk, cursor,  update, firstOrCreate, firstOrNew, updateOrCreate e softDelete.

findOrFail()

A função findOrFail trabalha com o tratamento de exceções nas buscas do banco de dados. Utilizando o nosso exemplo do artigo passado, ao fazermos uma busca pelo id de um produto, utilizando o findOFail($id), ele retornaria uma coleção com todos os resultados da busca ou dispararia um erro 404 se nenhum resultado for encontrado.

Este método é bastante útil para tratarmos os resultados de Rotas ou Controllers que necessitam do resultado desta busca para funcionar.

public function show($id){
 Product::findOrFail($id);
 }

firstOrFail()

Esta função é semelhante ao findOrFail. A única diferença é que ele limitará a busca apenas ao primeiro resultado obtido. E claro, se não obtiver resultados retornará o erro 404.

Este método é útil para fazer uma busca mais ampla e mesmo assim trazer apenas um resultado.

public function show($id){
 Product::where('price','>',3.5)->firstOrFail();
 }

Chunk e Cursor para melhorar o uso de memória nas buscas

Quando estamos trabalhando com buscas, podemos nos deparar com resultados gigantescos, dependendo da tabela que consultamos. Estas consultas podem demorar para trazer um retorno e/ou consumir muita memória. Para resolver este problema, o Eloquent possui a função chunk que fará a quebra desta consulta em pedaços menores e assim você conseguirá processar centenas de milhares de registros sem estourar o seu uso de memória.

Product::chunk(200, function ($products) {
 foreach ($products as $product) {
 // Faça o qualquer coisa que você queira com este dado.
 }
 });

No exemplo acima, temos dois parâmetros sendo passados na função. O primeiro é responsável por dizer o limite de resultados que cada bloco irá trabalhar. O segundo parâmetro é o que será executado para cada resultado de cada bloco da consulta. Podemos dizer que ele otimiza a consulta colocando um limite de resultados e fazendo um foreach automático até que todos os resultados da consulta sejam processados.

Ainda existe a opção de utilizar a função cursor. Ela tem uma aplicação semelhante. Neste caso, porém, ele trabalhará com apenas uma query. A otimização aqui fica por conta do retorno que a função cursor tem. Ela retornará um Generator. Um generator permite que escrevamos um código que utiliza foreach para interagir com um conjunto de informações sem precisar de registrar um array na memória. Se não existe a necessidade de gravar um array em memória, não existe o risco também de haver estouro de memória em um processamento de uma grande quantidade de dados.

No caso para usar esta função fazemos como abaixo:

foreach (Product::where('price',3.5)->cursor() as $product) {
 // Faça o qualquer coisa que você queira com este dado.
 }

Mass Update

No último artigo, eu apresentei como fazer um update de um registro em específico. Mas, existe uma  forma de atualizarmos também diversos registros que contemplam uma condição que a gente passar. Para isso, usamos o comando update do Eloquent. Com esta função, o Eloquent atualizará o campo passado em todos os resultados da busca que você fizer antes.

Product::where('product_line_id', 1)
 ->update(['product_line_id' => 2]);

firstOrCreate

O firstOrCreate fará a criação de um registro, mas primeiro ele validará se o registro já existe no banco. Caso o registro já exista, a função retornará o resultado, senão, ele criará o registro. Como fica claro, este comando só será útil para realizar a criação de dados que são únicos. No nosso exemplo, isto seria interessante para o product line, já que não quero que existam mais de um linha de produtos com o mesmo nome.

$productLine = Product_line::firstOrCreate(['description' => 'salgados']);

firstOrNew

Assim como o firstOrCreate o firstOrNew do Eloquent tentará encontrar um registro já existente do parâmetro que passarmos. A diferença é que ele não salvará o registro no banco de dados, mas sim, instanciará um novo model com este registro. Assim, para salvar realmente no banco será necessário executar o comando “save”.

$productLine = Product_line::firstOrCreate(['description' => 'salgados']);

updateOrCreate

Mais uma vez, a função updateOrCreate irá buscar um registro existente do parâmetro que passamos. Mas, como diz o nome da função, aqui ele vai atualizar o valor ou criar o novo registro no banco de dados. Esta função se torna útil para uma edição forçada onde, mesmo que o registro exista, eu queira atualizar um parâmetro vinculado a ele.

$units= Units::updateOrCreate(['description' => 'kilogramas'],['abbreviation' =>'kg']);

Aqui, o primeiro parâmetro será o campo que iremos fazer a busca. Caso a consulta retorne um valor o sistema irá atualizar o campo abbreviation. Caso não encontre, o mesmo irá criar um registro novo com a description “Kilogramas” e setará a abbreviation  como “Kg”.

SoftDelete com Eloquent

O Eloquent do Laravel permite o sistema trabalhar com a metodologia de Soft Delete. No Soft Delete, seus dados não serão deletados realmente, eles apenas terão setados um campo deleted_at sempre que for executada uma ação de delete().

Para isto funcionar, primeiramente temos que setar em nossa migration schema o campo softDeletes.

Lembra do código abaixo? Se não lembra é só conferir o post Criando migrations com o Laravel 5.5. Então, eu adicionei ao final o campo softDeletes.

class create_product extends Migration
 {
 public function up() {
 Schema::create('product', function (Blueprint $table) {
 $table->smallIncrements('id');
 $table->string('description')->unique();
 $table->string('expiration_date');
 $table->decimal('price', 5, 2);
 $table->timestamps();
 $table->softDeletes(); //ADICIONEI AQUI  O SOFTDELETE
 $table->engine = 'InnoDB';
 });
 }

Agora precisamos setar nossa model para trabalhar com softDelete. Para isto, chamaremos a classe  SoftDeletes para usarmos e criaremos uma variável $dates

use Illuminate\Database\Eloquent\SoftDeletes;
class Product extends Model {
 use SoftDeletes;
 protected $fillable = ['description','expiration_time','price','product_line_id'];
 protected $dates = ['deleted_at'];
public function product_line(){
 return $this->belongsTo(Product_line::Class);
 }
 }

Com tudo isto configurado, agora toda vez que executar a função delete() do Eloquent a mesma irá definir a coluna deleted_at com a data e hora do momento da exclusão.

Por fim, caso queira restaurar este dado, ficou bem fácil. Podemos executar a função restore() do Eloquent  como abaixo.

$product = Product::onlyTrashed()
 ->where('product_id', 1)
 ->get();
$product->restore();

Conclusão

O Eloquent tem diversas funções para facilitar e diminuir o seu trabalho com aquelas tarefas usuais de banco de dados. Apenas com estes dois artigos que compartilhei com você deu para ter apenas uma visão básica das diversas situações que ele pode resolver.

Para quem quiser aprofundar mais nesta questão e tiver habilidades com o inglês fica a dica de dar uma lida na documentação completa do Laravel.