نسخه:

گسترش چارچوب

معرفی

لاراول برای سفارشی کردن رفتار اجزای اصلی فریمورک، یا حتی جایگزینی کامل آنها، نقاط توسعه زیادی را به شما ارائه می دهد. به عنوان مثال، امکانات هش توسط یک 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 نمونه ایجاد می کند از این کلاس استفاده می کند و به راحتی به شما این امکان را می دهد که همیشه نمونه ای از کلاس درخواست سفارشی خود را حتی در تست های واحد در دسترس داشته باشید!