Laravel é um framework PHP de código aberto e fácil de usar. Um de seus recursos mais avançados é o Eloquent, um mapeador de objeto-relacional (ORM) que simplifica o manuseio de registros do banco de dados.

O Eloquent acelera as operações de criação, leitura, atualização e exclusão em um banco de dados a partir de um aplicativo. Ao usar o Eloquent, você cria modelos que espelham as tabelas do banco de dados e usa esses modelos para criar suas consultas.

Este artigo examina seis elementos da funcionalidade mais potente do Eloquent: escopos de consulta, relacionamentos, mutadores e acessores, coleções, exclusão de modelos e fábricas. Ele aborda o que cada recurso faz usando exemplos práticos. Esperamos que você possa usar esses exemplos para iniciar seu domínio do Laravel Eloquent.

1. Escopos de consulta do Eloquent

Ao criar um aplicativo, às vezes você se depara com situações em que usa condições mais de uma vez. Reescrever o código em cada caso pode aumentar a chance de erros e deixar seu código desorganizado. O Laravel resolve esse problema ao encapsular essas condições em declarações reutilizáveis chamadas escopos.

Os escopos de consulta são métodos para adicionar lógica do banco de dados a um modelo e reutilizar a lógica de consulta.

A seguir, você verá um exemplo de escopo de consulta. Suponha que você queira criar uma plataforma de desenvolvimento de software para sua equipe que rastreie recursos concluídos e em andamento. Você pode usar essa condição para recuperar apenas os recursos em andamento:

$onGoing = Project::where('ongoing', 1)->get();

Você pode precisar dessa condição em outras páginas do aplicativo, como a página de estatísticas. Os escopos de consulta permitem que uma página reutilize a condição acima, simplificando sua consulta e tornando seu código mais limpo.

Veja como você pode usar um escopo de consulta para esse cenário:

class Features extends Model
{
    public function scopeOngoing($query)
    {
        return $query->where('ongoing', 0);
    }
}

Em seguida, use o código abaixo para executar esse escopo:

$onGoing = Feature::ongoing()->get();

Há dois tipos de escopos: global e local.

Escopos globais

Os escopos globais permitem a adição de restrições a todas as consultas em um modelo. Por exemplo, você pode adicionar uma condição para filtrar recursos com base no nome do líder da equipe em todas as consultas do seu modelo.

Escopos locais

Os escopos locais permitem a definição de restrições comuns para reutilização. Por exemplo, você pode querer que o aplicativo retorne os recursos que têm bugs. Seu código pode implementar um escopo local como este:

namespace AppModels;
use IlluminateDatabaseEloquentModel;

class User extends Model
{
    public function scopeBugged($query)
    {
        return $query->where('bugged', '>', 1);
    }
}

O código acima retorna todos os recursos que têm bugs não corrigidos.

2. Relacionamentos do Eloquent

Os relacionamentos no Eloquent permitem que você relacione facilmente diferentes tabelas. Por exemplo, um produto em um site de eCommerce pode ter inventário, preço, visualizações e avaliações listados. Com o Eloquent, você pode gerenciar facilmente esses relacionamentos, mesmo quando os registros estão em tabelas diferentes.

Você pode definir relacionamentos como métodos em classes de modelo, da mesma forma que faria com um modelo do Eloquent. Alguns relacionamentos do Eloquent comumente usados incluem um para um, inverso e polimórfico.

Um para um

Aqui está um exemplo de um relacionamento básico de um para um que associa um modelo de produto a um inventário.

public function Inventory()
{
    return $this->hasOne('AppInventory');
}

No código acima, o método Inventory() chama o método hasOne() no modelo de produto. Isso verifica se o produto está disponível no momento.

Inverso

O Eloquent também permite que você crie uma relação inversa. Por exemplo, quando você deseja buscar produtos com base em sua contagem de visualizações. As relações inversas podem fornecer a você os produtos que despertam mais interesse dos visitantes de um site. Você pode usar o método belongsTo(), que é o inverso de hasOne(). O código abaixo ilustra isso.

public function product()
{
    return $this->belongsTo('AppProduct');
}

No código acima, o Eloquent faz a correspondência entre o product_id e o número de visualizações passadas. O product_id pode, então, ajudar você a buscar outros parâmetros, como preço e estoque.

Polimórfico

No desenvolvimento de aplicativos, as relações nem sempre são simples. Às vezes, você tem um modelo que pertence a mais de um tipo de modelo. Por exemplo, os modelos de produto e estoque podem ter relacionamentos polimórficos com um modelo de imagem.

Os relacionamentos polimórficos permitiriam que você usasse a mesma lista de imagens para o inventário e para os produtos. Abaixo está um trecho de código que implementa um relacionamento polimórfico.

class Image extends Model
{
    /**
     * Getting the shared image.
     */
    public function myimage()
    {
        return $this->morphTo();
    }
}

class Product extends Model
{
    /**
     * Get the image to use on the product's page.
     */
    public function image()
    {
        return $this->morphOne(Image::class, 'myimage');
    }
}

class Inventory extends Model
{
    /**
     * Get the image to use on the inventory page.
     */
    public function image()
    {
        return $this->morphOne(Image::class, 'myimage');
    }
}

O código acima usa o método morphTo() para recuperar o modelo polimórfico principal.

Essa é apenas a ponta do iceberg sobre esse tópico. Para saber mais, consulte nosso guia avançado sobre relacionamentos do Laravel Eloquent.

3. Mutadores e acessores do Eloquent

Os mutadores e acessores permitem que você altere os dados enquanto os armazena e recupera. Os mutadores modificam os dados antes de salvá-los, enquanto os acessores modificam os dados enquanto os recuperam.

Se você quiser armazenar nomes em letras minúsculas no banco de dados, poderá criar um mutador para executar essa transformação. Se quiser exibir o nome e o sobrenome do usuário como um único nome nas páginas do aplicativo, você pode criar um acessor para fazer isso.

Abaixo você encontra um exemplo de um mutador que coloca os nomes em maiúsculas antes de salvá-los.

class User extends Model
{
    /**
     * Mutators capitalizing first and last name.
     */
    public function setFirstNameAttribute($value)
    {
        $this->attributes['first_name'] = ucfirst($value);
    }

    public function setLastNameAttribute($value)
    {
        $this->attributes['last_name'] = ucfirst($value);
    }
}

Abaixo está um exemplo de um acessório que combina o nome e o sobrenome do usuário.

class User extends Model
{
    /**
     * Accessor combining both names.
     */
    public function getFullNameAttribute()
    {
        return ucfirst($this->first_name) . ' ' . ucfirst($this->last_name);
    }
}

4. Coleções eloquentes

As coleções eloquentes lidam com métodos que retornam vários resultados de modelos. Essa classe é encontrada em IlluminateDatabaseEloquentCollection.

Assim como ocorre com as arrays, é possível iterar pelas coleções. A seguir, você verá uma iteração simples.

use AppModelsProduct;

$products = Product::where('availability', 1)->get();

foreach ($products as $product) {
   echo $product->name;
}

As coleções são mais eficientes do que as arrays porque você pode executar operações mais complexas nelas. Por exemplo, você pode exibir a lista de todos os produtos disponíveis e ignorar todos os que não estão “ativos”.

$names = Product::all()->reject(function ($product) {
   return $product->active === false;
})->map(function ($product) {
   return $product->name;
});

Abaixo estão alguns dos métodos que a classe de coleções oferece.

contains

O método contains() verifica se o código contém um modo especificado, conforme mostrado no código abaixo:

$products->contains(1);
$products->contains(Product::find(1));

all

O método all() retorna os modelos contidos na coleção, conforme mostrado abaixo:

$collection = Product::all();

Muitos outros métodos são compatíveis com a classe de coleções.

5. Exclua modelos do Eloquent

No Eloquent, você cria modelos para ajudar na criação de consultas. No entanto, às vezes você precisa excluir modelos para tornar um aplicativo mais eficiente. Para isso, você deve chamar delete na instância do modelo.

use AppModelsStock;

$stock = Stock::find(1);
$stock->delete();

O código acima remove o modelo Stock de um aplicativo. Essa é uma remoção permanente que não pode ser desfeita.

Exclusão suave

Outro recurso que o Eloquent contém é o recurso de exclusão suave de modelos. Quando você realiza uma exclusão suave de um modelo, você não o remove do banco de dados.

Você marca o registro usandodeleted_at para indicar a hora e a data da exclusão suave. Isso é importante quando você deseja excluir uma parte dos registros do banco de dados, como aqueles que estão incompletos, sem removê-los permanentemente. Isso ajuda a limpar os resultados da consulta do Eloquent sem adicionar condições extras.

Você ativa a exclusão suave adicionando a característica softDeletes a um modelo e adicionando uma coluna deleted_at na tabela de banco de dados relacionada.

Adição de exclusão temporária a um modelo

Você ativa as exclusões suaves do modelo adicionando a característica IlluminateDatabaseEloquentSoftDeletes, conforme mostrado abaixo.

namespace AppModels;
use IlluminateDatabaseEloquentModel;
use IlluminateDatabaseEloquentSoftDeletes;

class Flight extends Model
{
   use SoftDeletes;
}

Como adicionar uma coluna delete_at

Antes que você possa começar a usar a exclusão temporária, seu banco de dados deve ter uma coluna delete_at. Você adiciona essa coluna usando um método auxiliar do Laravel Schema builder, conforme mostrado abaixo:

use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;

Schema::table('users', function (Blueprint $table) {
   $table->softDeletes();
});

Schema::table('users', function (Blueprint $table) {
   $table->dropSoftDeletes();
});

Isso adiciona uma coluna delete_at que é atualizada com a data e a hora, no caso de uma ação de exclusão temporária bem-sucedida.

Como incluir modelos com exclusão temporária

Se você quiser que os resultados da consulta incluam modelos com exclusão temporária, adicione o método withTrashed() à consulta. Um exemplo é mostrado abaixo:

$stocks = Stock::withTrashed()->where('stock_id', 20)->get();

A consulta acima também incluirá modelos com o atributo deleted_at.

Como recuperar apenas modelos com exclusão suave

O Eloquent também permite que você recupere exclusivamente modelos com exclusão temporária. Você pode fazer isso chamando o método onlyTrashed(), por exemplo:

$Stock = Stock::onlyTrashed()->where('stock_id', 1)->get();

Como restaurar modelos excluídos por software

Você também pode restaurar modelos excluídos por software chamando o método restore().

$stocks = Stock::withTrashed()->where('stock_id', 20)->restore();

Isso altera o campo delete_at de um modelo excluído suavemente para nulo. Se o modelo não tiver sido excluído suavemente, ele deixará o campo inalterado.

6. Eloquent Factories

O modelo factories no Laravel criam dados fictícios que você pode usar para testar seu aplicativo ou para alimentar seu banco de dados. Para implementar isso, você cria um modelo em uma classe de fábrica, conforme mostrado no exemplo abaixo. O trecho de código cria o modelo factories que pode gerar fornecedores falsos de um produto e seus preços.

namespace DatabaseFactories;
use IlluminateDatabaseEloquentFactoriesFactory;
use IlluminateSupportStr;

class StockFactory extends Factory
{
    public function definition()
    {
        return [
            'supplier_name' => fake()->name(),
            'price' => fake()->numberBetween($min = 1500, $max = 6000),
        ];
    }
}

O método definition() no exemplo acima retorna um conjunto de valores de atributos que o Laravel usa ao criar o modelo. O auxiliar falso ajuda o modelo factories a acessar a biblioteca do PHP, Faker.

Resumo

O Eloquent torna mais simples as tarefas de desenvolvimento de aplicativos no Laravel. Ele é igualmente eficaz na criação de consultas simples ou complexas, graças a implementações como relacionamentos. A simplicidade de gerar dados fictícios funcionais usando o modelo factories é ideal para desenvolvedores que buscam criar testes robustos para seus aplicativos. Adicionalmente, os escopos do Eloquent contribuem para simplificar consultas complexas, mantendo o código organizado e claro.

Embora este artigo tenha abordado apenas seis de seus principais recursos, o Eloquent tem outras funcionalidades poderosas. O uso de modelos compartilháveis e reutilizáveis tornou o Eloquent um recurso popular entre os desenvolvedores, e a simplicidade das consultas do Eloquent faz do Laravel um framework de fácil desenvolvimento, mesmo para iniciantes.

Seja qual for o seu nível de experiência, a plataforma de hospedagem de aplicativos web da Kinsta está aqui para apoiar desenvolvedores como você. Nosso modelo de início rápido do Laravel mostra como é fácil colocar seu aplicativo em funcionamento em nossos servidores dentro da rede de nível premium do Google Cloud.

Steve Bonisteel Kinsta

Steve Bonisteel is a Technical Editor at Kinsta who began his writing career as a print journalist, chasing ambulances and fire trucks. He has been covering Internet-related technology since the late 1990s.