Pimple运行流程浅析(PHP容器)-php教程

资源魔 31 0

需求具有的常识点

闭包

闭包以及匿名函数正在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容器)的具体内容,更多请存眷资源魔其它相干文章!

标签: php开发教程 php开发资料 php开发自学 Pimple

抱歉,评论功能暂时关闭!