دفع Laravel كذلك - أفضل النصائح والممارسات الجيدة لـ Laravel 5.7

تحتوي هذه المشاركة على إصدار صوتي بفضل تطبيق Blogcast من ميغيل بيدرافيتا.

Laravel معروف بالفعل من قبل العديد من مطوري PHP لكتابة رمز نظيف وعامل وقادر على تصحيح الأخطاء. يحتوي أيضًا على دعم للعديد من الميزات ، التي لا يتم إدراجها في بعض الأحيان في المستندات ، أو كانت موجودة ، ولكن تمت إزالتها لأسباب مختلفة.

لقد كنت أعمل مع لارافيل في مجال الاستخدام منذ عامين وتعلمت من كتابة الكود السيئ إلى الكود الأفضل وقد استفدت من لارافيل منذ أول مرة بدأت فيها بكتابة الكود معها. سأريك الحيل الغامضة التي قد تساعدك عند كتابة كود مع Laravel.

استخدم النطاقات المحلية عندما تحتاج للاستعلام عن الأشياء

لدى Laravel طريقة لطيفة لكتابة استعلامات لبرنامج تشغيل قاعدة البيانات باستخدام Query Builder. شيء من هذا القبيل:

$ orders = Order :: where ('الحالة' ، 'تسليم') -> حيث ('المدفوعة' ، صحيح) -> get ()؛

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

تتيح لنا النطاقات المحلية إنشاء أساليب منشئ الاستعلامات الخاصة بنا التي يمكننا سلسلة عندما نحاول استرداد البيانات. على سبيل المثال ، بدلاً من عبارات -> حيث () ، يمكننا استخدام -> تسليم () و -> مدفوع () بطريقة أنظف.

أولاً ، في نموذج الطلب لدينا ، يجب أن نضيف بعض الطرق:

ترتيب الصف يمتد النموذج
{
   ...
   نطاق الوظيفة العامةتقديم (استعلام $) {
      إرجاع $ query-> where ('status'، 'Delivery')؛
   }
   نطاق الوظيفة العامة (استعلام $) {
      إرجاع $ query-> where ("المدفوع" ، صواب) ؛
   }
}

عند الإعلان عن النطاقات المحلية ، يجب عليك استخدام النطاق [Something] للتسمية الدقيقة. وبهذه الطريقة ، ستعلم Laravel أن هذا نطاق وسوف تستفيد منه في Query Builder. تأكد من تضمين الوسيطة الأولى التي يتم حقنها تلقائيًا بواسطة Laravel ، وهي مثيل باني الاستعلام.

$ orders = Order :: Delivery () -> المدفوع () -> get ()؛

لاسترجاع أكثر ديناميكية ، يمكنك استخدام النطاقات المحلية الديناميكية. كل نطاق يسمح لك بإعطاء المعلمات.

ترتيب الصف يمتد النموذج
{
   ...
   نطاق الوظيفة العامة (الاستعلام $ ، حالة $ السلسلة) {
      إرجاع $ query-> where ('status'، $ status)؛
   }
}
$ orders = Order :: status ('تسليم') -> المدفوع () -> get ()؛

في وقت لاحق من هذه المقالة ، سوف تتعلم لماذا يجب عليك استخدام snake_case لحقول قاعدة البيانات ، ولكن هنا هو السبب الأول: Laravel يستخدم بشكل افتراضي حيث [شيء] ليحل محل النطاق السابق. لذا بدلاً من السابق ، يمكنك القيام بما يلي:

ترتيب :: whereStatus ( 'تسليم') -> دفع () -> الحصول على ()؛

سيبحث Laravel عن إصدار snake_case الخاص بـ Something من حيث [Something]. إذا كان لديك حالة في قاعدة بياناتك ، فستستخدم المثال السابق. إذا كان لديك shipping_status ، فيمكنك استخدام:

ترتيب :: whereShippingStatus ( 'تسليم') -> دفع () -> الحصول على ()؛

إنه اختيارك!

استخدم ملفات الطلبات عند الحاجة

يمنحك Laravel طريقة بليغة للتحقق من صحة النماذج. إما أنه طلب POST أو طلب GET ، فلن يفشل في التحقق من صحة ذلك إذا كنت في حاجة إليه.

يمكنك التحقق من صحة هذه الطريقة في وحدة التحكم الخاصة بك:

متجر الوظائف العامة (طلب $ request)
{
    ValidatedData = $ request-> validate ([
        'title' => 'required | unique: posts | max: 255'،
        "الجسم" => "مطلوب" ،
    ])؛

    // نشر المدونة صالح ...
}

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

يمنحك Laravel طريقة * جذابة * للتحقق من صحة الطلبات من خلال إنشاء فئات الطلبات واستخدامها بدلاً من فئة الطلب القديمة. عليك فقط إنشاء طلبك:

جعل الحرفيين php: طلب StoreBlogPost

داخل التطبيق / HTTP / طلبات / مجلد ، ستجد ملف الطلب الخاص بك:

فئة StoreBlogPostRequest يمتد FormRequest
{
   تخويل الوظيفة العامة ()
   {
      إرجاع $ this-> user () -> can ('create.posts')؛
   }
   قواعد الوظيفة العامة ()
   {
       إرجاع [
         'title' => 'required | unique: posts | max: 255'،
         "الجسم" => "مطلوب" ،
       ].
   }
}

الآن ، بدلاً من Illuminate \ Http \ Request في طريقتك ، يجب استبدال الفئة التي تم إنشاؤها حديثًا:

استخدم App \ Http \طلبات \ StoreBlogPostRequest؛
متجر الوظائف العامة (StoreBlogPostRequest $ request)
{
    // نشر المدونة صالح ...
}

يجب أن تكون طريقة الإذن () منطقية. إذا كانت خاطئة ، فسيؤدي ذلك إلى رمي 403 ، لذا تأكد من التقاطها في طريقة تقديم التطبيق / استثناءات / Handler.php:

عرض الوظيفة العامة (طلب $ ، استثناء $ استثناء)
{
   إذا ($ $ مثيل مثيل \ Illuminate \ Auth \ Access \ AuthorizationException) {
      //
   }
   إرجاع الأصل :: تقديم (طلب $ ، استثناء $) ؛
}

الطريقة المفقودة هنا ، في فئة الطلب ، هي الرسائل () ، وهي عبارة عن صفيف يحتوي على الرسائل التي سيتم إرجاعها في حالة فشل التحقق من الصحة:

فئة StoreBlogPostRequest يمتد FormRequest
{
   تخويل الوظيفة العامة ()
   {
      إرجاع $ this-> user () -> can ('create.posts')؛
   }
   قواعد الوظيفة العامة ()
   {
       إرجاع [
         'title' => 'required | unique: posts | max: 255'،
         "الجسم" => "مطلوب" ،
       ].
   }
   رسائل الوظائف العامة ()
   {
      إرجاع [
        'title.required' => 'العنوان مطلوب.' ،
        'title.unique' => 'عنوان المنشور موجود بالفعل.' ،
        ...
      ].
   }
}

لإمساكهم في وحدة التحكم الخاصة بك ، يمكنك استخدام متغير الأخطاء داخل ملفات الشفرة:

@ إذا (أخطاء $-> any ())
   foreach (أخطاء $-> all () كخطأ $)
      {{$ error}}
   endforeach
@إنهاء إذا

في حال كنت ترغب في الحصول على رسالة التحقق من صحة حقل معين ، يمكنك القيام بذلك مثل ذلك الحين (سيعود كيان منطقية كاذبة إذا تم التحقق من الصحة لهذا الحقل):


if ($ error-> has ('title'))
   
@إنهاء إذا

نطاقات السحر

عند بناء الأشياء ، يمكنك استخدام النطاقات السحرية المضمنة بالفعل

  • استرجع النتائج عن طريق create_at ، تنازليًا:
العضو :: آخر () -> الحصول على ()؛
  • استرجع النتائج حسب أي حقل ، تنازليًا:
العضو :: آخر ( 'last_login_at') -> الحصول على ()؛
  • استرجع النتائج بترتيب عشوائي:
العضو :: inRandomOrder () -> الحصول على ()؛
  • قم بتشغيل طريقة استعلام فقط إذا كان هناك شيء صحيح:
/ / لنفترض أن المستخدم موجود في صفحة الأخبار ، ويرغب في تصنيفها حسب الأحدث أولاً
// mydomain.com/news؟sort=new
User :: when ($ request-> query ('sort') ، وظيفة ($ query ، $ sort) {
   إذا ($ sort == 'new') {
      إرجاع $ query-> latest ()؛
   }
   
   إرجاع الاستعلام $؛
}) -> الحصول على ()؛

بدلاً من متى () يمكنك استخدام ما لم يكن هذا هو عكس متى ().

استخدم العلاقات لتجنب الاستعلامات الكبيرة (أو تلك المكتوبة بطريقة سيئة)

هل سبق لك استخدام طن من الصلات في استعلام فقط للحصول على مزيد من المعلومات؟ من الصعب جدًا كتابة أوامر SQL هذه ، حتى مع Query Builder ، لكن النماذج تفعل ذلك بالفعل مع العلاقات. ربما لن تكون على دراية في البداية ، نظرًا للكم الهائل من المعلومات التي توفرها الوثائق ، ولكن هذا سيساعدك على فهم أفضل لكيفية عمل الأشياء وكيفية جعل التطبيق الخاص بك يعمل بشكل أكثر سلاسة.

تحقق من وثائق العلاقات هنا.

استخدم الوظائف للمهام المستهلكة للوقت

Laravel Jobs هي أداة أساسية يجب تشغيلها لتشغيل المهام في الخلفية.

  • هل تريد إرسال بريد إلكتروني؟ وظائف.
  • هل تريد بث رسالة؟ وظائف.
  • هل تريد معالجة الصور؟ وظائف.

تساعدك الوظائف على التخلي عن وقت التحميل للمستخدمين في مهام مضيعة للوقت مثل هذه. يمكن وضعها في قوائم انتظار محددة ، ويمكن تحديد أولوياتها ، وتخمين ما - نفذت Laravel قوائم الانتظار في كل مكان تقريبًا حيث كان ذلك ممكنًا: إما معالجة بعض PHP في الخلفية أو إرسال إشعارات أو أحداث البث ، قوائم الانتظار هناك!

يمكنك التحقق من وثائق قوائم الانتظار هنا.

أحب استخدام Laravel Horizon لقوائم الانتظار لأنه من السهل إعدادها ، ويمكن إبطالها باستخدام المشرف ومن خلال ملف التكوين ، أستطيع أن أخبر Horizon عن عدد العمليات التي أريد لكل قائمة انتظار.

التمسك بمعايير قاعدة البيانات والملحقات

يعلمك Laravel منذ البداية أن المتغيرات والأساليب الخاصة بك يجب أن تكون $ camelCase camelCase () بينما يجب أن تكون حقول قاعدة البيانات الخاصة بك snake_case. لماذا ا؟ لأن هذا يساعدنا على بناء أفضل الملحقات.

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

الطبقة المستخدم يمتد النموذج
{
   ...
   الوظيفة العامة getNameAttribute (): string
   {
       إرجاع $ this-> first_name. ' '$ هذا-> LAST_NAME؛
   }
}

عند استخدام $ user-> name ، سيعود السلسلة.

بشكل افتراضي ، لا يتم عرض سمة الاسم إذا كنا dd (مستخدم $) ، ولكن يمكننا أن نجعل ذلك متاحًا عمومًا باستخدام متغير الإلحاق $:

الطبقة المستخدم يمتد النموذج
{
   إلحاق $ المحمية = [
      'اسم'،
   ].
   ...
   الوظيفة العامة getNameAttribute (): string
   {
       إرجاع $ this-> first_name. ' '$ هذا-> LAST_NAME؛
   }
}

الآن ، في كل مرة نقوم فيها (مستخدم $) ، سنرى أن المتغير موجود (ولكن لا يزال ، هذا غير موجود في قاعدة البيانات)

ومع ذلك ، كن حذرًا: إذا كان لديك بالفعل حقل اسم ، فإن الأمور مختلفة بعض الشيء: لم يعد هناك حاجة إلى الاسم الموجود في الإلحاق بالدولار ، وتنتظر وظيفة السمة معلمة واحدة ، وهي المتغير المخزن بالفعل (لن نقوم بعد الآن) استخدام $ هذا).

لنفس المثال ، قد نرغب في ucfirst () الأسماء:

الطبقة المستخدم يمتد النموذج
{
   إلحاق $ المحمية = [
      //
   ].
   ...
   الوظيفة العامة getFirstNameAttribute ($ firstName): string
   {
       return ucfirst ($ firstName) ؛
   }
   الوظيفة العامة getLastNameAttribute ($ اسم العائلة): سلسلة
   {
      return ucfirst ($ lastName) ؛
   }
}

الآن ، عندما نستخدم $ user-> first_name ، فسيتم إرجاع سلسلة أحرف كبيرة.

نظرًا لهذه الميزة ، من الجيد استخدام snake_case لحقول قاعدة البيانات الخاصة بك.

لا تقم بتخزين البيانات الثابتة المتعلقة بالطراز في التكوينات

ما أحب القيام به هو تخزين البيانات الثابتة المتعلقة بالنموذج داخل النموذج. دعني اريك.

بدلا من هذا:

BettingOdds.php

BettingOdds الطبقة يمتد النموذج
{
   ...
}

التكوين / bettingOdds.php

إرجاع [
   'الرياضة' => [
      "كرة القدم" => "الرياضة: 1" ،
      'التنس' => 'الرياضة: 2' ،
      'كرة السلة' => 'الرياضة: 3' ،
      ...
   ]،
].

والوصول إليها باستخدام:

التكوين ( 'bettingOdds.sports.soccer')؛

انا افضل القيام بذلك:

BettingOdds.php

BettingOdds الطبقة يمتد النموذج
{
   رياضة ثابتة $ محمية = [
      "كرة القدم" => "الرياضة: 1" ،
      'التنس' => 'الرياضة: 2' ،
      'كرة السلة' => 'الرياضة: 3' ،
      ...
   ].
}

والوصول إليها باستخدام:

BettingOdds :: $ الرياضية [ 'كرة القدم'].

لماذا ا؟ لأنه أسهل في الاستخدام في عمليات أخرى:

BettingOdds الطبقة يمتد النموذج
{
   رياضة ثابتة $ محمية = [
      "كرة القدم" => "الرياضة: 1" ،
      'التنس' => 'الرياضة: 2' ،
      'كرة السلة' => 'الرياضة: 3' ،
      ...
   ].
   نطاق الوظيفة العامةرياضة (استعلام $ ، سلسلة $ sport)
   {
      if (! isset (self :: $ sports [$ sport])) {
         إرجاع الاستعلام $؛
      }
      
      إرجاع $ query-> where ('sport_id'، self :: $ sports [$ sport]) ؛
   }
}

الآن يمكننا الاستمتاع بالنطاقات:

BettingOdds :: الرياضة ( 'كرة القدم') -> الحصول على ()؛

استخدم المجموعات بدلاً من معالجة الصفيف الخام

في الأيام الماضية ، اعتدنا على العمل مع المصفوفات بطريقة أولية:

ثمار = = "تفاحة" ، "كمثرى" ، "موز" ، "فراولة"] ؛
foreach ($ فواكه $ فواكه) {
   صدى "لدي". $ الفاكهة.
}

الآن ، يمكننا استخدام الأساليب المتقدمة التي ستساعدنا في معالجة البيانات داخل المصفوفات. يمكننا تصفية البيانات وتحويلها وتكرارها وتعديلها داخل مجموعة:

الفواكه = جمع (الفواكه $) ؛
فواكه $ = فواكه-> رفض (دالة (فاكهة $) {
   عودة الفاكهة $ === 'التفاح' ؛
}) -> toArray ()؛
["الكمثرى" ، "الموز" ، "الفراولة"]

لمزيد من التفاصيل ، راجع الوثائق الشاملة حول المجموعات.

عند العمل مع Query Builders ، تقوم الطريقة -> get () بإرجاع مثيل مجموعة. ولكن كن حذرا حتى لا تخلط بين المجموعة مع باني Query:

  • Insde the Query Builder ، لم نسترجع أي بيانات. لدينا الكثير من الأساليب المتعلقة بالاستعلام: orderBy () ، where () ، إلخ.
  • بعد أن وصلنا -> get () ، يتم استرداد البيانات ، وقد تم استهلاك الذاكرة ، وتقوم بإرجاع مثيل مجموعة. بعض أساليب Query Builder غير متاحة ، أو أنها متاحة ، لكن اسمها مختلف. تحقق من الطرق المتاحة للمزيد.

إذا كان يمكنك تصفية البيانات على مستوى Query Builder ، فافعل ذلك! لا تعتمد على التصفية عندما يتعلق الأمر بمثيل Collection - ستستخدم الكثير من الذاكرة في بعض الأماكن ولا تريد ذلك. حدد نتائجك واستخدم الفهارس على مستوى قاعدة البيانات.

استخدم الحزم ولا تعيد اختراع العجلة

إليك بعض الحزم التي أستخدمها:

  • توجيهات لارافيل بليد
  • Laravel CORS (حماية طرقك من أصول أخرى)
  • Laravel Tag Helper (استخدام أفضل لعلامات HTML في Blade)
  • Laravel Sluggable (مفيد عندما يتعلق الأمر بتوليد الرخويات)
  • Laravel Responder (بناء JSON API أسهل)
  • صورة التدخل (التعامل مع الصور في الاسلوب)
  • الأفق (قوائم الانتظار الإشراف مع الحد الأدنى من التكوين)
  • اجتماعي (الحد الأدنى من التكوين للدخول عبر وسائل التواصل الاجتماعي)
  • Passport (تطبيق OAuth للمسارات)
  • Spatie’s ActivityLog (نشاط المسار للنماذج)
  • Spatie’s Backup (ملفات النسخ الاحتياطي وقواعد البيانات)
  • Spatie’s Blade-X (حدد علامات HTML الخاصة بك ؛ يعمل بشكل جيد مع Laravel Tag Helper)
  • مكتبة الوسائط Spatie (طريقة سهلة لإرفاق الملفات بالموديلات)
  • Spatie's Response Cache (استجابات وحدة تحكم ذاكرة التخزين المؤقت)
  • Spatie’s Collection Macros (المزيد من وحدات الماكرو على المجموعات)

إليك بعض الحزم التي كتبت:

  • صديق (مثل ، اتبع وحظر كما هو الحال في وسائل الإعلام الاجتماعية)
  • جدول (إنشاء جداول زمنية والتحقق من ساعات وأيام)
  • تصنيف (نماذج معدل)
  • الوصي (نظام الأذونات ، الطريقة السهلة)

من الصعب جدا أن نفهم؟ اوصل لي!

إذا كان لديك المزيد من الأسئلة حول Laravel ، إذا كنت بحاجة إلى مساعدة بشأن أي معلومات متعلقة بـ DevOps أو تريد ببساطة أن تقول شكراً لك ، يمكنك أن تجدني على Twitterrennokki!