最新公告
  • 欢迎您访问爱上源码网,分享精品整站源码,网站模板,游戏源码,APP小程序源码以及视频教程免费下载;服务永无止境!立即加入我们
  • Pimple运行流程浅析(PHP容器)

    爱上源码网文章Pimple运行流程浅析(PHP容器)的内容插图

    需要具备的知识点

    闭包

    闭包和匿名函数在PHP5.3.0中引入的。

    闭包是指:

    创建时封装周围状态的函数。即使闭包所处的环境不存在了,闭包中封装的状态依然存在。

    理论上,闭包和匿名函数是不同的概念。但是PHP将其视作相同概念。

    实际上,闭包和匿名函数是伪装成函数的对象。他们是Closure类的实例。

    闭包和字符串、整数一样,是一等值类型。

    创建闭包:

    <?php
    $closure = function ($name) {
        return 'Hello ' . $name;
    };
    echo $closure('nesfo');//Hello nesfo
    var_dump(method_exists($closure, '__invoke'));//true

    我们之所以能调用$closure变量,是因为这个变量的值是一个闭包,而且闭包对象实现了__invoke()魔术方法。只要变量名后有(),PHP就会查找并调用__invoke()方法。

    通常会把PHP闭包当作函数的回调使用。

    array_map(), preg_replace_callback()方法都会用到回调函数,这是使用闭包的最佳时机!

    举个例子:

    <?php
    $numbersPlusOne = array_map(function ($number) {
        return $number + 1;
    }, [1, 2, 3]);
    print_r($numbersPlusOne);

    得到结果:

    [2, 3, 4]

    在闭包出现之前,只能单独创建具名函数,然后使用名称引用那个函数。这么做,代码执行会稍微慢点,而且把回调的实现和使用场景隔离了。

    <?php
    function incrementNum ($number) {
        return $number + 1;
    }
    $numbersPlusOne = array_map('incrementNum', [1, 2, 3]);
    print_r($numbersPlusOne);

    SPL

    ArrayAccess

    实现ArrayAccess接口,可以使得object像array那样操作。ArrayAccess接口包含四个必须实现的方法:

    interface ArrayAccess {
        //检查一个偏移位置是否存在 
        public mixed offsetExists ( mixed $offset  );
        
        //获取一个偏移位置的值 
        public mixed offsetGet( mixed $offset  );
        
        //设置一个偏移位置的值 
        public mixed offsetSet ( mixed $offset  );
        
        //复位一个偏移位置的值 
        public mixed offsetUnset  ( mixed $offset  );
    }

    SplObjectStorage

    SplObjectStorage类实现了以对象为键的映射(map)或对象的集合(如果忽略作为键的对象所对应的数据)这种数据结构。这个类的实例很像一个数组,但是它所存放的对象都是唯一。该类的另一个特点是,可以直接从中删除指定的对象,而不需要遍历或搜索整个集合。

    ::class语法

    因为 ::class 表示是字符串。用 ::class 的好处在于 IDE 里面可以直接改名一个 class,然后 IDE 自动处理相关引用。

    同时,PHP 执行相关代码时,是不会先加载相关 class 的。

    同理,代码自动化检查 inspect 也可以正确识别 class。

    Pimple容器流程浅析

    Pimpl是php社区中比较流行的容器。代码不是很多,详见

    https://github.com/silexphp/Pimple/blob/master/src/Pimple/Container.php 。

    我们的应用可以基于Pimple开发:

    namespace EasyWeChat\Foundation;
    use Pimple\Container;
    class Application extends Container
    {
        /**
         * Service Providers.
         *
         * @var array
         */
        protected $providers = [
            ServiceProviders\ServerServiceProvider::class,
            ServiceProviders\UserServiceProvider::class
        ];
        /**
         * Application constructor.
         *
         * @param array $config
         */
        public function __construct($config)
        {
            parent::__construct();
            $this['config'] = function () use ($config) {
                return new Config($config);
            };
            if ($this['config']['debug']) {
                error_reporting(E_ALL);
            }
            $this->registerProviders();
        }
        /**
         * Add a provider.
         *
         * @param string $provider
         *
         * @return Application
         */
        public function addProvider($provider)
        {
            array_push($this->providers, $provider);
            return $this;
        }
        /**
         * Set providers.
         *
         * @param array $providers
         */
        public function setProviders(array $providers)
        {
            $this->providers = [];
            foreach ($providers as $provider) {
                $this->addProvider($provider);
            }
        }
        /**
         * Return all providers.
         *
         * @return array
         */
        public function getProviders()
        {
            return $this->providers;
        }
        /**
         * Magic get access.
         *
         * @param string $id
         *
         * @return mixed
         */
        public function __get($id)
        {
            return $this->offsetGet($id);
        }
        /**
         * Magic set access.
         *
         * @param string $id
         * @param mixed  $value
         */
        public function __set($id, $value)
        {
            $this->offsetSet($id, $value);
        }
    }

    如何使用我们的应用:

    $app = new Application([]);
    $user = $app->user;

    之后我们就可以使用$user对象的方法了。我们发现其实并没有$this->user这个属性,但是可以直接使用。主要是这两个方法起的作用:

    public function offsetSet($id, $value){}
    public function offsetGet($id){}

    下面我们将解释在执行这两句代码,Pimple做了什么。但在解释这个之前,我们先看看容器的一些核心概念。

    服务提供者

    服务提供者是连接容器与具体功能实现类的桥梁。服务提供者需要实现接口ServiceProviderInterface:

    namespace Pimple;
    /**
     * Pimple service provider interface.
     *
     * @author  Fabien Potencier
     * @author  Dominik Zogg
     */
    interface ServiceProviderInterface
    {
        /**
         * Registers services on the given container.
         *
         * This method should only be used to configure services and parameters.
         * It should not get services.
         *
         * @param Container $pimple A container instance
         */
        public function register(Container $pimple);
    }

    所有服务提供者必须实现接口register方法。

    我们的应用里默认有2个服务提供者:

    protected $providers = [
        ServiceProviders\ServerServiceProvider::class,
        ServiceProviders\UserServiceProvider::class
    ];

    UserServiceProvider为例,我们看其代码实现:

    namespace EasyWeChat\Foundation\ServiceProviders;
    use EasyWeChat\User\User;
    use Pimple\Container;
    use Pimple\ServiceProviderInterface;
    /**
     * Class UserServiceProvider.
     */
    class UserServiceProvider implements ServiceProviderInterface
    {
        /**
         * Registers services on the given container.
         *
         * This method should only be used to configure services and parameters.
         * It should not get services.
         *
         * @param Container $pimple A container instance
         */
        public function register(Container $pimple)
        {
            $pimple['user'] = function ($pimple) {
                return new User($pimple['access_token']);
            };
        }
    }

    我们看到,该服务提供者的注册方法会给容器增加属性user,但是返回的不是对象,而是一个闭包。这个后面我再做讲解。

    服务注册

    我们在Application里构造函数里使用$this->registerProviders();对所有服务提供者进行了注册:

    private function registerProviders()
    {
        foreach ($this->providers as $provider) {
            $this->register(new $provider());
        }
    }

    仔细看,我们发现这里实例化了服务提供者,并调用了容器Pimple的register方法:

    public function register(ServiceProviderInterface $provider, array $values = array())
    {
        $provider->register($this);
        foreach ($values as $key => $value) {
            $this[$key] = $value;
        }
        return $this;
    }

    而这里调用了服务提供者的register方法,也就是我们在上一节中提到的:注册方法给容器增加了属性user,但返回的不是对象,而是一个闭包。

    当我们给容器Pimple添加属性user的同时,会调用offsetSet($id, $value)方法:给容器Pimple的属性values、keys分别赋值:

    $this->values[$id] = $value;
    $this->keys[$id] = true;

    到这里,我们还没有实例化真正提供实际功能的类EasyWeChat\User\Usr。但已经完成了服务提供者的注册工作。

    当我们运行到这里:

    $user = $app->user;

    会调用offsetGet($id)并进行实例化真正的类:

    $raw = $this->values[$id];
    $val = $this->values[$id] = $raw($this);
    $this->raw[$id] = $raw;
    $this->frozen[$id] = true;
    return $val;

    $raw获取的是闭包:

    $pimple['user'] = function ($pimple) {
        return new User($pimple['access_token']);
    };

    $raw($this)返回的是实例化的对象User。也就是说只有实际调用才会去实例化具体的类。后面我们就可以通过$this['user']或者$this->user调用User类里的方法了。

    当然,Pimple里还有很多特性值得我们去深入研究,这里不做过多讲解。

    更多相关php知识,请访问php教程!

    以上就是Pimple运行流程浅析(PHP容器)的详细内容,更多请关注爱上源码网其它相关文章!

  • 微信
  • 分享
  • 相关标签:Pimple
  • 本文转载于:cnblogs,如有侵犯,请联系916990011@qq.com删除
    • 上一篇:php中使用fsockopen实现异步请求(代码示例)
    • 下一篇:PHP钩子机制原理及详解

    相关文章

    相关视频

    • awesome PHP之依赖注入容器pimple
    • PHP容器Pimple运行流程的分析
    • php监听redis key失效触发回调事件
    • php中使用fsockopen实现异步请求(代码示…
    • Pimple运行流程浅析(PHP容器)
    • ThinkPHP6.0 请求
    • ThinkPHP6.0 数据库链式操作
    • ThinkPHP6.0 模型
    • ThinkPHP6.0 杂项

    本文有爱上源码下载完入驻作者发布,如果对您版权造成侵害,可以联系本站站长管理进行维权删除,本站收到维权24小时内进行处理,谢谢您关注23ym.cn!
    本站分享大量程序员技术文章以及对编程开发的初级入门教程,包括图文讲解笔记和高清视频下载~

    重要声明:
    1.本站视频教程,软件及网站源码版权均属于原作者所有,您必须在下载后的24个小时之内,从您的电脑中删除!非法商业用途,后果自负!
    2.本站不保证所提供下载资源的安全性和完整性,仅供下载学习之用!如链接失效或资源含外站广告,请联系客服处理!给予奖励!
    3.本站所有资源来源于用户上传和网络,因此不包含技术服务请大家谅解!本站提供有偿服务!如有侵权请联系在线客服!
    4.如您手中有优质资源或教程,可以自助投稿发布,成功分享后有奖励和额外收入!
    5.如您需要正版微擎模块可联系本站客服,我们有价值30w+商业微擎应用出售微擎坑位和招收代理!
    6.400电话/软著/ICP,EDI许可证/商标特价办理中!
    爱上源码下载网 » Pimple运行流程浅析(PHP容器)

    常见问题FAQ

    从网站下载的源码都有安装教程么?不会安装怎么办?
    本站发布的网站源码和模板资源大部分在压缩包内都有教程,如您不会安装可以联系本站在线技术进行付费安装。
    爱上源码的所有源码都是亲测能正常运行的么?
    本站目前拥有资源10w+,包含整站源码,网站模板,游戏源码,小程序源码,视频教程,破解软件等,每天也在测试更新;因时间和精力有限我们无法对资源进行一一测试,只能保证所分享资源内容无误,希望理解。
    我手中的优质资源可以在你这换钱或者VIP么?
    爱上源码支持投稿,欢迎发布您手中的优质资源进行售卖;本站VIP支持免费获取,目前邀请10人注册爱上源码即可免费获取VIP。
    爱上源码除了资源分享还有其他业务没?
    【价值30W+微擎模块出售正版商业微擎坑位及招收代理,详情咨询本站客服!】我们团队目前运营并推广几套商业化saas智能小程序系统能满足大部分小程序开发需求,并由SaaS和独立部署版商城小程序系统;另外销售400电话,各种ICP/EDI资质证书办理,软著和商标注册服务等。

    发表评论

    • 27会员总数(位)
    • 35644资源总数(个)
    • 0本周发布(个)
    • 0 今日发布(个)
    • 480稳定运行(天)

    提供最优质的资源集合

    开通VIP 源码下载