Relacionamentos com Laravel Eloquent

Laravel
Tempo de leitura: 6 minutos

Relacionamentos com Laravel Eloquent: Em qualquer aplicação complexa, os dados raramente existem isolados. Eles se relacionam entre si, formando estruturas e dependências. O laravel eloquent, o ORM do Laravel, oferece uma maneira elegante e intuitiva de definir e interagir com esses relacionamentos entre seus models. Compreender os relacionamentos do Eloquent é crucial para construir aplicações robustas e eficientes.

Este artigo explora em detalhes os principais tipos de relacionamentos oferecidos pelo Eloquent, com exemplos práticos e explicações claras.

One to One / Has One

O relacionamento “um para um” define uma conexão entre dois models onde um registro em uma tabela está associado a apenas um registro em outra tabela. Um exemplo clássico é um usuário que possui um único perfil.

  • Exemplo:

Temos os models User e Profile. Um usuário tem um perfil.

PHP

// app/Models/User.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function profile()
    {
        return $this->hasOne(Profile::class);
    }
}

// app/Models/Profile.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Profile extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class); // Relacionamento inverso (explicado mais adiante)
    }
}
  • Banco de Dados:

A tabela users deve ter um id como chave primária. A tabela profiles deve ter uma coluna user_id (chave estrangeira) referenciando o id da tabela users.

  • Utilização:

PHP

$user = User::find(1);
$profile = $user->profile; // Acessa o perfil do usuário

if ($profile) {
    echo $profile->bio;
}

One to Many / Has Many

O relacionamento “um para muitos” define uma conexão onde um registro em uma tabela pode estar associado a múltiplos registros em outra tabela. Um exemplo comum é um autor que pode ter vários posts.

  • Exemplo:

Temos os models Author e Post. Um autor tem muitos posts.

PHP

// app/Models/Author.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Author extends Model
{
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}

// app/Models/Post.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
        public function author()
    {
        return $this->belongsTo(Author::class);
    }
}
  • Banco de Dados:

A tabela authors deve ter um id como chave primária. A tabela posts deve ter uma coluna author_id (chave estrangeira) referenciando o id da tabela authors.

  • Utilização:

PHP

$author = Author::find(1);
$posts = $author->posts; // Acessa todos os posts do autor

foreach ($posts as $post) {
    echo $post->title;
}

One to Many (Inverse) / Belongs To

O relacionamento “pertence a” é o inverso do “tem muitos”. Ele define que um registro em uma tabela pertence a um único registro em outra tabela. No exemplo anterior, um post pertence a um autor. Já mostramos o exemplo acima, ele se encontra dentro do exemplo “One to Many / Has Many”.

  • Utilização:

PHP

$post = Post::find(1);
$author = $post->author; // Acessa o autor do post

echo $author->name;

Has One Of Many

O relacionamento “tem um de muitos” é útil quando você precisa obter o “último” ou o “mais recente” registro relacionado. Por exemplo, o último pedido de um cliente.

  • Exemplo:

Temos os models Customer e Order. Um cliente tem muitos pedidos, mas queremos acessar o último pedido.

PHP

// app/Models/Customer.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Customer extends Model
{
    public function latestOrder()
    {
        return $this->hasOne(Order::class)->latestOfMany();
    }
}

// app/Models/Order.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Order extends Model
{
    // ...
}
  • Utilização:

PHP

$customer = Customer::find(1);
$latestOrder = $customer->latestOrder;

if ($latestOrder) {
    echo $latestOrder->created_at;
}

Você também pode usar oldestOfMany() para obter o primeiro registro relacionado.

Has One Through

O relacionamento “tem um através de” fornece um atalho conveniente para acessar um relacionamento distante através de um relacionamento intermediário.

  • Exemplo:

Temos os models Country, User e Post. Um país tem usuários, e usuários têm posts. Queremos acessar o país de um post através do usuário.

PHP

// app/Models/Country.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Country extends Model
{
    // ...
}

// app/Models/User.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function country()
    {
        return $this->belongsTo(Country::class);
    }

    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}

// app/Models/Post.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function country()
    {
        return $this->hasOneThrough(Country::class, User::class);
    }
}
  • Banco de Dados:

As tabelas countries e users devem ter um relacionamento um-para-muitos (um país tem muitos usuários). A tabela users e posts também devem ter um relacionamento um-para-muitos (um usuário tem muitos posts).

  • Utilização:

PHP

$post = Post::find(1);
$country = $post->country; // Acessa o país do post através do usuário

echo $country->name;

Has Many Through

Semelhante ao “tem um através de”, o “tem muitos através de” fornece um atalho para acessar múltiplos registros relacionados através de um relacionamento intermediário.

  • Exemplo:

Usando o mesmo exemplo anterior, queremos acessar todos os posts de um país através dos usuários.

PHP

// app/Models/Country.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Country extends Model
{
    public function posts()
    {
        return $this->hasManyThrough(Post::class, User::class);
    }
}
  • Utilização:

PHP

$country = Country::find(1);
$posts = $country->posts; // Acessa todos os posts do país através dos usuários

foreach ($posts as $post) {
    echo $post->title;
}

Exemplo Completo: Listando posts com autor e país

PHP

use App\Models\Post;

Route::get('/posts', function () {
    $posts = Post::with(['user', 'user.country'])->get(); // Eager loading para evitar N+1

    return view('posts.index', compact('posts'));
});

Na view resources/views/posts/index.blade.php:

Blade

@foreach ($posts as $post)
    <div>
        <h2>{{ $post->title }}</h2>
        <p>Autor: {{ $post->user->name }}</p>
        <p>País: {{ $post->user->country->name }}</p>
    </div>
@endforeach

O uso do with() (eager loading) é crucial para otimizar as consultas e evitar o problema N+1, onde múltiplas consultas ao banco de dados são executadas dentro de um loop.

Conclusão

Relacionamentos com Laravel Eloquent: Os relacionamentos do laravel eloquent são uma ferramenta fundamental para o desenvolvimento de aplicações Laravel. Eles simplificam a interação com o banco de dados, tornando o código mais legível, manutenível e produtivo. Ao dominar os diferentes tipos de relacionamentos, você poderá modelar seus dados de forma eficiente e construir aplicações mais robustas e escaláveis.

Lembre-se de utilizar o eager loading (with()) sempre que necessário para otimizar as consultas e evitar o problema N+1. Com os exemplos e explicações apresentados neste artigo, você está pronto para explorar todo o potencial dos relacionamentos do Eloquent em seus projetos Laravel.

Considerações Adicionais:

  • Polymorphic Relationships (Relacionamentos Polimórficos): O Eloquent também oferece suporte a relacionamentos polimórficos, que permitem que um model pertença a mais de um model diferente em uma única associação. Existem dois tipos: “one to many” polimórfico e “many to many” polimórfico. Eles são úteis quando você tem um model que pode pertencer a diferentes tipos de models. Por exemplo, um sistema de comentários onde um comentário pode pertencer a um post, um vídeo ou uma foto.
  • Eager Loading Constraints (Restrições de Carregamento Adiantado): Você pode adicionar restrições às suas consultas de eager loading para carregar apenas os dados necessários. Por exemplo:

PHP

$posts = Post::with(['author' => function ($query) { $query->select('id', 'name'); // Carrega apenas o ID e o nome do autor }])->get();
  • Lazy Eager Loading: Se você não souber quais relacionamentos precisa carregar antecipadamente, pode usar o lazy eager loading:

PHP

$posts = Post::all(); if ($someCondition) { $posts->load('author'); }
  • Contagem de Relacionamentos: Você pode contar os models relacionados sem realmente carregá-los:

PHP

$authors = Author::withCount('posts')->get(); foreach ($authors as $author) { echo $author->posts_count; // Número de posts do autor }
  • Inserindo e Atualizando Models Relacionados: O Eloquent facilita a inserção e atualização de models relacionados:

PHP

$user = User::find(1); $user->profile()->create(['bio' => 'Nova biografia']); $post = Post::find(1); $post->author()->associate($author); // Associa um autor a um post $post->save();

Com essas informações adicionais, você terá um conhecimento ainda mais completo sobre os relacionamentos do Eloquent e poderá utilizá-los de forma eficaz em seus projetos Laravel. Lembre-se de consultar a documentação oficial do Laravel para obter informações mais detalhadas e exemplos avançados. A prática constante é fundamental para dominar completamente esse poderoso recurso.

Mas antes de dominar o Laravel, se for o seu caso, toda jornada tem um início. Vamos entender quais são os conhecimentos básicos necessários para aproveitar ao máximo este poderoso framework. Para iniciar seus estudos no Laravel, você precisará dominar as seguintes tecnologias:

HTML
HTML
CSS
CSS
Javascript
JavaScript

E se você gosta do nosso conteúdo, não deixe de contribuir adquirindo os serviços e produtos dos nossos apoiadores e empresas que somos associados:

Hospedagem Hostinger
Ofertas Amazon
Amazon Prime

Author: Thiago Rossi