Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Laravel best practices

NotificationsYou must be signed in to change notification settings

jonaselan/laravel-best-practices

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

65 Commits
 
 
 
 
 
 

Repository files navigation

Boas Práticas Laravel

Talvez você deva checar oreal-world Laravel example application

O que é descrito aqui não é uma adaptação ao principio SOLID, padrões e etc. Aqui você irá encontrar as melhores práticas que geralmente são ignoradas em um projeto Laravel na vida real.

Conteúdo

Princípio da responsabilidade única

Models gordos, controllers finos

Validação

Lógica de negócio deve ser posta em classes

Não se repita (Don't repeat yourself: DRY)

Usar o Eloquent em vez de Query Builder e consultas SQL puras (raw SQL). Usar collections no lugar de arrays

Atribuição em massa

Não executar consultas no Blade templates e usar eager loading (N + 1)

Use chunk para tarefas de dados pesadas

Comente seu código, mas prefira um método descritivo e nomes de variáveis em vez de comentários

Não coloque JS e CSS em templates Blade. Não coloque HTML em classes PHP

Use arquivos de linguagem e configuração. Constantes em vez de texto no código

Use ferramentas padrões do Laravel aceitas pela comunidade

Siga a convenção de nomes usada no Laravel

Tente sempre usar sintaxes pequenas e legíveis

Use contaneirs IoC (inversão de controle) ou facades no lugar de classes

Não recupere informações diretamente do.env

Armazene datas em formatos padrões. Use "accessors" e "mutators" para modificar o formato das datas

Outras boas práticas

Princípio da responsabilidade única

Classes e métodos devem possuir somente uma responsabilidade.

Ruim:

publicfunctiongetFullNameAttribute(){if (auth()->user() &&auth()->user()->hasRole('client') &&auth()->user()->isVerified()) {return'Sr.' .$this->first_name .'' .$this->middle_name .'' .$this->last_name;    }else {return$this->first_name[0] .'.' .$this->last_name;    }}

Bom:

publicfunctiongetFullNameAttribute(){return$this->isVerifiedClient() ?$this->getFullNameLong() :$this->getFullNameShort();}publicfunctionisVerifiedClient(){returnauth()->user() &&auth()->user()->hasRole('client') &&auth()->user()->isVerified();}publicfunctiongetFullNameLong(){return'Sr.' .$this->first_name .'' .$this->middle_name .'' .$this->last_name;}publicfunctiongetFullNameShort(){return$this->first_name[0] .'.' .$this->last_name;}

🔝 Voltar para o início

Models gordos, controllers finos

Coloque toda a lógica relacionada a banco em modelos Eloquent ou em repositórios caso você esteja usando Query Builder ou consultas SQL.

Ruim:

publicfunctionindex(){$clients = Client::verified()        ->with(['orders' =>function ($q) {$q->where('created_at','>', Carbon::today()->subWeek());        }])        ->get();returnview('index', ['clients' =>$clients]);}

Bom:

publicfunctionindex(){returnview('index', ['clients' =>$this->client->getWithNewOrders()]);}class Clientextends Model{publicfunctiongetWithNewOrders()    {return$this->verified()            ->with(['orders' =>function ($q) {$q->where('created_at','>', Carbon::today()->subWeek());            }])            ->get();    }}

🔝 Voltar para o início

Validação

Não use validações em controllers e sim em classes de Requisição.

Ruim:

publicfunctionstore(Request$request){$request->validate(['title' =>'required|unique:posts|max:255','body' =>'required','publish_at' =>'nullable|date',    ]);....}

Bom:

publicfunctionstore(PostRequest$request){....}class PostRequestextends Request{publicfunctionrules()    {return ['title' =>'required|unique:posts|max:255','body' =>'required','publish_at' =>'nullable|date',        ];    }}

🔝 Voltar para o início

Lógica de negócio deve ser posta em classes

Controllers devem ter somente uma responsabilidade, então mova lógica de negócio para outros serviços.

Ruim:

publicfunctionstore(Request$request){if ($request->hasFile('image')) {$request->file('image')->move(public_path('images') .'temp');    }....}

Bom:

publicfunctionstore(Request$request){$this->articleService->handleUploadedImage($request->file('image'));....}class ArticleService{publicfunctionhandleUploadedImage($image)    {if (!is_null($image)) {$image->move(public_path('images') .'temp');        }    }}

🔝 Voltar para o início

Não se repita (Don't repeat yourself: DRY)

Reutilize seu código sempre que possível. A ideia da responsabilidade única ajuda você a evitar duplicação. Isso serve também para templates Blade.

Ruim:

publicfunctiongetActive(){return$this->where('verified',1)->whereNotNull('deleted_at')->get();}publicfunctiongetArticles(){return$this->whereHas('user',function ($q) {$q->where('verified',1)->whereNotNull('deleted_at');        })->get();}

Bom:

publicfunctionscopeActive($q){return$q->where('verified',1)->whereNotNull('deleted_at');}publicfunctiongetActive(){return$this->active()->get();}publicfunctiongetArticles(){return$this->whereHas('user',function ($q) {$q->active();        })->get();}

🔝 Voltar para o início

Usar o Eloquent em vez de Query Builder e consultas SQL puras (raw SQL). Usar collections no lugar de arrays

Eloquent permite que você escreva código legível e manutenível. Além disso, Eloquent possui ferramentas ótimas para implementar "soft deletes", eventos, escopos e etc.

Ruim:

SELECT*FROM`articles`WHERE EXISTS (SELECT*FROM`users`WHERE`articles`.`user_id`=`users`.`id`AND EXISTS (SELECT*FROM`profiles`WHERE`profiles`.`user_id`=`users`.`id`)AND`users`.`deleted_at` ISNULL)AND`verified`='1'AND`active`='1'ORDER BY`created_at`DESC

Bom:

Article::has('user.profile')->verified()->latest()->get();

🔝 Voltar para o início

Atribuição em massa

Ruim:

$article =newArticle;$article->title =$request->title;$article->content =$request->content;$article->verified =$request->verified;// Adicionar categoria em artigos$article->category_id =$category->id;$article->save();

Bom:

$category->article()->create($request->all());

🔝 Voltar para o início

Não executar consultas no Blade templates e usar eager loading (N + 1)

Ruim (para 100 usuários, 101 consultas são feitas):

@foreach (User::all()as$user)    {{$user->profile->name }}@endforeach

Bom (para 100 usuários, duas consultas são feitas):

$users = User::with('profile')->get();...@foreach ($usersas$user)    {{$user->profile->name }}@endforeach

🔝 Voltar para o início

Use chunk para tarefas de dados pesadas

Ruim ():

$users =$this->get();foreach ($usersas$user) {...}

Bom:

$this->chunk(500,function ($users) {foreach ($usersas$user) {...    }});

🔝 Voltar para o início

Comente seu código, mas prefira um método descritivo e nomes de variáveis em vez de comentários

Ruim:

if (count((array)$builder->getQuery()->joins) >0)

Melhor:

// Determine se há algum join.if (count((array)$builder->getQuery()->joins) >0)

Bom:

if ($this->hasJoins())

🔝 Voltar para o início

Não coloque JS e CSS em templates Blade. Não coloque HTML em classes PHP

Ruim:

let article = `{{ json_encode($article) }}`;

Melhor:

<input type="hidden" value="{{json_encode($article) }}">Ou<button data-article="{{json_encode($article) }}">{{$article->name }}<button>

No #"auto" data-snippet-clipboard-copy-content="let article = $('#article').val();">

let article =$('#article').val();

🔝 Voltar para o início

Use arquivos de linguagem e configuração. Constantes em vez de texto no código

Ruim:

publicfunctionisNormal(){return$article->type ==='normal';}returnback()->with('message','Your article has been added!');

Bom:

publicfunctionisNormal(){return$article->type === Article::TYPE_NORMAL;}returnback()->with('message',__('app.article_added'));

🔝 Voltar para o início

Use ferramentas padrões do Laravel aceitas pela comunidade

Preferir usar funcionalidades do próprio Laravel e pacotes da comunidade em vez de pacotes de terceiros. Qualquer desenvolvedor que irá trabalhar em seu sistema terá que aprender novas ferramentas no futuro. Além disso, ter ajuda da comunidade do Laravel se torna significativamente menor quando você utiliza um pacote ou ferramenta de terceiros.

TarefasFerramentas padrõesPacotes de terceiros
AutorizaçãoPoliciesEntrust, Sentinel e outros pacotes
Compilar assetsLaravel MixGrunt, Gulp, pacotes de terceiros
Ambiente de desenvolvimentoHomestead, LaradockDocker
DeploymentLaravel ForgeDeployer e outras soluções
Testes unitáriosPHPUnit, MockeryPhpspec
Teste em navegadorLaravel DuskCodeception
DBEloquentSQL, Doctrine
TemplatesBladeTwig
Trabalhando com dadosLaravel collectionsArrays
Validação de formuláriosRequest classespacotes de terceiros, validação no controller
AutenticaçãoNativopacotes de terceiros, sua propria solução
Autenticação APILaravel PassportJWT e pacotes OAuth
Criar APINativoDingo API e similares
Trabalhando com estrutura de DBMigraçõesTrabalhar com banco diretamente
LocalizaçãoNativopacotes de terceiros
Interface em tempo realLaravel Echo, Pusherpacotes de terceiros e trabalhar com WebSockets diretamente
Gerar dados de testeSeeder classes, Model Factories, FakerCriar testes manualmente
Agendar tarefasLaravel Task SchedulerScripts e pacotes de terceiros
DBMySQL, PostgreSQL, SQLite, SQL ServerMongoDB

🔝 Voltar para o início

Siga a convenção de nomes usada no Laravel

SigaPSR standards.

Siga também a convenção de nomes aceita pelo a comunidade Laravel:

O queComoBomRuim
ControllersingularArticleControllerArticlesController
Routepluralarticles/1article/1
Named routesnake_case with dot notationusers.show_activeusers.show-active, show-active-users
ModelsingularUserUsers
hasOne or belongsTo relationshipsingulararticleCommentarticleComments, article_comment
All other relationshipspluralarticleCommentsarticleComment, article_comments
Tablepluralarticle_commentsarticle_comment, articleComments
Pivot tablesingular model names in alphabetical orderarticle_useruser_article, articles_users
Colunas em tabelassnake_case without model namemeta_titleMetaTitle; article_meta_title
Model propertysnake_case$model->created_at$model->createdAt
Foreign keysingular model name with _id suffixarticle_idArticleId, id_article, articles_id
Chaves primárias-idcustom_id
Migrações-2017_01_01_000000_create_articles_table2017_01_01_000000_articles
MétodoscamelCasegetAllget_all
Métodos em controllerstablestoresaveArticle
Métodos e classes de testecamelCasetestGuestCannotSeeArticletest_guest_cannot_see_article
VariáveiscamelCase$articlesWithAuthor$articles_with_author
Collectiondescriptive, plural$activeUsers = User::active()->get()$active, $data
Objectdescriptive, singular$activeUser = User::active()->first()$users, $obj
Config e arquivos de linguagemsnake_casearticles_enabledArticlesEnabled; articles-enabled
Viewkebab-caseshow-filtered.blade.phpshowFiltered.blade.php, show_filtered.blade.php
Configsnake_casegoogle_calendar.phpgoogleCalendar.php, google-calendar.php
Contract (interface)adjective or nounAuthenticatableAuthenticationInterface, IAuthentication
TraitadjectiveNotifiableNotificationTrait

🔝 Voltar para o início

Tente sempre usar sintaxes pequenas e legíveis

Ruim:

$request->session()->get('cart');$request->input('name');

Bom:

session('cart');$request->name;

Mais exemplos:

Sintaxe comumPequena e mais legível
Session::get('cart')session('cart')
$request->session()->get('cart')session('cart')
Session::put('cart', $data)session(['cart' => $data])
$request->input('name'), Request::get('name')$request->name, request('name')
return Redirect::back()return back()
is_null($object->relation) ? null : $object->relation->idoptional($object->relation)->id
return view('index')->with('title', $title)->with('client', $client)return view('index', compact('title', 'client'))
$request->has('value') ? $request->value : 'default';$request->get('value', 'default')
Carbon::now(), Carbon::today()now(), today()
App::make('Class')app('Class')
->where('column', '=', 1)->where('column', 1)
->orderBy('created_at', 'desc')->latest()
->orderBy('age', 'desc')->latest('age')
->orderBy('created_at', 'asc')->oldest()
->select('id', 'name')->get()->get(['id', 'name'])
->first()->name->value('name')

🔝 Voltar para o início

Use contaneirs IoC (inversão de controle) ou facades no lugar de classes

"new Class" sintaxe cria maior acoplamento de classes e teste. Use IoC ou facades em vez disso.

Ruim:

$user =newUser;$user->create($request->all());

Bom:

publicfunction__construct(User$user){$this->user =$user;}....$this->user->create($request->all());

🔝 Voltar para o início

Não recupere informações diretamente do.env

Coloque os dados em arquivos de configuração e recupere através do helperconfig().

Ruim:

$apiKey =env('API_KEY');

Bom:

// config/api.php'key' =>env('API_KEY'),// Use data$apiKey =config('api.key');

🔝 Voltar para o início

Armazene datas em formatos padrões. Use "accessors" e "mutators" para modificar o formato das datas

Ruim:

{{ Carbon::createFromFormat('Y-d-m H-i',$object->ordered_at)->toDateString() }}{{ Carbon::createFromFormat('Y-d-m H-i',$object->ordered_at)->format('m-d') }}

Bom:

// Modelprotected$dates = ['ordered_at','created_at','updated_at']publicfunctiongetSomeDateAttribute($date){return$date->format('m-d');}// View{{$object->ordered_at->toDateString() }}{{$object->ordered_at->some_date }}

🔝 Voltar para o início

Outras boas práticas

Nunca coloque lógica em arquivos de rota.

Minimize o uso de vanilla PHP em templates Blade.

🔝 Voltar para o início

About

Laravel best practices

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp