بررسی پشت صحنه لاراول برای درک عمیق تر

من تقریبا 6 سالی میشه که از Laravel تو پروژه های مختلف استفاده می کنم ولی میتونم بگم که شاید 3 4 سال اول فقط از قابلیت های مختلفی که میداد استفاده می کردم و بعدا که با django و سایر mvc های دیگه هم آشنا شدم دیگه Laravel جذابیت و منحصر به فرد بودن خودشو برام از دست داد، همه out of box authentication, session, database و … دارن و اینکه همیشه میگفتن “The PHP framework for Web Artisans” دیگه برام بی معنی بود.

تا اینکه یه روز PHPStorm نصب کردم و از رو کنجکاوی چنتا از کتابخونه هایی که از خود پیاده سازی Laravel بود رو دیدم و سعی در Code Review کردم. اوایل فهم بعضی مطالب سخت بود ولی به مرور و کم کم به طرز عجیبی از تکنیک ها و روش هایی که توی پیاده سازی قسمت های مختلف بود ذوق کردم.

حالا سعی میکنم تو این پست و چنتا پست مختلف دیگه توضیح بدم که خود Laravel چجوری کار میکنه و از چه روش ها و تکنیک هایی تو پشت صحنه از لحظه گرفتن یه request تا وقتی که response بر میگردونه استفاده می کنه. برای تکمیل و بهبود ادبیات فنی مطلب هم از برخی منابع استفاده و ترجمه میکنم که آخر هر پست لینک میکنم. تو این پست با مراحل مقدماتی بوت شدن خود چارچوب Laravel در Application Container آشنا میشیم.

حالا قبل اینکه وارد بحث فنی بشیم چنتا نکته مهم بگم:

  • نسخه ای که ازش توی توضیحات استفاده میکنم نسخه 7.28.0 هستش. (آخرین نسخه در زمان این پست)
  • توضیحات سعی میکنم طوری باشه که برای کسی هم که Laravel بلد نیست قابل فهم باشه (هر چند لازمه شاید چند بار مطالب خونده بشه). اگه هم موردی بود که متوجه نشدین توی کامنت ها بپرسین، با هم دیگه سعی میکنیم به جواب برسیم. مثل هر مطلب علمی در صورتی که ایراد فنی نیز داشت خوشحال میشم برطرف کنیم.
  • شاید برخی مطالب رو توی پاورقی آخر این پست و یا پست های بعدی توضیح میدم و لینکشون رو همین پست آپدیت میکنم.

ساختار کلی نحوه کار Laravel

اگه بخوایم اجرای یک برنامه ای که توی Laravel نوشته شده رو بررسی کنیم میتونیم اون رو به 3 قسمت اصلی تقسیم کنیم که این پست درباره بخش اول صحبت میکنیم فقط.

  • ایجاد یک Laravel Application: اینجا خود Laravel به همراه سرویس های مختلف مانند database, session و … اصطلاحا load میشه (فنی تر بگیم داخل app container قرار میگیرن که امروز این قسمت رو شروع میکنیم و پستهای بعدی کامل میکنیم).
  • پردازش request: اینجا درخواست کاربر گرفته میشه و عملیات routing انجام میشه (فنی تر بگیم http kernel ایجاد میشه).
  • ارسال response: اینجا هم که پاسخ کاربر تولید و ارسال میشه.

همونطور که بالا گفتیم، نقطه ابتدایی برنامه بوت شدن خود Laravel هستش که با ایجاد یک کلاس Application شروع میشه. حالا کجا ساخته میشه این Application؟ خب ببینیم!

نقطه شروع بوت شدن Laravel

اولین جایی که درخواست شما بعد از گذر از وب سرور فرستاده میشه فایل index.php داخل دایرکتوری /public هستش. حالا محتویات این فایل رو بررسی کنیم (کامنت ها پاک شده):

1234567891011121314151617<?php

define('LARAVEL_START', microtime(true));

require __DIR__.'/../vendor/autoload.php';

$app = require_once __DIR__.'/../bootstrap/app.php';

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

$response->send();

$kernel->terminate($request, $response);

خط اول یه متغیر ثابت (constant) تعریف میکنه که خب مثل یه تایمر میتونیم ازش استفاده کنیم و مثلا بعد از خط آخر همین فایل یه بار دیگه تایم رو بگیریم و نتیجه تفریق رو تو پایگاه داده یا فایل یا … بنویسیم و بفهمیم یه درخواست چقد طول کشیده. بیشتر جنبه benchmark داره و زیاد مهم نیست حالا. (این خط رو پاک کنید هم اتفاقی نمیافته چون تو کل Laravel ازش استفاده نشده :|)

خط بعدی هم میاد فایل autoload از composer رو لود میکنه. اینم یه اتفاق نرمال توی دنیای PHP هست، حتی تو پروژه ساده بدون Laravel هم که میشه از composer استفاده کنیم این خط رو مینویسیم. حالا خلاصه بگیم چیه این میشه که معمولا توی زبان های مختلف شما وقتی میخوای از یک کلاس توی کلاس یا به طور کلی جای دیگه استفاده کنی باید اون رو import یا include یا require و … کنی. ولی زبان PHP یه قابلیت داره به اسم autoloading که به شما امکان میده وقتی که یک کلاس در هر جای برنامه فراخوانی شد (مثلا با new)، شما بتونی اون رو بگیری و خودت هندل کنی (مثلا بگی برو این کلاس رو از فلان فولدر پیدا کن). حالا composer میاد این autoloading رو برا شما هندل میکنه (بعدا یه پست دیگه ریز توضیح میدم).

خب میریم سراغ خط اصلی برنامه که بحث اصلی امروز هست:

1$app = require_once __DIR__.'/../bootstrap/app.php';

تو این خط فایل bootstrap/app.php که تو دایرکتوری اصلی برنامه قرار داره رو لود میکنیم و چیزی که بر میگردونه رو توی متغیر $app قرار میدیم. حالا محتویات این فایل رو ببینیم:

12345678910111213141516171819202122<?php

$app = new Illuminate\Foundation\Application(
    $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);

$app->singleton(
    Illuminate\Contracts\Http\Kernel::class,
    App\Http\Kernel::class
);

$app->singleton(
    Illuminate\Contracts\Console\Kernel::class,
    App\Console\Kernel::class
);

$app->singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Exceptions\Handler::class
);

return $app;

تو این فایل به طور خلاصه 3 تا کار انجام میدیم؛ یک app از جنس Laravel می سازیم، بعدش چنتا binding و register داریم و نهایتا اون app ساخته شده رو برمیگردونیم. این پست فقط اون قسمت اول رو میبینیم و kernel رو میزارم پست بعدی.

توی خطای اول یه Application از جنس Illuminate\Foundation\Application میسازیم و یه پارامتر که نشون دهنده فولدر root پروژه هستش رو بهش پاس میدیم. این نمونه که ساختیم در واقع همون برنامه Laravel ما هستش. خیلی از اتفاقاتی جالبی که تو Laravel میفته از این کلاس شروع میشه و چیزای مختلف مثل ورژن، مسیرها و به ویژه Container تو این کلاسه.

برگردیم سراغ کد. حالا این کلاس Application که میخوایم بسازیم کجاس دقیقا؟ در واقع این کلاس Application ما داخل دایرکتوری پایین هستش.

1vendor\laravel\framework\src\Illuminate\Foundation\Application.php

حالا چرا و چجوری میشه که ما میگیم Illuminate\Foundation\Application بساز ولی از این مسیر کلاس رو برمیداره؟ یادتون باشه درباره composer و autoload صحبت کردیم و گفتیم که میتونیم از دایرکتوری مختلف کلاس رو ایجاد کنیم (البته منطق داره و الکی نیست ولی توضیحش از مجال این پست خارجه).

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

12345678910public function __construct($basePath = null)
{
    if ($basePath) {
        $this->setBasePath($basePath);
    }

    $this->registerBaseBindings();
    $this->registerBaseServiceProviders();
    $this->registerCoreContainerAliases();
}

ست کردن مسیرهای اصلی برنامه

تابع اولی که میبینیم setBasePath هستش که میاد همه مسیرهای نسبی برنامه (relative path) رو ست میکنه. داخل این تابع بریم خودش یه تابع دیگه bindPathsInContainer رو فراخوانی میکنه. این تابع میاد یه سری مسیرها رو توی Container قرار میده:

12345678protected function bindPathsInContainer()
{
    $this->instance('path', $this->path());
    $this->instance('path.base', $this->basePath());
    $this->instance('path.lang', $this->langPath());
    $this->instance('path.public', $this->publicPath());
    ...
}

یکم گنگ شد! الان اینجا چه اتفاقی افتاد؟

از اونجایی که اینجا درگیر instance شدیم و در ادامه توضیحات درگیر Container میشیم، خلاصه Container رو توضیح بدیم بعد ادامه بدیم. موضوع اینه که همونجور که از اسمش میاد یه جور ظرف یا نگه دارنده هستش که میاد اصطلاحا binding های ما (ترکیب abstract و concrete) رو نگه میداره. یعنی چی؟ یعنی اینجوری فک کنین که شما میتونین توی کد برنامه به Laravel بگین

وقتی که داخل برنامه ازت خواستن که X رو بهشون بدی (abstract)، یک پیاده سازی از X که من برای تو مشخص میکنم رو برگردون (concrete).

دوستان یکم با سواد میتونن متوجه بشن که این در واقع همون تعریف Dependency Injection یا تزریق وابستگی هستش. حالا شاید بفهمین که چرا میگم این Container فوق العاده مهم هستش. abstract هم چیزی فراتر از موجودیت انتزاعی نیست و میشه یک interface یا رشته یا عنوان ساده هم باشه! (توی نسخه های قبلی Laravel به جای abstract از کلمه contract استفاده میشد). concrete هم پیاده سازی از اون abstract رو میگن و میتونه یه کلاس باشه یا closure یا … ! این Container در واقع یکی از قدرتمندیهای Laravel نسبت به چارچوب های مشابهش هست که اونقدی مهم و جذاب هست که بعدا یه پست جدا براش میریم.

حالا کد بالا رو ریزتر بررسی کنیم. اونایی که Laravel کار کردن احتمالا از تابع public_path استفاده کردن که مسیر دایرکتوری public پروژه رو به ما برمیگردونه. پیاده سازی این تابع داخل فایل Helpers هستش و بهش نگاه کنیم در واقع میاد از تیکه کد پایین استفاده میکنه:

1app()->make('path.public')

استفاده از instance و make تو دو تا کد بالا در واقع مثل set و get توی مکانیزم Dependency Injection در Laravel هستش. ما تو تابع بالا از this->instance$ برای قرار دادن پیاده سازی مربوط به path.public توی Container که همون تابع ()this->publicPath$ میشه استفاده کردیم. و بعدا از تابع ()app()->make برای فراخوانی پیاده سازی اون از container استفاده می کنیم.

تا اینجا ما فقط اومدیم مسیرهای رو توی Container داخل Application قرار دادیم. حالا همینجا قبل ادامه برنامه بیایم محتویات Application رو با کد پایین و dd چاپ کنیم.

12345678public function __construct($basePath = null)
{
    if ($basePath) {
        $this->setBasePath($basePath);
    }
    dd($this);
    ...
}

خروجی که به ما میده تقریبا میشه این (برخی پارامترها حذف کردم تمیزتر دیده بشه):

1234567891011121314151617^ Illuminate\Foundation\Application {#2 ▼
  #basePath: "C:\xampp7.3\htdocs\Virgool"
  #hasBeenBootstrapped: false
  #booted: false
  #bindings: []
  #instances: array:9 [▼
    "path" => "C:\xampp7.3\htdocs\Virgool\app"
    "path.base" => "C:\xampp7.3\htdocs\Virgool"
    "path.lang" => "C:\xampp7.3\htdocs\Virgool\resources\lang"
    "path.config" => "C:\xampp7.3\htdocs\Virgool\config"
    "path.public" => "C:\xampp7.3\htdocs\Virgool\public"
    "path.storage" => "C:\xampp7.3\htdocs\Virgool\storage"
    "path.database" => "C:\xampp7.3\htdocs\Virgool\database"
    "path.resources" => "C:\xampp7.3\htdocs\Virgool\resources"
    "path.bootstrap" => "C:\xampp7.3\htdocs\Virgool\bootstrap"
  ]
}

دقت کنین همونطور که گفتیم فقط مسیرها ست شده و هنوز خود Laravel بالا نیومده (دقت کنین پارامتر booted برابر false هست).

رجیستر کردن خود برنامه و package-loader توی Container

بریم خط بعدی constructor که توش این کد رو داریم:

1$this->registerBaseBindings();

این تابع رو باز کنیم و خط به خط بررسیش کنیم:

123456789101112131415protected function registerBaseBindings()
{
    static::setInstance($this);

    $this->instance('app', $this);

    $this->instance(Container::class, $this);
    $this->singleton(Mix::class);

    $this->singleton(PackageManifest::class, function () {
        return new PackageManifest(
            new Filesystem, $this->basePath(), $this->getCachedPackagesPath()
        );
    });
}

خط اول میایم خود نمونه کلاس Application ساخته شده رو به صورت static توی خود Application ست میکنیم. چرا؟ چون قراره بعدا اونو به صورت الگوی طراحی Singleton فراخوانی کنیم. چرا singleton؟ چون فقط توی هر درخواست HTTP میخوایم فقط یه دونه application و container داشته باشیم.

این از این. خط بعدی میاد باز خود همین نمونه کلاس رو اینبار با نام app داخل Container میذاره.

خط بعدی هم باز خود نمونه کلاس رو این بار با نام Container::class میذاره داخل Container. اینجا یه چنتا نکته هست. اول اینکه در واقع باید توجه کنیم که همین Application ما در واقع Container ما هم هستش. چرا؟ چون در واقع Application خودش از کلاس Illuminate\Container\Container ارث بری کرده. نکته دوم هم اینه که بعد از PHP 5.5 وقتی که آخر هر کلاس ::class بنویسیم، میاد اسم کامل کلاس همراه با namespace رو براش به صورت رشته برمیگردونه. به عبارتی Container::class برابر با رشته Illuminate\Container\Container میشه.

خط بعدی Laravel Mix رو به صورت Singleton میزاره توی Container. کاری با این نداریم.

میرسیم نهایتا به خط آخر که قیافش خرابه ولی عملا اتفاق خاصی نمیافته. اینجا ما میایم package-loader رو میذاریم داخل container. این package-loader فعلا هیچ پکیج لود نمیکنه و فقط چنتا مسیر رو برمیداره و ست میکنه و یه نمونه از کلاس Filesystem هم برمیداره. واضحه دیگه، وقتی بعدا بخوایم package ها رو لود کنیم، مسیری که همه پکیج ها توشه رو لازم داره و باید با فایل سیستم کار کنه تا فایل ها رو بخونه و … .

حالا الان بیایم باز Application رو dd کنیم. خروجی میشه پایین (بعضی پارامترها برای تمیزی پاک کردم). عملا با قبل فرق خاصی نکرده و همچنان Application بوت نشده، فقط 2 تا نمونه دیگه به instance و 2 تا هم به bindings اضافه شده.

12345678910111213141516171819202122^ Illuminate\Foundation\Application {#2 ▼
  #basePath: "C:\xampp7.3\htdocs\Virgool"
  #hasBeenBootstrapped: false
  #booted: false
  #bindings: array:2 [▼
    "Illuminate\Foundation\Mix" => array:2 [▶]
    "Illuminate\Foundation\PackageManifest" => array:2 [▶]
  ]
  #instances: array:11 [▼
    "path" => "C:\xampp7.3\htdocs\Virgool\app"
    "path.base" => "C:\xampp7.3\htdocs\Virgool"
    "path.lang" => "C:\xampp7.3\htdocs\Virgool\resources\lang"
    "path.config" => "C:\xampp7.3\htdocs\Virgool\config"
    "path.public" => "C:\xampp7.3\htdocs\Virgool\public"
    "path.storage" => "C:\xampp7.3\htdocs\Virgool\storage"
    "path.database" => "C:\xampp7.3\htdocs\Virgool\database"
    "path.resources" => "C:\xampp7.3\htdocs\Virgool\resources"
    "path.bootstrap" => "C:\xampp7.3\htdocs\Virgool\bootstrap"
    "app" => Illuminate\Foundation\Application {#2}
    "Illuminate\Container\Container" => Illuminate\Foundation\Application {#2}
  ]
}

خب کارای مربوط به binding پایه ای که همون قرار دادن (register کردن) خود Application توی Container بود رو انجام دادیم. حالا ما بعدا هر جا از کدها که خواستیم میتونیم application رو به صورت global از داخل Container برداریم و ازش استفاده کنیم.

رجیستر کردن providerهای اصلی توی Container

برگردیم به خط بعدی تابع سازنده که این کد هست:

1$this->registerBaseServiceProviders();

تو این تابع میایم 3 تا سرویس پایه ای Laravel رو داخل container میذاریم.

123456protected function registerBaseServiceProviders()
{
    $this->register(new EventServiceProvider($this));
    $this->register(new LogServiceProvider($this));
    $this->register(new RoutingServiceProvider($this));
}

البته دقت کنین که این 3 تا سرویس پیاده سازیشون داخل مجموعه Illuminate هست و اون سرویس هایی نیستن که داخل app/providers قرار دارن (اینا رو بعدا قسمت دیگه برمیداریم و register می کنیم).

حالا خلاصه بگیم provider چی هست، معمولا Laravel برای بالا اومدن (boot) به اونا وابسته هست. همه provider میان به هر چی که برای اجرا لازم دارن به برنامه اضافه میکنن. برای مثال provider خود Laravel میاد middleware، event listener، error handler، session manager و … همه رو به برنامه اضافه میکنه. حالا پکیج های مختلفی که برای Laravel تو اینترنت هست هم همه معمولا یه provider دارن که توش میان کلاس های پیاده سازی شده خودشون رو توی Container اصطلاحا bind میکنن و یا Migration ها رو اضافه میکنن یا مجموعه ای از route به برنامه اضافه میکنن و … . معمولا وقتی هم میخوایم یه پکیج استفاده کنیم تو داکیومنت اون مینویسیه که Provider اون رو هم به لیست providerها توی config/app.php اضافه کنیم.

زیاد درگیر نشیم در همین حد که بدونیم هر پکیج یا کتابخونه (از جمله خود Laravel) برای بالا اومدن نیاز به provider دارن.

فقط یه نکته درباره این تابع this->register$ بگم که اگه پیاده سازی این تابع رو نگاه کنیم یه قسمت های جالبی داره:

1234567891011121314public function register($provider, $force = false)
{
    if (($registered = $this->getProvider($provider)) && ! $force) {
        return $registered;
    }
    ...
    $provider->register();
    ...
    $this->markAsRegistered($provider);
    if ($this->isBooted()) {
        $this->bootProvider($provider);
    }
    return $provider;
}

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

قسمت بعدی میاد تابع register داخل اون provider پاس داده شده رو اجرا میکنه و وضعیت اون رو با تابع markAsRegistered به حالت register شده تبدیل میکنیم. این register چیه؟ اونایی که با providerهای Laravel مثل AppServiceProvider کار کردن یا مستندات خوندن میدونن که معمولا هر provider دو تا تابع به اسم register و boot دارن. توی register اگه provider ما نیاز به binding ها یا register مختلف تو container داشته باشه اونا رو انجام میده.

حالا در ادامه بررسی میکنیم که آیا Application ما boot شده یا نه؟ اگه بوت شده باشه میایم تابع boot اون provider رو فراخوانی میکنیم. حالا این یعنی چی دقیقا؟ احتمالا توی مستندات Laravel دیدین که میگه اول همه توابع register همه provider ها فراخوانی میشه و بعدش توابع boot. این شرط هم همین رو بررسی میکنه. یعنی به طور کلی وقتی ما بخوایم یک provider رو داخل Container رجیستر کنیم، اول تابع register اون فراخوانی میشه و سپس در صورتی که Application اصلی ما بوت شده باشه، تابع boot اونم فراخوانی میشه. البته این شرط در این مرحله از برنامه که ما توش قرار داریم هیچوقت برقرار نمیشه (توجه کنین که فعلا داخل construct کلاس Application هستیم و هنوز بوت نشده).

حالا باز دوباره بیایم Application رو dd کنیم، خروجی پایین رو خواهیم داشت تقریبا (بعضی خروجیا پاک کردم). دقت کنین که با رجیستر کردن 3 تا provider به binding ما فقط چنتا چیز مثل log، router و events اضافه شده.

1234567891011121314151617181920212223242526272829303132^ Illuminate\Foundation\Application {#2 ▼
  #basePath: "C:\xampp7.3\htdocs\Virgool"
  #hasBeenBootstrapped: false
  #booted: false
  #bindings: array:11 [▼
    "Illuminate\Foundation\Mix" => array:2 [▶]
    "Illuminate\Foundation\PackageManifest" => array:2 [▶]
    "events" => array:2 [▶]
    "log" => array:2 [▶]
    "router" => array:2 [▶]
    "url" => array:2 [▶]
    "redirect" => array:2 [▶]
    "Psr\Http\Message\ServerRequestInterface" => array:2 [▶]
    "Psr\Http\Message\ResponseInterface" => array:2 [▶]
    "Illuminate\Contracts\Routing\ResponseFactory" => array:2 [▶]
    "Illuminate\Routing\Contracts\ControllerDispatcher" => array:2 [▶]
  ]
  #instances: array:11 [▼
    "path" => "C:\xampp7.3\htdocs\Virgool\app"
    "path.base" => "C:\xampp7.3\htdocs\Virgool"
    "path.lang" => "C:\xampp7.3\htdocs\Virgool\resources\lang"
    "path.config" => "C:\xampp7.3\htdocs\Virgool\config"
    "path.public" => "C:\xampp7.3\htdocs\Virgool\public"
    "path.storage" => "C:\xampp7.3\htdocs\Virgool\storage"
    "path.database" => "C:\xampp7.3\htdocs\Virgool\database"
    "path.resources" => "C:\xampp7.3\htdocs\Virgool\resources"
    "path.bootstrap" => "C:\xampp7.3\htdocs\Virgool\bootstrap"
    "app" => Illuminate\Foundation\Application {#2}
    "Illuminate\Container\Container" => Illuminate\Foundation\Application {#2}
  ]
  #aliases: []
}

اینجا دقت کنین که همونطور که بالا گفتیم فقط تابع register داخل اون providerها فراخوانی شده و یه سری binding ساده اضافه شده و هنوز هیچ عملیاتی انجام نشده. یعنی وقتی میبینیم که router رو داریم توی bindings، این به معنی نیست که router اومده همه route های ما رو خونده و کاراشونو اوکی کرده.

این یکی از ویژگی های خوب Laravel هستش. یعنی کلاس های مختلف رو توی Container خودش نگه میداره و تا وقتی که به اونا نیاز نداشته باشه نمیاد ازشون نمونه بسازه. همین باعث میشه اگه شما کتابخونه یا پکیجی به پروژتون اضافه کنین ولی ازش نمونه نسازین، تاثیر زیادی روی performance پروژتون نخواهد داشت (فقط به خاطر فراخوانی تابع register مربوط به provider اون پکیج یکم سربار میاد).

ست کردن کلاس های اصلی Laravel

برگردیم خط آخر تابع سازنده کلاس Application. خط قبلی ما اومدیم سرویس های اصلی Laravel رو رجیستر کردیم ولی Laravel کلی سرویس مثل auth، session، view و … داره اونا کی میان؟ این سرویس ها توسط این خط با تابع registerCoreContainerAliases به Container اضافه میشن. حالا شاید جزئیات این تابع نگاه کنیم از کلمه Alias یا اسم مستعار استفاده کرده. فرقش با register که قبلا استفاده میکردیم چیه؟ بعضا چنتا کلاس یا interface مختلف شاید بخوایم فقط به یک پیاده سازی bind بشن مثلا برای Application یا Container اسم مستعار app رو میذاریم. و وقتی اون ها رو خواستیم از container برداریم، Laravel خودش اول اسم مستعار رو از داخل متغیر aliases$ که همون مجموعه اسم مستعارها هست برمیداره و میره خودش اون رو resolve میکنه.

حالا باز محتوای Application رو چاپ کنیم، اینا رو میبینیم:

123456789101112131415161718192021222324252627^ Illuminate\Foundation\Application {#2 ▼
  #basePath: "C:\xampp7.3\htdocs\Virgool"
  #hasBeenBootstrapped: false
  #booted: false
  #bindings: array:11  [▶]
  #instances: array:11 [▶]
  #aliases: array:73 [▼
    "Illuminate\Foundation\Application" => "app"
    "Illuminate\Contracts\Container\Container" => "app"
    "Illuminate\Contracts\Foundation\Application" => "app"
    "Psr\Container\ContainerInterface" => "app"
    "Illuminate\Auth\AuthManager" => "auth"
    "Illuminate\Contracts\Auth\Factory" => "auth"
    "Illuminate\Contracts\Auth\Guard" => "auth.driver"
    ...
  ]
  #abstractAliases: array:38 [▼
    "app" => array:4 [▼
      0 => "Illuminate\Foundation\Application"
      1 => "Illuminate\Contracts\Container\Container"
      2 => "Illuminate\Contracts\Foundation\Application"
      3 => "Psr\Container\ContainerInterface"
    ]
    "auth" => array:2 [▶]
    ...
  ]
}

باز میگم توجه کنیم که ما تا الان فقط یه سری binding و alias به Application اضافه کردیم و فعلا هیچ اتفاقی اعم از ایجاد پردازش request، اتصال پایگاه داده، خوندن routeها و … انجام نشده. تا الان ما فقط مقدمات بوت شدن Laravel رو فقط انجام دادیم. بخش های بعدی اون رو بررسی میکنیم.


خب تا همینجا برای امروز کافیه. این پست رو خلاصه کنم میتونیم بگیم که:

  • با ساختار کلی چرخه اجرایی معماری Laravel آشنا شدیم.
  • مراحل مقدماتی بوت شدن خود چارچوب Laravel رو دیدیم.
  • به طور خلاصه نحوه کار Container در Laravel که برای Dependency Injection استفاده میشه بررسی کردیم.

پست بعدی درباره HTTP Kernel صحبت میکنیم. Stay Tuned.


پست بعدی (Framework Boot) ⇐

منابع مطالعه بیشتر:

Laravel Doc: Service ContainerService Providers Package Development

Laravel Behind the Scenes: Lifecycle – Container

DI in Laravel : Dependency Injection in LaravelLaravel&amp;#x27;s Dependency Injection Container in Depth

PHP Autoloading: Autoloading classes, interfaces or traitsComposer Autoloading

نویسنده مطلب: محسن نظری

منبع مطلب

به فکر سرمایه‌گذاری هستی؟

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

ثبت نام و دریافت جایزه
نظر شما درباره این مطلب

آدرس ایمیل شما منتشر نخواهد شد.