laravel容器延迟加载以及auth扩展详解


Posted in PHP onMarch 02, 2015

昨天按照手册教程,动手写一个Auth扩展,按照包独立性的原则,我不希望将Auth::extend()这种方法写在 start.php 中,毫无疑问,我选择了在服务提供器register()方法中注册扩展驱动。然而,事与愿违……

发现问题

当我在 LoauthServiceProvider 中这样写的时候:

public function register()

{

    //

    \Auth::extend('loauth',function($app){});

}

报错

Call to undefined method Illuminate\Support\Facades\Auth::extend()

寻找原因

当时就纳闷了,找原因,怀疑是Auth没注册?检查发现注册了,因为在路由中可以使用;php artisan clear-compiled 没用;百思不得其解,甚至怀疑是我不小心修改了核心类,还重新下载了一次laravel包,问题依旧。

折腾了一晚上,最终我把目光锁定在 AuthServiceProvider 的 $defer 属性。

根据手册以及注释,我们得知 $defer 属性是用来延迟加载该服务提供器,说直白点就是延迟执行 register() 方法,只需要配合provides()方法即可实现。举个例子:

public function provides()

{

    return array('auth');

}

这个是 AuthServiceProvider 里的方法,当框架初始化的时候,会依次加载服务提供器,如果发现这个服务提供器protected $defer=true 那么就会调用它的 provides() 方法,其返回的数组包含需要延迟加载的服务名称,这样当我们在路由、控制器或者其他地方调用 Auth::METHOD() 的时候,才会去调用提供器的 register() 方法。

确定症结

那么问题来了,既然是被动延迟加载,也就是说当我调用Auth类方法时应该会自动实例化Auth类啊,为什么我在LoauthServiceProvider中调用的时候却提示方法不存在,但是在路由中却可以呢。

我猜测是因为优先级的问题,可能在框架注册 LoauthServiceProvider::register() 的时候,Auth 还没有标记为延迟加载,这就造成了一个先后问题,任何即时加载的服务提供器都无法在register方法中调用延迟加载的服务。

经过研究,顺利在核心代码中找到证据 Illuminate\Foundation\ProviderRepository

public function load(Application $app, array $providers)

{

    //...省略

    // We will go ahead and register all of the eagerly loaded providers with the

    // application so their services can be registered with the application as

    // a provided service. Then we will set the deferred service list on it.

    foreach ($manifest['eager'] as $provider)

    {

        $app->register($this->createProvider($app, $provider));

    }

    //延迟加载标记在即时加载服务之后

    $app->setDeferredServices($manifest['deferred']);

}

解决之道

虽然发现了问题所在,但并不代表问题就解决了,修改核心代码不是个明智的选择,所以只能在我们自己的包里想办法咯,一个解决方案如下:

public function register()

{

    //

    $authProvider = new \Illuminate\Auth\AuthServiceProvider($this->app);

    $authProvider->register();

    \Auth::extend('loauth',function($app){});

}

既然auth还未注册,那么我们手动调用它的register方法帮它注册。

以上就是本文的全部内容了,希望大家能够喜欢。

PHP 相关文章推荐
使用php发送有附件的电子邮件-(PHPMailer使用的实例分析)
Apr 26 PHP
thinkphp中连接oracle时封装方法无法用的解决办法
Jun 17 PHP
php输入流php://input使用示例(php发送图片流到服务器)
Dec 25 PHP
php创建和删除目录函数介绍和递归删除目录函数分享
Nov 18 PHP
php中判断数组相等的方法以及数组运算符介绍
Mar 30 PHP
PHP准确取得服务器IP地址的方法
Jun 02 PHP
php自定义函数实现汉字转换utf8编码的方法
Sep 29 PHP
php中html_entity_decode实现HTML实体转义
Jun 13 PHP
PHP创建文件及写入数据(覆盖写入,追加写入)的方法详解
Feb 15 PHP
PHP中遍历数组的三种常用方法实例分析
Jun 24 PHP
thinkphp5 redis缓存新增方法实例讲解
Mar 24 PHP
php 解析非标准json、非规范json
Apr 01 PHP
laravel安装zend opcache加速器教程
Mar 02 #PHP
分享一个Laravel好用的Cache宏
Mar 02 #PHP
php解析http获取的json字符串变量总是空白null
Mar 02 #PHP
laravel 5 实现模板主题功能(续)
Mar 02 #PHP
laravel 5 实现模板主题功能
Mar 02 #PHP
Opcache导致php-fpm崩溃nginx返回502
Mar 02 #PHP
使用GDB调试PHP代码,解决PHP代码死循环问题
Mar 02 #PHP
You might like
用PHP实现的四则运算表达式计算实现代码
2011/08/02 PHP
一些需要禁用的PHP危险函数(disable_functions)
2012/02/23 PHP
thinkPHP简单实现多个子查询语句的方法
2016/12/05 PHP
Thinkphp5 自定义上传文件名的实现方法
2019/07/23 PHP
让广告代码不再影响你的网页加载速度
2006/07/07 Javascript
关于JavaScript的gzip静态压缩方法
2007/01/05 Javascript
JAVASCRIPT  THIS详解 面向对象
2009/03/25 Javascript
基于jQuery的淡入淡出可自动切换的幻灯插件打包下载
2010/09/15 Javascript
jquery jqPlot API 中文使用教程(非常强大的图表工具)
2011/08/15 Javascript
JavaScript中this的使用详解
2013/11/08 Javascript
asm.js使用示例代码
2013/11/28 Javascript
jQuery获取(选中)单选,复选框,下拉框中的值
2014/02/21 Javascript
jQuery操作表格(table)的常用方法、技巧汇总
2014/04/12 Javascript
js表头排序实现方法
2015/01/16 Javascript
vue.js获取数据库数据实例代码
2017/05/26 Javascript
详解angular 中的自定义指令之详解API
2017/06/20 Javascript
jquery获取链接地址和跳转详解(推荐)
2017/08/15 jQuery
JavaScript实现树的遍历算法示例【广度优先与深度优先】
2017/10/26 Javascript
vuex 项目结构目录及一些简单配置介绍
2018/04/08 Javascript
详细分析JavaScript中的深浅拷贝
2020/09/17 Javascript
echarts实现晶体球面投影的实例教程
2020/10/10 Javascript
[01:27]2014DOTA2展望TI 剑指西雅图IG战队专访
2014/06/30 DOTA
[01:25:33]完美世界DOTA2联赛PWL S3 INK ICE vs Magma 第二场 12.20
2020/12/23 DOTA
Python处理XML格式数据的方法详解
2017/03/21 Python
python实现excel读写数据
2021/03/02 Python
详解Python3注释知识点
2019/02/19 Python
详解使用PyInstaller将Pygame库编写的小游戏程序打包为exe文件
2019/08/23 Python
pandas将多个dataframe以多个sheet的形式保存到一个excel文件中
2019/10/10 Python
Python SQLAlchemy入门教程(基本用法)
2019/11/11 Python
python两个_多个字典合并相加的实例代码
2019/12/26 Python
利用python中集合的唯一性实现去重
2020/02/11 Python
Otticanet澳大利亚:最顶尖的世界名牌眼镜, 能得到打折季的价格
2018/08/23 全球购物
什么是ARP(Address Resolution Protocol)地址解析协议
2013/10/31 面试题
学校领导班子四风对照检查材料
2014/09/27 职场文书
部门主管竞聘书
2015/09/15 职场文书
php实现自动生成验证码的实例讲解
2021/11/17 PHP