개발 꿀팁/PHP

PHP 미리 정의된 인터페이스의 ArrayAccess

Jammie 2022. 9. 27. 14:53
반응형

ArrayAccess

  일단 ArrayAc.액세스하라! ArrayAccess는 당신의 객체가 배열처럼 접근할 수 있도록 하는 역할을 합니다.ArrayAccess는 PHP5에 처음 존재하기 시작했으며 PHP5에는 많은 새로운 특성이 추가되었으며 물론 클래스의 오버로드도 강화되었으며 PHP5에는 일련의 인터페이스가 추가되었으며 이러한 인터페이스와 구현된 클래스를 총칭하여 SPL이라고 합니다.

ArrayAccess 이 인터페이스는 구현해야 할 네 가지 방법을 정의합니다

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의 원형을 볼 수 있습니다

/**
 * Interface to provide accessing objects as arrays.
 * @link http://php.net/manual/en/class.arrayaccess.php
 */
interface ArrayAccess {

    /**
     * (PHP 5 >= 5.0.0)<br/>
     * Whether a offset exists
     * @link http://php.net/manual/en/arrayaccess.offsetexists.php
     * @param mixed $offset <p>
     * An offset to check for.
     * </p>
     * @return boolean true on success or false on failure.
     * </p>
     * <p>
     * The return value will be casted to boolean if non-boolean was returned.
     */
    public function offsetExists($offset);

    /**
     * (PHP 5 >= 5.0.0)<br/>
     * Offset to retrieve
     * @link http://php.net/manual/en/arrayaccess.offsetget.php
     * @param mixed $offset <p>
     * The offset to retrieve.
     * </p>
     * @return mixed Can return all value types.
     */
    public function offsetGet($offset);

    /**
     * (PHP 5 >= 5.0.0)<br/>
     * Offset to set
     * @link http://php.net/manual/en/arrayaccess.offsetset.php
     * @param mixed $offset <p>
     * The offset to assign the value to.
     * </p>
     * @param mixed $value <p>
     * The value to set.
     * </p>
     * @return void
     */
    public function offsetSet($offset, $value);

    /**
     * (PHP 5 >= 5.0.0)<br/>
     * Offset to unset
     * @link http://php.net/manual/en/arrayaccess.offsetunset.php
     * @param mixed $offset <p>
     * The offset to unset.
     * </p>
     * @return void
     */
    public function offsetUnset($offset);
}

아래에 우리는 예를 하나 쓸 수 있습니다. 아주 간단합니다

<?php
class Test implements ArrayAccess
{
    private $testData;

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

    public function offsetSet($key, $value)
    {
        $this->testData[$key] = $value;
    }

    public function offsetGet($key)
    {
        return $this->testData[$key];
    }

    public function offsetUnset($key)
    {
        unset($this->testData[$key]);
    }
}

  $obj = new Test();

  //자동 호출 offsetSet 메서드
  $obj['data'] = 'data';

  //자동 호출 offsetExists
  if(isset($obj['data'])){
    echo 'has setting!';
  }
  //자동 호출 offsetGet
  var_dump($obj['data']);

  //자동 호출 offsetUnset
  unset($obj['data']);
  var_dump($test['data']);

  //출력:
  //has setting!
  //data
  //null

자, 이제 Slim 프레임워크와 결합하여 실제 응용을 설명하겠습니다. Slim에서 사용하는 것은 매우 중요하고 매우 뛰어난 container를 사용합니다. container는 Pimple\Container에서 상속됩니다. Pimple은 php 커뮤니티에서 비교적 유행하는 ioc 컨테이너입니다. Pimple의 container 클래스는 의존 주입 방식을 사용하여 프로그램 간의 낮은 결합을 실현합니다. composer로 require "pimple/pimple": "1.*" 의존 클래스 라이브러리에 추가할 수 있습니다.

  Slim에서 container의 클래스를 사용하여 displayErrorDetails, renderer, logger, httpVersion, responseChunkSize, outputBuffering, determinRouteBeforeAppMiddleware, displayErrorDetails 등을 포함하여 배열에 액세스하여 프레임 로딩 시 먼저 로드되도록 합니다.사용하실 때 바로 찾으시면 됩니다.

다음은 이러한 로딩 메커니즘입니다

<?php

namespace Slim;

use Interop\Container\ContainerInterface;
use Interop\Container\Exception\ContainerException;
use Pimple\Container as PimpleContainer;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Exception\ContainerValueNotFoundException;

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입니다. 교묘하게 키 값을 사용하여 해당 값이 설정되었는지 여부를 판단합니다. 설정되면 바로 가져오고, 설정이 없으면 설정으로 이동합니다.배치 논리

public function offsetGet($id)
    {
        if (!isset($this->keys[$id])) {
            throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id));
        }

        if (
            isset($this->raw[$id])
            || !is_object($this->values[$id])
            || isset($this->protected[$this->values[$id]])
            || !method_exists($this->values[$id], '__invoke')
        ) {
            return $this->values[$id];
        }

        if (isset($this->factories[$this->values[$id]])) {
            return $this->values[$id]($this);
        }

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

        $this->frozen[$id] = true;

        return $val;
    }

PimpleContainer를 다시 살펴보겠습니다

우리는 그 중 하나의 SplObjectStorage를 볼 수 있습니다. 이것에 대해 이야기 해야 합니다. SplObjectStorage는 당신이 개체를 고유하게 식별해야 할 때 객체 세트를 저장하는 데 사용됩니다.공식 웹사이트에 따르면 PHP SPL SplObjectStorage 클래스는 Countable, Iterator, Serializable, Array Access의 4가지 인터페이스를 구현하여 통계, 반복, 직렬화, 배열 접근 등의 기능을 구현할 수 있습니다.따라서 SplObjectStorage는 표준 객체 컨테이너입니다.

  다들 ArrayAccess에 대해 잘 알고 있을 거야, 잘 모르겠으면 Slim의 소스 코드를 더 많이 보면 돼, 거기에 더 명확하게 적혀 있고, 그 소스 코드와 그 간결함은 우리가 배울 가치가 있어

 

반응형