'Programming/PHP'에 해당하는 글 117건

Composer

Programming/PHP 2016. 2. 26. 22:30

PHP 개발에서 패키지 간의 의존성을 관리하는 도구이다.

패키지 리스트(https://packagist.org/) 에서 원하는 패키지를 쉽게 검색할 수 있다.

원하는 패키지를 프로젝트의 composer.json 에 선언하고 설치하면 즉시 해당 라이브러리들을 사용할 수 있다.

멀티 플랫폼을 지원하며 Linux / Windows / OSX 에서 동일하게 동작한다.



시스템 요구사항


PHP 5.3.2 이상



설치


Windows 는 https://getcomposer.org/download/ 에서 다운받아 바로 설치 할 수 있다.

설치는 아래 방법보다 위 composer 사이트에서 최신 메뉴얼을 이용하는 것이 좋다.


Linux / Unix / OSX 의 경우, 프로젝트 디렉토리에서 다음과 같이 인스톨러를 실행하면, 현재 디렉토리에 컴포저 실행파일인 composer.phar 가 설치된다.


1
$ curl -sS https://getcomposer.org/installer | php
cs


curl 이 설치되어 있지 않거나 위 방법이 실패한다면 php 명령으로 인스톨러를 다운로드 한다.


1
$ php -"readfile('https://getcomposer.org/installer');" | php
cs


현재 디렉토리가 아닌 다른 디렉토리에 설치하고 싶다면 다음과 같이 원하는 디렉토리를 명시할 수 있다.


1
$ curl -sS https://getcomposer.org/installer | php -- --install-dir=bin
cs


환경 변수 PATH 가 설정되어 있는 디렉토리로 이동시키면 어디서든 컴포저를 구동할 수 있다.



컴포저를 사용하여 패키지 다운로드


원하는 패키지를 검색했다면, 프로젝트 디렉토리에 composer.json 을 생성하고 형식에 맞게 JSON 포맷으로 패키지를 선언한다.

예를 들어, 다음은 monolog 1.2 로 시작하는 패키지를 사용하는 방법이다.


1
2
3
4
5
{
    "require": {
        "monolog/monolog""1.2.*"
    }
}
cs


require 로 다운로드 할 패키지 이름(vendor/package)과 패키지 버전(1.2.*)을 선언하는 형태이다.

install 과 동시에 생성되는 composer.lock(잠금설정) 파일은 설치한 패키지들의 버전 목록이 저장된다.


composer.json 파일에 패키지를 선언했으면 다음 명령으로 패키지 라이브러리를 현재 디렉토리의 vendor 디렉토리에 다운로드한다.


1
2
3
$ php composer.phar install
or
$ composer install
cs



오토로딩


다운로드된 라이브러리의 모든 클래스들을 사용하려면 PHP 코드의 처음에 오토로딩이 필요하다.


1
2
<?
require 'vendor/autoload.php';
cs




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

PSR-7

Programming/PHP 2016. 2. 24. 23:19

PSR-7 : HTTP 메시지 인터페이스 (http://www.php-fig.org/psr/psr-7/)


웹브라우저와 cURL 같은 HTTP 클라이언트는 HTTP 응답 메시지를 제공하는 웹 서버로 보낼 HTTP 요청 메시지를 생성한다.

서버 사이드 코드는 요청 메시지를 받고 HTTP 응답을 반환한다.

모든 HTTP 요청 메시지는 특정한 형태로 되어 있다.


1
2
3
4
POST /path HTTP/1.1
Host: example.com
 
foo=bar&baz=bat
cs


첫번째 줄은 HTTP 요청 메소드, 요청 타겟(서버 경로나 절대주소), HTTP 프로토콜 버전 순으로 구성된다.

다음에 하나 이상의 HTTP 헤더와 빈줄과 요청 메시지 본문이 온다.


HTTP 응답 메시지는 아래와 유사한 구조로 되어 있다.


1
2
3
4
HTTP/1.1 200 OK
Content-Type: text/plain
 
This is the response body
cs


첫번째 줄은 상태줄(status line) 로 HTTP 프로토콜 버전, HTTP 상태 코드 번호, HTTP 상태 코드 문구 순으로 구성된다.

다음엔 요청 메시지처럼 하나 이상의 HTTP 헤더와 빈줄, 응답 메시지 본문이 온다.


이 문서에 설명된 인터페이스는 HTTP 메시지와 구성 요소들을 추상화 한다.



Messages


HTTP 메시지는 클라이언트가 서버로 보내는 요청이던지, 서버가 클라이언트로 보내는 응답이다.

이 명세는 HTTP 메시지를 위한 인터페이스를 정의한다.


Psr\Http\Message\RequestInterface

Psr\Http\Message\ResponseInterface


둘다 Psr\Http\Message\MessageInterface 인터페이스를 확장한다.

MessageInterface 는 직접 구현할 수도 있지만, RequestInterface 와 ResponseInterface 를 구현하도록 한다.



HTTP Headers


Case-insensitive header field names

HTTP 메시지는 대소문자 구분없는 헤더 필드 이름들을 포함한다.

헤더는 MessageInterface 를 구현하는 클래스에서 대소문자 구분없이 이름으로 검색된다. (Foo 와 FoO 는 같은 이름이다.)

대소문자를 구분하지 않지만, 특히 getHeaders() 로 이름을 검색할 때 원래 이름은 보존해야만 한다.

관행을 따르지 않는 HTTP 어플리케이션은 대소문자를 구분할 수도 있기 때문이다.


Headers with multiple values

헤더에 여러 값이 주어질 때는 MessageInterface 인스턴스에서 배열이나 문자열로 검색할 수 있다.

대소문자 구분없이 모든 헤더 값에서 콤마로 연결된 문자열로 검색하려면 getHeaderLine() 메소드를 사용한다.

대소문자 구분없이 모든 헤더 값에서 배열로 검색하려면 getHeaderLine() 메소드를 사용한다.

Set-Cookie 같은 헤더는 콤마로 연결할 수 없으므로, 이런 여러 값을 가지는 헤더를 검색할 때는 getHeader() 메소드를 사용하도록 한다.


1
2
3
4
5
6
7
8
9
10

$message = $message
    ->withHeader('foo''bar')
    ->withAddedHeader('foo''baz');
 
$header = $message->getHeaderLine('foo');
// $header contains: 'bar, baz'
 
$header = $message->getHeader('foo');
// ['bar', 'baz']
cs


Host header

요청에서, Host 헤더는 TCP 로 연결되었을 때(establishing) 사용된 host 처럼 URI 의 host 컴포넌트를 말한다.

Host 헤더가 제공되지 않았다면 제공된 URI 로부터 Host 헤더를 세팅해야 한다.

기본적으로 RequestInterface::withUri() 는 전달된 UriInterface 의 host 컴포넌트와 일치하는 Host 헤더로 반환된 요청 Host 헤더를 대신한다.

두번째 매개변수($preserveHost)를 true 로 하여 Host 헤더의 원래 상태를 유지할 수 있다.

우선순위 : 요청 Host 헤더 > 요청 Host 컴포넌트 > URI Host 컴포넌트



Streams


HTTP 메시지는 시작줄, 헤더, 본문으로 구성된다. 본문은 매우 짧거나 길 수 있다.

본문은 모두 메모리에 저장되어야 하기 때문에 문자열로 메시지 본문을 작성하면 예상보다 더 많은 메모리를 쉽게 소모한다.

메모리에 요청이나 응답 본문을 저장하려고면 큰 메시지 본문에서 작동이 가능하도록 구현시 제외한다.

StreamInterface 는 데이터 스트림을 읽거나 쓸 때, 상세 구현을 숨기기 위해 사용된다.

문자열이 적절한 메시지 구현이 될 경우 php://memory 나 php://temp 등 내장된 스트림이 사용될 것이다.


스트림은 isReadable(), isWritable(), isSeekable() 메소드 등의 기능을 가지며, 가능하다면 결합하여 사용할 수도 있다.

각 스트림 인스턴스는 읽기 전용, 쓰기 전용, 읽기-쓰기, 순차 검색, 병렬 검색, 소켓/파이프/콜백 등 다양한 기능을 가질 것이다.

마지막으로, StreamInterface 는 전체 본문 내용을 즉시 검색하거나 내보내는 것을 간소화 하기 위해 __toString() 메소드를 정의한다.

메시지의 상태가 변경될 수 있으므로, 구현시 요청과 응답은 읽기 전용 스트림으로 사용하는 것이 좋다.



Request Targets and URIs


요청 메시지의 첫번째 라인 두번째 매개변수에 "요청-타겟(request-target)" 이 포함된다.

요청 타겟은 다음 형식 중 하나가 될 수 있다.


origin-form

경로나 쿼리 스트링으로 구성되며 상대 URL 로도 불히며 가장 일반적인 형식이다.

TCP 로 전송된 메시지는 origin-form 이다.

scheme 과 authority 데이터는 CGI 변수로 표현된다.


absolute-form

scheme 과 authority([user-info@]host[:port]), 경로, 쿼리 스트링, 매개변수 등으로 구성된다.

절대 경로로 불리며, RFC 3986 에 설명된 URI 를 지정하기 위한 유일한 형태이다.

HTTP 프록시로 요청 생성시 사용된다.


authority-form

authority 만으로 구성된다. HTTP 클라이언트와 프록시 서버에 연결하기 위한 CONNECT 요청에만 사용된다.


asterisk-form

웹서버의 일반적인 기능을 결정하는 OPTIONS 메소드를 사용하는 문자열 * 만으로 구성된다.


이 외에도 effective URL 이 있는데, 이 형식은 HTTP 메시지로 전달되지 않고, UriInterface로 나타낸다.

effective URL 은 요청을 생성하는 프로토콜(http/https), 호스트이름, 포트를 결정하는데 사용된다.

UriInterface 는 RFC 3986 에 지정된대로 HTTP 와 HTTPS URI 를 모델링한다.

인터페이스는 URI 의 반복된 파싱을 제거하고 여러 URI 부분들을 처리하기 위한 메소드들을 제공한다.

또한 문자열로 표현하기 위해 모델링된 URI 를 캐스팅할 ___toString() 메소드를 지정한다.


getRequestTarget() 으로 요청 타겟을 검색할 때, 이 메소드는 URI 객체를 사용하고 origin-form 구성에 필요한 모든 컴포넌트를 추출할 것이다.

다른 세가지 형식을 사용하려거나, 요청 타겟을 덮어씌우길 원하면 withRequestTarget() 을 사용한다.

이 메소드를 호출하는 것은 getUri() 로 반환되는것 처럼 URI 에 영향을 미치지 않는다.


예를 들어 사용자가 서버에 asterisk-form 요청하도록 하려면,


1
2
3
4
5

$request = $request
    ->withMethod('OPTIONS')
    ->withRequestTarget('*')
    ->withUri(new Uri('https://example.org/'));
cs


이 예는 다음과 같은 요청을 나타낼 것이다.


1
OPTIONS * HTTP/1.1
cs


그러나 HTTP 클라이언트는 프로토콜, 호스트이름, tcp 포트를 결정하기 위해 getuRI() 로 effective URL 을 사용할 수도 있을 것이다.

HTTP 클라이언트는 Uri::getPath() 와 Uri::getQuery() 값을 생략하고, 대신 이 두 값을 연결하는 getRequestTarget() 의 반환값을 사용해야 한다.


4가지 요청 타겟 형식 중 하나 이상을 구현하지 않을 클라이언트는 getRequestTarget() 을 사용해야 한다.

이 클라이언트들은 지원하지 않는 요청 타겟을 거부해야 하고, getUri() 로 값을 반환해서는 안된다.


RequestInterface 는 요청 타겟을 검색하거나 제공된 요청 타겟으로 새 인스턴스를 생성하는 메소드를 제공한다.

인스턴스에 요청 타겟이 없드면, getRequestTarget() 은 URI 의 origin-form 이나 슬래시(/) 를 반환할 것이다.

withRequestTarget($requestTarget) 은 지정된 요청 타겟으로 새 인스턴스를 생성하고, 다른 세 요청 타겟 형식을 나타내는 요청 메시지를 생성할 수 있게 한다.

서버로 연결을 생성하는데 사용될 클라이언트에서 구성된 URI 인스턴스는 여전히 사용될 수 있다.



Server-side Requests


RequestInterface 는 HTTP 요청의 일반적 표현을 제공한다.

그러나 서버 측 환경의 특성 때문에, 서버 측 요청은 추가 처리가 필요하다.

서버 측 처리는 CGI 와 PHP 의 추상화, SAPI 를 통한 CGI 확장을 고려해야 한다.

PHP 는 다음처럼 슈퍼 전역을 통한 입력을 단순화 할 수 있다.


$_COOKIE : HTTP 쿠키로 쉽게 접근 가능

$_GET : 쿼리 스트링 매개변수로 쉽게 접근 가능

$_POST : HTTP POST 로 전달된 urlencoded 파라미터에 쉽게 접근 가능

$_FILES : 파일 업로드의 메타 데이터에 접근 가능

$_SERVER : CGI/SAPI 환경 변수에 접근 가능 (요청 메소드, 스킴, URI, 헤더 포함)


ServerRequestInterface 는 이러한 슈퍼 전역 변수들의 추상화를 위해 RequestInterface 를 확장한다.

이 작업은 슈퍼 전역 변수로의 연결을 줄이는데 도움이 되고 요청을 테스트 하기 위한 기능을 향상한다.


서버 요청은 어플리케이션의 특정 규칙에 대하여 요청을 검사하기 위해 "attributes" 라는 하나의 속성을 추가한다.

이처럼, 서버 요청은 다수의 요청 간에 메시지를 제공할 수 있다.



Uploaded files


ServerRequestInterface 는 UploadedFileInterface 의 각각의 인스턴스로 표준화된 구조의 업로드 파일 트리를 검색하기 위한 메소드를 지정한다.


$_FILES 슈퍼 전역 변수는 input 태그 에서 파일 배열을 처리할 때 약간의 문제가 발생한다.

files 란 이름의 배열로 파일들이 전송되는 폼이 있다면 PHP 는 다음과 같이 표현될 것이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14

array(
    'files' => array(
        'name' => array(
            0 => 'file0.txt',
            1 => 'file1.html',
        ),
        'type' => array(
            0 => 'text/plain',
            1 => 'text/html',
        ),
        /* etc. */
    ),
)
cs


하지만 우리가 원하는 것은 이런 형태일 것이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

array(
    'files' => array(
        0 => array(
            'name' => 'file0.txt',
            'type' => 'text/plain',
            /* etc. */
        ),
        1 => array(
            'name' => 'file1.html',
            'type' => 'text/html',
            /* etc. */
        ),
    ),
)
cs


이 구현 세부 사항을 알고, 주어진 업로드에 대한 데이터를 수집하기 위해 코드를 작성해야 한다.

추가적으로, 파일이 업로드될 때 $_FILES 가 존재하지 않는 시나리오가 있다.


  • HTTP 메소드가 POST 가 아닌 경우
  • 유닛 테스트인 경우 
  • ReactPHP 같은 non-SAPI 환경에서 동작하는 경우


이 경우 데이터는 다르게 시드해야 할 것이다. 예를 들면,


  • 프로세스는 파일 업로드를 발견하기 위해 메시지 본문을 파싱할 것이다. 이 때, 구현은 파일 시스템으로 파일 업로드를 작성하지 않을 것이고, 메모리, I/O, 스토리지 오버헤드를 줄이기 위해 스트림으로 포장할 것이다.
  • 유닛 테스트에서 다른 경우들을 확인하고 검증하기 위해 파일 업로드 메타 데이터를 속일 수 있어야 한다.


getUploadedFiles() 는 정규화된 구조를 제공한다.

  • 전달된 파일 업로드의 모든 정보를 모아서, Psr\Http\Message\UploadedFileInterface 인스턴스를 생성하기 위해 사용하라.
  • 트리의 주어진 위치에 적절한 Psr\Http\Message\UploadedFileInterface 의 각각의 인스턴스로 전송된 트리구조를 재생성하라.


아래는 배열이 아닌 이름으로 폼 전송하는 예이다.


1
<input type="file" name="avatar" />
cs


$_FILES 의 구조는 다음과 같다.


1
2
3
4
5
6
7
8
9
10

array(
    'avatar' => array(
        'tmp_name' => 'phpUxcOty',
        'name' => 'my-avatar.png',
        'size' => 90996,
        'type' => 'image/png',
        'error' => 0,
    ),
)
cs


getUploadedFiles() 로 반환된 정규화된 형태는 다음과 같다.


1
2
3
4

array(
    'avatar' => /* UploadedFileInterface instance */
)
cs


배열 이름의 표기를 사용한 예이다.


1
<input type="file" name="my-form[details][avatar]" />
cs


$_FILES 의 구조는 다음과 같다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14

array(
    'my-form' => array(
        'details' => array(
            'avatar' => array(
                'tmp_name' => 'phpUxcOty',
                'name' => 'my-avatar.png',
                'size' => 90996,
                'type' => 'image/png',
                'error' => 0,
            ),
        ),
    ),
)
cs


getUploadedFiles() 로 반환된 트리는 다음과 같다.


1
2
3
4
5
6
7
8

array(
    'my-form' => array(
        'details' => array(
            'avatar' => /* UploadedFileInterface instance */
        ),
    ),
)
cs


자바스크립트로 파일 멀티 업로드를 추가하는 예에서처럼 파일 타입의 배열을 지정해 본다.


1
2
Upload an avatar: <input type="file" name="my-form[details][avatars][]" />
Upload an avatar: <input type="file" name="my-form[details][avatars][]" />
cs


이러한 경우, $_FILES 정상적인 구조로부터 벗어나기 때문에 주어진 인덱스에 파일 관련 모든 정보를 나타낸다.


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

array(
    'my-form' => array(
        'details' => array(
            'avatars' => array(
                'tmp_name' => array(
                    0 => '...',
                    1 => '...',
                    2 => '...',
                ),
                'name' => array(
                    0 => '...',
                    1 => '...',
                    2 => '...',
                ),
                'size' => array(
                    0 => '...',
                    1 => '...',
                    2 => '...',
                ),
                'type' => array(
                    0 => '...',
                    1 => '...',
                    2 => '...',
                ),
                'error' => array(
                    0 => '...',
                    1 => '...',
                    2 => '...',
                ),
            ),
        ),
    ),
)
cs


다음은 위의 $_FILES 배열이 getUploadedFiles() 로부터 반환된 구조이다.


1
2
3
4
5
6
7
8
9
10
11
12

array(
    'my-form' => array(
        'details' => array(
            'avatars' => array(
                0 => /* UploadedFileInterface instance */,
                1 => /* UploadedFileInterface instance */,
                2 => /* UploadedFileInterface instance */,
            ),
        ),
    ),
)
cs


그리고 index 1 의 배열은 다음처럼 접근한다.


1
2
<?
$request->getUploadedFiles()['my-form']['details']['avatars'][1];
cs


업로드된 파일들은 $_FILES 나 요청 본문으로부터 파생되었기 때문에, withUploadedFiles() 는 다른 처리로 표준화 위임을 허용하기 위해 인터페이스에 존재한다.


1
2
3
4
5
6
7
8
9
10
11
<?
$file0 = $request->getUploadedFiles()['files'][0];
$file1 = $request->getUploadedFiles()['files'][1];
 
printf(
    "Received the files %s and %s",
    $file0->getClientFilename(),
    $file1->getClientFilename()
);
 
// "Received the files file0.txt and file1.html"
cs


위 예는 non-SAPI 환경에서도 작동함을 알아야 한다.

따라서, UploadedFileInterface는 환경에 관계없이 작동할 수 있는 메소드를 제공한다.


moveTo($targetPath)

임시 업로드 파일에 move_uploaded_file() 을 직접 호출하기 위한 대안으로 안전하다.

구현은 환경에 기반하여 사용할 수있는 올바른 동작을 감지한다.


getStream() 

StreamInterface 인스턴스를 반환한다. non-SAPI 환경에서 한가지 가능한 것은 php://temp 스트림에 개별 업로드 파일을 파싱하는 것이다.

따라서 getStream() 은 환경에 관계없이 동작할 것이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?
// Move a file to an upload directory
$filename = sprintf(
    '%s.%s',
    create_uuid(),
    pathinfo($file0->getClientFilename(), PATHINFO_EXTENSION)
);
$file0->moveTo(DATA_DIR . '/' . $filename);
 
// Stream a file to Amazon S3.
// Assume $s3wrapper is a PHP stream that will write to S3, and that
// Psr7StreamWrapper is a class that will decorate a StreamInterface as a PHP
// StreamWrapper.
$stream = new Psr7StreamWrapper($file1->getStream());
stream_copy_to_stream($stream$s3wrapper);
cs




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

PSR-6

Programming/PHP 2016. 2. 22. 00:57

PSR-6 : 캐싱 인터페이스 (http://www.php-fig.org/psr/psr-6/)


캐싱은 많은 프레임워크와 라이브러리의 주요 기능 중 하나로, 프로젝트의 성능을 향상시키는 일반적인 방법이다.

이 문서는 이미 사용중인 프레임워크와 시스템에 통합될 수 있는 캐싱 라이브러리를 생성할 수 있도록 한다.



Definitions


Calling Library

실제 캐시 서비스가 필요한 라이브러리나 코드.

이 라이브러리는 표준 인터페이스를 구현하는 캐싱 서비스를 이용할 것이다.


Implementing Library 

이 라이브러리는 Calling 라이브러리로 캐시 서비스를 제공하기 위한 표준을 구현하도록 응답한다.

Cache\CacheItemPoolInterface 와 Cache\CacheItemInterface 인터페이스를 구현하는 클래스를 제공해야 한다.

초 단위의 최소 TTL 을 제공해야 한다.


TTL

Item 이 저장되고 나서 유지될 때까지의 시간(Time To Live)으로, DateInterval 객체나 초 단위의 정수로 정의된다.


Expiration

Item 이 소멸될 실제 시간을 지정한다.

일반적으로 객체가 저장될 때 TTL 에 시간을 추가하면서 계산되고, DateTime 객체로 지정된다.

Calling Library 는 만료 시간이 지정되지 않거나, null 로 지정된 item 을 요청한다면, Implementing Library 는 기본 유효기간으로 사용할 것이다.

기본 유효기간이 지정되지 않으면, Implementing Library 는 그 item 을 계속해서 캐시 요청할 것이다.


Key

최소 한글자 이상의 유일한 문자열인 키는 캐시된 Item 을 식별한다.

Implementing libraries 는 UTF-8 인코딩 64길이의 A-Z, a-z, 0-9, _, . 문자들로 구성된 키를 제공한다.

Implementing libraries 는 추가 문자열과 인코딩, 추가 길이를 최소한으로 제공할 것이다.

라이브러리는 적절하게 이스케이프 된 키 문자열로 응답하지만 수정되지 않은 키 문자를 반환할 수 있어야 한다.

{}()/\@: 문자는 추후 확장을 위해 예약되었고 implementing libraries 로부터 제공되지 않아야 한다.


Hit

캐시 hit 은 Calling Library 가 키로 Item 을 요청하고 일치하는 값을 찾았을 때 발생한다. 그 값은 만료되지 않으며 언제나 유효하다.

Calling Libraries 는 모든 get() 호출에서 isHit() 로 hit 을 확인하도록 한다.


Miss

캐시 miss 는 캐시 hit 의 반대이다.

캐시 miss 은 Calling Library 가 키로 Item 을 요청하고 그 키에 해당하는 값을 찾을 수 없거나, 만료된 값일 때 발생한다.

만료된 값은 항상 캐시 miss 를 고려해야 한다.


Deferred

지연된 캐시 보관은 pool 로부터 즉시 지속되지 않는 캐시 Item 을 가리킨다.

Pool 객체는 스토리지 엔진으로부터 제공된 대량 설정 연산의 이점을 위해 지연된 캐시 Item 을 연기할 것이다.

Pool 은 지연된 캐시 Item 이 지속되었는지, 데이터를 잃지 않았는지 확인해야 한다.

Calling Library 는 지속되야 하는 지연된 Item 들을 commit() 메소드를 호출한다.

Implementing Library 는 객체 소멸자나 save() 로 모두 지속시키거나 시간 초과나 최대 Item 수 체크나 다른 적절한 로직 같이, 지연된 Item 들을 지속할 때 결정하는 어떤 로직이든 사용할 것이다.

지연된 캐시 Item 의 요청은 아직 지속되지 않은 지연된 Item 을 반환해야 한다.



Key Concepts


캐싱 시스템에서 Item 들의 집합을 Pool 이라 하며, 모든 Item의 논리적인 저장소이다.

캐싱이 가능한 모든 Item은 Item 객체로서 Pool 에서 검색되며, 캐시된 객체의 모든 처리는 Pool 을 통해 발생한다.

Item 은 Pool 안에 키/값 형태로 존재하며 키는 Item 의 유일한 식별자이고 변하지 말아야 한다.



Data


Implementing Library 는 모든 PHP 데이터 타입을 지원한다. (Strings, Integers, Floats, Boolean, Null, Arrays, Object)

Implementing Library 로 전달된 모든 데이터는 전달된 타입 그대로 반환되어야 하며, PHP의 serialize() 나 unserialize() 함수를 사용할 필요가 없다.

어떤 이유로 실제 저장된 값을 반환할 수 없다면, Implementing Library 는 손상된 데이터 보다는 캐시 miss 로 응답해야만 한다.



Error handling


캐싱은 어플리케이션 성능면에서 중요하지만 기능적으로는 그렇지 않다.

그래서 캐시 시스템에서 에러는 어플리케이션 실패로 나타나지 않아야 한다.

이런 이유로 Implementing Libraries 는 인터페이스로부터 정의된 예외를 제외하고는 발생하지 않아야 한다.

Implementing Library 는 그러한 에러를 기록하거나, 관리자에게 보고한다.



Interfaces


CacheItemInterface

CacheItemInterface 은 캐시 시스템 내부에 Item 을 정의한다.

각 Item 객체는 시스템 구현에 따라 설정할 수 있는 지정된 키로 할당되어야 한다.

일반적으로 이 키는 Cache\CacheItemPoolInterface 객체로부터 전달될 수 있다.

Cache\CacheItemInterface 객체는 캐시 Item 의 저장과 검색을 캡슐화한다.

각 Cache\CacheItemInterface 는 고유 키를 가진 객체를 할당할 뿐 아니라 어떤 요구된 설정에도 응답 가능한 Cache\CacheItemPoolInterface 객체로부터 생성된다.

Cache\CacheItemInterface 객체는 이 문서에 정의된 Data type 으로 저장되고 검색될 수 있어야 한다.

Calling Library 는 자신의 Item 객체를 인스턴스화하지 않아야 하며, getItem() 메소드를 통해 Pool 객체로부터만 요청될 것이다.

Calling Library 는 하나의 Implementing Library 에 의해 생성 된 Item 이 다른 Implementing Library 에서 Pool로 호환될 것으로 가정해서는 안된다.


CacheItemPoolInterface

Cache\CacheItemPoolInterface 의 목적은 Calling Library 로부터 키를 받고, 할당된 Cache\CacheItemInterface 객체를 반환하는 것이다.

또한 전체 캐시 컬렉션과의 상호작용도 중요한 부분이다.

Pool 의 모든 설정과 초기화는 Implementing Library 에 남아 있다.


CacheException

이 예외 인터페이스는 캐시 서버로의 연결처럼 캐시 설정에만 제한되지 않는 중요한 오류가 발생했을 때 사용하기 위한 것이다.

Implementing Library 로부터 발생한 오류는 이 인터페이스를 구현해야 한다.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

PSR-4

Programming/PHP 2016. 2. 21. 23:32

PSR-4 : 오토로더 (http://www.php-fig.org/psr/psr-4/)



파일 경로로부터 클래스를 오토로딩하기 위한 표준이다.

PSR-0 를 포함하는 다른 어떤 오토로딩도 사용될 수 있으며, 오토로드 될 파일들의 위치도 설명한다.


정규화된 클래스 이름은 다음과 같은 형태를 가진다.


\<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>


vendor 네임스페이스로 알려진 최상위 네임스페이스 이름과 하나 이상의 서브 네임스페이스 이름, 마지막에 클래스 이름을 가져야 한다.

밑줄은 정규화된 클래스 이름에서 어떤 의미도 가지지 않으며, 모든 클래스 이름은 대소문자를 구분한다.


정규화된 클래스 이름에 해당하는 파일을 로딩할 때, 

최상위 네임스페이스 부터 서브 네임스페이스 이름은 \ 구분자로 디렉토리로 구분되어 최소 하나의 베이스 디렉토리에 대응된다.

최상위 네임스페이스 부터 서브 네임스페이스 까지는 네임스페이스 접두어가 되며 마지막 클래스 이름인은 경로의 .php 파일과 매칭된다.

오토로딩 구현은 예외나 에러를 발생하지 않아야 하고, 값을 리턴해서도 안된다.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

PSR-3

Programming/PHP 2016. 2. 20. 00:30

PSR-3 : 로거 인터페이스 (http://www.php-fig.org/psr/psr-3/)


Logging 라이브러리에 대한 공통 인터페이스를 설명한다.

Psr\Log\LoggerInterface 인터페이스를 구현하여 간단하게 로그를 기록할 수 있도록 한다.

사용자의 프레임워크나 CMS 에서 이 인터페이스를 확장하려면, 이 문서와 호환성을 유지하도록 한다.



Basic


LoggerInterface 에는 RFC 5424 레벨의 8가지 메소드가 있다. (debug, info, notice, warning, error, critical, alert, emergency).

9번째 메소드인 log 는 첫번째 매개변수로 로그 레벨을 지정할 수 있다.

로그 레벨 상수 중 하나를 지정하여 log 메소드를 호출하는 것은 해당 레벨의 메소드를 호출하는 것과 같은 결과를 가진다.

로그 레벨 상수 없이 log 메소드를 호출하면 Psr\Log\InvalidArgumentException 이 발생한다.

이 외에 임의의 사용자 레벨을 사용하지 않도록 한다.


1
2
3
4
5
6
7
8
<?php
namespace Psr\Log;
 
interface LoggerInterface
{
    public function info($messagearray $context = array());
...
 
cs



Message


모든 메소드는 객체(__toString())나 문자열로 된 매개변수(message)를 가진다.

이 때 전달된 객체를 특별히 다룰게 아니라면, 문자열로 캐스팅 해야 한다.

message는 context 배열의 값을 대체할 placeholder 를 포함할 것이다.

Placeholder 이름은 context 배열의 키와 일치해야 하며, 중괄호{}로 구분되어야 한다.

Placeholder 와 구분자 사이에 공백이 없어야 한다.

Placeholder 이름은 A-Z, a-z, 0-9, _(밑줄), .(마침표) 로만 구성하도록 한다.



Context


모든 메소드는 문자열이 아닌 값도 다루기 위해 배열로 된 context 매개변수를 가진다.

context 의 값은 예외나 경고, 에러를 발생시킬 수 없으므로 구현시 가능한 확실하게 처리한다.

context 값으로 Exception 객체가 전달되면, exception 키가 되므로, 구현시 exception 키가 실제 Exception 객체인지 확인해야 한다.



Helper classes and interfaces


  • Psr\Log\AbstractLogger
    LoggerInterface 를 확장하고, log 메소드를 구현하여 쉽게 logging 할 수 있게 한다.
    8가지 메소드들이 log 로 message 와 context 를 전달한다.

  • Psr\Log\LoggerTrait
    Psr\Log\AbstractLogger 와 유사하게 log 메소드만 구현할 수 있게 한다.
    trait 는 interface 를 구현할 수 없으므로, 이 경우 LoggerInterface 를 직접 구현해야 한다.

  • Psr\Log\NullLogger
    인터페이스와 함께 제공되며, logger 가 없을  때 로그를 남길 수 있게 한다.
    그러나 context 데이터 작성이 어렵다면 조건부 로깅이 더 나을 수 있다.

  • Psr\Log\LoggerAwareInterface
    setLogger(LoggerInterface $logger) 메소드만 가지고 있다.
    logger 임시 인스턴스와 연결되도록 프레임워크에서 사용될 수 있다.

  • Psr\Log\LoggerAwareTrait
    모든 클래스에 동일한 인터페이스를 쉽게 구현하도록 한다.
    $this->logger 에 접근할 수 있다.

  • Psr\Log\LogLevel
    8가지 로그 레벨 상수를 가진다.



WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,