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的信息
结果为:
然后在执行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;
}
}
这段代码指明加载
这个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 协议》,转载必须注明作者和本文链接
就喜欢看这种源码分析
耐思
期待下集分享 :+1:
@xxx 明天加班继续
兄弟 期待你下次更新 :kissing_heart: