Anophel-آنوفل بررسی تزریق وابستگی Dependency Injection و Service Container در لاراول

بررسی تزریق وابستگی Dependency Injection و Service Container در لاراول

انتشار:
2

در این مقاله در مورد ساخت برنامه های تحت وب با استفاده از PHP Laravel، اصل تزریق وابستگی (Dependency Injection) را که به عنوان Inversion of Control (IoC) container نیز شناخته می شود، معرفی خواهیم کرد و چگونگی استفاده داخلی لاراول و ارائه این مفهوم به توسعه دهندگان برنامه را بررسی می کنم. برای استفاده و شفاف سازی کد آنها و جداسازی آنها صحبت خواهیم کرد.

تزریق وابستگی چیست؟

تزریق وابستگی (Dependency Injection) یک تکنیک برنامه نویسی است که به شما امکان می دهد اجزای نرم افزار خود را از یکدیگر جدا کنید. هنگامی که در حال ساخت برنامه های کاربردی در مقیاس بزرگ هستید، اغلب با مواردی مواجه می شوید که یک کلاس برای عملکرد صحیح به کلاس سرویس دیگری نیاز دارد. وقتی به کلاس اجازه می دهید وابستگی های خود را ایجاد کند، در حال تحمیل جفت شدن بین کلاس های خود و وابستگی شدید آنها به یکدیگر هستید.

نتیجه این اتصال محکم منجر به عواقب زیر می شود:

کدی که تست آن سخت تر است
کدی که نگهداری آن سخت تر است


در اینجا مثالی آورده شده است که نشان می دهد چگونه یک کلاس وابستگی های خود را نمونه سازی می کند.

class InvoiceController extends Controller
{
    protected PaymentService $paymentService;

    public function __construct()
    {
        $this->paymentService = new PaymentService();
    }
}

به همین دلیل است که برای معکوس کردن جریان نمونه سازی آبجکت به IoC Container/Dependency Injection نیاز دارید. به جای اینکه یک کلاس وابستگی های خود را نمونه سازی و مدیریت کند، IoC Container در عوض آن وابستگی ها را آماده کرده و به کلاس هایی که به آنها نیاز دارند تزریق می کند.

class InvoiceService
{
    public function __construct(
      protected PaymentService $paymentService) { }
}

کلاس ها این گزینه را دارند که اجرای concrete را بپذیرند یا رابطی که در زمان اجرا با اجرای concrete جایگزین شود.

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

انواع مختلفی از تزریق وابستگی وجود دارد، مانند setter injection، constructor injection، method injection، و انواع دیگر.

ما در طول این مقاله بر تزریق constructor تمرکز خواهم کرد.

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

کار با ENUM در PHP : همراه با مثال

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

چهار نقش اصلی در تزریق وابستگی

برای پیاده سازی تزریق وابستگی در کد خود، چهار نقش اصلی وجود دارد که باید در مورد آنها بدانید:

1.سرویسی که می خواهید استفاده کنید، مانند سرویس پرداخت یا سرویس ایمیل.
2.کلاینتی که از خدمات استفاده می کند. این کلاسی است که سرویس را به آن تزریق خواهید کرد.
3.رابطی که توسط کلاینت استفاده می شود و توسط سرویس پیاده سازی می شود. این اختیاری است. شما می توانید یک کلاس concrete بدون رابط تزریق کنید. اما با تزریق یک رابط، شما این شانس را دارید که پیاده سازی های concrete را در زمان اجرا تعویض کنید.
4. injector یک نمونه سرویس ایجاد می کند و آن را به کلاینت تزریق می کند. این معمولا به عنوان کانتینر تزریق (injection container) وابسته شناخته می شود. مسئولیت آن مدیریت نمونه سازی شی و پیگیری وابستگی های آنهاست.


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

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

اکنون که ایده ای از تزریق وابستگی دارید، بیایید ببینیم Laravel چگونه آن را پیاده سازی می کند.

تزریق وابستگی به سادگی به این معنی است که وابستگی از بیرون به کلاس اضافه می شود. این بدان معنی است که شما نباید وابستگی ها را با استفاده از عملگر جدید از داخل کلاس نمونه سازی کنید، بلکه در عوض، آن را به عنوان پارامتر سازنده یا از طریق یک setter در نظر بگیرید.

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

لاراول چگونه تزریق وابستگی را پیاده سازی می کند

IoC Container در قلب چارچوب Laravel قرار دارد. لاراول با یک سرویس Container عرضه می‌شود که وظیفه مدیریت وابستگی‌ها در برنامه و تزریق آن‌ها در هر کجا که نیاز باشد را بر عهده دارد.

کانتینر به شما این فرصت را می دهد که اتصالات به کلاس ها و رابط ها را تعریف کنید. در عین حال، دارای یک ویژگی منحصر به فرد به نام Zero Configuration Resolution است که باعث می شود کانتینر وابستگی ها را حتی بدون ثبت آن ها برطرف کند. می‌تواند این کار را انجام دهد به شرطی که وابستگی، وابستگی دیگری نداشته باشد یا وابستگی‌هایی داشته باشد که کانتینر قبلاً می‌داند چگونه آن‌ها را نمونه‌سازی کند.

Service container یک سرویس لاراول است که به شما امکان می دهد به لاراول بگویید که یک شی یا کلاس چگونه باید ساخته شود و سپس لاراول می تواند آن را از آنجا بفهمد.

تزریق وابستگی ساده

بیایید به یک مثال نگاه کنیم تا به شما نشان دهیم که چگونه تزریق وابستگی در یک برنامه لاراول کار می کند. نمونه زیر کل کد منبع این مثال را نشان می دهد.

public class PaymentService
{
    public function doPayment ()
    {
        // ...
    }
}

class PaymentController extends Controller
{
    public function __construct (protected PaymentService $paymentService)
    {

    }

    public function payment ()
    {
        // $paymentService
    }
}

ابتدا یک PaymentService را تعریف کنید که حاوی یک متد به نام ()doPayment باشد. در نهایت، کدی را که مسئول انجام پرداخت پس از تسویه حساب یا خرید است، قرار می دهید.

سپس، در داخل PaymentController، سازنده ای را تعریف کنید که به عنوان پارامتر ورودی یک شی PaymentService را می پذیرد. متد ()payment از شی paymentService$ برای انجام پرداخت استفاده می کند.

هنگامی که درخواستی را به متد ()payment ارسال می کنید، لاراول وظایف زیادی را در پشت صحنه انجام می دهد. یکی از این وظایف، نمونه سازی کلاس PaymentController است. هنگام نمونه سازی آن، مشاهده می کند که سازنده به یک وابستگی نیاز دارد.

لاراول از Service Container خود برای جستجوی وابستگی ها استفاده می کند. در حال حاضر، شما لاراول را در مورد نحوه نمونه سازی وابستگی PaymentService راهنمایی نکرده اید. با این حال، لاراول به اندازه کافی هوشمند است تا این وابستگی را حل کند و آن را به سازنده PaymentController تزریق کند. PaymentService هیچ وابستگی دیگری ندارد، بنابراین برای لاراول آسان است که آن را نمونه‌سازی کند و از آن یک شی بسازد.

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

شما دیده اید که چگونه Laravel Dependency Injection برای موارد ساده ای که یک کلاس وابستگی به کلاس دیگری دارد که وابستگی دیگری ندارد کار می کند. وقتی PaymentService خود وابستگی داشته باشد چه اتفاقی می افتد؟

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

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

بیایید با مثال دیگری که در زیر نشان داده شده است، ببینیم.

public class PaymentService
{
    public function __construct (protected string $secretKey){ }

    public function doPayment ()
    {
        // ...
    }
}

class PaymentController extends Controller
{
    public function __construct(protected PaymentService $paymentService)
    {

    }

    public function payment ()
    {
        // $paymentService
    }
}

کلاس PaymentService اکنون سازنده‌ای را تعریف می‌کند که وابستگی رشته‌ای به نام secretKey$ را می‌پذیرد. در این صورت، لاراول نمی‌تواند به تنهایی و بدون کمک شما، سرویس پرداخت را ارائه کند. دلیل؟ لاراول نمی تواند وابستگی جدید را پیش بینی یا ارائه دهد.

شما باید دستورالعمل های اضافی را در مورد نحوه نمونه سازی PaymentService به لاراول ارائه دهید.

در داخل فایل app\Providers\AppServiceProvider.php، یک binding ثبت می کنید تا به لاراول بگویید چگونه یک شی جدید از PaymentService را نمونه سازی کند.

public function register()
{
    $this->app()->bind(PaymentService::class, function() {
        return new PayentService('123456');
    }
);

فراخوانی متد ()app نمونه ای از کلاس Illuminate\Foundation\Application را برمی گرداند. این کلاس به نوبه خود کلاس Illuminate\Container\Container را گسترش می دهد. از این رو، متد ()app به شما امکان می دهد مستقیماً با سرویس کانتینر لاراول کار کنید.

Container متد ()bind را تعریف می کند که به شما امکان می دهد یک binding جدید در داخل Service کانتینر تعریف کنید.

متد ()bind به عنوان اولین پارامتر ورودی نام یا نوع وابستگی را می‌پذیرد که می‌خواهید برای آن یک اتصال تعریف کنید. آرگومان دوم Closure PHP است. این کد با ارائه کلید مخفی صحیح مورد نیاز سرویس، نمونه جدیدی از PaymentService را نشان می دهد و برمی گرداند.

وقتی زمان آن فرا می رسد که لاراول PaymentService را به PaymentController تزریق کند، بررسی می کند که آیا شما برای این وابستگی یک اتصال تعریف کرده اید یا خیر. اگر یکی را پیدا کرد، Closure شدن را اجرا و اجرا می کند تا نمونه ای از این وابستگی را برگرداند.

به طور خلاصه، شما این شانس را دارید که نه تنها از Service Container برای نمونه‌سازی و تزریق وابستگی‌ها استفاده کنید، بلکه به آن آموزش دهید که چگونه وابستگی‌ها را نمونه‌سازی کند.

وقتی چندین پیاده سازی concrete از یک سرویس داشته باشید کمی پیچیده تر می شود. بیایید ببینیم که چگونه به Laravel Service Container دستور می دهید تا این پیچیدگی را مدیریت کند.

یک وابستگی با چند پیاده سازی concrete

اغلب اوقات، شما نیاز دارید که همزمان به چندین درگاه پرداخت متصل شوید. بسته به اولویت کاربر یا معیارهای دیگر در برنامه شما، ممکن است لازم باشد چندین پیاده سازی concrete از یک سرویس داشته باشید و آماده باشید که هر بار از یک پیاده سازی مشخص یا هر دو با هم بسته به منطقی استفاده کنید.

نمونه زیر کل کد این مثال را نشان می دهد.

interface PaymentGateway
{
    public function doPayment ();
}

classPaypalGateway implements PaymentGateway
{
    public function __construct (protected string $secretKey) { }

    public function doPayment ()
    {

    }
}

classStripeGateway implements PaymentGateway
{
    public function __construct (protected string $secretKey) { }

    public function doPayment ()
    {

    }
}

class PaymentController
{
    public function __construct (
        protected PaymentGateway $paymentGateway) { }

    public function __invoke (Request $request)
    {
        // ...
    }
}

$this->app()->bind(PaymentServiceContract::class, function () {
    if (request()->gateway() === 'stripe') {
        return new StripeGateway('123');
    }

    return new PaypalGateway('123');
});

شما با تعریف رابط PaymentGateway شروع می کنید. این رابط نشان می دهد که چه متد هایی باید وجود داشته باشد و در درگاه های پرداخت مختلف موجود در برنامه اجرا شود.

در مرحله بعد، دو سرویس پرداخت جدید را تعریف کنید: PaypalGateway و StripeGateway. هر سرویس رابط PaymentGateway را پیاده‌سازی می‌کند و پیاده‌سازی مشخص متفاوتی را برای دروازه پرداخت مربوطه خود ارائه می‌کند. PaypalGateway به سرویس Paypal و دومی به سرویس Stripe متصل می شود.

PaymentController رابط PaymentGateway را به عنوان یک وابستگی تعریف می کند. در این حالت، کنترل کننده به جای اجرای واقعی concrete، یک رابط درخواست می کند. آنچه در زمان اجرا اتفاق می‌افتد این است که بر اساس نحوه پیکربندی سرویس کانتینر، لاراول یک پیاده‌سازی concrete خاص را به این کنترل‌کننده تزریق می‌کند تا نمونه رابط را جایگزین کند.

در نهایت، Laravel Service Container را راهنمایی می کنید تا یک نمونه مشخص از PaymentGateway را بر اساس پارامتر درخواستی به نام gateway بازگرداند. اگر مقدار stripe داشته باشد، StripeGateway را برمی گردانید، در غیر این صورت، PaypalGateway را برمی گردانید. این یک پیاده سازی ساده برای نشان دادن ID است. شما می توانید آن را به متدی که با نیازهای برنامه شما مطابقت دارد گسترش دهید.

استفاده از رابط ها به عنوان وابستگی به شما امکان می دهد پیاده سازی ها را در زمان اجرا بدون هیچ تلاشی تعویض کنید. همچنین، به این ترتیب، در صورتی که سرویس PayPal یا Stripe تغییر کرده باشد، لازم نیست کل منبع را تغییر دهید. در آینده، ممکن است نیاز به اضافه کردن یک سرویس پرداخت اضافی داشته باشید، و این را می توان به راحتی با افزودن یک پیاده سازی جدید از رابط PaymentGateway و ثبت آن با متد ()bind کانتینر سرویس در لاراول انجام داد.

اکنون که چندین مورد استفاده از سرویس کانتینر لاراول و روش‌های مختلف ارائه تزریق وابستگی در یک برنامه لاراول را پوشش داده‌ام، بیایید ببینیم که تست وابستگی‌های ساختگی چقدر آسان است، مخصوصاً وقتی از آنها به عنوان رابط استفاده می‌کنیم.

جهت آشنایی با دیزاین پترن ها در لاراول می توانید این مقاله را بررسی کنید.

چگونه یک فایل README خوب بنویسیم؟

تست با وابستگی ها

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

لاراول تست PHPUnit را مستقیماً از جعبه ارائه می دهد. اخیراً یک کتابخانه تستی جدید به نام Pest PHP ظاهر شده است. این کتابخانه به صورت داخلی مبتنی بر PHPUnit است. با این حال، تجربه گویاتر و آسان‌تری برای تست و expect/assert نتایج تست ارائه می‌دهد.

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

به طور خلاصه، ماک اشیا دارای مزایای زیر است:

یک کلاس تحت تست را می توان از وابستگی های آن جدا کرد.
تست ها به سرعت اجرا می شوند، به خصوص اگر کلاسی را ماک می کنید که با پایگاه داده یا I/O تعامل دارد.
 

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

برای ایجاد یک شیء ساختگی هنگام استفاده از Pest PHP، باید یک افزونه با composer نصب کنید.

در اینجا نحوه ایجاد و استفاده از اشیاء ماک در PHPUnit آورده شده است.

بیایید نمونه ای از نحوه ماک کردن یک وابستگی با استفاده از کتابخانه PHPUnit را ببینیم.

برای ایجاد یک تست ویژگی جدید در لاراول، دستور زیر را اجرا کنید:

php artisan make:test PaymentTest

دستور یک فایل PaymentTest.php جدید در داخل پوشه tests\Feature ایجاد می کند. نمونه زیر کل کد مورد تست را نشان می دهد.

<?php

namespace Tests\Feature  ;

// use Illuminate\Foundation\Testing\RefreshDatabase;

use App\Payments\PaymentGateway  ;
use App\Payments\PaypalGateway  ;
use Mockery  ;
use Tests\TestCase  ;

class PaymentTest extends TestCase
{
    public function test_payment_returns_a_successful_response ()
    {
        // Create a mock
        $mock = Mockery::mock(PaypalGateway::class)->makePartial();

        // Set expectations
        $mock->shouldReceive('doPayment')
             ->once()->andReturnNull();

        // Add this mock to the service container
        // to take the service class' place.
        app()->instance(PaymentGateway::class, $mock);

        // Run endpoint
        $this->get('/payment')->assertStatus(200);
    }
}

برای این مورد تستی، از مثال پیاده‌سازی تزریق وابستگی با استفاده از رابط‌ها استفاده می‌کنم.

استفاده از تزریق وابستگی، ایجاد دو تست را ساده می کند (اغلب به عنوان "ماک" نامیده می شود). اگر وابستگی‌ها را به کلاس‌ها منتقل می‌کنید، قبول کردن در اجرای دوتایی تستی ساده است.

ایجاد دو برابر تست برای وابستگی هایی که کدگذاری سختی دارند غیرممکن است.

شروع توسط:

ساخت یک مدل جدید برای کلاس PaypalGateway.
expectations را برای شیء ساختگی تنظیم کنید. به عنوان مثال، به شیء ساختگی دستور می دهید که متد ()doPayment یک بار اجرا شود و null برگرداند. اینجاست که شما کنترل می‌کنید چه چیزی را به متد ها منتقل کنید و چه چیزی را برگردانید. شما کنترل کاملی بر آنچه که از متد ها ارسال و برگردانده می‌شود دارید.


شما اتصال برای واسط PaymentGateway را با شی نمونه ساختگی جایگزین می کنید. این جایگزین هر گونه پیوندهای قبلی تنظیم شده در AppServiceProvider می شود. 

هنگام اجرای تست‌ها، می‌خواهید نگاشت‌های Service Container را برای استفاده از شی ساختگی خود جایگزین کنید.
در نهایت، یک درخواست GET به نقطه پایانی payment/ ارسال می کنید.


این نقطه پایانی جدید را در داخل فایل routes\web.php به صورت زیر تعریف کنید:

Route::get('/payment', PaymentController::class);

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

class PaymentController extends Controller
{
    public function __construct (
        protected PaymentGateway $paymentGateway)
    {
    }

    public function __invoke (Request $request)
    {
        $this->paymentGateway->doPayment();
    }
}

PaymentController به واسط PaymentGateway وابستگی دارد. هنگام اجرای تست، پارامتر paymentGateway$ با شیء ساختگی PaypalGateway جایگزین می شود. با استفاده از یک ماک، هیچ چیز در مورد نحوه فراخوانی متد های PaymentController در رابط PaymentGateway تغییر نکرده است. یک شیء ساختگی تضمین می کند که کد بدون در نظر گرفتن اجرای واقعی concrete ، با همان طرح اولیه به کار خود ادامه می دهد.

اکنون که مزایای تزریق وابستگی و سرویس کانتینر لاراول را می‌دانید، بیایید بررسی کنیم که سرویس کانتینر چه گزینه‌های اتصالی را ارائه می‌دهد.

جهت آشنایی با بهترین روش های تست این مقاله را بررسی کنید.

سواگر در مقابل پست من کدام یک را انتخاب کنیم؟

Service Container Bindings

Laravel Service Container راه های مختلفی برای اتصال (bind) و ثبت وابستگی ها ارائه می دهد. تاکنون نحوه استفاده از متد ()app()->bind را برای اتصال یک وابستگی در برنامه مشاهده کرده اید. کانتینر سرویس راه‌های دیگری برای اتصال وابستگی‌ها ارائه می‌کند. اسناد لاراول در جزئیات همه آنها کار بسیار خوبی انجام می دهد. با این حال، می‌خواهم سه تکنیک اصلی bind را که ممکن است بیشتر اوقات از آنها استفاده کنید، روشن کنم.

bind به صورت دستی

قبلاً دیده اید که چگونه binding دستی با استفاده از متد ()bind انجام می شود. هر بار که لاراول وابستگی را درخواست می کند که با متد ()bind ثبت شده است، از سرویس Container می خواهد که نمونه جدیدی از وابستگی ثبت شده را ایجاد و برگرداند. در برخی موارد، این ممکن است ناکارآمد باشد، به خصوص زمانی که در حال ایجاد کلاس های منابع گران قیمت هستید.

در اینجا مثالی از استفاده از متد ()bind آورده شده است:

$this->app()->bind(PaymentService::class, function() {
    return new PaymentService('123456');
});

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

بیایید ببینیم که چگونه Singleton Binding با Binding دستی متفاوت است.

Singleton Binding 

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

در اینجا نمونه ای از استفاده از متد ()singleton آورده شده است:

$this->app()->singleton(PaymentService::class, function() {
    return new PaymentService('123456');
});

Instance Binding

Instance binding مانند singleton binding است، با این تفاوت که شما یک نمونه جدید از یک وابستگی ایجاد می کنید و به Laravel Service Container دستور می دهید که همیشه این نمونه را برگرداند.

در اینجا مثالی از استفاده از متد ()instance آورده شده است:

$paymentService = new PaymentService('123456');
$this->app()->instance(PaymentService::class, $paymentService);

تفاوت اصلی بین instance binding و دو شکل دیگر binding این است که شما همیشه یک نمونه جدید ایجاد می کنید و آن را به Service Container اضافه می کنید. در مورد اتصال دستی یا سینگلتون، تنها زمانی که برنامه یک نمونه از وابستگی را درخواست می‌کند، تابع Closure اجرا می‌شود و یک نمونه را برمی‌گرداند. آن را به عنوان یک اتصال زود هنگام در مقابل اتصال دیرهنگام در نظر بگیرید.

همانطور که اشاره کردم، راه های دیگری برای گسترش سرویس کانتینر و ثبت وابستگی ها وجود دارد. شما می توانید تمام جزئیات را در داکیومنت های لاراول بخوانید.

رفع وابستگی سرویس کانتینر

سرویس Container راه های مختلفی را برای نمونه سازی نمونه های وابستگی ارائه می دهد. من تعدادی از این راه‌ها را که معمولاً استفاده می‌کنم فهرست می‌کنم:

app(PaymentService::class);

شما به سادگی می توانید از متد ()app برای حل و بررسی وابستگی استفاده کنید.

app()->make(PaymentService::class);

روش دیگر برای نمونه سازی اشیا، استفاده از متد ()make تعریف شده بر روی شی ()app است.

resolve(PaymentService::class);

تابع ()resol یک تابع کمکی است که یک شی را بر اساس نام نگاشت ارسال شده به آن نمونه سازی می کند. در این مورد، شما از Service Container درخواست می‌کنید که نمونه‌ای از کلاس PaymentService را نمونه‌سازی کند.

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

نتیجه

Laravel یک چارچوب غنی PHP با موضوعات متعدد برای بحث و یادگیری است. در این مجموعه سعی می کنم تا حد امکان ویژگی ها و مفاهیم لاراول را پوشش دهم تا به شما در ساخت برنامه های بهتر با استفاده از این فریمورک کمک کنم.

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

#laravel#service_container#dependency_injection#تزیق_وابستگی#لاراول#سرویس_کانتینر
نظرات ارزشمند شما :

در حال دریافت...

مقاله های مشابه

در حال دریافت...