Skip to content

Latest commit

 

History

History
632 lines (467 loc) · 22.7 KB

arabic.md

File metadata and controls

632 lines (467 loc) · 22.7 KB

Laravel best practices

الترجمات

Nederlands (by Protoqol)

한국어 (by cherrypick)

日本語 (by 2bo)

漢語 (by xiaoyi)

ภาษาไทย (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)

Türkçe (by Burak)

Deutsch (by Sujal Patel)

Italiana (by Sujal Patel)

Azərbaycanca (by Maharramoff)

العربية (by ahmedsaoud31)

هذا المحتوى لا يصنف كمبادئ SOLID للارافيل أو أنماط التصميم، إلخ... هنا ستجد أفضل الممارسات التي يتم تجاهلها عادةً في مشاريع لارافيل الفعلية.

الفهرس

نمط المسئولية الواحدة

كود أكثر في النماذج، كود أقل في المتحكمات

الفلترة

الأكواد المنطقية يجب أن تكون في فئة خادمة منفصلة

لا تكرر نفس الكود

يفضل استخدام نظام التعامل مع قواعد البيانات والمسمى ب Eloquent عن استخدام باني الإستعلامات Query Builder أو الإستخدام المباشر لأوامر الإستعلامات SQL عبر raw، ويفضل استخدام المجموعات عن المصفوفات

تقليص المهام

لا تقم بتنفيذ الإستعلامات داخل ملفات blade واستخدم التحميل الحثيث مشكلة (N+1)

اضف التعليقات للكود ويفضل استخدام صيع التعليقات القياسية للمتغيرات والخواص والقيم المعادة إلخ

لا تضع شفرات js و css داخل ملفات Blade ولا تضع أي شفرات HTML في فئات php

استخدم ملفات الإعدادت واللغات, والثوابت بدلاً من النص داخل الكود

استخدم الأدوات القياسية المعتمدة من مجتمع لارافيل

اتبع طريقة لارافيل في التسميات

استخدم كود أقصر قابل للقراءة والفهم السريع قدر المستطاع

استخدم الحاويات أو الواجهات بدلاً من الفئات الجديدة

لا تقم بجلب البيانات من ملف .env

احفظ البيانات في الشكل القياسي. استخدم المسترجعات والمُعدلات في تعديل شكل صيغة التاريخ

ممارسات جيدة أخر

1

نمط المسئولية الواحدة

وظيفة الفئة والطريقة يجب ان تكون مسئولية واحدة فقط، بمعنى أخر يجب ألا تكون الفئة أو الطريقة متعددة المهام وجيب أن تختص بمهمة واحدة فقط

❌ طريقة سيئة:

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;
    }
}

✔️ طريقة جيدة:

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;
}

🔝 الرجوع للفهرس

2

كود أكثر في النماذج، كود أقل في المتحكمات

ضع كل الأكواد الخاصة بالتعامل مع قواعد البيانات في فئات خاصة منفصلة ولا تضعها في المتحكمات

❌ طريقة سيئة:

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

    return view('index', ['clients' => $clients]);
}

✔️ طريقة جيدة:

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();
    }
}

🔝 الرجوع للفهرس

3

الفلترة

انقل أكواد الفلترة من المتحكمات الي فئات الطلبات Request classes

❌ طريقة سيئة:

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

    ....
}

✔️ طريقة جيدة:

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',
        ];
    }
}

🔝 الرجوع للفهرس

4

الأكواد المنطقية يجب أن تكون في فئة خادمة منفصلة

المتحكم يجب أن يكون له مسئولية واحدة فقط، أنقل الأكواد المنطقية لفئات خادمة منفصلة

❌ طريقة سيئة:

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

✔️ طريقة جيدة:

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');
        }
    }
}

🔝 الرجوع للفهرس

5

لا تكرر نفس الكود

اعد استخدام نفس الكود قدر المستطاع ولا تقم بإعادة كتابته سيساعدك هذا على عدم وجود أكثر من كود لتنفيذ نفس المهمة، وإعادة استخدام قوالب blade و وفئات التعامل مع قواعد البيانات Eloquent

وكمثال استخدم scope في فئات التعامل مع قواعد البيانات Eloquent

❌ طريقة سيئة:

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();
}

✔️ طريقة جيدة:

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();
}

🔝 الرجوع للفهرس

6

يفضل استخدام نظام التعامل مع قواعد البيانات والمسمى ب Eloquent عن استخدام باني الإستعلامات Query Builder أو الإستخدام المباشر لأوامر الإستعلامات SQL عبر raw، ويفضل استخدام المجموعات عن المصفوفات

Eloquent يجعلك تكتب كود قابل للقراءة والصيانة. وأيضاً، Eloquent يحتوي على أدوات وخواص داخلية كالحذف الناعم والأحداث والنطاقات إلخ...

❌ طريقة سيئة:

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

✔️ طريقة جيدة:

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

🔝 الرجوع للفهرس

7

تقليص المهام

❌ طريقة سيئة:

$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();

✔️ طريقة جيدة:

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

🔝 الرجوع للفهرس

8

لا تقم بتنفيذ الإستعلامات داخل ملفات blade واستخدم التحميل الحثيث مشكلة (N+1)

❌ طريقة سيئة:

~لعدد 100 مستخدم سيُنفذ 101 استعلام على قاعدة البيانات

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

✔️ طريقة جيدة:

~لعدد 100 مستخدم سيُنفذ 2 استعلام فقط على قاعدة البيانات~

$users = User::with('profile')->get();

...

@foreach ($users as $user)
    {{ $user->profile->name }}
@endforeach

🔝 الرجوع للفهرس

9

اضف التعليقات للكود ويفضل استخدام صيع التعليقات القياسية للمتغيرات والخواص والقيم المعادة إلخ

❌ طريقة سيئة:

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

طريقة أفضل:

// Determine if there are any joins.
if (count((array) $builder->getQuery()->joins) > 0)

✔️ طريقة جيدة:

if ($this->hasJoins())

🔝 الرجوع للفهرس

10

لا تضع شفرات js و css داخل ملفات Blade ولا تضع أي شفرات HTML في فئات php

❌ طريقة سيئة:

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

✔️ طريقة أفضل:

<input id="article" type="hidden" value='@json($article)'>

Or

<button class="js-fav-article" data-article='@json($article)'>{{ $article->name }}<button>

في ملف جافا سكريبت:

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

الطريقة الأفضل هو استخدام الحزم الخاصة بنقل البيانات من بي إتش بي إلى جافا سكريبت.

🔝 الرجوع للفهرس

11

استخدم ملفات الإعدادت واللغات, والثوابت بدلاً من النص داخل الكود

❌ طريقة سيئة:

public function isNormal()
{
    return $article->type === 'normal';
}

return back()->with('message', 'Your article has been added!');

✔️ طريقة جيدة:

public function isNormal()
{
    return $article->type === Article::TYPE_NORMAL;
}

return back()->with('message', __('app.article_added'));

🔝 الرجوع للفهرس

12

استخدم الأدوات القياسية المعتمدة من مجتمع لارافيل

يفضل استخدام الأدوات المدمجة مع إطار عمل لارافيل والحزم المقترحة من مجتمع لارفيل عن استخدام غيرها، أي مطور سيعمل على تطبيقك في وقت لاحق سيحتاج لتعلم تلك الأدوات التي لا يشيع استخدامها في تطبيقات لارافيل، وأيضاً أطلب المساعدة من مجتمع لارافيل عندما تقرر الإعتماد على أحد الأدوات او الحزم، ولا تجع عميلك يدفع مقابل ذلك.

الوظيفة الأدوات القياسية أدوات الطرف الثالث
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

🔝 الرجوع للفهرس

13

اتبع طريقة لارافيل في التسميات

راجع PSR standards.

وأيضاً, راجع اصطلاح التسميات المقبول من جهه مجتمع لارافيل:

ماذا كيف جيدة سيئة
Controller singular ArticleController ArticlesController
Route plural articles/1 article/1
Named route snake_case with dot notation users.show_active users.show-active, show-active-users
Model singular User Users
hasOne or belongsTo relationship singular articleComment articleComments, article_comment
All other relationships plural articleComments articleComment, article_comments
Table plural article_comments article_comment, articleComments
Pivot table singular model names in alphabetical order article_user user_article, articles_users
Table column snake_case without model name meta_title MetaTitle; article_meta_title
Model property snake_case $model->created_at $model->createdAt
Foreign key singular model name with _id suffix article_id ArticleId, id_article, articles_id
Primary key - id custom_id
Migration - 2017_01_01_000000_create_articles_table 2017_01_01_000000_articles
Method camelCase getAll get_all
Method in resource controller table store saveArticle
Method in test class camelCase testGuestCannotSeeArticle test_guest_cannot_see_article
Variable camelCase $articlesWithAuthor $articles_with_author
Collection descriptive, plural $activeUsers = User::active()->get() $active, $data
Object descriptive, singular $activeUser = User::active()->first() $users, $obj
Config and language files index snake_case articles_enabled ArticlesEnabled; articles-enabled
View kebab-case show-filtered.blade.php showFiltered.blade.php, show_filtered.blade.php
Config snake_case google_calendar.php googleCalendar.php, google-calendar.php
Contract (interface) adjective or noun Authenticatable AuthenticationInterface, IAuthentication
Trait adjective Notifiable NotificationTrait

🔝 الرجوع للفهرس

14

استخدم كود أقصر قابل للقراءة والفهم السريع قدر المستطاع

❌ طريقة سيئة:

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

✔️ طريقة جيدة:

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

أمثلة أكثر:

جمل مركبة جمل أقصر وأكثر قابلية للقراءة
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')

🔝 الرجوع للفهرس

15

استخدم الحاويات أو الواجهات بدلاً من الفئات الجديدة

إنشاء فئات جديدة يخلق شئ من التشويش بين الفئات ويعقد عملة الإختبار، الأفضل الإعتماد على الحاويات او الواجهات في هذا الأمر

❌ طريقة سيئة:

$user = new User;
$user->create($request->validated());

✔️ طريقة جيدة:

public function __construct(User $user)
{
    $this->user = $user;
}

....

$this->user->create($request->validated());

🔝 الرجوع للفهرس

16

لا تقم بجلب البيانات من ملف .env مباشراً

مرر البيانات لملف الإعدادت ومن ثَم استخدم الدالة المساعدة `config()` لاستخدامها في جلب البيانات المخزنة في ملف الإعدادت داخل تطبيقك.

❌ طريقة سيئة:

$apiKey = env('API_KEY');

✔️ طريقة جيدة:

// config/api.php
'key' => env('API_KEY'),

// Use the data
$apiKey = config('api.key');

🔝 الرجوع للفهرس

17

خزن التواريخ بأشكالها القياسية، واستخدم المسترجعات والمُعدلات لتعديل صيغة التواريخ كما تريد.

❌ طريقة سيئة:

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

✔️ طريقة جيدة:

// Model
protected $dates = ['ordered_at', 'created_at', 'updated_at'];
public function getSomeDateAttribute($date)
{
    return $date->format('m-d');
}

// ملف العرض
{{ $object->ordered_at->toDateString() }}
{{ $object->ordered_at->some_date }}

🔝 الرجوع للفهرس

18

ممارسات جيدة أخرى

لا تضع أي شيفرة برمجية في ملفات الموجهات.

قلل من استخدامك الشيفرات البرمجية المنطقية في ملفات العرض blade.

🔝 الرجوع للفهرس