摘要:組件擴展通常有兩種方法向容器中綁定自己的接口實現痛過使用工廠模式實現的類注冊自己的擴展。類庫管理類以工廠模式實現,負責諸如緩存等驅動的實例化。閉包須要傳入繼承自和容器的實例化對象。當完成擴展之后要記住中替換成自己的擴展名稱。
聲明:本文并非博主原創,而是來自對《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當然也不是原汁原味的翻譯,能保證90%的原汁性,另外因為是理解翻譯,肯定會有錯誤的地方,歡迎指正。
歡迎轉載,轉載請注明出處,謝謝!
框架的擴展 介紹Laravel為我們提供了很多自定義系統組件的擴展點,你甚至可以完全的替換掉他們。比如,哈希結構是由HasherInterface接口約定的,你可以根據你的應用來實現自己的需求。你也可以擴展自己的Request對象,并添加自己的“輔助”方法。甚至我們完全添加自己的認證、緩存、SESSION驅動。
Laravel組件擴展通常有兩種方法:向IoC容器中綁定自己的接口實現;痛過使用“工廠模式”實現的Manager類注冊自己的擴展。本章將探索多種擴展框架的方法,以及必要的測試代碼。
類庫管理類和工廠方法</>復制代碼
擴展方式
牢記Laravel組件擴展的兩種方式:IoC容器綁定和使用Manager類注冊。類庫管理類以工廠模式實現,負責諸如緩存、session等驅動的實例化。
Laravel有諸多Manager類庫來管理創建那些基于驅動的組件。它包括緩存、session、認證、隊列組件。管理類的職責是根據應用的配置來創建特殊的驅動實例。例如,CacheManager可以創建APC、Memcached、Native、以及其他緩存驅動系統的實現。
所有這些管理器都有個extend方法,可以輕易的將新的驅動功能注入到其中。對于上面所有的管理器,我們通過實例來演示如何注入我們自定義的那些服務驅動。
緩存 Cache</>復制代碼
學習我們自己的管理器
請花一些事件來熟悉下Laravel提供的Manager類庫,如CacheManager、SessionManager。通讀這些代碼可以讓你加深理解。所有的管理器類都繼承自IlluminateSupportManager基類,他為每個具體的管理器提供了很多常見使用的方法。
我們通過在CacheManager類中的extend方法綁定自定義的驅動解析器來擴展Laravel的緩存機制。比如,注冊一個“mongo”驅動到緩存驅動中,代碼如下:
</>復制代碼
Cache::extend("mongo", function($app)
{
// Return IlluminateCacheRepository instance...
});
傳入method方法的第一個參數是驅動名稱。通常和app/config/app.php配置文件中的driver選項匹配。第二個參數是返回IlluminateCacheRepository實例的閉包。閉包須要傳入繼承自IlluminateFoundationApplication和IoC容器的實例化對象$app。
對于我們自定義的緩存驅動,要實現IlluminateCacheStoreInterface接口的約定。因此,我們的MongoDB緩存實現代碼為這樣:
</>復制代碼
class MongoStore implements IlluminateCacheStoreInterface {
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 IlluminateCacheRepository;
Cache::extend("mongo", function($app)
{
return new Repository(new MongoStore);
}
如上可見,我們可使用IlluminateCacheRepository來直接創建我們自定義的緩存驅動,而無需創建自己的(Repository)倉庫類。
如果不知道該把代碼放在哪里,可以考慮放到Packagist!或者在應用主目錄下創建一個Extensions命名空間的目錄存放。例如你的應用起名叫個Snappy,可以把這個擴展放到app/Snappy/Extensions/MongoStore.php。Laravel創建的應用沒有死板的各種結構的要求,根據你的喜好自己來組織就好。
Session 會話</>復制代碼
何處引入擴展
如果你還在考慮該在何處引入擴展,不妨繼續使用服務提供器。我們已經討論過這是組織我們代碼的一個利器,要善用利器。
擴展Session機制其實像擴展緩存機制一樣簡單。同樣,使用extend方法來注冊我們自己的驅動:
</>復制代碼
Session::extend("mongo", function($app)
{
// Return implementation of SessionHandlerInterface
});
注意,我們自定義的驅動須要實現SessionHandlerInterface接口。此接口是被包含在PHP5.4+核心中的。如果你在使用PHP5.3,Laravel也是向前兼容的,Laravel已經為您定義好此接口。接口中包含了一些我們須要實現的方法。一個基于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方法一般是在基于文件系統的實現中被用到。自從Laravel基于以PHP自身的本地存儲實現了native會話驅動方式,你基本上不需要在本方法中添加任何東西了。你可以把他留空。PHP這種接口設計很顯然是一種不好的設計方式(我們后續討論)。
close方法同open方法,通常不用理會。大多數驅動都不需要他。
read方法返回根據$sessionId變量關聯session數據的字符串。這里不需要進行序列化或者其他類型的轉義,Laravel已經幫你進行了處理。
write方法根據$sessionId關聯session數據將$data數據寫入持久化存儲系統中,如MongoDB、Dynamo等。
gc方法將根據$lifetime指定UNIX時間戳銷毀之前所有的session數據。對于可以自動刪除過期數據的系統比如Memcached或者Redis,該方法留空即可。
當實現SessionHandlerInterface之后,我們就可以向Session管理器中注冊他了:
</>復制代碼
Session::extend("mongo", function($app)
{
return new MongoHandler;
});
當會話驅動注冊之后,在配置文件app/config/session.php中指定mongo配置就能使用我們自定義的session驅動了。
認證</>復制代碼
分享你的成果
記住,如果你實現了自己的session驅動,可以在Packagist上分享給大家!
類似緩存和會話擴展,我們繼續從method方法開始:
</>復制代碼
Session::extend("mongo", function($app)
{
return new MongoHandler;
});
接口UserProviderInterface的實現指責是從各種持久化存儲系統如MySQL、Riak等中獲取數據,并返回接口UserInterface實現的對象。這兩個接口可以讓Laravel專注于驗證本身,而無需關心用戶數據的存儲實現,以及用戶對象是那種類來表示的問題。
讓我們先看一下UserProviderInterface接口:
</>復制代碼
interface UserProviderInterface {
public function retrieveById($identifier);
public function retrieveByCredentials(array $credentials);
public function validateCredentials(UserInterface $user, array $credentials);
}
retrieveById方法通常接收的參數是一個唯一標識符,例如MySQL數據庫中的主鍵自增索引ID。該方法將獲取$identifier對應的數據,并返回接口UserInterface實現類的實例化對象。
當用戶試圖登錄系統時,retrieveByCredentials方法接收參數是一個驗證數組,同時他也是傳入Auth::attempt的參數。該方法會“查詢”給定的用戶驗證數據,通常,它會根據$credentials["username"]運行一個“查詢”條件語句來匹配數據。請不要用本方法進行任何密碼的校驗或驗證。
方法validateCredentials會通過對比$user和$credentials來驗證用戶。例如,方法中會對$user->getAuthPassword();得到的字符串和$credentials["password"]通過Hash::make加密后的結果進行對比。
上面我們探索了UserProviderInterface中的各個方法,接下來看一看UserInterface接口。記住,上面提供器中的retrieveById和retrieveByCredentials方法返回的就是本接口實現類的實例化對象:
</>復制代碼
interface UserInterface {
public function getAuthIdentifier();
public function getAuthPassword();
}
接口很簡單。getAuthIdentifier返回用戶的“主鍵索引”。在MySQL后臺存儲系統中,這里就指代用戶表的主鍵自增索引。getAuthPassword返回用戶密碼的哈希值。這種接口的實現方式使認證系統和User類完全分離,并能在各種類型的實現下正常工作,而不用關心我們用的是ORM方式還是其他存儲層實現的方式。在app/models下,Laravel已經實現了該接口的User類,你可以參考下這個類。
實現接口UserProviderInterface后,我們就做好了將我們的擴展注冊進Auth門面的準備:
</>復制代碼
Auth::extend("riak", function($app)
{
return new RiakUserProvider($app["riak.connection"]);
});
在method注冊之后,我們就能在app/config/auth.php中切換新的驗證驅動了。
基于IoC容器的擴展幾乎所有Laravel框架包含的服務提供器都是作為對象綁定到IoC容器中的。在配置文件app/config/app.php中有詳細的列表。有時間的話,最好過一遍源碼。這樣,你能了解框架都加載了哪些服務,也就是容器中綁定的各式的服務。
比如,PaginationServiceProvider把paginator綁定到容器中,他對應的是IlluminatePaginationEnvironment的實例。你可以很容易的通過擴展重寫這些類并重新綁定到容器中。又如,我們來擴展下基礎的Environment類:
</>復制代碼
namespace SnappyExtensionsPagination;
class Environment extends IlluminatePaginationEnvironment {
//
}
擴展完成之后,在創建一個新的SnappyPaginationProvider服務提供器,并在boot方法中替換掉原有的paginator:
</>復制代碼
class SnappyPaginationProvider extends PaginationServiceProvider {
public function boot()
{
App::bind("paginator", function()
{
return new SnappyExtensionsPaginationEnvironment;
}
parent::boot();
}
}
注意,本類繼承的PaginationServiceProvider,并不是默認的ServiceProvider。當完成擴展之后要記住app/config/app.php中替換成自己的擴展名稱。
這就是對容器中已經綁定的核心類庫進行擴展的方法。實際上,所有核心類庫都能用這種方式進行重寫。深入閱讀源碼,能幫你熟練知曉Laravel是怎么將各個部分組織在一起運轉的。
請求的擴展因為在每個請求的生命周期中,請求是很早就會被實例化的一個最基礎的部分,所以Request的擴展會有稍許不同。
首先,還是像往常一樣實現一個子類:
</>復制代碼
namespace QuickBillExtensions;
class Request extends IlluminateHttpRequest {
// Custom, helpful methods here...
}
然后,打開bootstrap/start.php,它是請求到達應用時最早被包含的文件。注意這里被執行的第一個動作就是創建Laravel的實例化對象$app:
</>復制代碼
$app = new IlluminateFoundationApplication;
當對象被創建,同時也會創建IlluminateHttpRequest實例,并以request鍵綁定到IoC容器中。這里,我們應該另辟途徑實現一個類來作為“默認的”請求類型,對不對?還好,requestClass方法就能幫我們那實現它!所以我們需要在bootstrap/start.php文件開頭加上這樣一行:
</>復制代碼
use IlluminateFoundationApplication;
Application::requestClass("QuickBillExtensionsRequest");
當添加玩自定義的請求類后,Laravel在任何地方都能用到我們的這個自定義的Request實例,這能使我們實現的定義請求類的實例可用,甚至在單元測試中也能使用。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/23008.html
摘要:官方地址是目前最流行的框架,發展勢頭迅猛,應用非常廣泛,有豐富的擴展包可以應付你能想到的各種應用場景,框架思想前衛,跟隨時代潮流,提倡優雅代碼,自稱為工匠,其中的模板引擎容器以及擴展包為業務的開發提供了極大的便利。 laravel5.5+ laravel官方地址 laravel是目前最流行的php框架,發展勢頭迅猛,應用非常廣泛,有豐富的擴展包可以應付你能想到的各種應用場景,lara...
摘要:前言年底了不太忙,最近一段時間也一直在研究,就想寫篇關于比較深一點的教程系列啥的,于是就找到站長給開了寫教程的渠道。優點的就是為藝術家創造的框架,它也是工程化的趨勢。項目維護方便也是事實。如果有遇到問題可以直接在教程下面留言。 前言 年底了不太忙,最近一段時間也一直在研究laravel,就想寫篇關于laravel比較深一點的教程系列啥的,于是就找到站長給開了寫教程的渠道。由于第一次寫,...
摘要:一個服務提供器必須包含至少一種方法。服務提供器一旦被注冊,就可被用于程序的各個地方。注意服務提供器的變量來自類中。啟動服務當所有的服務提供器注冊之后,他們就變成了已啟動狀態。再次提示,把服務提供器作為一種組織工具來使用。 聲明:本文并非博主原創,而是來自對《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當然也不是原汁原味的翻譯,能保證90%...
摘要:目前來看等語言還難以企及和。作為一個資深的開發者,在技術上給各位程序十點未來的建議,希望對大家有所幫助。開發者應當學習掌握規范,在開發程序時應當盡量遵循規范。程序員除了寫后臺程序之外,還有很大一部分工作在展現層,和瀏覽器前端打交道。 PHP 從誕生到現在已經有20多年歷史,從Web時代興起到移動互聯網退潮,互聯網領域各種編程語言和技術層出不窮, Node.js 、 GO 、 Pytho...
閱讀 2323·2021-11-08 13:13
閱讀 1256·2021-10-09 09:41
閱讀 1701·2021-09-02 15:40
閱讀 3195·2021-08-17 10:13
閱讀 2558·2019-08-29 16:33
閱讀 3134·2019-08-29 13:17
閱讀 3143·2019-08-29 11:00
閱讀 3306·2019-08-26 13:40