يرجى التوقف عن الحديث عن قالب السجل مع Eloquent

أرى بانتظام مقالات في أسلوب "كيفية استخدام قالب السجل مع Eloquent" (أحدها حصل على ملخص PHP حديثًا). محتواها المعتاد: دعنا ننشئ واجهة PostRepositoryInterface ، فئة EloquentPostRepository ، اربطها جيدًا في حاوية التبعية واستخدم الحفظ والبحث عن أساليب Ekovent القياسية.


لماذا هناك حاجة إلى هذا القالب في بعض الأحيان لا يكتبون على الإطلاق ("هذا قالب ! أليس كذلك؟") ، في بعض الأحيان يكتبون شيئًا عن تغيير محتمل لقاعدة البيانات (حدث شائع جدًا في كل مشروع) ، وكذلك عن الاختبار ورموز المخاطرة. يصعب الحصول على فوائد إدخال مثل هذا القالب في مشروع Laravel منتظم في مثل هذه المقالات.


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


تنقسم أمثلة المستودع الفصيح إلى نوعين:


  1. الاختلاف المزدوج الفصيح
  2. المستودع الفصيح النقي

الاختلاف المزدوج الفصيح


مثال على الأول (مأخوذ من مقال عشوائي):


<?php interface FaqRepository { public function all($columns = array('*')); public function newInstance(array $attributes = array()); public function paginate($perPage = 15, $columns = array('*')); public function create(array $attributes); public function find($id, $columns = array('*')); public function updateWithIdAndInput($id, array $input); public function destroy($id); } class FaqRepositoryEloquent implements FaqRepository { protected $faqModel; public function __construct(Faq $faqModel) { $this->faqModel = $faqModel; } public function newInstance(array $attributes = array()) { if (!isset($attributes['rank'])) { $attributes['rank'] = 0; } return $this->faqModel->newInstance($attributes); } public function paginate($perPage = 0, $columns = array('*')) { $perPage = $perPage ?: Config::get('pagination.length'); return $this->faqModel ->rankedWhere('answered', 1) ->paginate($perPage, $columns); } public function all($columns = array('*')) { return $this->faqModel->rankedAll($columns); } public function create(array $attributes) { return $this->faqModel->create($attributes); } public function find($id, $columns = array('*')) { return $this->faqModel->findOrFail($id, $columns); } public function updateWithIdAndInput($id, array $input) { $faq = $this->faqModel->find($id); return $faq->update($input); } public function destroy($id) { return $this->faqModel->destroy($id); } } 

الكل ، العثور على ، ترقيم الصفحات إرجاع الكائنات Eloquent ، ومع ذلك إنشاء ، updateWithIdAndInput في انتظار صفيف.


اسم updateWithIdAndInput نفسه يعني أن هذا "المخزون" سيتم استخدامه فقط لعمليات CRUD.


ليس من المتوقع وجود منطق أعمال عادي ، لكننا سنحاول تطبيق أبسط:


 <?php class FaqController extends Controller { public function publish($id, FaqRepository $repository) { $faq = $repository->find($id); //...-   $faq->... $faq->published = true; $repository->updateWithIdAndInput($id, $faq->toArray()); } } 

وإذا كان بدون مستودع:


 <?php class FaqController extends Controller { public function publish($id) { $faq = Faq::findOrFail($id); //...-   $faq->... $faq->published = true; $faq->save(); } } 

أسهل مرتين.


لماذا إدخال التجريد في المشروع من شأنه أن يعقد فقط؟


  • اختبار وحدة؟
    يعلم الجميع أن مشروع CRUD العادي في Laravel مغطى باختبارات الوحدات بأكثر من 100٪ بقليل.
    لكننا سنناقش اختبار وحدة في وقت لاحق قليلا.
  • من أجل القدرة على تغيير قاعدة البيانات؟
    لكن Eloquent يوفر بالفعل العديد من خيارات قاعدة البيانات.
    استخدام كيانات Eloquent لقاعدة غير مدعومة للتطبيق الذي يحتوي على منطق CRUD فقط سيكون ألمًا ومضيعة للوقت.
    في هذه الحالة ، يبدو المستودع ، الذي يعرض صفيف PHP خالصًا ويقبل المصفوفات فقط ، أكثر طبيعية.
    عن طريق إزالة Eloquent ، نحصل على تجريد حقيقي من مستودع البيانات.

المستودع الفصيح النقي


مثال على مستودع مع العمل فقط مع Eloquent (موجود أيضًا في مقال واحد):


 <?php interface PostRepositoryInterface { public function get($id); public function all(); public function delete($id); public function save(Post $post); } class PostRepository implements PostRepositoryInterface { public function get($id) { return Post::find($id); } public function all() { return Post::all(); } public function delete($id) { Post::destroy($id); } public function save(Post $post) { $post->save(); } } 

أنا لن تأنيب لاحقة لا لزوم لها واجهة في هذه المقالة.


يشبه هذا التطبيق قليلاً ما يقوله وصف القالب.


يبدو تنفيذ المنطق الأبسط أكثر طبيعية قليلاً:


 <?php class FaqController extends Controller { public function publish($id, PostRepositoryInterface $repository) { $post = $repository->find($id); //...-   $post->... $post->published = true; $repository->save($post); } } 

ومع ذلك ، فإن تطبيق مستودع لأبسط مشاركات المدونة يعد لعبة يمكن للأطفال الاستمتاع بها.


لنجرب شيئًا أكثر تعقيدًا.


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


حالة إنشاء كائن مثل هذا المسح. خياران:


  • إنشاء PollRepository و PollOptionRepository واستخدام كليهما.
    المشكلة في هذا الخيار هي أن التجريد لم ينجح.
    المسح الذي يحتوي على إجابات محتملة هو كيان واحد ، ويجب أن يتم تخزينه في قاعدة البيانات بواسطة فصل PollRepository واحد.
    PollOptionRepository :: delete لن يكون سهلاً ، لأنه سيحتاج إلى كائن Poll لفهم ما إذا كان يمكن حذف خيار الإجابة هذا (لأنه إذا كان لدى الاستطلاع خيار واحد فقط ، فلن يكون استطلاعًا).
    ولا يعني قالب المستودع تنفيذ منطق الأعمال داخل المستودع.
  • داخل PollRepository إضافة أساليب saveOption و deleteOption .
    المشاكل هي نفسها تقريبا. اتضح أن التجريد من التخزين هو نوع من التحجيم ... يجب أن تؤخذ خيارات الإجابة بشكل منفصل.
    ولكن ماذا لو كان الجوهر أكثر تعقيدًا؟ مع مجموعة من العناصر الفرعية الأخرى؟

السؤال نفسه يطرح نفسه: لماذا كل هذا؟
الحصول على مزيد من التجريد من نظام التخزين مما يعطي Eloquent - لن ينجح.


اختبار وحدة؟


فيما يلي مثال على اختبار وحدة محتمل من كتابي - https://gist.github.com/adelf/a53ce49b22b32914879801113cf79043
لإجراء مثل هذه الاختبارات الضخمة لأبسط العمليات ليس كافيًا لاستمتاع أي شخص.


أنا متأكد تقريبًا من أنه سيتم التخلي عن مثل هذه الاختبارات في المشروع.


لا أحد يريد دعمهم. كنت في مشروع مع مثل هذه الاختبارات ، وأنا أعلم.


من الأسهل والأكثر صحة التركيز على الاختبار الوظيفي.
خاصة إذا كان مشروع API.


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


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

Source: https://habr.com/ru/post/ar444688/


All Articles