پیاده‌سازی Repository Pattern در لاراول

اگر با فریمورک‌های مختلف مثل laravel کار کرده باشید، اینو می‌دونید که نوشتن یه وب اپلیکیشن یا یه پروژه میتونه خیلی راحت‌تر از زمانی باشه که میخواهید از پایه با کتابخونه‌های خودتون بنویسید. یکی از مزیت‌های مهم استفاده از فریمورک‌ها، مستندات قوی و جامعه پشتیبان اون‌هاست که بهشون قدرت میده و شما هم می‌تونید از این قدرت به نفع خودتون و یا نفع همون جامعه کاربریش استفاده کنید.

در لاراول با استفاده از کتابخونه‌های قوی کارتون خیلی سرعت دارهو به راحتی پیش میره ولی بعضی موقع این راحتی کار دستتون میده. به عنوان مثال به کد زیر دقت کنید:

 

تو کد بالا ما یه کنترلر Post داریم و یه متد index که میشه صفحه اصلی کنترلرمون و توش با استفاده از مدل Post تمام رکورد‌ها رو ریختیم داخل یه متغیر و اونو پاس دادیم به View مون. تا اینجای کار، لذت بخش و آسون بود.

مشکل کجاست؟

مشکل موقعی پیش میاد که بخواهید کدتونو تست کنید. خب تو این مورد انجامش ممکن نیست، چون Dependencyها یا نیازمندی‌های کنترلرمون که از یک کلاس دیگه استفاده می‌کنه تعیین نشده و نمیشه از اون توی تست استفاده کرد. پس به مشکل میخوریم.

یکی دیگه از مشکلات هم برمیگیرده به زمانی که بخواهیم نوع دیتابیسمونو عوض کنیم. مثلن بخواهیم از mongoDB به جای Mysql یا هر نوع دیتابیس از نوع Sql، استفاده کنیم. خب، توی استفاده از انواع Sql دیگر مثل SqlServer یا Postgesql نباید مشکلی باشه و نیازی نیست کدمونو تغییر بدیم ولی اگر به mongoDB بخواهیم کوچ کنیم مجبوریم تمام قسمت‌های کدمونو بازنویسی کنیم که این به دور از اصول توسعه سریع و تمیزه.

راه حل چیه؟

یکی از بهترین راه‌حل ها استفاده از Repository ها برای جدا کردن مدل‌ها از کنترلر‌هامون و مدیریت Dependency Injectionهاست. خب اول باید ببینیم Repository چی کار می‌کنه؟ Repositoryها میان یه واسطی میشن به بخش دیتابیس و کنترلرهامون و مثل یه تونل و فیلتر عمل می‌کنن تا ما از یک نوع کدنویسی و استاندارد برای ارتباط با پایگاه‌های داده اعم از (Redis, Sql, NoSql) استفاده کنیم.

به طور کلی Repositoryها به معنای ارتباط دهنده بین دو چیز هستند.

اگر به واژه رابط یا واسط توجه کرده‌باشد درمی‌یابید که Repository چیزی نیست جز interfaceها. بله، ما به کمک یکی از امکانات شی‌گرایی برای حل این مشکلات استفاده می‌کنیم.

حالا کد بالا رو می‌خواهیم بازنویسی کنیم:

ابتدا یک Repository برای Post ایجاد می‌کنیم:

 

سپس میاییم یک کلاس دیگر که از این interface ارث برده را ایجاد می‌کنیم: (توجه داشته باشید تمام کلاس‌هایی که از interfaceها implement می‌شوند باید تمام متدهایی که در interface نام برده شده‌اند‌ را داخل خودشون پیاده‌سازی کنند:

ما یک کلاس برای کار با انواع دیتابیس Sql ایجاد می‌کنیم و همونطور که میدونید برای این کار از کتابخونه Eloqunet لاراول استفاده می‌کنیم:

 

حالا کنترلرمونو بازنویسی می‌کنیم:

 

همونطور که میبینید دیگه کنترلر ما براش فرق نمیکنه که از چه نوع دیتابیسی استفاده کنه. ما به راحتی می‌تونید کلاس مربوط به اونو بنویسیم و با استفاده از Ioc Container لاراول، اونو به عنوان مدلمون معرفی کنیم.

چیزی که تو این پست نوشتم یه خورده خورده کاری داره مثل bind کردن کلاسمون به interface تا بتونیم تو پروژه‌هامون ازش استفاده کنیم که به صورت تفصیلی تو پست‌های آینده در موردش صحبت می‌کنم. فقط میخواستم یه دیدی از این کار داشته باشید.

7 دیدگاه در “پیاده‌سازی Repository Pattern در لاراول

  1. سلام بنظرم باید اونجایی که تو کانستراکتور کنترلر ، Repository رو type-hint میکنید ، از EloquentPostRepository استفاده کنید . این موضوع یکمی منو به شک انداخته !

    • نه درستش همونه. باید interface رو inject کنیم. وگرنه چه نیازی به نوشتن Interface داریم؟ در ادامه فقط باید کلاسی مثل EloquentPostRepository رو به PostRepository به وسیله Service Providerها Bind کنیم.

      البته این پست مثال خیلی خیلی ساده ریپازیتوری پترن توی لاراوله.

  2. دستتون درد نکنه . یه سوال. اگه به مانگو دیبی تغییر بدیم باید خود متد ها فرق بکنن دیگه. لاراول به صورت پیش فرض ساپورت نمیکنه و یه سری پکیج ها براش نوشته شده . دیدم که از کالکشن به جای دستورات عادی الوکوئنت استفاده کرده. ممنون میشم راهنمایی کنید

    • بله همینطوره. باید یه بار دیگه Repository Interfaceها رو برای mongodb پیاده‌سازی کنید. کلا استفاده از Repository Pattern موقعی پیشنهاد میشه که لازم باشه در اپلیکیشنتون از چند نوع دیتابیس بخواد استفاده بکنه.

  3. خوب الان یه سوال. اینطوری این رپوزیتوری به چه دردی میخوره وقتی دستورات مانگو دیبی فرق میکنن؟ درست نمیفهمم قضیه چیه. چطور میشه با این روش مانگو دیبی رو اینتگریت کرد؟

    • ببینید با استفاده ار ریپازیتوری‌پترن، یه لایه به برنامه‌تون اضافه میشه که بین لایه‌های دیگه برنامه با لایه دیتا‌استوریج قرار می‌گیره. حالا اگه شما قرار باشه دیتابیس رو عوض کنید نیاز نیست تو جاهای دیگه تغییر بدید و تنها لایه مربوط به پیاده‌سازی دیتااستوریجتون رو باید بنویسید. ولی در غیر اینصورت هر جای برنامه با دیتابیس کار کردید رو باید دست بزنید.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *