laravel 的整個框架中蜡励,任何一個模塊都可以刪除和修改,也可以任意增加自己的模塊阻桅,這也是laravel的靈活和強(qiáng)大之處凉倚。
laravel工作流程以及自定義provider創(chuàng)建
首先 laravel構(gòu)架的文件都在下面這個文件夾中
vendor/laravel/framework/src
具體流程
1.首先進(jìn)入我們熟悉的public下面,這是項(xiàng)目訪問的默認(rèn)目錄嫂沉,打開index.php,加載了一個app文件
$app = require_once __DIR__.'/../bootstrap/app.php';
2.打開這個bootstrap/app.php稽寒,看到里面實(shí)例化了一個叫做Application的類
$app = new Illuminate\Foundation\Application( realpath(__DIR__.'/../'));
3.打開這個文件,發(fā)現(xiàn)這個application文件繼承了container對象
class Application extends Container
4.所以這個bootstrap下面的app.php其實(shí)是實(shí)例化了Application,而Application又繼承自容器對象趟章。
5.重新回到bootstrap/app.php,發(fā)現(xiàn)他在里面綁定了很多類并返回,
每個綁定里面有兩個類杏糙,第一個是接口慎王,第二個才是真正的類。
$app->singleton(Illuminate\Contracts\Http\Kernel::class, App\Http\Kernel::class);
......
return $app;
6.所以我們自己也可以在這里綁定我們自己寫的類,并通過下面兩種方法來調(diào)用宏侍。
//綁定自己的類
$app->singleton('Test',App\Http\Test);
//調(diào)用(全局環(huán)境下)
$u = $this->app->make('Test');
$u = $this->appp['Test'];
這個就叫做工廠模式赖淤,所謂工廠的意思就是,以前你要每次實(shí)例化一個類才能獲得這個類的方法屬性谅河,但是現(xiàn)在你可以通過make(),或app['']咱旱,得到這個類。
7.假如你寫了以下兩個對象绷耍,將Ta對象作為參數(shù)傳入Tb對象的構(gòu)造函數(shù)中吐限,將會自動為你實(shí)例化Ta類為ta,這個叫做依賴注入褂始,經(jīng)持畹洌看到的(REQUEST $request),就是這個道理。但是前提是你的Ta 和Tb類都已經(jīng)綁定注冊過了崎苗。
class Ta
{
public $jacklin狐粱;
public function test()
{
echo 'tb';
}
}
class Tb
{
private $ta;
public function __construct(Ta $ta)
{
$this->ta = $ta;
}
public function test()
{
echo "tb";
}
}
8.剛才說到,我們自定義的對象可以在bootstrap/app.php中綁定注冊益缠,但是這個文件是個入口文件脑奠,多人合作的項(xiàng)目中,合并版本的時候會遇到?jīng)_突幅慌,所以要有一個合適的位置進(jìn)行注冊綁定的步驟宋欺。全局唯一的文件肯定不合適,那么控制器能不能注冊呢胰伍,不行齿诞,比如(Request $request)這個例子來說,肯定是要先已經(jīng)注冊過Request這個類骂租,才能依賴注入祷杈,所以假如寫在控制器有很多情況是無法使用我們注冊的類的。那么重新回到開始的文件渗饮,在public/index.php下但汞,除了剛才的加載app類,還有下面一句
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
這句話按照他的文件去找我是蒙逼了互站,但是大概的意思就是make了一個http的kernel內(nèi)核私蕾,按照龍哥的指示,直接找到http下面的kernel
9.找到app/Http/Kernel之后發(fā)現(xiàn)他除了加載我們熟悉的中間件胡桃,還繼承了一個內(nèi)核文件
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel{}
找到這個文件踩叭,發(fā)現(xiàn)下面的啟動數(shù)組,環(huán)境,配置容贝,處理異常等等自脯。laravel會遍歷這個數(shù)組,把里面的東西分別啟動斤富。
protected $bootstrappers = [
'Illuminate\Foundation\Bootstrap\DetectEnvironment',
'Illuminate\Foundation\Bootstrap\LoadConfiguration',//config/app.php
'Illuminate\Foundation\Bootstrap\ConfigureLogging',
'Illuminate\Foundation\Bootstrap\HandleExceptions',
'Illuminate\Foundation\Bootstrap\RegisterFacades',
'Illuminate\Foundation\Bootstrap\RegisterProviders',//注冊服務(wù)提供者
'Illuminate\Foundation\Bootstrap\BootProviders',
];
在加載配置的時候膏潮,程序會加載config里面中的app.php,有一段下面的程序,可以看到满力,他加載了所有的服務(wù)提供者的模塊戏罢。并且 'Illuminate\Foundation\Bootstrap\RegisterProviders',會把a(bǔ)pp.php里面記錄的的服務(wù)提供者都注冊
'providers' => [
/*
* Laravel Framework Service Providers...
*/
Illuminate\Foundation\Providers\ArtisanServiceProvider::class,
Illuminate\Auth\AuthServiceProvider::class,
Illuminate\Broadcasting\BroadcastServiceProvider::class,
Illuminate\Bus\BusServiceProvider::class,
Illuminate\Cache\CacheServiceProvider::class,
Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
Illuminate\Routing\ControllerServiceProvider::class,
Illuminate\Cookie\CookieServiceProvider::class,
Illuminate\Database\DatabaseServiceProvider::class,
Illuminate\Encryption\EncryptionServiceProvider::class,
Illuminate\Filesystem\FilesystemServiceProvider::class,
Illuminate\Foundation\Providers\FoundationServiceProvider::class,
Illuminate\Hashing\HashServiceProvider::class,
Illuminate\Mail\MailServiceProvider::class,
Illuminate\Pagination\PaginationServiceProvider::class,
Illuminate\Pipeline\PipelineServiceProvider::class,
Illuminate\Queue\QueueServiceProvider::class,
Illuminate\Redis\RedisServiceProvider::class,
Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
Illuminate\Session\SessionServiceProvider::class,
Illuminate\Translation\TranslationServiceProvider::class,
Illuminate\Validation\ValidationServiceProvider::class,
Illuminate\View\ViewServiceProvider::class,
/*
* Application Service Providers...
*/
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
],
9.那么我們要注冊的方法到底在哪里呢,找到App/Providers,隨便打開里面的文件脚囊。發(fā)現(xiàn)下面代碼
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
打開這個文件
public function __construct($app){$this->app = $app;}
發(fā)現(xiàn)這個類注入了app對象,所以在Provider的范圍內(nèi)也可以寫
$this->app
重新回到剛才打開的AppServiceProvider桐磁,里面有一個注冊方法
public function register()
這里就是我們要注冊自己寫的類的地方了悔耘,把我們綁定的語句寫進(jìn)來,注意是$this->app
public function register()
{
$this->app->singleton(\App\Ta::class,\App\Ta::class);
$this->app->singleton(\App\Tb::class,\App\Tb::class);
}
這里要注意命名空間的問題我擂,App前面要加上\從根命名空間查找
這樣衬以,laravel加載內(nèi)核文件的時候,就會將我們寫好的服務(wù)提供者文件加載進(jìn)去校摩。
剛才是在AppServiceProvider中注冊了我們的模塊看峻,那怎么創(chuàng)建自己的Provider呢,首先在同樣的目錄下創(chuàng)建文件JacklinServiceProvider.php衙吩,基礎(chǔ)內(nèi)容可以從別的Provider文件復(fù)制互妓,然后同樣在注冊方法中寫入自己的類,最后坤塞,還要在剛才的config\app.php中的冯勉,providers[]里面加入我們新的服務(wù)提供者類,OK了摹芙。
10.上面已經(jīng)能夠把我們自己寫的模塊加進(jìn)去了灼狰,那還有一個問題,我們這樣每次調(diào)用自己的模塊都要通過工廠模式make出來浮禾,還是很麻煩交胚,但是系統(tǒng)的方法似乎很簡單,比如DB::盈电,Input::,就 可以直接調(diào)用方法蝴簇,這是為什么呢?laravel又提供了另外一個東西挣轨,叫做facades军熏,這個單詞的本意是門面的意思,下面開始解釋這個東西卷扮。
首先隨意創(chuàng)建一個Test.php,我們先創(chuàng)建在App\Http荡澎,寫入以下內(nèi)容
<?php
namespace App\Http\Facades;
class Ta extends \Illuminate\Support\Facades\Facade
{
protected static function getFacadeAccessor()
{
return '\App\Ta';
}
}
從內(nèi)容上不難看到均践,這是\Illuminate\Support\Facades\Facade,的一個方法摩幔,大概的意思就是把Ta這個對象實(shí)例化出來彤委,并且嵌套在自己的一個靜態(tài)方法里面,給這個class起個跟Ta一樣的名字或衡,那么當(dāng)你Ta的時候焦影,這個類也就加載了\App\Ta,所以就造成了Ta::也能用Ta里面的方法封断。
//調(diào)用
App\Http\Facades\Ta::test();
這么調(diào)用好像也很麻煩斯辰,怎么樣能像DB::那樣直接用呢,還有一步坡疼,配置aliases彬呻,本意別名
還是剛才的config/app.php中,在aliases中加入
'Jacklin' => App\Http\Facades\Ta::class,
這樣又把Ta類的方法轉(zhuǎn)移到了Jacklin身上柄瑰,試試闸氮,下面方法可以執(zhí)行,一套自己的‘靜態(tài)’provider就弄好了教沾,而且還把訪問的方式美化了蒲跨,這也就是laravel用facader這個詞命名這個方法的意思吧
Jacklin::test();
11.最后剛才創(chuàng)建的這個JacklinServiceProvider.php是隨便放了個文件夾授翻,顯然不合適或悲,那么在app/Http 下面創(chuàng)建一個Facades文件夾,然后把JacklinServiceProvider.php放進(jìn)去藏姐,并修改命名空間即可隆箩。
12.另外,我們的Ta Tb也是直接創(chuàng)建在了app里羔杨,同樣的道理捌臊,在app/Http下建立Module文件夾,把我們的模塊放進(jìn)去兜材。
總結(jié)
為了便于記憶理澎,整理一下完成一個provider的思路。
1.建立Modules文件夾和Facades
2.在Modules建立模塊文件Test.php
3.在Provider中建立TestServiceProvider.php曙寡,復(fù)制AppServiceProvider.php,里的基礎(chǔ)內(nèi)容糠爬,在register()方法中注冊前面寫的Test模塊
$this->app->singleton(\App\Http\Modules\Test::class,\App\Http\Modules\Test::class);
4.在config/app.php的providers[]中加入
App\Providers\TestServiceProvider::class,
5.在app/Http/Facades中建立Jacklin.php,模仿靜態(tài)方法
<?php
namespace App\Http\Facades;
class Test extends \Illuminate\Support\Facades\Facade
{
protected static function getFacadeAccessor()
{
return '\App\Http\Modules\Test';
}
}
6.在config/app.php的aliases[]中加入
'Test' => App\Http\Facades\Test::class,
7.OK了