Laravel-admin 原始碼分析系列 1——註冊服務與安裝分析

❤seven發表於2019-08-03

Laravel-admin 安裝分析

最近閒的無聊,近來想著把laravel-admin的原始碼看一看,寫個筆記記錄一下,廢話不多說,開始搞起。第一次寫,沒經驗

一、安裝

1. Composer 以及 Laravel 的自動發現服務

首先執行composer安裝 Laravel-admin

composer require encore/laravel-admin

安裝後,目錄結構在 vendor\encore\admin

| -- config 配置檔案目錄
| -- database 資料庫檔案目錄
    | -- migrations 資料遷移檔案目錄 用於遷移admin的初始資料庫結構
| -- docs 文件目錄
| -- resources 靜態資源模板目錄
    | --  assets 存放 js、css 資源目錄
    | --  lang   國際化語言目錄
    | --  views blade模板目錄
| --    src 
    |-- Actions  
        |-- Interactor 返回操作資訊的提醒目錄
    |-- Auth 許可權目錄
        |-- Database model目錄
|-- Console Artisan 命令目錄
|-- Controllers 控制器目錄
|-- Exception 異常處理目錄
|-- Facades 門面目錄
|-- Form 表單目錄
|-- grid 列表目錄
|-- Layout 佈局目錄
|-- Middleware 中介軟體目錄
|-- Show 欄位、皮膚等小元件展示渲染處理目錄
|-- Trait Trait目錄
|-- Tree  樹形元件渲染目錄
|-- Widgets 小部件目錄
|-- Tests 測試目錄

Composer 安裝完以後執行,就執行下面的命令來發布資源:

php artisan vendor:publish --provider="Encore\Admin\AdminServiceProvider"

能釋出資源也就是說此時 “Encore\Admin\AdminServiceProvider” 就已經被註冊到 Laravel 的容器裡面了,不用手動寫在 app.php 配置檔案裡面,那麼這個功能是如何實現的呢,答案是 Laravel5.5 的自動發現功能,看一下 Laravel-admin 的 composer.json 這個檔案中的一個配置

    "extra": {
        "laravel": {
            "providers": [
                "Encore\\Admin\\AdminServiceProvider"
            ],
            "aliases": {
                "Admin": "Encore\\Admin\\Facades\\Admin"
            }
        }
    }

Laravel 會通過這一段配置自動將此服務註冊進容器(注:需框架5.5以上才有此功能), Laravel-admin 通過 AdminServiceProvider 將 自身攜帶的 路由、中介軟體、Artisan命令列註冊進入框架使用

二、AdminServiceProvider註冊服務

開啟AdminServiceProvider檔案,我們先從 register() 這個方法看起,因為laravel框架會首先執行裡面的程式碼。

  public function register()
    {
        //載入 admin 許可權的資訊
        $this->loadAdminAuthConfig();
        //註冊路由中介軟體
        $this->registerRouteMiddleware();
        //註冊Artisan 命令
        $this->commands($this->commands);
    }

1. $this->loadAdminAuthConfig() 載入 admin 許可權的資訊;

    /**
     * Setup auth configuration.
     *
     * @return void
     */
    protected function loadAdminAuthConfig()
    {
        config(Arr::dot(config('admin.auth', []), 'auth.'));        
    }

Arr::dot() 作用把多維陣列扁平化成一維陣列,並用「點」式語法表示深度。config('admin.auth') 獲取配置檔案admin.php裡面auth的資訊
結果為:

Laravel-admin 原始碼分析系列 1——註冊服務與安裝分析

然後在執行config($key ) 這個外部的判斷形參為一個陣列就會執行 app('config')->set($key) 也就是說設定配置,至此相關許可權的配置被載入到框架中

2. $this->registerRouteMiddleware(); 註冊路由中介軟體

    protected function registerRouteMiddleware()
    {
        // register route middleware.
        foreach ($this->routeMiddleware as $key => $middleware) {
            app('router')->aliasMiddleware($key, $middleware);
        }

        // register middleware group.
        foreach ($this->middlewareGroups as $key => $middleware) {
            app('router')->middlewareGroup($key, $middleware);
        }
    }

其中 $this->routeMiddleware 屬性為

    protected $routeMiddleware = [
        //負責檢測管理員是否登入,以及登入後跳轉的頁面或未登入跳轉 login 頁面
        'admin.auth'       => Middleware\Authenticate::class,
        //此中介軟體為後置中介軟體,檢測是否開啟pajx  如果開啟採取pajx方式返回資訊。以及判斷錯誤資訊的返回格式都在這裡面
        'admin.pjax'       => Middleware\Pjax::class,
        //日誌中介軟體 記錄管理員操作資訊
        'admin.log'        => Middleware\LogOperation::class,
        //檢測管理員許可權的中介軟體 包括路由許可權 
        'admin.permission' => Middleware\Permission::class,
        //初始化admin 可以在bootstrap.php 檔案裡面載入擴充套件 靜態資源等等o.o
        'admin.bootstrap'  => Middleware\Bootstrap::class,
        //設定admin的session資訊 可以在配置檔案裡面找到這些
        'admin.session'    => Middleware\Session::class,
    ];

路由中介軟體主要就是做了這些工作(都在註釋裡面寫著裡- -)然後通過

   foreach ($this->routeMiddleware as $key => $middleware) {
            app('router')->aliasMiddleware($key, $middleware);
        }

迴圈註冊到 router 例項裡面 路由群組同理:

 protected $middlewareGroups = [
        'admin' => [
            'admin.auth',
            'admin.pjax',
            'admin.log',
            'admin.bootstrap',
            'admin.permission',
//            'admin.session',
        ],
    ];

這些都是每個admin的路由需要的中介軟體,後面的程式碼會用到
接下來就是註冊 Artisan 命令列了

protected $commands = [
  Console\AdminCommand::class,
  Console\MakeCommand::class,
  Console\MenuCommand::class,
  Console\InstallCommand::class,
  Console\PublishCommand::class,
  Console\UninstallCommand::class,
  Console\ImportCommand::class,
  Console\CreateUserCommand::class,
  Console\ResetPasswordCommand::class,
  Console\ExtendCommand::class,
  Console\ExportSeedCommand::class,
  Console\MinifyCommand::class,
  Console\FormCommand::class,
  Console\PermissionCommand::class,
  Console\ActionCommand::class,
];
 /**
     * Register the package's custom Artisan commands.
     *
     * @param  array|mixed  $commands
     * @return void
     */
    public function commands($commands)
    {
        $commands = is_array($commands) ? $commands : func_get_args();

        Artisan::starting(function ($artisan) use ($commands) {
            $artisan->resolveCommands($commands);
        });
    }

這些命令沒啥解讀的 把這個命令註冊進入框架後 執行 php artisan list 就能看到 admin 之類的命令 就是在這裡實現的。
至此 服務註冊已經完成了 ,主要就是註冊 許可權配置 ,路由中介軟體,以及 Artisan 命令例如後面用到的

 php artisan admin:install

三、AdminServiceProvider啟動環節

接下來就是服務容器的啟動,也就是 boot() 方法, 來看看 Laravel-admin 的啟動環節

  /**
     * Boot the service provider.
     *
     * @return void
     */
    public function boot()
    {
        //得到Blade檢視的路徑 註冊到 view 例項裡面
        $this->loadViewsFrom(__DIR__.'/../resources/views', 'admin');
        //根據配置檔案 admin.https 是否設定 Https 強制轉換 Https
        $this->ensureHttps();
        //載入路由檔案
        if (file_exists($routes = admin_path('routes.php'))) {
            $this->loadRoutesFrom($routes);
        }
        //註冊需要釋出的資源 只在 artisan 命令列下生效
        $this->registerPublishing();
        //相容 Laravel 版本的方法 大概就是不要兩次 'echo'?? 這個俺也不懂= =
        $this->compatibleBlade();
    }

1.Blade檢視的路徑

 // $this->loadViewsFrom(__DIR__.'/../resources/views', 'admin');
  protected function loadViewsFrom($path, $namespace)
    {
        //$this->app->config['view']['paths'])="E:\www\blog\resources\views"
        if (is_array($this->app->config['view']['paths'])) {
            foreach ($this->app->config['view']['paths'] as $viewPath) {
                if (is_dir($appPath = $viewPath.'/vendor/'.$namespace)) {
                    $this->app['view']->addNamespace($namespace, $appPath);
                }
            }
        }
        $this->app['view']->addNamespace($namespace, $path);
    }

上面的程式碼主要是註冊了 Laravel-admin 的倆個檢視路徑 其中一個是擴充套件包裡面的路徑,另外一個在框架的resource\views\admin這個路徑。實現方法如下:

   public function addNamespace($namespace, $hints)
    {
        $hints = (array) $hints;
        //判斷是否存在這個hints
        if (isset($this->hints[$namespace])) {
            //將後來的檢視路徑新增到陣列前面,先使用
            $hints = array_merge($this->hints[$namespace], $hints);
        }

        $this->hints[$namespace] = $hints;
    }

也就是說 'admin' 空間下有倆個檢視路徑 其中的作用就是你可以在框架下面的 resource\views 下新建 admin 的檔案目錄。Laravel 會優先使用這個檢視路徑,這也就對應文件裡面如何修改檢視的解決方案啦-。- (其中用 php artisan serve 啟動伺服器的方法 resource下面的 admin目錄 目測不起作用,因為路徑是錯著裡。。所以你這種方式按照文件覆蓋估計也麼啥作用 請用apache nginx)

2. https 配置

//        $this->ensureHttps();
protected function ensureHttps()
{
//還是配置檔案裡面配置
  if (config('admin.https') || config('admin.secure')) {
          //強制https
        url()->forceScheme('https');
       $this->app['request']->server->set('HTTPS', true);
  }
}

這個沒啥說的,就是將後臺切換到https

3.載入路由檔案

   /** if (file_exists($routes = admin_path('routes.php'))) {
            $this->loadRoutesFrom($routes);
        }**/
    protected function loadRoutesFrom($path){
      if (! $this->app->routesAreCached()) {
          require $path;
  }
}           

這段程式碼指明載入

Laravel-admin 原始碼分析系列 1——註冊服務與安裝分析

這個routes.php,這個是麼辦法改變了,可以通過 admin.php 指定哪個目錄下的 routes.php。執行之後。就能訪問後臺管理的連結了

4 註冊遷移靜態資源

    protected function registerPublishing()
    {
        if ($this->app->runningInConsole()) {
            $this->publishes([__DIR__.'/../config' => config_path()], 'laravel-admin-config');
            $this->publishes([__DIR__.'/../resources/lang' => resource_path('lang')], 'laravel-admin-lang');
            $this->publishes([__DIR__.'/../database/migrations' => database_path('migrations')], 'laravel-admin-migrations');
            $this->publishes([__DIR__.'/../resources/assets' => public_path('vendor/laravel-admin')], 'laravel-admin-assets');
        }
    }

在命令列模式下。會將 config lang migrations assets 註冊到資源釋出裡面,通過

php artisan vendor:publish --provider="Encore\Admin\AdminServiceProvider"

釋出到框架下面

總結:

至此 Laravel-admin 前期需要的服務載入到框架裡面,先寫這麼多,後面再看看

php artisan admin:install

相關文章