Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
October 19, 2022 12:14 am GMT

ORM Eloquent: Model

ORM - Object Relational Mapping

ORM uma tcnica que busca aproximar o paradigma da programao orientada a objetos ao paradigma dos bancos de dados relacionais.

E o ORM pode ser adotado de duas formas:

  • database first
  • code first

Database first

Esta abordagem mais usual em sistemas legados, quando o schema do banco de dados est definido e bastante evoludo.

Porm, preciso um cuidado maior ao analisar os relacionamentos entre as tabelas e como resolver dentro do ORM. Um estudo pouco aprofundado pode resultar em perda da performance da aplicao, levando-se falsa impresso que o problema est no ORM quando na verdade a estratgia adotada no foi a mais apropriada.

Code First

Nesta abordagem as entidades so criadas na aplicao para depois serem criadas no banco de dados, atravs de um processo chamado de migrao, cujo objetivo guardar o histrico de alteraes feitas no schema. Este processo anlogo ao versionamento de cdigo feito, por exemplo, no GitHub.

Entretanto, h situaes onde este cenrio no aplicvel. Para casos como este, o ORM pode gerar scripts DDL que sero executados no banco de dados, seja por meio de uma sesso aberta no terminal ou atravs de uma aplicao desenvolvida especificamente para essa finalidade.

Eloquent

O Eloquent o ORM oficial em aplicaes Laravel.

Entretanto a utilizao do Eloquent no obrigatria, sendo possvel desenvolver uma aplicao completa, com acesso a bancos de dados utilizando apenas a classe Illuminate\Support\Facades\DB.

Assim como outros ORMs, o Eloquent traz uma classe (abstrata) para representar as entidades do banco de dados. Trata-se do Illuminate\Database\Eloquent\Model.

Ao longo deste artigo veremos algumas das caractersticas da classe model e como resolver problemas que podem aparecer durante o processo de mapeamento de um schema de banco de dados.

Apesar deste ser um artigo com cunho tcnico, no criaremos projetos ou aplicaes e tambm no haver interao com bancos de dados.

Todas as informaes contidas neste artigo podem ser encontradas na documentao oficial do framework Laravel neste link.

Model

O modelo, dentro da arquitetura MVC, representado aqui pela letra 'M'. O modelo o objeto da aplicao que mais se aproxima do schema do banco de dados, sendo usado com frequncia para persistncia de informaes.

Em outras aplicaes, o modelo exerce uma funo diferente, realizando o transporte de dados entre as camadas de apresentao e negcio.

Neste caso, cria-se uma entidade para fazer a persistncia. Este novo objeto (entidade) no se comunica diretamente com o modelo, embora existam projetos com essa caracterstica.

Em aplicaes Laravel a maneira mais fcil de criar um modelo atravs do Artisan, que pode ser executado a partir do terminal no diretrio raiz da aplicao, com o seguinte comando:

php artisan make:model <nome_do_modelo>

Assim que o comando for concludo, obteremos um novo arquivo que estender de Illuminate\Database\Eloquent\Model e ser salvo no diretrio \App\Models.

O cdigo gerado pelo comando ser semelhante a este:

<?phpnamespace App\Models;use Illuminate\Database\Eloquent\Factories\HasFactory;use Illuminate\Database\Eloquent\Model;class Job extends Model{    use HasFactory;}

Note que a criao do modelo adicionou a trait HasFactory, responsvel por 'conectar' esta modelo com uma classe factory, que no ser abordada neste artigo.

Tabela

Como dito anteriormente, o modelo representar uma tabela do banco de dados da nossa aplicao. Por conveno, o Laravel assumir que o nome da tabela representada pelo modelo Job ser Jobs. Ou seja, o nome da classe no plural.

Porm, haver casos onde o nome da tabela no se encaixar nessa conveno. A soluo para situaes como esta informar o nome da tabela explicitamente. Isto feito adicionando o atributo privado $table nossa classe.

O exemplo a seguir ilustra como implementar esta modificao.

protected $table = 'company_jobs';

Chave primria

Os nomes de chaves primrias so definidos pelo banco de dados. A exceo ocorre quando, no script DDL, o nome da chave primria atribudo manualmente.

A exemplo do que fizemos para identificar explicitamente o nome da tabela referenciada pelo modelo, vamos 'informar' ao modelo qual o nome da chave primria, atravs do atributo protegido $primaryKey.

E podemos ver no trecho de cdigo logo abaixo, como deve ficar a implementao dentro do nosso modelo:

protected $primaryKey = 'job_id';

O Eloquent ORM no suporta chaves primrias compostas nativamente. Entretanto, uma pesquisa na internet trar diversas solues aplicveis a vrios cenrios.

Chave estrangeira

Chaves estrangeiras tem como objetivo relacionar tabelas evitando a replicao de todas as informaes de uma tabela em outras.

Para facilitar a compreenso do conceito de chave estrangeira, vamos imaginar o cliente de uma instituio financeira, cujo cadastro contm informaes sobre endereo, fonte de renda e filiao, por exemplo.

Para este cliente, sempre que ele realizar alguma operao financeira, sero gravadas somente informaes relativas operao, como data, valor, nmero do documento (se houver), tipo da operao (crdito ou dbito) e o ID do cliente.

Ao informamos o ID do cliente na tabela de operaes financeiras estamos evitando que todas as informaes relativas ao cadastro sejam replicadas em todas as operaes, o que aumentaria significativamente o tamanho de cada registro e, por consequncia, prejudicar a performance da aplicao.

A configurao de chave estrangeira no modelo pode ser feita atravs da criao de um mtodo pblico que retornar o modelo que possui a chave primria.

Um exemplo desse mtodo pode ser visto logo abaixo.

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

O mtodo belongsTo recebe como primeiro argumento o modelo que representa a 'tabela pai' do relacionamento e, atravs de mtodos auxiliares, identifica a coluna que corresponde chave primria da tabela pai.

Este cenrio pode ser conveniente, quando a abordagem adotada na aplicao tenha sido code first. Na eventualidade de uma abordagem diferente, como database first, convm no delegar ao framework, a tarefa de encontrar os relacionamentos automaticamente.

Para resolver essa questo, o mtodo belongsTo pode receber outros argumentos, como nome da chave estrangeira ($foreignKey), nome da chave primria da tabela pai ($ownerKey) e nome da constraint no banco de dados ($relation).

Abaixo a assinatura do mtodo belongsTo.

/** * Define an inverse one-to-one or many relationship. * * @param  string  $related * @param  string|null  $foreignKey * @param  string|null  $ownerKey * @param  string|null  $relation * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */public function belongsTo($related, $foreignKey = null, $ownerKey = null, $relation = null)

Relacionamento 'um pra um'

Este tipo de relacionamento entre entidades indica que, para cada instncia do modelo 'A' pode existir uma ou nenhuma instncia do modelo 'B'. Para citar um exemplo real, uma pessoa fsica tem apenas um CPF.

A forma de implementar este relacionamento no modelo 'A' atravs de um mtodo que retornar a instncia do modelo 'B' associado.

Abaixo um exemplo da implementao deste relacionamento.

public function cpf(){     return $this->hasOne(Cpf::class);    }

O mtodo hasOne recebe como primeiro argumento o modelo associado. O framework ento, cria uma instncia do modelo informado para inferir informaes sobre o relacionamento entre os modelos.

E para reduzir o 'trabalho' feito pelo framework, o mtodo hasOne pode receber o nome da chave estrangeira ($foreignKey) e o nome da chave primria ($localKey) do modelo associado.

Abaixo temos a assinatura do mtodo hasOne.

/** * Define a one-to-one relationship. * * @param  string  $related * @param  string|null  $foreignKey * @param  string|null  $localKey * @return \Illuminate\Database\Eloquent\Relations\HasOne */public function hasOne($related, $foreignKey = null, $localKey = null)

Relacionamento 'um pra muitos'

Este o relacionamento mais comum que vemos na maioria (seno em todas...rs) das aplicaes. Utilizando um exemplo do mundo real, significa dizer que uma pessoa pode ter um ou mais filhos, ou nenhum filho.

Este tipo de relacionamento entre modelos tambm resolvido atravs de um mtodo, que ao ser chamado, retornar uma ou mais instncias do modelo associado.

Abaixo temos um exemplo da implementao deste mtodo em um modelo.

public function kid(){    return $this->hasMany(Kid::class);}

O mtodo hasMany receber como argumento a classe do modelo 'B', associado ao modelo 'A'.

Logo abaixo, podemos notar que a assinatura do mtodo hasMany semelhante assinatura do mtodo hasOne, visto anteriormente.

/** * Define a one-to-many relationship. * * @param  string  $related * @param  string|null  $foreignKey * @param  string|null  $localKey * @return \Illuminate\Database\Eloquent\Relations\HasMany */public function hasMany($related, $foreignKey = null, $localKey = null)

Ocultar propriedades

Como dito anteriormente, h cenrios onde o modelo tem um papel diferente interagindo com a camada de apresentao da aplicao e se comunicando somente com a camada de negcio.

Persistir os dados, nestes casos, ficar a cargo de outro objeto conhecido como entidade. Assim como o modelo, a entidade se comunica somente com a camada de negcio.

Esta abordagem traz isolamento entre as camadas de apresentao e persistncia.

Mas existem aplicaes onde o modelo utilizado para fazer a persistncia dos dados e mostrar informaes na camada de apresentao.

Quando essa situao ocorre, convm ocultar algumas propriedades do modelo para no serem mostradas na camada de apresentao.

E fazemos isso atravs do atributo protegido $hidden, que recebe um array das propriedades que no devem ser mostradas.

Abaixo um exemplo da declarao deste atributo.

protected $hidden = [    'shop_id',    'created_at',    'updated_at',];

Insero em massa

Insero em massa uma tcnica que visa a reduo de cdigo, sendo mais comum em aplicaes web.

Nesta tcnica, ao invs atribuir os valores explicitamente para cada propriedade do modelo, indicamos ao modelo quais colunas podero receber os valores diretamente da camada de negcio.

A utilizao desta tcnica reduz significativamente a manuteno com cdigo. Outro benefcio evitar que um registro seja persistido atravs da tcnica de 'sql injection'.

Para implementar a insero em massa no modelo, declaramos o atributo protegido $fillable. Esse atributo receber um array com os campos que podero ser tratados durante o processo de insero em massa.

A seguir um exemplo da implementao deste atributo em um modelo.

protected $fillable = [    'description',    'price',];

Created_at e Updated_at

Quando a migrao criada, temos a possibilidade de adicionar duas colunas na tabela representada pelo modelo: created_at e update_at.

As duas colunas sero do tipo 'datetime' e o objetivo delas armazenar o momento que o registro foi criado e a ltima vez que o registro foi atualizado.

Embora sejam informaes teis, elas nem sempre sero necessrias no modelo. E para evitar que o Eloquent faa esse controle basta adicionar o atributo pblico $timestamps, que receber um valor booleano.

O valor padro deste atributo true e informamos false para desabilitar esse controle.

Abaixo um exemplo da implementao desse atributo.

public $timestamps = false;

Concluso

Neste artigo busquei trazer algumas das caractersticas do modelo do Eloquent ORM propondo solues aos problemas mais comuns.

Tudo o que foi mostrado est na documentao oficial do Eloquent.

Mas no fique preso apenas documentao pois ela pode no apresentar soluo para problemas mais especficos.

At breve.


Original Link: https://dev.to/marciopolicarpo/orm-eloquent-model-361g

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To