Laravel-admin 源码分析系列 1——注册服务与安装分析

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
本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 3年前 自动加精
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 5
Jourdon

就喜欢看这种源码分析

4年前 评论
❤seven (楼主) 4年前

期待下集分享 :+1:

4年前 评论

@xxx 明天加班继续

4年前 评论
jlwgeneral 4年前

兄弟 期待你下次更新 :kissing_heart:

4年前 评论
❤seven (楼主) 4年前
caomaoboy (作者) 4年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!