pimple 学习

368 阅读1分钟

pimple是一个实现了ArrayAccess接口的容器,实现ArrayAccess接口的容器可以通过访问数组的方式访问对象

前置知识

ArrayAccess容器

Interface to provide accessing objects as arrays.

官方文档

接口定义:

ArrayAccess {
/* Methods */
abstract public offsetExists (mixed $offset ): bool
abstract public offsetGet (mixed $offset ): mixed
abstract public offsetSet (mixed $offset , mixed $value ): void
abstract public offsetUnset (mixed $offset ): void
}

实现例子:

<?php
class Obj implements ArrayAccess {
    private $container = array();

    public function __construct() {
        $this->container = array(
            "one"   => 1,
            "two"   => 2,
            "three" => 3,
        );
    }

    public function offsetSet($offset, $value) {
        if (is_null($offset)) {
            $this->container[] = $value;
        } else {
            $this->container[$offset] = $value;
        }
    }

    public function offsetExists($offset) {
        return isset($this->container[$offset]);
    }

    public function offsetUnset($offset) {
        unset($this->container[$offset]);
    }

    public function offsetGet($offset) {
        return isset($this->container[$offset]) ? $this->container[$offset] : null;
    }
}

$obj = new Obj;

var_dump(isset($obj["two"]));
var_dump($obj["two"]);
unset($obj["two"]);
var_dump(isset($obj["two"]));
$obj["two"] = "A value";
var_dump($obj["two"]);
$obj[] = 'Append 1';
$obj[] = 'Append 2';
$obj[] = 'Append 3';
print_r($obj);
?>

魔术方法__invoke

实现_invoke方法的对象可以像访问函数一样使用

class ShowProfile2
{
    public function __invoke($c)
    {
        echo "ShowProfile2" . chr(10);
//        return $c;
        return new stdClass();
    }
}
$a = new ShowProfile2();
var_dump($a(3));

SplObjectStorage

Standed PHP Library 对象存储,实现以下接口Countable, Iterator, Serializable, ArrayAccess.

自身主要实现了对象唯一性存储

官方解释

The SplObjectStorage class provides a map from objects to data or, by ignoring data, an object set. This dual purpose can be useful in many cases involving the need to uniquely identify objects.

官方文档

官方实例:

<?php
// As an object set
$s = new SplObjectStorage();

$o1 = new StdClass;
$o2 = new StdClass;
$o3 = new StdClass;

$s->attach($o1);
$s->attach($o2);

var_dump($s->contains($o1));
var_dump($s->contains($o2));
var_dump($s->contains($o3));

$s->detach($o2);

var_dump($s->contains($o1));
var_dump($s->contains($o2));
var_dump($s->contains($o3));
?>

PHP 之 SplObjectStorage对象存储

pimple使用

silexphp/pimple

使用方法参看官方README.

容器代码实现很少,阅读很容易

属性

    private $values = []; //id=>value键值对
    private $factories; // 对象工厂
    private $protected; // 受保护对象,这里的对象不会执行,可以返回作为参数使用
    private $frozen = [];  //防止对象取出后被重新定义
    private $raw = []; //原始格式的对象,对象被取出执行后这里保存原始定制
    private $keys = []; // 保存键值

方法

前置类

header.php

<?php
require_once "vendor/autoload.php";

use Pimple\Container;

/**
 * @property string str
 */
class SessionStorage
{
    private string $msg = 'SessionStorageClass';

    public function __construct(string $str)
    {
        $this->str = $str;
    }
}

/**
 * @property SessionStorage st
 */
class Session
{
    private string $msg = 'SessionClass';
    private int $rand;

    public function __construct(SessionStorage $st, int $rand = null)
    {
        $this->st = $st;
        if ($rand != null)
            $this->rand = $rand;
    }
}

offsetSet offsetGet offsetExists offsetUnset

ArrayAccess接口实现

赋值时调用offsetSet方法,取值时调用offsetGet方法

<?php
require_once "header.php";

use Pimple\Container;

$container = new Container();

// define some parameters
$container['cookie_name'] = 'SESSION_ID';
$container['session_storage_class'] = 'SessionStorage';
//var_dump($container['cookie_name'],$container['session_storage_class']);
//exit;xx

$container['session_storage'] = function ($c) {
    //$c 为null或者offsetGet传值后为container
    return new $c['session_storage_class']($c['cookie_name']);
};

var_dump($container['session_storage']);
//$container['session_storage'] = function ($c) {
//
//};
//var_dump($container['session_storage']);
exit;

factory

保存到factories变量,offsetGet存在时执行并返回,和普通的offsetGet返回区别是少了raw的保存,且没有frozen赋值为true,每次get重新执行对象

<?php

require_once "header.php";

use \Pimple\Container;

$container = new Container();
// define some parameters
$container['cookie_name'] = 'SESSION_ID';
$container['session_storage_class'] = 'SessionStorage';
//var_dump($container['cookie_name'],$container['session_storage_class']);
//exit;

$container['session_storage'] = function ($c) {
    //$c 为null或者offsetGet传值后为container
    return new $c['session_storage_class']($c['cookie_name']);
};
//var_dump($container['session_storage']);
//exit;

$container['session'] = $container->factory(function ($c) {
    return new Session($c['session_storage'], rand(0, 10000));
});

var_dump($container['session']);
var_dump($container['session']);

$container['session2'] = function ($c) {
    return new Session($c['session_storage'], rand(0, 1000));
};
var_dump($container['session2']);
var_dump($container['session2']);

protect

保存到protected变量,offsetGet时直接返回不执行,可作为变量

<?php
require_once "header.php";

use \Pimple\Container;

$container = new Container();
$container['random_func'] = $container->protect(function () {
return rand();
});
var_dump($container['random_func']);

$container['random_func2'] = function () {
return rand();
};
var_dump($container['random_func2']);

raw

<?php
require_once "header.php";

use \Pimple\Container;

$container = new Container();
$container['session'] = function ($c) {
    return new Session($c['session_storage']);
};

$sessionFunction = $container->raw('session');
var_dump($sessionFunction);

extend

<?php
require_once "header.php";

use Pimple\Container;

$container = new Container();

// define some parameters
$container['cookie_name'] = 'SESSION_ID';
$container['session_storage_class'] = 'SessionStorage';
//var_dump($container['cookie_name'],$container['session_storage_class']);
//exit;

$container['session_storage'] = function ($c) {
    //$c 为null或者offsetGet传值后为container
    return new $c['session_storage_class']($c['cookie_name']);
};
$storage = "hello";
$container->extend('session_storage', function ($storage, $c) {
    echo "hello".chr(10);
    return $storage;
});
var_dump($container['session_storage']);

keys

没啥可说的

register

<?php
require_once "header.php";

use Pimple\Container;

class FooProvider implements Pimple\ServiceProviderInterface
{
    public function register(Container $pimple)
    {
        echo "register func" . chr(10);
        // register some services and parameters
        // on $pimple
    }
}

class ShowProfile
{
    public function __invoke($id)
    {
        return "I'm showProfile " . $id;
    }
}

class ShowProfile2
{
    public function __invoke($c)
    {
        echo "ShowProfile2" . chr(10);
//        return $c;
        return new stdClass();
    }
}

$a = new ShowProfile2();
var_dump($a(3));

//test register and raw
$pimple = new Container();
$pimple->register(new FooProvider(), ['a' => new ShowProfile2()]);

$newA = $pimple->offsetGet('a');
var_dump($newA);
var_dump($pimple->raw('a'));

pimple源码解析

pimple 源码很少,上面已经串着说完了...

代码来源

初始代码来自以下来源,经过自己加工理解

  1. php官方文档(文中有)
  2. pimple README