আপনি এইমাত্র একটি নতুন লারাভেল অ্যাপ্লিকেশন ইনস্টল করেছেন, এটি বুট আপ করেছেন এবং স্বাগত পৃষ্ঠা পেয়েছেন। অন্য সবার মতো, আপনি এটি কীভাবে রেন্ডার করা হয়েছে তা দেখার চেষ্টা করেন, তাই আপনি web.php
ফাইলটিতে প্রবেশ করুন এবং এই কোডটির মুখোমুখি হন:
<?php use Illuminate\Support\Facades\Route; Route::get('/', function () { return view('welcome'); });
এটা স্পষ্ট যে আমরা কীভাবে স্বাগত দৃশ্যটি পেয়েছি, কিন্তু আপনি লারাভেলের রাউটার কীভাবে কাজ করে সে সম্পর্কে আগ্রহী, তাই আপনি কোডটিতে ডুব দেওয়ার সিদ্ধান্ত নেন। প্রাথমিক অনুমান হল: একটি Route
ক্লাস আছে যার উপর আমরা একটি স্ট্যাটিক মেথড get()
কল করছি। যাইহোক, এটি ক্লিক করার পরে, সেখানে কোন get()
পদ্ধতি নেই। তাহলে, কি ধরনের অন্ধকার জাদু ঘটছে? এর রহস্যময় করা যাক!
দয়া করে মনে রাখবেন যে আমি বেশিরভাগ PHPDocs ছিনিয়ে নিয়েছি এবং কেবল সরলতার জন্য প্রকারগুলিকে ইনলাইন করেছি, "..." আরও কোড বোঝায়।
আমি দৃঢ়ভাবে আপনার IDE খুলতে এবং কোনো বিভ্রান্তি এড়াতে কোডটি অনুসরণ করার পরামর্শ দিচ্ছি।
আমাদের উদাহরণ অনুসরণ করে, আসুন Route
ক্লাসটি অন্বেষণ করি।
<?php namespace Illuminate\Support\Facades; class Route extends Facade { // ... protected static function getFacadeAccessor(): string { return 'router'; } }
এখানে খুব বেশি কিছু নেই, শুধু getFacadeAccessor()
পদ্ধতি যা স্ট্রিং router
রিটার্ন করে। এটি মাথায় রেখে, আসুন অভিভাবক শ্রেণিতে চলে যাই।
<?php namespace Illuminate\Support\Facades; use RuntimeException; // ... abstract class Facade { // ... public static function __callStatic(string $method, array $args): mixed { $instance = static::getFacadeRoot(); if (! $instance) { throw new RuntimeException('A facade root has not been set.'); } return $instance->$method(...$args); } }
অভিভাবক শ্রেণীর মধ্যে, প্রচুর পদ্ধতি রয়েছে, যদিও একটি get()
পদ্ধতি নেই। কিন্তু একটি আকর্ষণীয় একটি আছে, __callStatic()
পদ্ধতি। এটি একটি জাদু পদ্ধতি, যখনই আমাদের ক্ষেত্রে get()
এর মতো একটি অনির্ধারিত স্ট্যাটিক পদ্ধতি বলা হয়। অতএব, আমাদের কল __callStatic('get', ['/', Closure()])
আমরা যা পাস করেছি তা উপস্থাপন করে যখন আমরা Route::get()
, রুট /
এবং একটি Closure()
যা স্বাগত ভিউ প্রদান করে।
যখন __callStatic()
ট্রিগার হয়, এটি প্রথমে getFacadeRoot()
কল করে একটি ভেরিয়েবল $instance
সেট করার চেষ্টা করে, $instance
প্রকৃত ক্লাসটি ধারণ করে যেখানে কলটি ফরোয়ার্ড করা উচিত, আসুন একটু ঘনিষ্ঠভাবে দেখা যাক, এটি একটু পরেই বোঝা যাবে
// Facade.php public static function getFacadeRoot() { return static::resolveFacadeInstance(static::getFacadeAccessor()); }
আরে, দেখুন এটি চাইল্ড ক্লাস Route
getFacadeAccessor()
যা আমরা জানি স্ট্রিং router
ফেরত দিয়েছে। এই router
স্ট্রিংটি তারপর resolveFacadeInstance()
এ পাস করা হয়, যা এটিকে একটি ক্লাসে সমাধান করার চেষ্টা করে, এক ধরণের ম্যাপিং যা বলে "এই স্ট্রিংটি কোন শ্রেণীর প্রতিনিধিত্ব করে?" দেখা যাক।
// Facade.php protected static function resolveFacadeInstance($name) { if (isset(static::$resolvedInstance[$name])) { return static::$resolvedInstance[$name]; } if (static::$app) { if (static::$cached) { return static::$resolvedInstance[$name] = static::$app[$name]; } return static::$app[$name]; } }
এটি প্রথমে পরীক্ষা করে যে একটি স্ট্যাটিক অ্যারে, $resolvedInstance
, প্রদত্ত $name
(যা আবার router
) সহ একটি মান সেট আছে কিনা। যদি এটি একটি মিল খুঁজে পায়, এটি শুধুমাত্র সেই মানটি ফেরত দেয়। পারফরম্যান্সকে কিছুটা অপ্টিমাইজ করার জন্য এটি লারাভেল ক্যাশিং। এই ক্যাশিং একটি একক অনুরোধের মধ্যে ঘটে। যদি এই পদ্ধতিটি একই অনুরোধের মধ্যে একই যুক্তি সহ একাধিকবার কল করা হয় তবে এটি ক্যাশে মান ব্যবহার করে। ধরা যাক এটি প্রাথমিক কল এবং এগিয়ে যান।
এটি তারপরে $app
সেট করা আছে কিনা তা পরীক্ষা করে এবং $app
হল অ্যাপ্লিকেশন কন্টেইনারের একটি উদাহরণ
// Facade.php protected static \Illuminate\Contracts\Foundation\Application $app;
আপনি যদি একটি অ্যাপ্লিকেশন কন্টেইনার কি তা নিয়ে কৌতূহলী হন তবে এটিকে একটি বাক্স হিসাবে ভাবুন যেখানে আপনার ক্লাসগুলি সংরক্ষণ করা হয়৷ যখন আপনার সেই ক্লাসগুলির প্রয়োজন হয়, আপনি কেবল সেই বাক্সে পৌঁছান। কখনও কখনও, এই ধারকটি কিছুটা জাদু করে। এমনকি যদি বাক্সটি খালি থাকে, এবং আপনি একটি ক্লাস নিতে পৌঁছান, এটি আপনার জন্য এটি পাবে। এটি অন্য নিবন্ধের জন্য একটি বিষয়.
এখন, আপনি ভাবতে পারেন, " $app
কখন সেট করা হয়?", কারণ এটি হওয়া দরকার, অন্যথায়, আমাদের $instance
থাকবে না। এই অ্যাপ্লিকেশন ধারকটি আমাদের অ্যাপ্লিকেশনের বুটস্ট্র্যাপিং প্রক্রিয়া চলাকালীন সেট করা হয়। আসুন একটি দ্রুত দেখে নেওয়া যাক \Illuminate\Foundation\Http\Kernel
ক্লাস:
<?php namespace Illuminate\Foundation\Http; use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Support\Facades\Facade; use Illuminate\Contracts\Http\Kernel as KernelContract; // ... class Kernel implements KernelContract { // ... protected $app; protected $bootstrappers = [ \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class, \Illuminate\Foundation\Bootstrap\LoadConfiguration::class, \Illuminate\Foundation\Bootstrap\HandleExceptions::class, \Illuminate\Foundation\Bootstrap\RegisterFacades::class, // <- this guy \Illuminate\Foundation\Bootstrap\RegisterProviders::class, \Illuminate\Foundation\Bootstrap\BootProviders::class, ]; public function bootstrap(): void { if (! $this->app->hasBeenBootstrapped()) { $this->app->bootstrapWith($this->bootstrappers()); } } }
যখন একটি অনুরোধ আসে, এটি রাউটারে পাঠানো হয়। তার ঠিক আগে, bootstrap()
পদ্ধতিটি চালু করা হয়, যা অ্যাপ্লিকেশন প্রস্তুত করতে bootstrappers
অ্যারে ব্যবহার করে। আপনি যদি \Illuminate\Foundation\Application
ক্লাসে bootstrapWith()
পদ্ধতিটি অন্বেষণ করেন, তাহলে এটি এই বুটস্ট্র্যাপারদের মাধ্যমে পুনরাবৃত্তি করে, তাদের bootstrap()
পদ্ধতি বলে।
সরলতার জন্য, আসুন শুধুমাত্র \Illuminate\Foundation\Bootstrap\RegisterFacades
এর উপর ফোকাস করা যাক, যা আমরা জানি যে একটি bootstrap()
পদ্ধতি রয়েছে যা bootstrapWith()
এ ব্যবহার করা হবে।
<?php namespace Illuminate\Foundation\Bootstrap; use Illuminate\Contracts\Foundation\Application; use Illuminate\Foundation\AliasLoader; use Illuminate\Foundation\PackageManifest; use Illuminate\Support\Facades\Facade; class RegisterFacades { // ... public function bootstrap(Application $app): void { Facade::clearResolvedInstances(); Facade::setFacadeApplication($app); // Interested here AliasLoader::getInstance(array_merge( $app->make('config')->get('app.aliases', []), $app->make(PackageManifest::class)->aliases() ))->register(); } }
এবং এটি আছে, আমরা স্থির পদ্ধতি setFacadeApplication().
ব্যবহার করে Facade
ক্লাসে অ্যাপ্লিকেশন কন্টেইনার সেট করছি।
// RegisterFacades.php public static function setFacadeApplication($app) { static::$app = $app; }
দেখুন, আমরা $app
প্রপার্টি বরাদ্দ করি যা আমরা resolveFacadeInstance()
এর মধ্যে পরীক্ষা করছি। এই প্রশ্নের উত্তর দেয়; চল অবিরত রাখি।
// Facade.php protected static function resolveFacadeInstance($name) { if (isset(static::$resolvedInstance[$name])) { return static::$resolvedInstance[$name]; } if (static::$app) { if (static::$cached) { return static::$resolvedInstance[$name] = static::$app[$name]; } return static::$app[$name]; } }
আমরা নিশ্চিত করেছি যে অ্যাপ্লিকেশন বুটস্ট্র্যাপিংয়ের সময় $app
সেট করা আছে। পরবর্তী ধাপ হল $cached
যাচাই করে সমাধান করা উদাহরণটি ক্যাশ করা উচিত কিনা তা পরীক্ষা করা, যা ডিফল্ট সত্য। অবশেষে, আমরা অ্যাপ্লিকেশন কন্টেইনার থেকে উদাহরণটি পুনরুদ্ধার করি, আমাদের ক্ষেত্রে, এটি স্ট্রিং router
আবদ্ধ যেকোন ক্লাস প্রদান করতে static::$app['router']
জিজ্ঞাসা করার মতো।
এখন, আপনি ভাবতে পারেন কেন আমরা অ্যারের মতো $app
অ্যাক্সেস করি যদিও এটি অ্যাপ্লিকেশন কন্টেইনারের একটি উদাহরণ, তাই একটি বস্তু । ওয়েল, আপনি ঠিক! যাইহোক, অ্যাপ্লিকেশন কন্টেইনার ArrayAccess
নামক একটি PHP ইন্টারফেস প্রয়োগ করে, যা অ্যারের মতো অ্যাক্সেসের অনুমতি দেয়। এই সত্যটি নিশ্চিত করার জন্য আমরা এটি দেখে নিতে পারি:
<?php namespace Illuminate\Container; use ArrayAccess; // <- this guy use Illuminate\Contracts\Container\Container as ContainerContract; class Container implements ArrayAccess, ContainerContract { // ... }
সুতরাং, resolveFacadeInstance()
প্রকৃতপক্ষে router
স্ট্রিং-এ আবদ্ধ একটি উদাহরণ প্রদান করে, বিশেষ করে, \Illuminate\Routing\Router
। আমি কিভাবে জানলাম? Route
সম্মুখভাগটি একবার দেখুন; প্রায়শই, আপনি একটি PHPDoc @see
ইঙ্গিত পাবেন যে এই মুখোশটি কী লুকিয়ে রাখে বা আরও স্পষ্টভাবে বলতে গেলে, আমাদের পদ্ধতির কলগুলি প্রক্সি করা হবে।
এখন, আমাদের __callStatic
পদ্ধতিতে ফিরে যান।
<?php namespace Illuminate\Support\Facades; use RuntimeException; // ... abstract class Facade { // ... public static function __callStatic(string $method, array $args): mixed { $instance = static::getFacadeRoot(); if (! $instance) { throw new RuntimeException('A facade root has not been set.'); } return $instance->$method(...$args); } }
আমাদের কাছে $instance
আছে, \Illuminate\Routing\Router
ক্লাসের একটি অবজেক্ট। এটি সেট করা আছে কিনা তা আমরা পরীক্ষা করি (যা আমাদের ক্ষেত্রে নিশ্চিত), এবং আমরা সরাসরি এটিতে পদ্ধতিটি আহ্বান করি। সুতরাং, আমরা সঙ্গে শেষ.
// Facade.php return $instance->get('/', Closure());
এবং এখন, আপনি \Illuminate\Routing\Router
ক্লাসের মধ্যে get()
বিদ্যমান রয়েছে তা নিশ্চিত করতে পারেন।
<?php namespace Illuminate\Routing; use Illuminate\Routing\Route; use Illuminate\Contracts\Routing\BindingRegistrar; use Illuminate\Contracts\Routing\Registrar as RegistrarContract; // ... class Router implements BindingRegistrar, RegistrarContract { // ... public function get(string $uri, array|string|callable|null $action = null): Route { return $this->addRoute(['GET', 'HEAD'], $uri, $action); } }
যে এটা গুটিয়ে! শেষ পর্যন্ত যে কঠিন ছিল না? রিক্যাপ করার জন্য, একটি সম্মুখভাগ একটি স্ট্রিং প্রদান করে যা কন্টেইনারে আবদ্ধ। উদাহরণস্বরূপ, hello-world
HelloWorld
ক্লাসের সাথে আবদ্ধ হতে পারে। যখন আমরা স্থিরভাবে একটি সম্মুখভাগে একটি অনির্ধারিত পদ্ধতি চালু করি, HelloWorldFacade
উদাহরণস্বরূপ, __callStatic()
ধাপে ধাপে।
এটি তার getFacadeAccessor()
পদ্ধতিতে নিবন্ধিত স্ট্রিংটিকে কন্টেইনারের মধ্যে আবদ্ধ যা কিছুর সাথে সমাধান করে এবং সেই পুনরুদ্ধার করা উদাহরণে আমাদের কলকে প্রক্সি করে। এইভাবে, আমরা (new HelloWorld())->method()
দিয়ে শেষ করি। এটাই এর সারমর্ম! এখনও আপনার জন্য ক্লিক করেননি? তাহলে আমাদের সম্মুখভাগ তৈরি করা যাক!
বলুন আমাদের এই ক্লাস আছে:
<?php namespace App\Http\Controllers; class HelloWorld { public function greet(): string { return "Hello, World!"; } }
লক্ষ্য হল HelloWorld::greet()
আহ্বান করা। এটি করার জন্য, আমরা আমাদের ক্লাসকে অ্যাপ্লিকেশন কন্টেইনারে আবদ্ধ করব। প্রথমে, AppServiceProvider
এ নেভিগেট করুন।
<?php namespace App\Providers; use App\Http\Controllers; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function register(): void { $this->app->bind('hello-world', function ($app) { return new HelloWorld; }); } // ... }
এখন, যখনই আমরা আমাদের অ্যাপ্লিকেশন কন্টেইনার (বা বাক্স, যেমনটি আমি আগেই বলেছি) থেকে hello-world
অনুরোধ করি, এটি HelloWorld
এর একটি উদাহরণ প্রদান করে। কি বাকী আছে? শুধু একটি সম্মুখভাগ তৈরি করুন যা স্ট্রিং hello-world
রিটার্ন করে।
<?php namespace App\Http\Facades; use Illuminate\Support\Facades\Facade; class HelloWorldFacade extends Facade { protected static function getFacadeAccessor() { return 'hello-world'; } }
এই জায়গায়, আমরা এটি ব্যবহার করার জন্য প্রস্তুত. এর আমাদের web.php.
<?php use App\Http\Facades; use Illuminate\Support\Facades\Route; Route::get('/', function () { return HelloWorldFacade::greet(); // Hello, World! });
আমরা জানি যে greet()
HelloWorldFacade
সম্মুখভাগে বিদ্যমান নেই, __callStatic()
ট্রিগার হয়েছে। এটি অ্যাপ্লিকেশন কন্টেইনার থেকে একটি স্ট্রিং (আমাদের ক্ষেত্রে hello-world
) দ্বারা উপস্থাপিত একটি শ্রেণিকে টানে। এবং আমরা ইতিমধ্যেই AppServiceProvider
এ এই বাঁধাই তৈরি করেছি; যখনই কেউ hello-world
অনুরোধ করে তখন আমরা এটিকে HelloWorld
এর একটি উদাহরণ প্রদান করার নির্দেশ দিয়েছি। ফলস্বরূপ, যে কোনো কল, যেমন greet()
, HelloWorld
এর সেই পুনরুদ্ধার করা উদাহরণে কাজ করবে। এবং এটাই।
অভিনন্দন! আপনি আপনার নিজের সম্মুখভাগ তৈরি করেছেন!
এখন যেহেতু আপনার সম্মুখভাগ সম্পর্কে ভালো ধারণা আছে, উন্মোচন করার জন্য আরও একটি যাদু কৌশল রয়েছে। কল্পনা করুন HelloWorld::greet()
একটি ফ্যাসাড তৈরি না করেই, রিয়েল-টাইম ফ্যাকেড ব্যবহার করে কল করতে।
চল একটু দেখি:
<?php use Facades\App\Http\Controllers; // Notice the prefix use Illuminate\Support\Facades\Route; Route::get('/', function () { return HelloWorld::greet(); // Hello, World! });
Facades
এর সাথে কন্ট্রোলারের নামস্থানের উপসর্গ দিয়ে, আমরা আগের মত একই ফলাফল অর্জন করি। কিন্তু, এটা নিশ্চিত যে HelloWorld
কন্ট্রোলারের greet()
নামে কোনো স্ট্যাটিক পদ্ধতি নেই! এবং Facades\App\Http\Controllers\HelloWorld
এমনকি কোথা থেকে আসে? আমি বুঝতে পারি এটি কিছু জাদুবিদ্যার মতো মনে হতে পারে, কিন্তু একবার আপনি এটি উপলব্ধি করলে, এটি বেশ সহজ।
আসুন $app:
সেট করার জন্য দায়ী ক্লাস, আমরা আগে চেক করেছিলাম \Illuminate\Foundation\Bootstrap\RegisterFacades
কে ঘনিষ্ঠভাবে দেখে নেওয়া যাক:
<?php namespace Illuminate\Foundation\Bootstrap; use Illuminate\Contracts\Foundation\Application; use Illuminate\Foundation\AliasLoader; use Illuminate\Foundation\PackageManifest; use Illuminate\Support\Facades\Facade; class RegisterFacades { public function bootstrap(Application $app): void { Facade::clearResolvedInstances(); Facade::setFacadeApplication($app); AliasLoader::getInstance(array_merge( $app->make('config')->get('app.aliases', []), $app->make(PackageManifest::class)->aliases() ))->register(); // Interested here } }
আপনি একেবারে শেষে দেখতে পারেন যে register()
পদ্ধতিটি চালু করা হয়েছে। আসুন ভিতরে উঁকি দেওয়া যাক:
<?php namespace Illuminate\Foundation; class AliasLoader { // ... protected $registered = false; public function register(): void { if (! $this->registered) { $this->prependToLoaderStack(); $this->registered = true; } } }
$registered
ভেরিয়েবল প্রাথমিকভাবে false
সেট করা হয়েছে। অতএব, আমরা if
স্টেটমেন্ট লিখি এবং prependToLoaderStack()
পদ্ধতিতে কল করি। এখন, এর বাস্তবায়ন অন্বেষণ করা যাক.
// AliasLoader.php protected function prependToLoaderStack(): void { spl_autoload_register([$this, 'load'], true, true); }
জাদু ঘটবে এই যেখানে! লারাভেল spl_autoload_register()
ফাংশনকে কল করছে, একটি অন্তর্নির্মিত PHP ফাংশন যা একটি অনির্ধারিত ক্লাস অ্যাক্সেস করার চেষ্টা করার সময় ট্রিগার করে। এটি এই ধরনের পরিস্থিতিতে কার্যকর করার যুক্তি সংজ্ঞায়িত করে। এই ক্ষেত্রে, লারাভেল একটি অনির্ধারিত কলের সম্মুখীন হওয়ার সময় load()
পদ্ধতি ব্যবহার করতে বেছে নেয়।
অতিরিক্তভাবে, spl_autoload_register()
স্বয়ংক্রিয়ভাবে অনির্ধারিত ক্লাসের নাম যে কোন পদ্ধতি বা ফাংশনে কল করে।
আসুন load()
পদ্ধতিটি অন্বেষণ করি; এটা মূল হতে হবে.
// AliasLoader.php public function load($alias) { if (static::$facadeNamespace && str_starts_with($alias, static::$facadeNamespace)) { $this->loadFacade($alias); return true; } if (isset($this->aliases[$alias])) { return class_alias($this->aliases[$alias], $alias); } }
$facadeNamespace
সেট করা আছে কিনা তা আমরা পরীক্ষা করি এবং আমাদের ক্ষেত্রে যে ক্লাস পাস করা হোক না কেন, Facades\App\Http\Controllers\HelloWorld
$facadeNamespace
এ যা সেট করা আছে তা দিয়ে শুরু হয়।
যুক্তি পরীক্ষা করে যে $facadeNamespace
সেট করা আছে কিনা এবং পাস করা ক্লাস, আমাদের ক্ষেত্রে Facades\App\Http\Controllers\HelloWorld
(যা অনির্ধারিত), $facadeNamespace.
// AliasLoader.php protected static $facadeNamespace = 'Facades\\';
যেহেতু আমরা আমাদের কন্ট্রোলারের নামস্থান Facades
এর সাথে উপসর্গ করেছি, শর্তটি সন্তুষ্ট করে, আমরা loadFacade()
// AliasLoader.php protected function loadFacade($alias) { require $this->ensureFacadeExists($alias); }
এখানে, পদ্ধতির জন্য ensureFacadeExists()
থেকে যে পাথ ফেরত দেওয়া হয় তা প্রয়োজন। সুতরাং, পরবর্তী পদক্ষেপটি হল এর বাস্তবায়নের দিকে নজর দেওয়া।
// AliasLoader.php protected function ensureFacadeExists($alias) { if (is_file($path = storage_path('framework/cache/facade-'.sha1($alias).'.php'))) { return $path; } file_put_contents($path, $this->formatFacadeStub( $alias, file_get_contents(__DIR__.'/stubs/facade.stub') )); return $path; }
প্রথমে framework/cache/facade-'.sha1($alias).'.php'
নামের একটি ফাইল আছে কিনা তা নিশ্চিত করার জন্য একটি চেক করা হয়। আমাদের ক্ষেত্রে, এই ফাইলটি উপস্থিত নয়, পরবর্তী ধাপটি ট্রিগার করে: file_put_contents()
। এই ফাংশনটি একটি ফাইল তৈরি করে এবং নির্দিষ্ট $path
এ সংরক্ষণ করে। ফাইলের বিষয়বস্তু formatFacadeStub()
দ্বারা তৈরি করা হয়, যা, এর নামের দ্বারা বিচার করে, একটি স্টাব থেকে একটি সম্মুখভাগ তৈরি করে। আপনি facade.stub
পরিদর্শন করলে, আপনি নিম্নলিখিতগুলি পাবেন:
<?php namespace DummyNamespace; use Illuminate\Support\Facades\Facade; /** * @see \DummyTarget */ class DummyClass extends Facade { /** * Get the registered name of the component. */ protected static function getFacadeAccessor(): string { return 'DummyTarget'; } }
পরিচিত মনে হচ্ছে? যে মূলত আমরা ম্যানুয়ালি কি কি. এখন, formatFacadeStub()
Facades\\
উপসর্গ অপসারণের পরে আমাদের অনির্ধারিত ক্লাসের সাথে ডামি সামগ্রী প্রতিস্থাপন করে। এই আপডেট করা সম্মুখভাগ তারপর সংরক্ষণ করা হয়. ফলস্বরূপ, যখন loadFacade()
ফাইলটির প্রয়োজন হয়, তখন এটি সঠিকভাবে করে এবং এটি শেষ পর্যন্ত নিম্নলিখিত ফাইলটির প্রয়োজন হয়:
<?php namespace Facades\App\Http\Controllers; use Illuminate\Support\Facades\Facade; /** * @see \App\Http\Controllers\HelloWorld */ class HelloWorld extends Facade { /** * Get the registered name of the component. */ protected static function getFacadeAccessor(): string { return 'App\Http\Controllers\HelloWorld'; } }
এবং এখন, স্বাভাবিক প্রবাহে, আমরা অ্যাপ্লিকেশন কন্টেইনারকে App\Http\Controllers\HelloWorld
স্ট্রিং-এর সাথে আবদ্ধ যেকোন ইন্সট্যান্স ফেরত দিতে বলি। আপনি হয়তো ভাবছেন, আমরা এই স্ট্রিংটিকে কিছুতেই আবদ্ধ করিনি, এমনকি আমরা আমাদের AppServiceProvider
স্পর্শও করিনি। কিন্তু আমি খুব শুরুতে আবেদন ধারক সম্পর্কে কি উল্লেখ করেছি মনে আছে?
এমনকি যদি বাক্সটি খালি থাকে তবে এটি উদাহরণটি ফিরিয়ে দেবে , তবে একটি শর্তের সাথে, ক্লাসের একটি কনস্ট্রাক্টর থাকতে হবে না। অন্যথায়, এটি আপনার জন্য এটি কীভাবে তৈরি করা যায় তা জানবে না। আমাদের ক্ষেত্রে, আমাদের HelloWorld
ক্লাস নির্মাণের জন্য কোনো আর্গুমেন্টের প্রয়োজন নেই। সুতরাং, ধারক এটি সমাধান করে, এটি ফেরত দেয় এবং সমস্ত কল এটির সাথে প্রক্সি করা হয়।
রিক্যাপিং রিয়েল-টাইম ফ্যাকাডস: আমরা আমাদের ক্লাসের সাথে Facades
উপসর্গ দিয়েছি। অ্যাপ্লিকেশন বুটস্ট্র্যাপিংয়ের সময়, লারাভেল spl_autoload_register()
নিবন্ধন করে, যা আমরা যখন অনির্ধারিত ক্লাস কল করি তখন ট্রিগার করে। এটি অবশেষে load()
পদ্ধতির দিকে নিয়ে যায়। load()
ভিতরে, আমরা পরীক্ষা করি যে বর্তমান অনির্ধারিত শ্রেণীটি Facades
এর সাথে উপসর্গযুক্ত কিনা। এটি মেলে, তাই লারাভেল এটি লোড করার চেষ্টা করে।
যেহেতু সম্মুখভাগটি বিদ্যমান নেই, এটি একটি স্টাব থেকে এটি তৈরি করে এবং তারপর ফাইলটির প্রয়োজন হয়। আর ভয়েলা! আপনি একটি নিয়মিত সম্মুখভাগ পেয়েছেন, কিন্তু এটি একটি উড়তে তৈরি করা হয়েছে। বেশ শান্ত, হাহ?
এটা এতদূর করার জন্য অভিনন্দন! আমি বুঝতে পারি এটি কিছুটা অপ্রতিরোধ্য হতে পারে। বিনা দ্বিধায় ফিরে যান এবং আপনার জন্য ক্লিক করা হয়নি এমন কোনো বিভাগ পুনরায় পড়ুন। আপনার IDE এর সাথে অনুসরণ করাও সাহায্য করতে পারে। কিন্তু আরে, আর ব্ল্যাক ম্যাজিক নয়, ভালো লাগতে হবে, অন্তত আমি প্রথমবার এমনই অনুভব করলাম!
এবং মনে রাখবেন, পরের বার যখন আপনি স্ট্যাটিকভাবে কোনো পদ্ধতিতে কল করবেন, তখন তা নাও হতে পারে 🪄