Terjemahan :
Nederlands (by Protoqol)
νκ΅μ΄ (by cherrypick)
δΈζηΆεΊηΎη§ (by woeichern)
ΰΈ ΰΈ²ΰΈ©ΰΈ²ΰΉΰΈΰΈ’ (by kongvut sangkla)
বাΰ¦ΰ¦²ΰ¦Ύ (by Anowar Hossain)
ΩΨ§Ψ±Ψ³Ϋ (by amirhossein baghaie)
PortuguΓͺs (by jonaselan)
Π£ΠΊΡΠ°ΡΠ½ΡΡΠΊΠ° (by Tenevyk)
TiαΊΏng Viα»t (by Chung Nguyα» n)
EspaΓ±ol (by CΓ©sar Escudero)
Français (by Mikayil S.)
Polski (by Maciej Jeziorski)
Deutsch (by Sujal Patel)
Italiana (by Sujal Patel)
AzΙrbaycanca (by Maharramoff)
Ψ§ΩΨΉΨ±Ψ¨ΩΨ© (by ahmedsaoud31)
Ini bukan adaptasi Laravel dari prinsip SOLID, pola dll. Di sini Anda akan menemukan praktik terbaik yang biasanya diabaikan dalam proyek Laravel kehidupan nyata.
Prinsip tanggung jawab tunggal
Logika bisnis harus dalam kelas layanan
Jangan ulangi diri sendiri (DRY)
Jangan mengeksekusi kueri dalam templat Blade dan menggunakan eager loading (masalah N + 1)
Komentari kode Anda, tetapi lebih suka metode deskriptif dan nama variabel daripada komentar
Jangan letakkan JS dan CSS di templat Blade dan jangan letakkan HTML apa pun di kelas PHP
Gunakan file config dan bahasa, konstanta alih-alih teks dalam kode
Gunakan alat Laravel standar yang diterima oleh komunitas
Ikuti konvensi penamaan Laravel
Gunakan sintaks yang lebih pendek dan lebih mudah dibaca jika memungkinkan
Gunakan wadah atau fasad IoC sebagai ganti Kelas baru
Jangan mendapatkan data dari file .env
secara langsung
Simpan tanggal dalam format standar. Gunakan pengakses dan mutator untuk mengubah format tanggal
Kelas dan metode seharusnya hanya memiliki satu tanggung jawab
Kurang Bagus:
public function getFullNameAttribute()
{
if (auth()->user() && auth()->user()->hasRole('client') && auth()->user()->isVerified()) {
return 'Mr. ' . $this->first_name . ' ' . $this->middle_name . ' ' . $this->last_name;
} else {
return $this->first_name[0] . '. ' . $this->last_name;
}
}
Bagus:
public function getFullNameAttribute()
{
return $this->isVerifiedClient() ? $this->getFullNameLong() : $this->getFullNameShort();
}
public function isVerifiedClient()
{
return auth()->user() && auth()->user()->hasRole('client') && auth()->user()->isVerified();
}
public function getFullNameLong()
{
return 'Mr. ' . $this->first_name . ' ' . $this->middle_name . ' ' . $this->last_name;
}
public function getFullNameShort()
{
return $this->first_name[0] . '. ' . $this->last_name;
}
Masukkan semua logika terkait DB ke model Eloquent atau ke dalam kelas Repositori jika anda menggunakan Query Builder atau kueri SQL mentah.
Kurang Bagus:
public function index()
{
$clients = Client::verified()
->with(['orders' => function ($q) {
$q->where('created_at', '>', Carbon::today()->subWeek());
}])
->get();
return view('index', ['clients' => $clients]);
}
Bagus:
public function index()
{
return view('index', ['clients' => $this->client->getWithNewOrders()]);
}
class Client extends Model
{
public function getWithNewOrders()
{
return $this->verified()
->with(['orders' => function ($q) {
$q->where('created_at', '>', Carbon::today()->subWeek());
}])
->get();
}
}
Pindahkan validasi dari Controller ke class Request
Kurang Bagus:
public function store(Request $request)
{
$request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
'publish_at' => 'nullable|date',
]);
....
}
Bagus:
public function store(PostRequest $request)
{
....
}
class PostRequest extends Request
{
public function rules()
{
return [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
'publish_at' => 'nullable|date',
];
}
}
Controller harus hanya memiliki satu tanggung jawab, jadi pindahkan logika bisnis dari Controller ke kelas Service
Kurang Bagus:
public function store(Request $request)
{
if ($request->hasFile('image')) {
$request->file('image')->move(public_path('images') . 'temp');
}
....
}
Bagus:
public function store(Request $request)
{
$this->articleService->handleUploadedImage($request->file('image'));
....
}
class ArticleService
{
public function handleUploadedImage($image)
{
if (!is_null($image)) {
$image->move(public_path('images') . 'temp');
}
}
}
Gunakan kembali kode ketika anda bisa. SRP membantu anda menghindari duplikasi. juga gunakan kembali template blade gunakan lingkup Eloquent dll.
Kurang Bagus:
public function getActive()
{
return $this->where('verified', 1)->whereNotNull('deleted_at')->get();
}
public function getArticles()
{
return $this->whereHas('user', function ($q) {
$q->where('verified', 1)->whereNotNull('deleted_at');
})->get();
}
Bagus:
public function scopeActive($q)
{
return $q->where('verified', 1)->whereNotNull('deleted_at');
}
public function getActive()
{
return $this->active()->get();
}
public function getArticles()
{
return $this->whereHas('user', function ($q) {
$q->active();
})->get();
}
Lebih suka menggunakan Eloquent daripada menggunakan Query Builder dan query SQL mentah. Lebih suka koleksi daripada array
Eloquent memungkinkan anda menulis kode bisa dibaca dan dipelihara. juga Eloquent memilki alat bawaan yang hebat seperti penghapus lunak, acara, cakupan, dll
Kurang Bagus:
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` IS NULL)
AND `verified` = '1'
AND `active` = '1'
ORDER BY `created_at` DESC
Bagus:
Article::has('user.profile')->verified()->latest()->get();
Kurang Bagus:
$article = new Article;
$article->title = $request->title;
$article->content = $request->content;
$article->verified = $request->verified;
// Add category to article
$article->category_id = $category->id;
$article->save();
Bagus:
$category->article()->create($request->validated());
Buruk ( untuk 100 pengguna, 101 permintaan DB akan dieksekusi):
@foreach (User::all() as $user)
{{ $user->profile->name }}
@endforeach
Bagus (untuk 100 pengguna, 2 permintaan DB akan dieksekusi):
$users = User::with('profile')->get();
...
@foreach ($users as $user)
{{ $user->profile->name }}
@endforeach
Kurang Bagus:
if (count((array) $builder->getQuery()->joins) > 0)
Lebih Baik:
// Determine if there are any joins.
if (count((array) $builder->getQuery()->joins) > 0)
Bagus:
if ($this->hasJoins())
Kurang Bagus:
let article = `{{ json_encode($article) }}`;
Lebih Baik:
<input id="article" type="hidden" value='@json($article)'>
Atau
<button class="js-fav-article" data-article='@json($article)'>{{ $article->name }}<button>
Dalam file javascript:
let article = $('#article').val();
Cara terbaik adalah dengan menggunakan paket PHP ke JS khusus untuk mentransfer data.
Kurang Bagus:
public function isNormal()
{
return $article->type === 'normal';
}
return back()->with('message', 'Your article has been added!');
Bagus:
public function isNormal()
{
return $article->type === Article::TYPE_NORMAL;
}
return back()->with('message', __('app.article_added'));
Lebih suka menggunakan fungsionalitas bawaan dan paket komunitas daripada menggunakan paket dan alat pihak ke-3. Pengembang apa pun yang akan bekerja dengan aplikasi Anda di masa mendatang perlu mempelajari alat baru. Juga, peluang untuk mendapatkan bantuan dari komunitas Laravel jauh lebih rendah saat Anda menggunakan paket atau alat pihak ke-3. Jangan membuat klien Anda membayar untuk itu.
Task | Standard tools | 3rd party tools |
---|---|---|
Authorization | Policies | Entrust, Sentinel and other packages |
Compiling assets | Laravel Mix | Grunt, Gulp, 3rd party packages |
Development Environment | Homestead | Docker |
Deployment | Laravel Forge | Deployer and other solutions |
Unit testing | PHPUnit, Mockery | Phpspec |
Browser testing | Laravel Dusk | Codeception |
DB | Eloquent | SQL, Doctrine |
Templates | Blade | Twig |
Working with data | Laravel collections | Arrays |
Form validation | Request classes | 3rd party packages, validation in controller |
Authentication | Built-in | 3rd party packages, your own solution |
API authentication | Laravel Passport | 3rd party JWT and OAuth packages |
Creating API | Built-in | Dingo API and similar packages |
Working with DB structure | Migrations | Working with DB structure directly |
Localization | Built-in | 3rd party packages |
Realtime user interfaces | Laravel Echo, Pusher | 3rd party packages and working with WebSockets directly |
Generating testing data | Seeder classes, Model Factories, Faker | Creating testing data manually |
Task scheduling | Laravel Task Scheduler | Scripts and 3rd party packages |
DB | MySQL, PostgreSQL, SQLite, SQL Server | MongoDB |
Ikuti PSR standards.
Juga, ikuti konvensi penamaan yang diterima oleh komunitas Laravel:
What | How | Good | Bad |
---|---|---|---|
Controller | singular | ArticleController | |
Route | plural | articles/1 | |
Named route | snake_case with dot notation | users.show_active | |
Model | singular | User | |
hasOne or belongsTo relationship | singular | articleComment | |
All other relationships | plural | articleComments | |
Table | plural | article_comments | |
Pivot table | singular model names in alphabetical order | article_user | |
Table column | snake_case without model name | meta_title | |
Model property | snake_case | $model->created_at | |
Foreign key | singular model name with _id suffix | article_id | |
Primary key | - | id | |
Migration | - | 2017_01_01_000000_create_articles_table | |
Method | camelCase | getAll | |
Method in resource controller | table | store | |
Method in test class | camelCase | testGuestCannotSeeArticle | |
Variable | camelCase | $articlesWithAuthor | |
Collection | descriptive, plural | $activeUsers = User::active()->get() | |
Object | descriptive, singular | $activeUser = User::active()->first() | |
Config and language files index | snake_case | articles_enabled | |
View | kebab-case | show-filtered.blade.php | |
Config | snake_case | google_calendar.php | |
Contract (interface) | adjective or noun | AuthenticationInterface | |
Trait | adjective | Notifiable |
Kurang Bagus:
$request->session()->get('cart');
$request->input('name');
Bagus:
session('cart');
$request->name;
Contoh:
Common syntax | Shorter and more readable syntax |
---|---|
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->id |
optional($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') |
Sintaks Kelas baru menciptakan kopling ketat antara kelas dan mempersulit pengujian. Gunakan wadah atau fasad IoC sebagai gantinya.
Kurang Bagus:
$user = new User;
$user->create($request->validated());
Bagus:
public function __construct(User $user)
{
$this->user = $user;
}
....
$this->user->create($request->validated());
Alihkan data ke file konfigurasi sebagai gantinya dan kemudian gunakan fungsi pembantu config ()
untuk menggunakan data dalam aplikasi.
Kurang Bagus:
$apiKey = env('API_KEY');
Bagus:
// config/api.php
'key' => env('API_KEY'),
// Use the data
$apiKey = config('api.key');
Kurang Bagus:
{{ Carbon::createFromFormat('Y-d-m H-i', $object->ordered_at)->toDateString() }}
{{ Carbon::createFromFormat('Y-d-m H-i', $object->ordered_at)->format('m-d') }}
Bagus:
// Model
protected $dates = ['ordered_at', 'created_at', 'updated_at'];
public function getSomeDateAttribute($date)
{
return $date->format('m-d');
}
// View
{{ $object->ordered_at->toDateString() }}
{{ $object->ordered_at->some_date }}
Jangan pernah menaruh logika apa pun di file rute.
Minimalkan penggunaan vanilla PHP di templat Blade.