ホームページ > バックエンド開発 > PHPチュートリアル > PHP 定義済みインターフェイス ArrayAccess、php スケジュール済み arrayaccess_PHP チュートリアル

PHP 定義済みインターフェイス ArrayAccess、php スケジュール済み arrayaccess_PHP チュートリアル

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
リリース: 2016-07-12 08:58:21
オリジナル
1005 人が閲覧しました

PHP预定义接口之 ArrayAccess,php预定arrayaccess

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

ArrayAccess

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

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

1

2

3

4

5

6

<span>1</span> <span>{

</span><span>2</span>    <span>abstract</span> <span>public</span> offsetExists (<span>$offset</span>)  <span>//</span><span>检查偏移位置是否存在</span>

<span>3</span>    <span>abstract</span> <span>public</span> offsetGet (<span>$offset</span>)     <span>//</span><span>获取一个偏移位置的值</span>

<span>4</span>    <span>abstract</span> <span>public</span> void offsetSet (<span>$offset</span> ,<span>$value</span>) <span>//</span><span>设置一个偏移位置的值</span>

<span>5</span>    <span>abstract</span> <span>public</span> void offsetUnset (<span>$offset</span>)       <span>//</span><span>复位一个偏移位置的值</span>

<span>6</span> }

ログイン後にコピー

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

<span> 1</span> <span>/*</span><span>*

</span><span> 2</span> <span> * Interface to provide accessing objects as arrays.

</span><span> 3</span> <span> * @link http://php.net/manual/en/class.arrayaccess.php

</span><span> 4</span>  <span>*/</span>

<span> 5</span> <span>interface</span><span> ArrayAccess {

</span><span> 6</span>

<span> 7</span>     <span>/*</span><span>*

</span><span> 8</span> <span>     * (PHP 5 &gt;= 5.0.0)<br/>

</span><span> 9</span> <span>     * Whether a offset exists

</span><span>10</span> <span>     * @link http://php.net/manual/en/arrayaccess.offsetexists.php

</span><span>11</span> <span>     * @param mixed $offset <p>

</span><span>12</span> <span>     * An offset to check for.

</span><span>13</span> <span>     * </p>

</span><span>14</span> <span>     * @return boolean true on success or false on failure.

</span><span>15</span> <span>     * </p>

</span><span>16</span> <span>     * <p>

</span><span>17</span> <span>     * The return value will be casted to boolean if non-boolean was returned.

</span><span>18</span>      <span>*/</span>

<span>19</span>     <span>public</span> <span>function</span> offsetExists(<span>$offset</span><span>);

</span><span>20</span>

<span>21</span>     <span>/*</span><span>*

</span><span>22</span> <span>     * (PHP 5 &gt;= 5.0.0)<br/>

</span><span>23</span> <span>     * Offset to retrieve

</span><span>24</span> <span>     * @link http://php.net/manual/en/arrayaccess.offsetget.php

</span><span>25</span> <span>     * @param mixed $offset <p>

</span><span>26</span> <span>     * The offset to retrieve.

</span><span>27</span> <span>     * </p>

</span><span>28</span> <span>     * @return mixed Can return all value types.

</span><span>29</span>      <span>*/</span>

<span>30</span>     <span>public</span> <span>function</span> offsetGet(<span>$offset</span><span>);

</span><span>31</span>

<span>32</span>     <span>/*</span><span>*

</span><span>33</span> <span>     * (PHP 5 &gt;= 5.0.0)<br/>

</span><span>34</span> <span>     * Offset to set

</span><span>35</span> <span>     * @link http://php.net/manual/en/arrayaccess.offsetset.php

</span><span>36</span> <span>     * @param mixed $offset <p>

</span><span>37</span> <span>     * The offset to assign the value to.

</span><span>38</span> <span>     * </p>

</span><span>39</span> <span>     * @param mixed $value <p>

</span><span>40</span> <span>     * The value to set.

</span><span>41</span> <span>     * </p>

</span><span>42</span> <span>     * @return void

</span><span>43</span>      <span>*/</span>

<span>44</span>     <span>public</span> <span>function</span> offsetSet(<span>$offset</span>, <span>$value</span><span>);

</span><span>45</span>

<span>46</span>     <span>/*</span><span>*

</span><span>47</span> <span>     * (PHP 5 &gt;= 5.0.0)<br/>

</span><span>48</span> <span>     * Offset to unset

</span><span>49</span> <span>     * @link http://php.net/manual/en/arrayaccess.offsetunset.php

</span><span>50</span> <span>     * @param mixed $offset <p>

</span><span>51</span> <span>     * The offset to unset.

</span><span>52</span> <span>     * </p>

</span><span>53</span> <span>     * @return void

</span><span>54</span>      <span>*/</span>

<span>55</span>     <span>public</span> <span>function</span> offsetUnset(<span>$offset</span><span>);

</span><span>56</span> }

ログイン後にコピー

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

<span> 1</span> <?<span>php

</span><span> 2</span> <span>class</span> Test <span>implements</span><span> ArrayAccess

</span><span> 3</span> <span>{

</span><span> 4</span>     <span>private</span> <span>$testData</span><span>;

</span><span> 5</span>

<span> 6</span>     <span>public</span> <span>function</span> offsetExists(<span>$key</span><span>)

</span><span> 7</span> <span>    {

</span><span> 8</span>         <span>return</span> <span>isset</span>(<span>$this</span>->testData[<span>$key</span><span>]);

</span><span> 9</span> <span>    }

</span><span>10</span>

<span>11</span>     <span>public</span> <span>function</span> offsetSet(<span>$key</span>, <span>$value</span><span>)

</span><span>12</span> <span>    {

</span><span>13</span>         <span>$this</span>->testData[<span>$key</span>] = <span>$value</span><span>;

</span><span>14</span> <span>    }

</span><span>15</span>

<span>16</span>     <span>public</span> <span>function</span> offsetGet(<span>$key</span><span>)

</span><span>17</span> <span>    {

</span><span>18</span>         <span>return</span> <span>$this</span>->testData[<span>$key</span><span>];

</span><span>19</span> <span>    }

</span><span>20</span>

<span>21</span>     <span>public</span> <span>function</span> offsetUnset(<span>$key</span><span>)

</span><span>22</span> <span>    {

</span><span>23</span>         <span>unset</span>(<span>$this</span>->testData[<span>$key</span><span>]);

</span><span>24</span> <span>    }

</span><span>25</span> <span>}

</span><span>26</span>

<span>27</span>   <span>$obj</span> = <span>new</span><span> Test();

</span><span>28</span>

<span>29</span>   <span>//</span><span>自动调用offsetSet方法</span>

<span>30  </span> <span>$obj</span>['data'] = 'data'<span>;

</span><span>31</span>

<span>32</span>   <span>//</span><span>自动调用offsetExists</span>

<span>33  </span> <span>if</span>(<span>isset</span>(<span>$obj</span>['data'<span>])){

</span><span>34</span>     <span>echo</span> 'has setting!'<span>;

</span><span>35</span>   <span>}

</span><span>36</span>   <span>//</span><span>自动调用offsetGet</span>

<span>37</span>   <span>var_dump</span>(<span>$obj</span>['data'<span>]);

</span><span>38</span>

<span>39</span>   <span>//</span><span>自动调用offsetUnset</span>

<span>40</span>   <span>unset</span>(<span>$obj</span>['data'<span>]);

</span><span>41</span>   <span>var_dump</span>(<span>$test</span>['data'<span>]);

</span><span>42</span>

<span>43</span>   <span>//</span><span>输出:

</span><span>44</span>   <span>//has setting!

</span><span>45</span>   <span>//data 

</span><span>46</span>   <span>//null</span>

ログイン後にコピー

  好了,下面我们会结合Slim框架来说在实际中的应用,在Slim中使用非常重要,也非常出色的使用了 container,container继承自Pimple\Container,说到这,就有必要说一下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等等,使他们在框架加载的时候首先被加载。使用的时候直接取就可以了,

下面就是这种加载机制:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

<?<span>php

 

namespace Slim;

 

</span><span>use</span><span> Interop\Container\ContainerInterface;

</span><span>use</span> Interop\Container\<span>Exception</span><span>\ContainerException;

</span><span>use</span> Pimple\Container <span>as</span><span> PimpleContainer;

</span><span>use</span><span> Psr\Http\Message\ResponseInterface;

</span><span>use</span><span> Psr\Http\Message\ServerRequestInterface;

</span><span>use</span> Slim\<span>Exception</span><span>\ContainerValueNotFoundException;

 

</span><span>class</span> Container <span>extends</span> PimpleContainer <span>implements</span><span> ContainerInterface

{

    </span><span>/*</span><span>*

     * Default settings

     *

     * @var array

     </span><span>*/</span>

    <span>private</span> <span>$defaultSettings</span> =<span> [

        </span>'httpVersion' => '1.1',

        'responseChunkSize' => 4096,

        'outputBuffering' => 'append',

        'determineRouteBeforeAppMiddleware' => <span>false</span>,

        'displayErrorDetails' => <span>false</span>,<span>

    ];

 

    </span><span>/*</span><span>*

     * Create new container

     *

     * @param array $values The parameters or objects.

     </span><span>*/</span>

    <span>public</span> <span>function</span> __construct(<span>array</span> <span>$values</span> =<span> [])

    {

        </span><span>//</span><span>var_dump($values);          exit;</span>

        parent::__construct(<span>$values</span><span>);

 

        </span><span>$userSettings</span> = <span>isset</span>(<span>$values</span>['settings']) ? <span>$values</span>['settings'] :<span> [];

        </span><span>$this</span>->registerDefaultServices(<span>$userSettings</span><span>);

    }

 

    </span><span>private</span> <span>function</span> registerDefaultServices(<span>$userSettings</span><span>)

    {

        </span><span>$defaultSettings</span> = <span>$this</span>-><span>defaultSettings;

 

        </span><span>$this</span>['settings'] = <span>function</span> () <span>use</span> (<span>$userSettings</span>, <span>$defaultSettings</span><span>) {

            </span><span>return</span> <span>new</span> Collection(<span>array_merge</span>(<span>$defaultSettings</span>, <span>$userSettings</span><span>));

        };

         

        </span><span>$defaultProvider</span> = <span>new</span><span> DefaultServicesProvider();

        </span><span>$defaultProvider</span>->register(<span>$this</span><span>);

    }

   

    </span>. . .<span>

 

}</span>

ログイン後にコピー

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

<span> 1</span>     <span>public</span> <span>function</span> offsetGet(<span>$id</span><span>)

</span><span> 2</span> <span>    {

</span><span> 3</span>         <span>if</span> (!<span>isset</span>(<span>$this</span>->keys[<span>$id</span><span>])) {

</span><span> 4</span>             <span>throw</span> <span>new</span> \InvalidArgumentException(<span>sprintf</span>('Identifier "%s" is not defined.', <span>$id</span><span>));

</span><span> 5</span> <span>        }

</span><span> 6</span>

<span> 7</span>         <span>if</span><span> (

</span><span> 8</span>             <span>isset</span>(<span>$this</span>->raw[<span>$id</span><span>])

</span><span> 9</span>             || !<span>is_object</span>(<span>$this</span>->values[<span>$id</span><span>])

</span><span>10</span>             || <span>isset</span>(<span>$this</span>-><span>protected</span>[<span>$this</span>->values[<span>$id</span><span>]])

</span><span>11</span>             || !<span>method_exists</span>(<span>$this</span>->values[<span>$id</span>], '__invoke'<span>)

</span><span>12</span> <span>        ) {

</span><span>13</span>             <span>return</span> <span>$this</span>->values[<span>$id</span><span>];

</span><span>14</span> <span>        }

</span><span>15</span>

<span>16</span>         <span>if</span> (<span>isset</span>(<span>$this</span>->factories[<span>$this</span>->values[<span>$id</span><span>]])) {

</span><span>17</span>             <span>return</span> <span>$this</span>->values[<span>$id</span>](<span>$this</span><span>);

</span><span>18</span> <span>        }

</span><span>19</span>

<span>20</span>         <span>$raw</span> = <span>$this</span>->values[<span>$id</span><span>];

</span><span>21</span>         <span>$val</span> = <span>$this</span>->values[<span>$id</span>] = <span>$raw</span>(<span>$this</span><span>);

</span><span>22</span>         <span>$this</span>->raw[<span>$id</span>] = <span>$raw</span><span>;

</span><span>23</span>

<span>24</span>         <span>$this</span>->frozen[<span>$id</span>] = <span>true</span><span>;

</span><span>25</span>

<span>26</span>         <span>return</span> <span>$val</span><span>;

</span><span>27</span>     }

ログイン後にコピー

我们再看看 PimpleContainer,如下图:

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

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

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

转载请注明出处,后面会持续更新,谢谢大家!

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/1104066.htmlTechArticlePHP预定义接口之 ArrayAccess,php预定arrayaccess 最近这段时间回家过年了,博客也没有更新,感觉少学习了好多东西,也错失了好多的学习机会...
関連ラベル:
php
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート