zoukankan      html  css  js  c++  java
  • PHP预定义接口之 ArrayAccess

      最近这段时间回家过年了,博客也没有更新,感觉少学习了好多东西,也错失了好多的学习机会,就像大家在春节抢红包时常说的一句话:一不留神错过了好几亿。废话少说,这篇博客给大家说说关于PHP预定义接口中常用到的重量级人物: ArrayAccess。大家也许会问,最基本、最常用的预定义接口有6个呢,为啥非得说这个。从日常的使用情况来看:这个出现的频率非常高,特别是在框架中,比如Laravel、Slim等都会用到,并且用得非常经典,让人佩服啊。从技术上说:说实话其他的我用的少啊!只是知道简单的用法,对他的理解比较浅显,不敢在这里误导大家,哈哈!今天我要写的内容也不一定都正确,不对之处还请指正。

    ArrayAccess

      先说 ArrayAccess 吧!ArrayAccess 的作用是使得你的对象可以像数组一样可以被访问。应该说 ArrayAccess 在PHP5中才开始有的,PHP5中加入了很多新的特性,当然也使类的重载也加强了,PHP5 中添加了一系列接口,这些接口和实现的 Class 统称为 SPL。

    ArrayAccess 这个接口定义了4个必须要实现的方法:

    1 {
    2    abstract public offsetExists ($offset)  //检查偏移位置是否存在
    3    abstract public offsetGet ($offset)     //获取一个偏移位置的值
    4    abstract public void offsetSet ($offset ,$value) //设置一个偏移位置的值
    5    abstract public void offsetUnset ($offset)       //复位一个偏移位置的值
    6 }

    所以我们要使用ArrayAccess这个接口,就要实现相应的方法,这几个方法不是随便写的,我们可以看一下 ArrayAccess 的原型:

     1 /**
     2  * Interface to provide accessing objects as arrays.
     3  * @link http://php.net/manual/en/class.arrayaccess.php
     4  */
     5 interface ArrayAccess {
     6 
     7     /**
     8      * (PHP 5 &gt;= 5.0.0)<br/>
     9      * Whether a offset exists
    10      * @link http://php.net/manual/en/arrayaccess.offsetexists.php
    11      * @param mixed $offset <p>
    12      * An offset to check for.
    13      * </p>
    14      * @return boolean true on success or false on failure.
    15      * </p>
    16      * <p>
    17      * The return value will be casted to boolean if non-boolean was returned.
    18      */
    19     public function offsetExists($offset);
    20 
    21     /**
    22      * (PHP 5 &gt;= 5.0.0)<br/>
    23      * Offset to retrieve
    24      * @link http://php.net/manual/en/arrayaccess.offsetget.php
    25      * @param mixed $offset <p>
    26      * The offset to retrieve.
    27      * </p>
    28      * @return mixed Can return all value types.
    29      */
    30     public function offsetGet($offset);
    31 
    32     /**
    33      * (PHP 5 &gt;= 5.0.0)<br/>
    34      * Offset to set
    35      * @link http://php.net/manual/en/arrayaccess.offsetset.php
    36      * @param mixed $offset <p>
    37      * The offset to assign the value to.
    38      * </p>
    39      * @param mixed $value <p>
    40      * The value to set.
    41      * </p>
    42      * @return void
    43      */
    44     public function offsetSet($offset, $value);
    45 
    46     /**
    47      * (PHP 5 &gt;= 5.0.0)<br/>
    48      * Offset to unset
    49      * @link http://php.net/manual/en/arrayaccess.offsetunset.php
    50      * @param mixed $offset <p>
    51      * The offset to unset.
    52      * </p>
    53      * @return void
    54      */
    55     public function offsetUnset($offset);
    56 }

     下面我们可以写一个例子,非常简单:

     1 <?php
     2 class Test implements ArrayAccess
     3 {
     4     private $testData;
     5 
     6     public function offsetExists($key)
     7     {
     8         return isset($this->testData[$key]);
     9     }
    10 
    11     public function offsetSet($key, $value)
    12     {
    13         $this->testData[$key] = $value;
    14     }
    15 
    16     public function offsetGet($key)
    17     {
    18         return $this->testData[$key];
    19     }
    20 
    21     public function offsetUnset($key)
    22     {
    23         unset($this->testData[$key]);
    24     }
    25 }
    26 
    27   $obj = new Test();
    28 
    29   //自动调用offsetSet方法
    30   $obj['data'] = 'data';
    31 
    32   //自动调用offsetExists
    33   if(isset($obj['data'])){
    34     echo 'has setting!';
    35   }
    36   //自动调用offsetGet
    37   var_dump($obj['data']);
    38 
    39   //自动调用offsetUnset
    40   unset($obj['data']);
    41   var_dump($test['data']);
    42 
    43   //输出:
    44   //has setting!
    45   //data  
    46   //null

      好了,下面我们会结合Slim框架来说在实际中的应用,在Slim中使用非常重要,也非常出色的使用了 container,container继承自PimpleContainer,说到这,就有必要说一下Pimple,pimple是php社区中比较流行的一种ioc容器,pimple中的container类使用了依赖注入的方式来实现实现了程序间的低耦合,可以用composer添加 require  "pimple/pimple": "1.*" 添加Pimple到依赖类库,Pimple还是要多看看的,就一个文件,在程序整个生命周期中,各种属性、方法、对象、闭包都可以注册其中,但pimple只是实现了一个容器的概念,还有好多依赖注入、自动创建、关联等功能需要看Laravel才能深刻学到。

      在Slim中它使用 container 的类实现了将配置文件依次加载,可以像访问数组一样访问他们,包括displayErrorDetails,renderer, logger,httpVersion,responseChunkSize,outputBuffering,determineRouteBeforeAppMiddleware,displayErrorDetails等等,使他们在框架加载的时候首先被加载。使用的时候直接取就可以了,

    下面就是这种加载机制:

    <?php
    
    namespace Slim;
    
    use InteropContainerContainerInterface;
    use InteropContainerExceptionContainerException;
    use PimpleContainer as PimpleContainer;
    use PsrHttpMessageResponseInterface;
    use PsrHttpMessageServerRequestInterface;
    use SlimExceptionContainerValueNotFoundException;
    
    class Container extends PimpleContainer implements ContainerInterface
    {
        /**
         * Default settings
         *
         * @var array
         */
        private $defaultSettings = [
            'httpVersion' => '1.1',
            'responseChunkSize' => 4096,
            'outputBuffering' => 'append',
            'determineRouteBeforeAppMiddleware' => false,
            'displayErrorDetails' => false,
        ];
    
        /**
         * Create new container
         *
         * @param array $values The parameters or objects.
         */
        public function __construct(array $values = [])
        {
            //var_dump($values);          exit;
            parent::__construct($values);
    
            $userSettings = isset($values['settings']) ? $values['settings'] : [];
            $this->registerDefaultServices($userSettings);
        }
    
        private function registerDefaultServices($userSettings)
        {
            $defaultSettings = $this->defaultSettings;
    
            $this['settings'] = function () use ($userSettings, $defaultSettings) {
                return new Collection(array_merge($defaultSettings, $userSettings));
            };
            
            $defaultProvider = new DefaultServicesProvider();
            $defaultProvider->register($this);
        }
      
        . . .
    
    }

    其中 defaultSettings 为系统默认配置,userSettings为用户的配置,比如日志,模板等。

    下面这段是offsetGet,巧妙使用键值来判断该值是否已经设置过,如果设置过就会直接去取了,没有设置就会转到设置的逻辑。

     1     public function offsetGet($id)
     2     {
     3         if (!isset($this->keys[$id])) {
     4             throw new InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id));
     5         }
     6 
     7         if (
     8             isset($this->raw[$id])
     9             || !is_object($this->values[$id])
    10             || isset($this->protected[$this->values[$id]])
    11             || !method_exists($this->values[$id], '__invoke')
    12         ) {
    13             return $this->values[$id];
    14         }
    15 
    16         if (isset($this->factories[$this->values[$id]])) {
    17             return $this->values[$id]($this);
    18         }
    19 
    20         $raw = $this->values[$id];
    21         $val = $this->values[$id] = $raw($this);
    22         $this->raw[$id] = $raw;
    23 
    24         $this->frozen[$id] = true;
    25 
    26         return $val;
    27     }

    我们再看看 PimpleContainer,如下图:

         我们可以看到其中有个 SplObjectStorage,需要说一下这个,SplObjectStorage是用来存储一组对象,当你需要唯一标识对象的时候。按照官网的说法 PHP SPL SplObjectStorage类实现了Countable, Iterator, Serializable, ArrayAccess四个接口,可实现统计、迭代、序列化、数组式访问等功能。所以SplObjectStorage是一个标准的对象容器。

      说到这大家对ArrayAccess应该有所了解了,如果还不清楚,可以多看看Slim的源码,上面写的比较清楚,而且那套源码及其的简练,值得我们学习。

          博客会同步更新到我的个人网站,欢迎大家访问!

    注意:
    1、本博客同步更新到我的个人网站:http://www.zhaoyafei.cn
    2、本文属原创内容,为了尊重他人劳动,转载请注明本文地址:
    http://www.cnblogs.com/zyf-zhaoyafei/p/5228652.html
  • 相关阅读:
    背景大图隔几秒切换(非轮播,淡入淡出)--变形金刚joy007 项目总结
    call(京基填小票拍照片)
    加载图片、倒计时--Columbia项目总结
    kellogg项目总结
    js 跨域
    js 继承inheritance/extends
    一号店分享会
    日历,类似旅行网站的酒店入住
    js 数组的判断
    Building a Non-blocking TCP server using OTP principles
  • 原文地址:https://www.cnblogs.com/zyf-zhaoyafei/p/5228652.html
Copyright © 2011-2022 走看看