دیزاین پترن ریپازیتوری در لاراول

What is Repository Design Pattern in Laravel

26 شهریور 1402
What is repository design pattern in laravel

در توسعه وب مدرن، ساخت برنامه های کاربردی قابل نگهداری و مقیاس پذیر بسیار مهم است. لاراول، یکی از محبوب ترین فریم ورک های PHP، مجموعه ای قدرتمند از ابزارها را برای دستیابی به این هدف در اختیار توسعه دهندگان قرار می دهد. یکی از این ابزارها دیزاین پترن ریپازیتوری (Repository Design Pattern) است، که یک الگوی طراحی یا دیزاین پترن پذیرفته شده است که استفاده از کد تمیز و سازمان یافته را ترویج می کند.

در این مقاله به بررسی دیزاین پترن ریپازیتوری و پیاده سازی آن در لاراول می پردازیم. ما مزایای استفاده از repository ها را بررسی خواهیم کرد، ساختار آنها را درک خواهیم کرد و یاد خواهیم گرفت که چگونه از آنها برای ایجاد برنامه های کاربردی قوی و انعطاف پذیر استفاده کنیم.

دیزاین پترن ریپازیتوری (Repository Pattern) چیست؟

دیزاین پترن ریپازیتوری یک الگوی ساختاری است که به عنوان یک واسطه بین لایه دسترسی به داده های برنامه (معمولا پایگاه داده) و بقیه برنامه عمل می کند. هدف اصلی آن جداسازی منطق پایداری داده است و به توسعه‌دهندگان اجازه می‌دهد بین منابع داده مختلف جابجا شوند، بدون اینکه بر بقیه کد برنامه تاثیر بگذارند.

در لاراول، repository ها اغلب برای کپسوله کردن کوئری های پایگاه داده و ارائه یک لایه اضافی از انتزاع استفاده می شوند. این جداسازی نگرانی‌ها، قابلیت نگهداری، آزمایش‌پذیری و مقیاس‌پذیری کد را بهبود می‌بخشد.

مزایای استفاده از دیزاین پترن ریپازیتوری

  1. سازماندهی کد: با استفاده از دیزاین پترن ریپازیتوری، می‌توانید منطق دسترسی به داده‌های خود را در لایه‌ای جداگانه سازماندهی کنید و پایگاه کد خود را مرتب تر و مدیریت آن را آسان‌تر کنید.
  2. قابلیت استفاده مجدد از کد: repository ها استفاده مجدد از کد را آسان می کنند زیرا بر منطق دسترسی به داده ها متمرکز است. به این معنی که شما می توانید از همان متدهای ریپازیتوری در چندین بخش برنامه خود استفاده مجدد کنید.
  3. تست پذیری: با repository ها، می توانید به راحتی دسترسی به داده ها را در طول تست یونیت ماکینگ کنید و متدهای تست قابل اعتمادتر و کارآمدتری را استفاده کنید.
  4. انعطاف‌پذیری: repository ها به شما امکان می‌دهند از منابع مختلف داده مانند پایگاه‌های داده یا APIهای خارجی استفاده کنید، بدون اینکه منطق اصلی برنامه خود را تغییر دهید.

استفاده از دیزاین پترن ریپازیتوری در لاراول

بیایید یک برنامه ساده لاراول ایجاد کنیم تا الگوی ریپازیتوری را در عمل ببینیم. برنامه ما یک api ساده دارد که می تواند محصولات موجود در پایگاه داده را مدیریت کند.

مرحله 1: ایجاد یک پروژه جدید لاراول  

اگر از مک استفاده می کنید، می توانید دستور زیر را برای شروع کار اجرا کنید:

curl -s "https://laravel.build/laravel-products-app" | bash
cd laravel-products-app
./vendor/bin/sail up -d

برای بررسی موفقیت آمیز بودن نصب، آدرس http://localhost را در مرورگر خود ببینید.

ایجاد یک پروژه جدید لاراول

مرحله 2: ایجاد یک جدول و populate کردن آن:

دستور زیر را برای ایجاد یک مدل برای محصولات و مهاجرت، seeder،factory، درخواست‌های فرم، قوانین و کنترلر مربوطه اجرا کنید:

sail artisan make:model Product -a

فایل های زیر ایجاد خواهند شد.

app/Models/Product.php
database/factories/ProductFactory.php
database/migrations/2023_07_23_113810_create_products_table.php
database/seeders/ProductSeeder.php
app/Http/Requests/StoreProductRequest.php
app/Http/Requests/UpdateProductRequest.php
app/Http/Controllers/ProductController.php

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

بیایید مهاجرت را تغییر دهیم تا لاراول بداند که می خواهیم کدام فیلدها را در جدول داشته باشیم. متد up را به صورت زیر تغییر دهید:

public function up(): void
{
    Schema::create('products', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->text('description');
        $table->boolean('is_available')->default(false);
        $table->timestamps();
    });
}

سپس ProductFactory را تغییر دهید تا بتوانیم برای هر محصول در پایگاه داده مقداری داده فیک ایجاد کنیم.

public function definition() 
{
    return [
        'name' => fake()->name,
        'description' => fake()->paragraph,
        'is_available' => fake()->boolean,
    ];
}

اکنون ProductSeeder را تغییر دهید تا 100 محصول با استفاده از تعریف ProductFactory برای ما ایجاد کند. همچنین باید DatabaseSeeder را تغییر دهیم رسانی کنیم تا از کلاس ProductSeeder ما استفاده کند.

public function run(): void
{
    $this->call([
        ProductSeeder::class
    ]);
}

اکنون می‌توانیم دستور زیر را برای اجرای migrations و seed دیتابیس اجرا کنیم:

sail artisan migrate --seed

IDE پایگاه داده خود را باز کنید و باید چیزی شبیه به این را در جدول محصولات خود مشاهده کنید:

پیاده سازی ریپازیتوری پترن در لاراول

ابتدا یک رابط ایجاد کنید که اینترفیس را برای ریپازیتوری شما تعریف کند. این رابط متدهایی را که ریپازیتوری باید پیاده سازی کند فهرست می کند.

?php 

namespace App\Repositories;

interface ProductRepositoryInterface
{
    public function getAllProducts();
    public function getProductById($productId);
    public function deleteProduct($productId);
    public function createProduct(array $productData);
    public function updateProduct($productId, array $productData);
    public function getAvailableProducts();

    // Add more methods as per your application needs
}

بعد، یک پیاده سازی مشخص از رابط ریپازیتوری ایجاد کنید. این کلاس حاوی منطق واقعی دسترسی به داده ها خواهد بود.

<?php

namespace App\Repositories;

use App\Models\Product;

class ProductRepository implements ProductRepositoryInterface
{
    public function getAllProducts()
    {
        return Product::all();
    }

    public function getProductById($productId)
    {
        return Product::findOrFail($productId);
    }

    public function deleteProduct($productId)
    {
        Product::destroy($productId);
    }

    public function createProduct(array $productData)
    {
        return Product::create($productData);
    }

    public function updateProduct($productId, array $productData)
    {
        return Product::whereId($productId)->update($productData);
    }

    public function getAvailableProducts()
    {
        return Product::where('is_available', true);
    }
}

در لاراول، می توانید اینترفیس ریپازیتوری را به پیاده سازی آن در کانتینر سرویس متصل کنید. این به شما امکان می دهد تا ریپازیتوری را به طور خودکار در هر کجا که نیاز دارید تزریق (inject) کنید. دستور زیر را اجرا کنید:

sail artisan make:provider RepositoryServiceProvider

متد register را در کلاس تازه ایجاد شده ویرایش کنید تا ریپازیتوری خود را به کانتیتر سرویس لاراول متصل کنید:

public function register()
{
    $this->app->bind(ProductRepositoryInterface::class, ProductRepository::class);
}

آخرین مرحله ای که باید پشت سر بگذاریم این است که آرایه providers را در فایل app/config.php خود ویرایش کنیم:

'providers' => ServiceProvider::defaultProviders()->merge([
    // Other providers...
    App\Providers\RepositoryServiceProvider::class,
 ])->toArray(),

 ایجاد مسیریابی (routing) و کنترلر

اکنون که ریپازیتوری راه اندازی شده است، می توانید آن را به کنترلرها یا سرویس های خود تزریق کنید و از متدهای آن برای تعامل با لایه داده استفاده کنید.

<?php

namespace App\Http\Controllers;

use App\Http\Requests\StoreProductRequest;
use App\Http\Requests\UpdateProductRequest;
use App\Models\Product;
use App\Repositories\ProductRepository;
use App\Repositories\ProductRepositoryInterface;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;


class ProductController extends Controller
{
    public function __construct(
        private ProductRepositoryInterface $productRepository
    ) {
    }

    public function index(): JsonResponse
    {
        return response()->json([
            'data' => $this->productRepository->getAllProducts()
        ]);
    }

    public function store(StoreProductRequest $request): JsonResponse
    {
        return response()->json(
            [
                'data' => $this->productRepository->createProduct($request->validated())
            ],
            Response::HTTP_CREATED
        );
    }

    public function show(Product $product)
    {
        return response()->json([
            'data' => $this->productRepository->getProductById($product->id)
        ]);
    }

    public function update(UpdateProductRequest $request, Product $product)
    {
        return response()->json([
            'data' => $this->productRepository->updateProduct($product->id, $request->validated())
        ]);
    }

    public function destroy(Product $product)
    {
        $this->productRepository->deleteProduct($product->id);

        return response()->json(null, Response::HTTP_NO_CONTENT);
    }
}

خط زیر را به routes/api.php اضافه کنید:

Route::apiResource('product', ProductController::class);

می توانید برنامه خود را با استفاده از Postman یا موارد مشابه تست کنید. در اینجا یک اسکرین شات وجود دارد تا بتوانید ببینید روت index چه چیزی را برمی گرداند:

ایجاد و ویرایش مدل

برای ایجاد محصولات و به روز رسانی آنها کار بیشتری باید انجام شود. اول از همه اجازه دهید فایل StoreProductRequest.php را ویرایش کنیم:

<?php

namespace App\Http\Requests;

use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;

class StoreProductRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }
    
    public function rules(): array
    {
        return [
            'name' => 'required|min:3|max:255',
            'description' => 'required|min:3|max:255',
            'is_available' => 'required|boolean'
        ];
    }
}

توجه داشته باشید که برای بازگشت true باید متد autorize را ویرایش کنید. اگر بخواهیم محصولی ایجاد کنیم و فقط از قسمت نام استفاده کنیم، یک پاسخ خطای 422 دریافت می کنیم:

همچنین باید مدل را ویرایش کنیم تا بتوانیم عملیات انتساب را انجام دهیم. این برای جلوگیری از ویرایش اشتباه فیلدها برای مثال ستون id است. فایل app/Models/Product.php خود را ویرایش کنید و ویژگی $fillable را اضافه کنید:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    use HasFactory;
    
    protected $fillable = ['name', 'description', 'is_available'];
}

اکنون وقتی درخواست POST ارسال می کنیم، پاسخ 201 را دریافت می کنیم:

و همچنین می توانیم ببینیم که محصول ما در پایگاه داده ایجاد شده است:

برای درخواست PUT می توانید همان تغییرات را در فایل UpdateProductRequest.php ایجاد کنید.

نتیجه گیری

دیزاین پترن ریپازیتوری ابزار قدرتمندی است که می تواند ساختار و قابلیت نگهداری برنامه های لاراول شما را به میزان قابل توجهی بهبود بخشد. با جداسازی منطق دسترسی به داده ها، به قابلیت استفاده مجدد، آزمایش پذیری و انعطاف پذیری کد دست پیدا می کنید. این مقاله یک راهنمای گام به گام برای پیاده سازی دیزاین پترن ریپازیتوری در لاراول ارائه می دهد که به شما امکان می دهد کد خود را مانند یک حرفه ای مدیریت کنید و برنامه های قوی و مقیاس پذیر بسازید. پس ادامه دهید، کد خود را تغییر دهید و از پتانسیل کامل دیزاین پترن ریپازیتوری لاراول استفاده کنید.

می توانید ریپازیتوری Github را در اینجا مشاهده کنید.

نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.