কিছু দিন আগে, আমি একটি অস্পষ্ট পরীক্ষা ঠিক করছিলাম, এবং দেখা গেল আমার কারখানার মধ্যে আমার কিছু অনন্য এবং বৈধ মান প্রয়োজন। Laravel FakerPHP কে মোড়ানো, যা আমরা সাধারণত fake()
হেল্পারের মাধ্যমে অ্যাক্সেস করি। FakerPHP valid()
এবং unique()
এর মত মডিফায়ারের সাথে আসে, কিন্তু আপনি একবারে শুধুমাত্র একটি ব্যবহার করতে পারেন, তাই আপনি fake()->unique()->valid()
করতে পারবেন না, যা আমার প্রয়োজন ছিল।
এটি আমাকে ভাবতে বাধ্য করেছে, যদি আমরা আমাদের নিজস্ব সংশোধক তৈরি করতে চাই? উদাহরণস্বরূপ, uniqueAndValid()
বা অন্য কোন পরিবর্তনকারী। আমরা কিভাবে কাঠামো প্রসারিত করতে পারি?
আমি আমার চিন্তার ট্রেন ডাম্প করা হবে.
যেকোন ওভার-ইঞ্জিনিয়ারড সমাধানে ঝাঁপিয়ে পড়ার আগে, আমি সর্বদা একটি সহজ বিকল্প আছে কিনা তা পরীক্ষা করতে চাই এবং আমি কী নিয়ে কাজ করছি তা বুঝতে চাই। তো, আসুন fake()
হেল্পারটি দেখে নেওয়া যাক:
function fake($locale = null) { if (app()->bound('config')) { $locale ??= app('config')->get('app.faker_locale'); } $locale ??= 'en_US'; $abstract = \Faker\Generator::class.':'.$locale; if (! app()->bound($abstract)) { app()->singleton($abstract, fn () => \Faker\Factory::create($locale)); } return app()->make($abstract); }
কোডটি পড়া, আমরা দেখতে পাচ্ছি যে লারাভেল একটি সিঙ্গলটনকে ধারকটিতে আবদ্ধ করে। যাইহোক, যদি আমরা বিমূর্ত পরিদর্শন করি, এটি একটি নিয়মিত ক্লাস যা কোনো ইন্টারফেস বাস্তবায়ন করে না এবং বস্তুটি একটি কারখানার মাধ্যমে তৈরি করা হয়। এটি জিনিসগুলিকে জটিল করে তোলে। কেন?
কারণ এটি একটি ইন্টারফেস হলে, আমরা কেবল একটি নতুন ক্লাস তৈরি করতে পারতাম যা বেস \Faker\Generator
ক্লাসকে প্রসারিত করে, কিছু নতুন বৈশিষ্ট্য যুক্ত করে এবং এটিকে কন্টেইনারে রিবাইন্ড করে। কিন্তু আমাদের এই বিলাসিতা নেই।
এর সাথে জড়িত একটি কারখানা। এর মানে এটি একটি সাধারণ ইনস্ট্যান্টেশন নয়; কিছু যুক্তি চালানো হচ্ছে. এই ক্ষেত্রে, কারখানা কিছু প্রদানকারী (ফোন নম্বর, পাঠ্য, ব্যবহারকারী এজেন্ট, ইত্যাদি) যোগ করে। সুতরাং, এমনকি যদি আমরা পুনরায় বাঁধার চেষ্টা করি, আমাদের কারখানাটি ব্যবহার করতে হবে, যা আসল \Faker\Generator
ফিরিয়ে দেবে।
সমাধান 🤔? কেউ ভাবতে পারে, "আমাদের নিজস্ব কারখানা তৈরি করতে কী বাধা দিচ্ছে যা পয়েন্ট 1 এ বর্ণিত নতুন জেনারেটর ফিরিয়ে দেয়?" ওয়েল, কিছুই, আমরা তা করতে পারি, কিন্তু আমরা করব না! আমরা বিভিন্ন কারণে একটি ফ্রেমওয়ার্ক ব্যবহার করি, যার মধ্যে একটি হচ্ছে আপডেট। FakerPHP একটি নতুন প্রদানকারী যোগ করলে বা একটি বড় আপগ্রেড হলে কি হবে? Laravel কোড সামঞ্জস্য করবে, এবং যারা কোন পরিবর্তন করেনি তারা কিছুই লক্ষ্য করবে না। যাইহোক, আমাদের বাদ দেওয়া হবে, এবং আমাদের কোড এমনকি ভেঙে যেতে পারে (সম্ভবত)। তাই, হ্যাঁ, আমরা এতদূর যেতে চাই না।
এখন যেহেতু আমরা মৌলিক বিকল্পগুলি অন্বেষণ করেছি, আমরা ডিজাইন প্যাটার্নের মতো আরও উন্নতগুলির কথা ভাবতে শুরু করতে পারি৷ আমাদের সঠিক বাস্তবায়নের প্রয়োজন নেই, শুধু আমাদের সমস্যার সাথে পরিচিত কিছু। এই কারণেই আমি সবসময় বলি তাদের জানা ভালো। এই ক্ষেত্রে, আমরা পুরানোগুলি বজায় রেখে নতুন বৈশিষ্ট্য যুক্ত করে Generator
ক্লাসটিকে "সাজাইয়া" পারি। ভালো শোনাচ্ছে? দেখা যাক কিভাবে!
প্রথমে, আসুন একটি নতুন ক্লাস তৈরি করি, FakerGenerator
:
<?php namespace App\Support; use Closure; use Faker\Generator; use Illuminate\Support\Traits\ForwardsCalls; class FakerGenerator { use ForwardsCalls; public function __construct(private readonly Generator $generator) { } public function uniqueAndValid(Closure $validator = null): UniqueAndValidGenerator { return new UniqueAndValidGenerator($this->generator, $validator); } public function __call($method, $parameters): mixed { return $this->forwardCallTo($this->generator, $method, $parameters); } }
এটি হবে আমাদের "ডেকোরেটর" (একরকম)। এটি একটি সাধারণ শ্রেণী যা নির্ভরতা হিসাবে বেস Generator
আশা করে এবং একটি নতুন পরিবর্তনকারী, uniqueAndValid()
প্রবর্তন করে। এটি Laravel থেকে ForwardsCalls
বৈশিষ্ট্যও ব্যবহার করে, যা এটিকে বেস অবজেক্টে প্রক্সি কল করার অনুমতি দেয়।
এই বৈশিষ্ট্যটির দুটি পদ্ধতি রয়েছে:
forwardCallTo
এবংforwardDecoratedCallTo
। আপনি যখন সজ্জিত বস্তুর উপর চেইন পদ্ধতি করতে চান তখন পরবর্তীটি ব্যবহার করুন। আমাদের ক্ষেত্রে, আমাদের সবসময় একটি একক কল থাকবে।
আমাদের UniqueAndValidGenerator
প্রয়োগ করতে হবে, যা কাস্টম সংশোধক, কিন্তু এটি নিবন্ধের বিন্দু নয়। আপনি যদি বাস্তবায়নে আগ্রহী হন, এই ক্লাসটি মূলত ValidGenerator এবং UniqueGenerator এর মিশ্রণ যা FakerPHP এর সাথে পাঠানো হয়, আপনি এটি এখানে খুঁজে পেতে পারেন।
এখন, AppServiceProvider
এ ফ্রেমওয়ার্ক প্রসারিত করা যাক:
<?php namespace App\Providers; use Closure; use Faker\Generator; use App\Support\FakerGenerator; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function register(): void { $this->app->extend( $this->fakerAbstractName(), fn (Generator $base) => new FakerGenerator($base) ); } private function fakerAbstractName(): string { // This is important, it matches the name bound by the fake() helper return Generator::class . ':' . app('config')->get('app.faker_locale'); } }
প্রদত্ত নামের সাথে মিলে যাওয়া একটি বিমূর্ত ধারকটির সাথে আবদ্ধ হয়েছে কিনা তা extend()
পদ্ধতি পরীক্ষা করে। যদি তাই হয়, এটি বন্ধের ফলাফলের সাথে তার মানকে ওভাররাইড করে, একবার দেখুন:
// Laravel: src/Illuminate/Container/Container.php public function extend($abstract, Closure $closure) { $abstract = $this->getAlias($abstract); if (isset($this->instances[$abstract])) { // You are interested here $this->instances[$abstract] = $closure($this->instances[$abstract], $this); $this->rebound($abstract); } else { $this->extenders[$abstract][] = $closure; if ($this->resolved($abstract)) { $this->rebound($abstract); } } }
তাই আমরা fakerAbstractName()
পদ্ধতি সংজ্ঞায়িত করেছি, যা fake()
সাহায্যকারী কন্টেইনারে বাঁধার মতো একই নাম তৈরি করে।
আপনি যদি এটি মিস করেন তবে উপরের কোডটি পুনরায় পরীক্ষা করুন, আমি একটি মন্তব্য রেখেছি।
এখন, যতবারই আমরা fake()
কল করব, FakerGenerator
এর একটি উদাহরণ ফেরত দেওয়া হবে, এবং আমাদের প্রবর্তিত কাস্টম মডিফায়ারে অ্যাক্সেস থাকবে। যখনই আমরা FakerGenerator
ক্লাসে বিদ্যমান নেই এমন একটি কল আহ্বান করি, __call()
ট্রিগার করা হবে, এবং এটি forwardCallTo()
পদ্ধতি ব্যবহার করে বেস Generator
প্রক্সি করবে।
এটাই! আমি অবশেষে fake()->uniqueAndValid()->randomElement()
করতে পারি, এবং এটি একটি কবজ মত কাজ করে!
আমরা শেষ করার আগে, আমি উল্লেখ করতে চাই যে এটি একটি বিশুদ্ধ ডেকোরেটর প্যাটার্ন নয়। যাইহোক, নিদর্শন পবিত্র গ্রন্থ নয়; আপনার প্রয়োজনের সাথে মানানসই করতে এবং সমস্যা সমাধানের জন্য তাদের পরিবর্তন করুন।
ফ্রেমওয়ার্কগুলি অবিশ্বাস্যভাবে সহায়ক, এবং লারাভেল অনেকগুলি অন্তর্নির্মিত বৈশিষ্ট্য সহ আসে। যাইহোক, তারা আপনার প্রকল্পের সমস্ত প্রান্তের কেস কভার করতে পারে না এবং কখনও কখনও, আপনি একটি শেষ প্রান্তে আঘাত করতে পারেন। যখন এটি ঘটে, আপনি সবসময় ফ্রেমওয়ার্ক প্রসারিত করতে পারেন। আমরা দেখেছি এটি কতটা সহজ, এবং আমি আশা করি আপনি মূল ধারণাটি বুঝতে পেরেছেন, যা এই ফেকার উদাহরণের বাইরেও প্রযোজ্য।
সর্বদা সহজ শুরু করুন এবং সমস্যার সবচেয়ে সহজ সমাধান সন্ধান করুন। যখন প্রয়োজন হবে তখন জটিলতা আসবে, তাই যদি মৌলিক উত্তরাধিকার কৌশলটি করে, তাহলে ডেকোরেটর বা অন্য কিছু বাস্তবায়ন করার দরকার নেই। আপনি যখন ফ্রেমওয়ার্ক প্রসারিত করবেন, নিশ্চিত করুন যে আপনি খুব বেশি দূরে যাবেন না, যেখানে ক্ষতি লাভের চেয়ে বেশি। আপনি নিজেই ফ্রেমওয়ার্কের একটি অংশ বজায় রাখতে চান না।