گسترش چارچوب
- معرفی
- مدیران و کارخانه ها
- کجا برای گسترش
- حافظه پنهان
- جلسه
- احراز هویت
- برنامه افزودنی مبتنی بر IoC
- درخواست پسوند
معرفی
لاراول برای سفارشی کردن رفتار اجزای اصلی فریمورک، یا حتی جایگزینی کامل
آنها، نقاط توسعه زیادی را به شما ارائه می دهد.
به عنوان مثال، امکانات هش توسط یک
HasherInterface
قرارداد تعریف شده است که شما ممکن است بر اساس نیازهای برنامه خود آن را
پیاده سازی کنید.
همچنین میتوانید
Request
شی را گسترش دهید و به شما این امکان را میدهد که روشهای «کمککننده» راحت
خود را اضافه کنید.
حتی ممکن است درایورهای احراز هویت، حافظه پنهان و جلسه کاملاً جدید را
اضافه کنید!
اجزای لاراول عموماً به دو صورت گسترش مییابند: اتصال پیادهسازیهای جدید
در کانتینر IoC، یا ثبت پسوند با یک
Manager
کلاس، که پیادهسازی الگوی طراحی «Factory» هستند.
در این فصل روشهای مختلف گسترش چارچوب را بررسی میکنیم و کدهای لازم را
بررسی میکنیم.
توجه: به یاد داشته باشید که اجزای لاراول معمولاً به یکی از دو روش گسترش مییابند: اتصالات IoC و
Manager
کلاسها. کلاسهای مدیر بهعنوان پیادهسازی الگوی طراحی «فاکتوری» عمل میکنند و مسئول نمونهسازی امکانات مبتنی بر درایور مانند حافظه پنهان و جلسه هستند.
مدیران و کارخانه ها
لاراول چندین
Manager
کلاس دارد که ایجاد کامپوننت های مبتنی بر درایور را مدیریت می کنند.
این شامل اجزای کش، جلسه، احراز هویت و صف است.
کلاس manager مسئول ایجاد یک پیاده سازی درایور خاص بر اساس پیکربندی برنامه
است.
به عنوان مثال،
CacheManager
کلاس می تواند APC، Memcached، File، و پیاده سازی های مختلف دیگر از
درایورهای کش را ایجاد کند.
هر یک از این مدیران شامل
extend
روشی است که ممکن است برای تزریق آسان قابلیت وضوح درایور جدید به مدیر
استفاده شود.
ما هر یک از این مدیران را در زیر با مثال هایی از نحوه تزریق پشتیبانی
درایور سفارشی به هر یک از آنها پوشش خواهیم داد.
توجه: چند لحظه وقت بگذارید و کلاسهای مختلفی
Manager
را که با لاراول ارائه میشوند، مانندCacheManager
و کاوش کنیدSessionManager
. خواندن این کلاس ها به شما درک کامل تری از نحوه عملکرد لاراول در زیر کاپوت می دهد. همه کلاسهای مدیرIlluminate\Support\Manager
کلاس پایه را گسترش میدهند، که برخی از عملکردهای مفید و مشترک را برای هر مدیر فراهم میکند.
کجا برای گسترش
این مستندات نحوه گسترش انواع کامپوننت های لاراول را پوشش می دهد، اما ممکن
است تعجب کنید که کد افزونه خود را کجا قرار دهید.
مانند بسیاری از کدهای بوت استرپینگ دیگر، شما می توانید برخی از پسوندها را
در
start
فایل های خود قرار دهید.
پسوندهای Cache و Auth نامزدهای خوبی برای این رویکرد هستند.
سایر برنامههای افزودنی مانند
Session
, باید در روش ارائهدهنده خدمات قرار داده شوند
register
زیرا در اوایل چرخه عمر درخواست به آنها نیاز است.
حافظه پنهان
برای گسترش تسهیلات کش لاراول، از روشی
extend
در . استفاده می کنیم
CacheManager
که برای اتصال یک درایور حل کننده سفارشی به مدیر استفاده می شود و در همه
کلاس های مدیر رایج است.
به عنوان مثال، برای ثبت یک درایور کش جدید به نام "mongo"، باید موارد زیر
را انجام دهیم:
Cache::extend('mongo', function($app){ // Return Illuminate\Cache\Repository instance...});
اولین آرگومان ارسال شده به
extend
متد، نام درایور است.
driver
این با گزینه شما در فایل پیکربندی
مطابقت دارد
app/config/cache.php
.
آرگومان دوم یک Closure است که باید یک
Illuminate\Cache\Repository
نمونه را برگرداند.
بسته شدن یک
$app
نمونه ارسال می شود، که یک نمونه از
Illuminate\Foundation\Application
و یک ظرف IoC است.
برای ایجاد درایور کش سفارشی خود، ابتدا باید
Illuminate\Cache\StoreInterface
قرارداد را پیاده سازی کنیم.
بنابراین، پیاده سازی کش MongoDB ما چیزی شبیه به این خواهد بود:
class MongoStore implements Illuminate\Cache\StoreInterface { public function get($key) {} public function put($key, $value, $minutes) {} public function increment($key, $value = 1) {} public function decrement($key, $value = 1) {} public function forever($key, $value) {} public function forget($key) {} public function flush() {} }
ما فقط باید هر یک از این روش ها را با استفاده از اتصال MongoDB پیاده سازی کنیم. هنگامی که پیاده سازی ما کامل شد، می توانیم ثبت نام درایور سفارشی خود را به پایان برسانیم:
use Illuminate\Cache\Repository; Cache::extend('mongo', function($app){ return new Repository(new MongoStore);});
همانطور که در مثال بالا می بینید، ممکن است
Illuminate\Cache\Repository
هنگام ایجاد درایورهای کش سفارشی از پایه استفاده کنید.
معمولاً نیازی به ایجاد کلاس مخزن خود نیست.
اگر نمیخواهید کد درایور کش سفارشی خود را کجا قرار دهید، آن را در
Packagist در دسترس قرار دهید!
یا، می توانید یک
Extensions
فضای نام در پوشه اصلی برنامه خود ایجاد کنید.
به عنوان مثال، اگر برنامه نام دارد
Snappy
، می توانید پسوند کش را در آن قرار دهید
app/Snappy/Extensions/MongoStore.php
.
با این حال، به خاطر داشته باشید که لاراول ساختار نرم افزاری سفت و سختی
ندارد و شما آزاد هستید که برنامه خود را بر اساس ترجیحات خود سازماندهی کنید.
توجه: اگر تا به حال به این فکر می کنید که یک کد را کجا قرار دهید، همیشه یک ارائه دهنده خدمات را در نظر بگیرید. همانطور که گفتیم، استفاده از یک ارائه دهنده خدمات برای سازماندهی افزونه های فریم ورک، راه بسیار خوبی برای سازماندهی کد شما است.
جلسه
گسترش لاراول با یک درایور نشست سفارشی به آسانی گسترش سیستم کش است.
extend
مجدداً از این روش برای ثبت کد سفارشی خود
استفاده خواهیم کرد :
Session::extend('mongo', function($app){ // Return implementation of SessionHandlerInterface});
محل تمدید جلسه
پسوندهای جلسه باید متفاوت از سایر برنامه های افزودنی مانند Cache و Auth
ثبت شوند.
از آنجایی که جلسات خیلی زود در چرخه عمر درخواست شروع می شوند، ثبت پسوندها
در یک
start
فایل خیلی دیر اتفاق می افتد.
در عوض، به یک
ارائه دهنده خدمات
نیاز خواهد بود.
شما باید کد پسوند جلسه خود را در
register
روش ارائه دهنده خدمات خود قرار دهید و ارائه دهنده باید
در زیر
پیش فرض
Illuminate\Session\SessionServiceProvider
در
providers
آرایه پیکربندی قرار گیرد.
نوشتن پسوند جلسه
توجه داشته باشید که درایور جلسه سفارشی ما باید
SessionHandlerInterface
.
این رابط در هسته PHP 5.4+ گنجانده شده است.
اگر از PHP 5.3 استفاده میکنید، رابط کاربری توسط لاراول برای شما تعریف
میشود، بنابراین شما سازگاری رو به جلو دارید.
این رابط فقط شامل چند روش ساده است که باید پیاده سازی کنیم.
یک پیاده سازی Stubbed MongoDB چیزی شبیه به این خواهد بود:
class MongoHandler implements SessionHandlerInterface { public function open($savePath, $sessionName) {} public function close() {} public function read($sessionId) {} public function write($sessionId, $data) {} public function destroy($sessionId) {} public function gc($lifetime) {} }
از آنجایی که این روش ها به آسانی حافظه پنهان قابل درک نیستند
StoreInterface
، اجازه دهید به سرعت کارهایی که هر یک از روش ها انجام می دهند را پوشش
دهیم:
-
این
open
روش معمولاً در سیستمهای ذخیرهسازی جلسه مبتنی بر فایل استفاده میشود. از آنجایی که لاراول با یکfile
درایور جلسه ارائه می شود، تقریباً هرگز نیازی به قرار دادن چیزی در این روش نخواهید داشت. می توانید آن را به عنوان یک خرد خالی بگذارید. این به سادگی یک واقعیت طراحی رابط ضعیف است (که بعداً در مورد آن صحبت خواهیم کرد) که PHP ما را ملزم به پیاده سازی این روش می کند. -
روش
close
، مانندopen
روش، معمولاً می تواند نادیده گرفته شود. برای اکثر رانندگان، به آن نیازی نیست. -
متد
read
باید نسخه رشته ای داده های جلسه مرتبط با داده شده را برگرداند$sessionId
. هنگام بازیابی یا ذخیره داده های نشست در درایور، نیازی به انجام سریال سازی یا رمزگذاری دیگری نیست، زیرا لاراول سریال سازی را برای شما انجام می دهد. -
این
write
روش باید$data
رشته داده شده مرتبط با$sessionId
سیستم ذخیره سازی پایدار مانند MongoDB، Dynamo و غیره را بنویسد. -
این
destroy
روش باید داده های مرتبط با آن را$sessionId
از ذخیره سازی دائمی حذف کند. -
این
gc
روش باید تمام دادههای جلسهای را که قدیمیتر از دادهشده است$lifetime
، که یک مهر زمانی یونیکس است، از بین ببرد. برای سیستم های خود انقضا مانند Memcached و Redis، این روش ممکن است خالی بماند.
پس از
SessionHandlerInterface
پیاده سازی، ما آماده هستیم تا آن را در Session manager ثبت کنیم:
Session::extend('mongo', function($app){ return new MongoHandler;});
هنگامی که درایور جلسه ثبت شد، ممکن است از
mongo
درایور در
app/config/session.php
فایل پیکربندی خود استفاده کنیم.
توجه: به یاد داشته باشید، اگر یک کنترل کننده جلسه سفارشی می نویسید، آن را در Packagist به اشتراک بگذارید!
احراز هویت
احراز هویت ممکن است به همان روشی که حافظه پنهان و امکانات جلسه گسترش
یابد.
extend
مجدداً از روشی که با آن آشنا شده ایم
استفاده خواهیم کرد :
Auth::extend('riak', function($app){ // Return implementation of Illuminate\Auth\UserProviderInterface});
پیادهسازیها
UserProviderInterface
فقط مسئول واکشی یک
UserInterface
پیادهسازی از یک سیستم ذخیرهسازی دائمی مانند MySQL، Riak و غیره هستند.
این دو رابط به مکانیسمهای احراز هویت لاراول اجازه میدهند بدون توجه به نحوه ذخیره دادههای کاربر یا نوع
کلاس استفاده شده، به عملکرد خود ادامه دهند. برای نمایندگی آن
بیایید نگاهی به موارد زیر بیندازیم
UserProviderInterface
:
interface UserProviderInterface { public function retrieveById($identifier); public function retrieveByToken($identifier, $token); public function updateRememberToken(UserInterface $user, $token); public function retrieveByCredentials(array $credentials); public function validateCredentials(UserInterface $user, array $credentials); }
تابع
retrieveById
معمولاً یک کلید عددی که کاربر را نشان می دهد، مانند یک شناسه افزایش
خودکار از پایگاه داده MySQL دریافت می کند.
پیاده
UserInterface
سازی منطبق با شناسه باید با روش بازیابی و برگردانده شود.
این
retrieveByToken
تابع یک کاربر را با استفاده از
$identifier
"مرا به خاطر بسپار" را
$token
که در یک فیلد ذخیره شده است، بازیابی می کند
remember_token
.
همانند روش قبلی،
UserInterface
پیاده سازی باید برگردانده شود.
این
updateRememberToken
روش
$user
فیلد را
remember_token
با جدید به روز می کند
$token
.
توکن جدید میتواند یک توکن تازه باشد که در تلاش موفق برای ورود به سیستم
"مرا به خاطر بسپار" یا زمانی که کاربر از سیستم خارج میشود، تهی باشد.
این روش
هنگام تلاش برای ورود به یک برنامه،
retrieveByCredentials
آرایه ای از اعتبارنامه ها را دریافت می کند .
Auth::attempt
سپس این روش باید برای کاربر مطابق با آن اعتبارنامه ها، فضای ذخیره سازی
دائمی زیرین را "پرس و جو" کند.
به طور معمول، این روش یک پرس و جو را با شرط "where" در
$credentials['username']
.
این روش نباید هیچ گونه اعتبارسنجی یا احراز هویت رمز عبور را انجام
دهد.
این روش باید
برای احراز هویت کاربر،
validateCredentials
داده های داده شده را
$user
با آن مقایسه کند.
$credentials
به عنوان مثال، این روش ممکن است
$user->getAuthPassword()
رشته را با یک
Hash::make
از مقایسه کند
$credentials['password']
.
اکنون که هر یک از روش ها را بررسی کردیم
UserProviderInterface
، بیایید نگاهی به
UserInterface
.
به یاد داشته باشید، ارائهدهنده باید پیادهسازیهای این رابط را از
retrieveById
و
retrieveByCredentials
متدهای زیر برگرداند:
interface UserInterface { public function getAuthIdentifier(); public function getAuthPassword(); }
این رابط کاربری ساده است.
روش
getAuthIdentifier
باید «کلید اصلی» کاربر را برگرداند.
در یک بکاند MySQL، دوباره، این کلید اصلی افزایش خودکار است.
باید
getAuthPassword
رمز عبور هش شده کاربر را برگرداند.
این رابط به سیستم احراز هویت اجازه می دهد تا با هر کلاس کاربری، صرف نظر
از اینکه از چه ORM یا لایه انتزاعی ذخیره سازی استفاده می کنید، کار کند.
بهطور پیشفرض، لاراول شامل یک
User
کلاس در
app/models
دایرکتوری است که این رابط را پیادهسازی میکند، بنابراین میتوانید برای
مثال پیادهسازی با این کلاس مشورت کنید.
در نهایت، پس از پیاده سازی
UserProviderInterface
، آماده هستیم تا پسوند خود را با
Auth
نما ثبت کنیم:
Auth::extend('riak', function($app){ return new RiakUserProvider($app['riak.connection']);});
بعد از اینکه درایور را با متد ثبت کردید ، در
فایل پیکربندی
extend
خود به درایور جدید سوئیچ می کنید .
app/config/auth.php
برنامه افزودنی مبتنی بر IoC
تقریباً هر ارائهدهنده خدماتی که در چارچوب لاراول گنجانده شده است، اشیاء
را به کانتینر IoC متصل میکند.
می توانید لیستی از ارائه دهندگان خدمات برنامه خود را در
app/config/app.php
فایل پیکربندی پیدا کنید.
همانطور که زمان دارید، باید کد منبع هر یک از این ارائه دهندگان را مرور
کنید.
با انجام این کار، درک بسیار بهتری از آنچه که هر ارائه دهنده به چارچوب
اضافه می کند و همچنین از چه کلیدهایی برای اتصال سرویس های مختلف به کانتینر IoC استفاده می شود، به دست خواهید
آورد.
برای مثال،
کلیدی را به محفظه IoC
HashServiceProvider
متصل می کند ، که در یک
نمونه حل می شود.
شما به راحتی می توانید این کلاس را در برنامه خود با لغو این اتصال IoC
گسترش دهید و لغو کنید.
مثلا:
hash
Illuminate\Hashing\BcryptHasher
class SnappyHashProvider extends Illuminate\Hashing\HashServiceProvider { public function boot() { App::bindShared('hash', function() { return new Snappy\Hashing\ScryptHasher; }); parent::boot(); } }
توجه داشته باشید که این کلاس
HashServiceProvider
نه
ServiceProvider
کلاس پایه پیش فرض را گسترش می دهد.
هنگامی که ارائه دهنده سرویس را گسترش دادید، فایل پیکربندی
HashServiceProvider
خود
app/config/app.php
را با نام ارائه دهنده توسعه یافته خود تعویض کنید.
این روش کلی برای گسترش هر کلاس هسته ای است که در ظرف محدود شده است. اساساً هر کلاس اصلی به این شکل در ظرف محدود می شود و می توان آن را نادیده گرفت. مجدداً، خواندن ارائهدهندگان خدمات فریمورک ارائهشده، شما را با مکانهایی که کلاسهای مختلف به کانتینر متصل شدهاند و با چه کلیدهایی متصل میشوند، آشنا میکند. این یک راه عالی برای یادگیری بیشتر در مورد نحوه چیدمان لاراول است.
درخواست پسوند
از آنجا که این یک قطعه اساسی از چارچوب است و در اوایل چرخه درخواست نمونه
سازی می شود، گسترش کلاس
Request
کمی متفاوت از نمونه های قبلی عمل می کند.
ابتدا کلاس را مانند حالت عادی تمدید کنید:
<?php namespace QuickBill\Extensions; class Request extends \Illuminate\Http\Request { // Custom, helpful methods here... }
پس از تمدید کلاس،
bootstrap/start.php
فایل را باز کنید.
این فایل یکی از اولین فایل هایی است که در هر درخواست به برنامه شما اضافه
می شود.
توجه داشته باشید که اولین اقدام انجام شده ایجاد
$app
نمونه لاراول است:
$app = new \Illuminate\Foundation\Application;
هنگامی که یک نمونه برنامه جدید ایجاد می شود، یک نمونه جدید ایجاد می کند
Illuminate\Http\Request
و با استفاده از کلید آن را به ظرف IoC متصل می کند
request
.
بنابراین، ما به راهی برای تعیین یک کلاس سفارشی نیاز داریم که باید به
عنوان نوع درخواست "پیشفرض" استفاده شود، درست است؟
و خوشبختانه،
requestClass
روش موجود در نمونه برنامه دقیقاً این کار را انجام می دهد!
بنابراین، ما می توانیم این خط را در بالای
bootstrap/start.php
فایل خود اضافه کنیم:
use Illuminate\Foundation\Application; Application::requestClass('QuickBill\Extensions\Request');
هنگامی که کلاس درخواست سفارشی را مشخص کردید، لاراول هر زمان که یک
Request
نمونه ایجاد می کند از این کلاس استفاده می کند و به راحتی به شما این امکان
را می دهد که همیشه نمونه ای از کلاس درخواست سفارشی خود را حتی در تست های واحد در دسترس داشته باشید!