شبکه ایمن

مفهوم Facade در لاراول – آموزش لاراول

مفهوم Facade در لاراول

Facade در لاراول یک رابط استاتیک برای کلاس هایی که در داخل Service Container در دسترس هستند ارائه می کند. لاراول به صورت پیشفرض facade های بسیاری دارد که تقریبا دسترسی به همه ویژگی های لاراول را فراهم می کنند. Facade های لاراول به عنوان “پروکسی های استاتیک” برای کلاس های اصلی موجود در Service Container عمل می کنند. آن ها در مقایسه با متدهای استاتیک قدیمی قابلیت تست پذیری و انعطاف بیشتری دارند.

تمام facade های لاراول تحت فضای نام IlluminateSupportFacades تعریف شده اند. بنابراین برای دسترسی به آن ها می توانیم ماننده نمونه زیر عمل کنیم:

use IlluminateSupportFacadesCache; use IlluminateSupportFacadesRoute; Route::get('/cache', function () { return Cache::get('key'); });

123456 use IlluminateSupportFacadesCache;use IlluminateSupportFacadesRoute; Route::get('/cache', function () { return Cache::get('key');});

توابع کمکی

برای تکمیل کار facade ها، لاراول انواع مختلفی از توابع کمکی سراسری (Global) را ارائه می دهد که با کمک آن ها تعامل با ویژگی های رایج فریم ورک آسان تر می شود. برخی از این توابع کمکی رایج عبارت اند از: view، response، url، config و غیره. برای مثال برای تولید یک پاسخ از نوع JSON به جای استفاده از IlluminateSupportFacadesResponse می توانیم از تابع کمکی response استفاده کنیم. همانطور که گفتیم توابع کمکی به صورت سراسری در دسترس هستند، نیازی به مشخص کردن هیچ گونه فضای نامی نیست. نمونه کد:

use IlluminateSupportFacadesResponse; Route::get('/users', function () { return Response::json([ // … ]); }); Route::get('/users', function () { return response()->json([ // … ]); });

123456789101112 use IlluminateSupportFacadesResponse; Route::get('/users', function () { return Response::json([ // … ]);});Route::get('/users', function () { return response()->json([ // … ]);});

چه زمانی باید از Facade ها استفاده کنیم

Facade ها مزایای زیادی دارند. آن ها یک سینتکس مختصر و به یاد ماندنی ارائه می کنند که به توسعه دهنده اجازه می دهد تا بدون به خاطر سپردن نام طولانی کلاس ها که باید به صورت دستی تزریق یا پیکربندی شوند، از ویژگی های لاراول استفاده کنید. علاوه بر این، به دلیل استفاده از قابلیت متدهای پویا در زبان PHP، تست کردن آن ها نیز آسان است.

با این حال هنگام استفاده از facade ها باید به بعضی از موارد توجه داشته باشید. اصلی ترین خطر استفاده از facade ها، خزش دامنه (Scope Creep) است. از آنجا که استفاده از facade ها بسیار آسان است و نیازی به هیچ گونه تزریق ندارد، کلاس های استفاده کننده از آن ها این قابلیت را پیدا می کنند تا بدون جلب توجه با استفاده از facade های زیاد رشد کرده و بزرگتر شوند. اما زمانی وابستگی های کلاس تزریق شوند این پتانسیل کاهش می یابد و دلیل آن هم این است که سازنده کلاس هر چقدر که تزریق بیشتری داشته باشد، بزرگتر به نظر می رسد و شما با مشاهده آن سازنده متوجه می شوید که کلاس شما بیش از حد بزرگ شده است. پس مهم ترین نکته در هنگام استفاده از facade ها توجه به اندازه کلاس است تا دامنه مسئولیت و کارهایی که انجام می دهد محدود بماند. اگر کلاس شما خیلی بزرگ شد، می توانید آن را به کلاس های کوچکتر تقسیم کنید.

Facade ها در مقابل تزریق وابستگی

یکی از مزایای اصلی تزریق وابستگی امکان جایگزین کردن یک وابستگی با پیاده‌سازی های مختلف است. این موضوع در هنگام تست کردن به درد می خورد زیرا می توانیم یک پیاده‌سازی ساختگی و الکی را به جای پیاده‌سازی اصلی تزریق کنیم.

به طور معمول امکان ساخت یک نمونه ساختگی از متد مربوط به یک کلاس استاتیک وجود ندارد. با این حال از آنجا که facade ها از قابلیت متدهای پویا در PHP استفاده می کنند امکان تست کردن آن ها نیز مانند کلاس های تزریق شده فراهم می شود. برای مثال به تکه کد زیر توجه کنید:

use IlluminateSupportFacadesCache; Route::get('/cache', function () { return Cache::get('key'); });

12345 use IlluminateSupportFacadesCache; Route::get('/cache', function () { return Cache::get('key');});

با استفاده از متدهای مربوط به تست کردن facade در لاراول، می توانیم برای مثال فوق به این شکل تست بنویسم تا مطمئن شویم که متد Cache::get با آرگومانی که انتظار داریم فراخوانی می شود:

use IlluminateSupportFacadesCache; /** * A basic functional test example. * * @return void */ public function testBasicExample() { Cache::shouldReceive('get') ->with('key') ->andReturn('value'); $response = $this->get('/cache'); $response->assertSee('value'); }

1234567891011121314151617 use IlluminateSupportFacadesCache; /** * A basic functional test example. * * @return void */public function testBasicExample(){ Cache::shouldReceive('get') ->with('key') ->andReturn('value'); $response = $this->get('/cache'); $response->assertSee('value');}

Facade ها در مقابل توابع کمکی

علاوه بر facade ها، لاراول شامل توابع کمکی مختلفی است که می توانند به منظور انجام عملیات رایج مانند تولید ویوها، انتشار رویدادها توزیع کارها و یا ارسال پاسخ HTTP استفاده شوند. بسیاری از این توابع کمکی همان کار facade مربوطه انجام می دهند. در نمونه کد زیر هر دو خط یک کار مشابه را انجام می دهند:

return IlluminateSupportFacadesView::make('profile'); return view('profile');

123 return IlluminateSupportFacadesView::make('profile'); return view('profile');

مطلقاً هیچ تفاوت عملی بین facade و تابع کمکی وجود ندارد. به این معنی که هنگام استفاده از توابع کمکی می توانید آنها را دقیقا مانند facade مربوطه تست کنید. برای مثال به کد زیر توجه کنید:

Route::get('/cache', function () { return cache('key'); });

123 Route::get('/cache', function () { return cache('key');});

در اصل تابع کمکی cache متد get که در کلاس Cache تعریف شده است را فراخوانی می کند. بنابراین اگرچه ما از یک تابع کمکی استفاده کرده ایم، می توانیم مانند یک facade برای آن تست بنویسم:

use IlluminateSupportFacadesCache; /** * A basic functional test example. * * @return void */ public function testBasicExample() { Cache::shouldReceive('get') ->with('key') ->andReturn('value'); $response = $this->get('/cache'); $response->assertSee('value'); }

1234567891011121314151617 use IlluminateSupportFacadesCache; /** * A basic functional test example. * * @return void */public function testBasicExample(){ Cache::shouldReceive('get') ->with('key') ->andReturn('value'); $response = $this->get('/cache'); $response->assertSee('value');}

Facade ها چگونه کار می کنند؟

در یک برنامه لاراول، facade یک کلاسی است که دسترسی به یک شیء از طریق Container را فراهم می کند. مکانیزمی که این سیستم با آن کار می کند در داخل کلاس IlluminateSupportFacadesFacade که کلاس پایه برای همه facade ها است تعریف شده است. در داخل کلاس پایه برای فراخوانی توابع مورد نظر از متد __callStatic() استفاده می شود. در مثال زیر از متد get برای گرفتن مقدار کش شده استفاده شده است. در نگاه اول شاید فکر کنید که متد استاتیک get به کلاس Cache تعلق دارد:

<?php namespace AppHttpControllers; use AppHttpControllersController; use IlluminateSupportFacadesCache; class UserController extends Controller { /** * Show the profile for the given user. * * @param int $id * @return Response */ public function showProfile($id) { $user = Cache::get('user:'.$id); return view('profile', ['user' => $user]); } }

12345678910111213141516171819202122 <?php namespace AppHttpControllers; use AppHttpControllersController;use IlluminateSupportFacadesCache; class UserController extends Controller{ /** * Show the profile for the given user. * * @param int $id * @return Response */ public function showProfile($id) { $user = Cache::get('user:'.$id); return view('profile', ['user' => $user]); }}

اما اگر به پیاده‌سازی کلاس IlluminateSupportFacadesCache نگاه کنید مشاهده خواهید کرد که هیچ متد استاتیکی در آن وجود ندارد:

class Cache extends Facade { /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return 'cache'; } }

123456789 class Cache extends Facade{ /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return 'cache'; }}

در کد فوق کلاس Cache کلاس پایه Facade را توسعه می دهد و یک متد با نام getFacadeAccessor() نیز تعریف کرده است. کار این متد بازگرداندن نام سرویس مربوطه در Service Container است. زمانی که متدهای استاتیک بر روی facade مربوط به Cache فراخوانی می شود، لاراول با استفاده از متد گفته شده سرویس مورد نیاز را از Container میگیرد و متد درخواست شده (در این مورد get) را بر روی آن سرویس اجرا می کند.

Facade های موجود در لاراول

در جدول زیر می توانید facade های موجود در فریم ورک لاراول را مشاهده کنید.

Facade

Class

Service Container Binding

App

IlluminateFoundationApplication

app

Artisan

IlluminateContractsConsoleKernel

artisan

Auth

IlluminateAuthAuthManager

auth

Auth (Instance)

IlluminateContractsAuthGuard

auth.driver

Blade

IlluminateViewCompilersBladeCompiler

blade.compiler

Broadcast

IlluminateContractsBroadcastingFactory

Broadcast (Instance)

IlluminateContractsBroadcastingBroadcaster

Bus

IlluminateContractsBusDispatcher

Cache

IlluminateCacheCacheManager

cache

Cache (Instance)

IlluminateCacheRepository

cache.store

Config

IlluminateConfigRepository

config

Cookie

IlluminateCookieCookieJar

cookie

Crypt

IlluminateEncryptionEncrypter

encrypter

Date

IlluminateSupportDateFactory

date

DB

IlluminateDatabaseDatabaseManager

db

DB (Instance)

IlluminateDatabaseConnection

db.connection

Event

IlluminateEventsDispatcher

events

File

IlluminateFilesystemFilesystem

files

Gate

IlluminateContractsAuthAccessGate

Hash

IlluminateContractsHashingHasher

hash

Http

IlluminateHttpClientFactory

Lang

IlluminateTranslationTranslator

translator

Log

IlluminateLogLogManager

log

Mail

IlluminateMailMailer

mailer

Notification

IlluminateNotificationsChannelManager

Password

IlluminateAuthPasswordsPasswordBrokerManager

auth.password

Password (Instance)

IlluminateAuthPasswordsPasswordBroker

auth.password.broker

Queue

IlluminateQueueQueueManager

queue

Queue (Instance)

IlluminateContractsQueueQueue

queue.connection

Queue (Base Class)

IlluminateQueueQueue

Redirect

IlluminateRoutingRedirector

redirect

Redis

IlluminateRedisRedisManager

redis

Redis (Instance)

IlluminateRedisConnectionsConnection

redis.connection

Request

IlluminateHttpRequest

request

Response

IlluminateContractsRoutingResponseFactory

Response (Instance)

IlluminateHttpResponse

Route

IlluminateRoutingRouter

router

Schema

IlluminateDatabaseSchemaBuilder

Session

IlluminateSessionSessionManager

session

Session (Instance)

IlluminateSessionStore

session.store

Storage

IlluminateFilesystemFilesystemManager

filesystem

Storage (Instance)

IlluminateContractsFilesystemFilesystem

filesystem.disk

URL

IlluminateRoutingUrlGenerator

url

Validator

IlluminateValidationFactory

validator

Validator (Instance)

IlluminateValidationValidator

View

IlluminateViewFactory

view

View (Instance)

IlluminateViewView

دیدگاهتان را بنویسید