├── config.json ├── .gitignore ├── README.md ├── SUMMARY.md ├── accepted ├── PSR-20-clock.md ├── PSR-4-autoloader.md ├── PSR-15-request-handlers.md ├── PSR-1-basic-coding-standard.md ├── PSR-11-container.md ├── PSR-18-http-client.md ├── PSR-17-http-factory.md ├── PSR-14-event-dispatcher.md ├── PSR-3-logger-interface.md ├── PSR-16-simple-cache.md ├── PSR-13-links.md ├── PSR-4-autoloader-examples.md ├── PSR-6-cache.md └── PSR-12-extended-coding-style-guide.md ├── deprecated ├── PSR-0.md └── PSR-2-coding-style-guide.md └── LICENSE.md /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "language": "ko" 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /_site 2 | *.gem 3 | .sass-cache 4 | Gemfile.lock 5 | .idea -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHP Standards Recommendations 한글 버전 2 | 3 | ## 주의사항 4 | - 모든 내용은 공식 문서인 [https://www.php-fig.org/psr/](https://www.php-fig.org/psr/)의 내용이 더 우선시 됩니다. 5 | - PHP Standards Recommendations 한글 번역본입니다. 6 | - 개인이 학습용도로 번역한 내용이니 일부 오역이 있을 수 있습니다. 7 | - 일부 내용은 한글로 번역 후 어색하지 않기 위해 의역을 하였습니다. 8 | 9 | 10 | ## 번역 가이드 11 | 12 | - Class, Method, Properties 같은 개발자라면 번역하면 어색한 문장은 원문을 그대로 사용합니다 -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | ## 승인 완료된 사항 (Accepted) 4 | 5 | * [PSR-1-basic-coding-standard](accepted/PSR-1-basic-coding-standard.md) 6 | * [PSR-3-logger-interface](accepted/PSR-3-logger-interface.md) 7 | * [PSR-4-autoloader](accepted/PSR-4-autoloader.md) 8 | * [PSR-4-autoloader-examples](accepted/PSR-4-autoloader-examples.md) 9 | * [PSR-6-cache](accepted/PSR-6-cache.md) 10 | * [PSR-7-http-message](accepted/PSR-7-http-message.md) 11 | * [PSR-11-container](accepted/PSR-11-container.md) 12 | * [PSR-12-extended-coding-style-guide](accepted/PSR-12-extended-coding-style-guide.md) 13 | * [PSR-13-links](accepted/PSR-13-links.md) 14 | * [PSR-14-event-dispatcher](accepted/PSR-14-event-dispatcher.md) 15 | * [PSR-15-request-handlers](accepted/PSR-15-request-handlers.md) 16 | * [PSR-16-simple-cache](accepted/PSR-16-simple-cache.md) 17 | * [PSR-17-http-factory](accepted/PSR-17-http-factory.md) 18 | * [PSR-18-http-client](accepted/PSR-18-http-client.md) 19 | * [PSR-20-clock](accepted/PSR-20-clock.md) 20 | 21 | ## 종료된 사항 (Deprecated) 22 | 23 | * [PSR-0](deprecated/PSR-0.md) 24 | * [PSR-2-coding-style-guide](deprecated/PSR-2-coding-style-guide.md) 25 | 26 | ## 참고자료 27 | 28 | * [RFC2119 한글번역본](https://techhtml.github.io/rfc/RFC2119.html) -------------------------------------------------------------------------------- /accepted/PSR-20-clock.md: -------------------------------------------------------------------------------- 1 | Common Interface for Accessing the Clock 2 | ======================================== 3 | 4 | 이 문서는 시스템의 시간을 읽기 위한 간단한 인터페이스에 대해 설명합니다. 5 | 6 | 이 문서에서 핵심이 되는 단어는 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", "OPTIONAL" 입니다. 7 | 이것은 [RFC 2119](http://tools.ietf.org/html/rfc2119)에 설명 된대로 해석해야 합니다. 8 | 9 | > 역자주: 위의 키워드는 아래의 번역문에 괄호안에 표시하였습니다 10 | 11 | 최종 구현은 제안된 것보다 더 많은 기능을 가진 개체로 만들 수도 있지만, 표시한 인터페이스/기능을 먼저 구현해야 합니다. 12 | 13 | # 1. 명세서 14 | 15 | ## 1.1 소개 16 | 17 | 시간에 접근하기위한 표준 메서드를 만들면, 시점에 기반한 사이드이펙트가 있는 동작을 테스트할 때, 상호 운용성을 가지게 됩니다. 18 | 19 | > 역자주: 특정한 시간에만 동작하는 코드를 테스트할 때, 강제로 시간을 바꿔서 해당 코드가 동작하거나 하지 않는 테스트를 하기 좋아진다는 의미입니다 20 | 21 | 일반적으로 현재 시간을 가져오는 방법으로는 `\time()` 또는 `new \DateTimeImmutable('now')`을 사용하는 것이 포함됩니다. 22 | 그러나 이것은 일부 상황에서 현재 시간을 모킹-mocking하는 것을 불가능하게 만듭니다. 23 | 24 | > 역자주: 이 메서드들은 강제로 시간을 바꾸는 기능을 지원하지 않습니다. 따라서 시점에 따른 코드의 동작을 테스트 할 수 없습니다 25 | 26 | ## 1.2 정의 27 | 28 | * **Clock** - clock은 현재 시간과 날짜를 읽을 수 있습니다. 29 | 30 | * **Timestamp** - Jan 1, 1970 00:00:00 UTC 이후의 초-second로 표시되는 현재 시간 31 | 32 | ### 1.3 사용법 33 | 34 | **현재 타임스탬프 가져오기** 35 | 36 | 이 작업은 반환된 `\DateTimeImmutable`에서 `getTimestamp()` 메서드를 사용해서 처리해야 합니다. 37 | 38 | ```php 39 | $timestamp = $clock->now()->getTimestamp(); 40 | ``` 41 | 42 | # 2. Interfaces 43 | 44 | ## 2.1 ClockInterface 45 | 46 | clock 인터페이스는 clock에서 현재 시간과 날짜를 읽는 가장 기본적인 동작을 정의합니다. 47 | 48 | 이것은 반드시 `\DateTimeImmutable`로 시간을 반환해야 합니다 (MUST). 49 | 50 | ```php 51 | **사용중단** - 2014-10-21을 기준으로 PSR-0은 사용이 중단되었습니다. 새로운 표준으로 [PSR-4]을 사용하시길 권장합니다. 5 | 6 | [PSR-4]: /accepted/psr-4-autoloader 7 | 8 | 9 | 다음은 오토로더 상호 운용성을 위해 반드시 준수해야하는 필수 요구 사항에 대해 설명합니다. 10 | 11 | 필수 요구사항 12 | --------- 13 | 14 | * 정규화된 네임스페이스 및 클래스는 다음과 같은 구조를 따라야 합니다. 15 | `\\(\)*` 16 | * 각 네임스페이스의 최상위 네임스페이스에는 `공급자(Vendor)의 이름`을 사용해야 합니다. 17 | * 각 네임스페이스는 원하는 만큼의 하위 네임스페이스를 가질 수 있습니다. 18 | * 각 네임스페이스의 구분기호는 `DIRECTORY_SEPARATOR`로 변환됩니다. 19 | * CLASS 이름에서 각 `_` 문자는 `DIRECTORY_SEPARATOR`로 변환됩니다. `_`는 네임스페이스에서 특별한 의미가 없습니다. 20 | * 규칙에 맞게 작성된 클래스를 파일시스템에서 불러올 때 `.php`가 마지막에 붙습니다. 21 | * 공급자(Vendor) 이름, 네임 스페이스 및 클래스 이름의 알파벳 문자는 소문자와 대문자의 조합으로 구성 될 수 있습니다. 22 | 23 | 예제 24 | -------- 25 | 26 | * `\Doctrine\Common\IsolatedClassLoader` => `/path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php` 27 | * `\Symfony\Core\Request` => `/path/to/project/lib/vendor/Symfony/Core/Request.php` 28 | * `\Zend\Acl` => `/path/to/project/lib/vendor/Zend/Acl.php` 29 | * `\Zend\Mail\Message` => `/path/to/project/lib/vendor/Zend/Mail/Message.php` 30 | 31 | 밑줄이 있는 네임스페이스와 클래스의 예제 32 | ----------------------------------------- 33 | 34 | * `\namespace\package\Class_Name` => `/path/to/project/lib/vendor/namespace/package/Class/Name.php` 35 | * `\namespace\package_name\Class_Name` => `/path/to/project/lib/vendor/namespace/package_name/Class/Name.php` 36 | 37 | 고통받지 않고 오토로더를 사용하려면 최소한 이런 규약들을 지켜야 합니다. 38 | PHP 5.3 이상에서 아래와 같은 샘플 SplClassLoader 구현을 사용하여 이러한 표준을 따르고 있는지 테스트 할 수 있습니다. 39 | 40 | 41 | 구현 예제 42 | ---------------------- 43 | 44 | 다음은 위에 제안 된 표준이 자동으로 로드되는 방식을 간단하게 보여주는 예제입니다. 45 | 46 | ~~~php 47 | 역자주: 위의 키워드는 아래의 번역문에 괄호안에 표시하였습니다 6 | 7 | ## 1. 개요 8 | 9 | 이 PSR은 Class [autoloading] 에서 파일 경로에 대한 사양(specification)을 설명합니다. 10 | 이 PSR은 완벽하게 상호 운용이 가능하며 [PSR-0]을 포함한 다른 오토로딩 사양과 함께 사용할 수 있습니다. 11 | 또한 이 PSR은 사양에 따라 오토로드되는 파일을 저장할 위치를 설명합니다. 12 | 13 | ## 2. 명세서 14 | 15 | 1. "Class"라는 용어는 Class, Interface, Trait 등의 기타 유사한 구조를 말합니다. 16 | 17 | 2. 정규화 된 클래스 이름의 형식은 다음과 같습니다. 18 | 19 | \(\)*\ 20 | 21 | 1. 정규화 된 Class 이름은 "공급자 네임스페이스"라고도하는 최상위 네임스페이스를 가져야만 합니다(MUST). 22 | 23 | 2. 정규화 된 Class 이름은 하나 이상의 하위 네임스페이스를 가질 수 있습니다 (MAY). 24 | 25 | 3. 정규화된 Class 이름은 마지막 클래스 이름(terminating class name)을 가져야합니다 (MUST). 26 | > 역자주: 좀 더 좋은 의미의 표현을 찾지 못하였습니다 27 | 28 | 4. 밑줄은 정규화 된 클래스 이름의 어느 부분에도 특별한 의미가 없습니다. 29 | 30 | 5. 정규화 된 클래스 이름의 알파벳 문자는 대소문자의 조합 일 수 있습니다 (MAY). 31 | 32 | 6. 모든 클래스 이름은 대소문자를 구분하여 참조해야합니다 (MUST). 33 | 34 | 3. 정규화 된 클래스 이름에 해당하는 파일을 로드 할 때 ... 35 | 36 | 1. 정규화 된 클래스 이름에서 최초의 네임스페이스 구분 기호를 제외하고 연속된 하나 이상의 상위 네임스페이스와 하위 네임스페이스로 구성된 ( "네임스페이스 접두사")는 적어도 하나의 "기본 디렉토리"에 대응합니다. 37 | > 역자주: 표현을 더 다듬어야 할 듯 하지만 네임스페이스의 조합은 하나의 디렉토리와 매치가 된다는 의미로 이해하시면 될 것 같습니다 38 | 39 | 2. "네임스페이스 접두사" 다음의 이어지는 하위 네임스페이스 이름은 "기본 디렉토리" 내의 하위 디렉토리에 해당하며 네임스페이스 구분 기호는 디렉토리 구분 기호를 나타냅니다. 40 | 하위 디렉토리 이름은 하위 네임스페이스 이름의 대소문자와 일치해야합니다. 41 | 42 | 3. 마지막에 존재하는 Class 이름은 `.php` 로 끝나는 파일 이름과 같아야 합니다. 43 | 44 | 파일 이름은 Class 이름의 대소문자와 일치해야합니다(MUST). 45 | > 역자주: \Vendor\Packages\Class => Class.php 46 | 47 | 4. 오토로더 구현체는 예외(exception)를 throw해서는 안되며(MUST NOT), 모든 레벨의 오류를 발생해서는 안되며(MUST NOT), 값을 반환해서는 안됩니다 (SHOULD NOT). 48 | 49 | ## 3. 예제 50 | 51 | 아래의 표는 주어진 정규화 된 Class 이름, 네임스페이스 접두사 및 기본 디렉토리에 해당하는 파일 경로를 보여줍니다. 52 | 53 | | 정규화된 Class 이름 | Namespace 접두사 | 기본 디렉토리 | 결과 파일 경로 54 | | ----------------------------- |--------------------|--------------------------|------------------------------------------- 55 | | \Acme\Log\Writer\File_Writer | Acme\Log\Writer | ./acme-log-writer/lib/ | ./acme-log-writer/lib/File_Writer.php 56 | | \Aura\Web\Response\Status | Aura\Web | /path/to/aura-web/src/ | /path/to/aura-web/src/Response/Status.php 57 | | \Symfony\Core\Request | Symfony\Core | ./vendor/Symfony/Core/ | ./vendor/Symfony/Core/Request.php 58 | | \Zend\Acl | Zend | /usr/includes/Zend/ | /usr/includes/Zend/Acl.php 59 | 60 | 명세를 따르는 Autoloader의 구현 예제는 [examples file]을 참조하십시오. 61 | 예제 구현체는 명세(specification)의 일부로 간주되어서는 안되며(MUST NOT) 언제든지 변경 될 수 있습니다. 62 | 63 | [autoloading]: http://php.net/autoload 64 | [PSR-0]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md 65 | [examples file]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md 66 | -------------------------------------------------------------------------------- /accepted/PSR-15-request-handlers.md: -------------------------------------------------------------------------------- 1 | HTTP Server Request Handlers 2 | ============================ 3 | 4 | 이 문서에서는 [PSR-7][psr7] 또는 후속 PSR로 설명 된 HTTP 메시지를 사용하는 HTTP 서버 요청 처리기 ("요청 처리기") 및 HTTP 서버 미들웨어 구성 요소 ("미들웨어")에 대한 일반적인 인터페이스에 대해 설명합니다. 5 | 6 | HTTP 요청 처리기는 모든 웹 응용 프로그램의 기본 요소입니다. 7 | 서버 측 코드는 요청 메시지를 수신하여 처리하고 응답 메시지를 생성합니다. 8 | HTTP 미들웨어는 공통 요청 및 응답 처리를 응용 프로그램 계층에서 분리하는 한 방법입니다. 9 | 10 | 이 문서에서 설명하는 인터페이스는 요청 처리기 및 미들웨어에 대한 추상화입니다. 11 | 12 | _참고 : "요청 처리기"와 "미들웨어"에 대한 모든 참조는 **서버 요청** 처리에만 해당됩니다 ._ 13 | 14 | 15 | 이 문서에서 핵심이 되는 단어는 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", "OPTIONAL" 입니다. 16 | 이것은 [rfc2119]에 설명 된대로 해석해야 합니다. 17 | 18 | > 역자주: 위의 키워드는 아래의 번역문에 괄호안에 표시하였습니다 19 | 20 | [psr7]: http://www.php-fig.org/psr/psr-7/ 21 | [rfc2119]: http://tools.ietf.org/html/rfc2119 22 | 23 | ### References 24 | 25 | - [PSR-7][psr7] 26 | - [RFC 2119][rfc2119] 27 | 28 | ## 1. 명세서 29 | 30 | ### 1.1 Request Handlers 31 | 32 | 요청 처리기는 PSR-7에 정의 된대로 요청을 처리하고 응답을 생성하는 개별 구성 요소입니다. 33 | 34 | 요청 처리자가 응답을 생성하지 못하는 경우 요청 처리기가 예외를 던질 수 있습니다 (MAY). 35 | 예외 유형이 정의되지 않았습니다. 36 | 37 | 이 표준을 사용하는 요청 처리기는 다음 인터페이스를 구현해야합니다 (MUST). 38 | 39 | - `Psr\Http\Server\RequestHandlerInterface` 40 | 41 | ### 1.2 Middleware 42 | 43 | 미들웨어 구성 요소는 들어오는 요청을 처리하고 PSR-7에 정의 된 결과 응답을 생성 할 때 다른 미들웨어 구성 요소와 함께 참여하는 개별 구성 요소입니다. 44 | 45 | 미들웨어 컴포넌트는 충분한 조건이 만족된다면 요청 처리자에게 위임하지 않고 응답을 생성하고 리턴 할 수 있습니다 (MAY). 46 | 47 | 이 표준을 사용하는 미들웨어는 다음 인터페이스를 구현해야합니다(MUST). 48 | 49 | - `Psr\Http\Server\MiddlewareInterface` 50 | 51 | ### 1.3 Generating Responses 52 | 53 | 응답을 생성하는 미들웨어 또는 요청 처리기는 특정 HTTP 메시지 구현에 대한 의존을 방지하기 위해 PSR-7 `ResponseInterface` 의 프로토타입 또는 `ResponseInterface` 인스턴스를 생성 할 수 있는 팩토리를 작성하는 것이 좋습니다(RECOMMENDED). 54 | 55 | ### 1.4 Handling Exceptions 56 | 57 | 미들웨어를 사용하는 모든 응용 프로그램에는 예외를 잡아서 응답으로 변환하는 구성 요소가 포함되는 것이 좋습니다(RECOMMENDED). 58 | 이 미들웨어는 실행 된 첫 번째 구성 요소 여야하며(SHOULD) 응답이 항상 생성되도록하기 위해 모든 추가 처리를 래핑해야합니다. 59 | 60 | ## 2. Interfaces 61 | 62 | ### 2.1 Psr\Http\Server\RequestHandlerInterface 63 | 64 | 요청 처리기는 다음의 인터페이스를 구현되어야합니다(MUST). 65 | 66 | ```php 67 | namespace Psr\Http\Server; 68 | 69 | use Psr\Http\Message\ResponseInterface; 70 | use Psr\Http\Message\ServerRequestInterface; 71 | 72 | /** 73 | * Handles a server request and produces a response. 74 | * 75 | * An HTTP request handler process an HTTP request in order to produce an 76 | * HTTP response. 77 | */ 78 | interface RequestHandlerInterface 79 | { 80 | /** 81 | * Handles a request and produces a response. 82 | * 83 | * May call other collaborating code to generate the response. 84 | */ 85 | public function handle(ServerRequestInterface $request): ResponseInterface; 86 | } 87 | ``` 88 | 89 | ### 2.2 Psr\Http\Server\MiddlewareInterface 90 | 91 | 미들웨어 구성 요소는 다음 인터페이스에 호환 가능하게 구현해야합니다(MUST). 92 | 93 | ```php 94 | namespace Psr\Http\Server; 95 | 96 | use Psr\Http\Message\ResponseInterface; 97 | use Psr\Http\Message\ServerRequestInterface; 98 | 99 | /** 100 | * Participant in processing a server request and response. 101 | * 102 | * An HTTP middleware component participates in processing an HTTP message: 103 | * by acting on the request, generating the response, or forwarding the 104 | * request to a subsequent middleware and possibly acting on its response. 105 | */ 106 | interface MiddlewareInterface 107 | { 108 | /** 109 | * Process an incoming server request. 110 | * 111 | * Processes an incoming server request in order to produce a response. 112 | * If unable to produce the response itself, it may delegate to the provided 113 | * request handler to do so. 114 | */ 115 | public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface; 116 | } 117 | ``` 118 | -------------------------------------------------------------------------------- /accepted/PSR-1-basic-coding-standard.md: -------------------------------------------------------------------------------- 1 | # PSR-1 기본 코딩 표준 2 | 3 | 이 섹션은 공유되는 PHP 코드 간의 높은 수준의 기술적 상호 호환성을 보장하는 데 필요한 표준 코딩 사항으로 간주되어야 하는 것을 포함합니다. 4 | 5 | 6 | 7 | 이 문서에서 핵심이 되는 단어는 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", "OPTIONAL" 입니다. 8 | 이것은 [RFC 2119]에 설명 된대로 해석해야 합니다. 9 | 10 | > 역자주: 위의 키워드는 아래의 번역문에 괄호안에 표시하였습니다 11 | 12 | 13 | 14 | [RFC 2119]: http://www.ietf.org/rfc/rfc2119.txt 15 | [PSR-0]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md 16 | [PSR-4]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md 17 | 18 | ## 1. 개요 19 | 20 | - 반드시(MUST) ` 역자주: StudlyCaps 라는것은 단어의 첫글자가 대문자인 규칙을 말합니다. ex: DefaultClass 30 | 31 | - Class의 상수(constants)는 반드시(MUST) 전부 대문자와 밑줄`_`만으로 작성해야합니다. 32 | 33 | - Method는 반드시(MUST) `camelCase`로 작성해야합니다. 34 | 35 | ## 2. 파일 36 | 37 | ### 2.1. PHP Tags 38 | 39 | PHP 코드는 반드시(MUST) 긴 `` 태그나 짧은 `` 태그를 사용해야합니다 40 | 그외의 태그를 사용해서는 안됩니다 (MUST NOT). 41 | 42 | ### 2.2. Character Encoding 43 | PHP 코드는 반드시(MUST) BOM이 없는 UTF-8 문자열만 사용해야합니다 44 | 45 | ### 2.3. 사이드이펙트 46 | 47 | 각 파일은 새로운 무언가 (클래스, 함수, 상수 등)를 선언하고 다른 사이드이펙트를 일으키지 않거나, 48 | 사이드이펙트가 있는 로직를 실행하지만(SHOULD) 둘 다 수행하면 안됩니다(SHOULD NOT). 49 | 50 | "사이드이펙트"는 클래스, 함수, 상수 등을 선언하는 것과 직접적으로 관련이없는 논리를 파일에 단순히 포함하는 것부터 실행하는 것 전부를 의미합니다. 51 | 52 | > 역자주: 일반적으로 프로그래밍에서 사용되는 사이드이펙트의 의미와 이 문장에서 사용되는 사이드이펙트의 의미는 약간의 차이가 있습니다 53 | 54 | "사이드이펙트"에는 Output 생성, 명시적인 "require"또는 "include"의 사용, 외부 서비스 연결, ini 설정 변경, 오류 또는 예외 발생, 전역 변수 또는 정적 변수 변경, 파일의 읽기 또는 쓰기 등이 있습니다. 55 | 56 | 다음은 선언과 사이드이펙트가 모두 포함 된 파일의 예입니다. 57 | 58 | 예제: 59 | 60 | ~~~php 61 | \n"; 70 | 71 | // declaration 72 | function foo() 73 | { 74 | // function body 75 | } 76 | ~~~ 77 | 78 | 다음 예제는 사이드이펙트가 없이 작성된 파일입니다. 79 | 80 | 예제: 81 | 82 | ~~~php 83 | 역자주: 위의 키워드는 아래의 번역문에 괄호안에 표시하였습니다 11 | 12 | 이 문서에서 `implementor` 라는 단어는 의존성 삽입 관련 라이브러리나 프레임워크에서 `ContainerInterface`를 구현하는 누군가로 해석되어야합니다. 13 | 의존성 주입 컨테이너 (DIC)의 사용자는 `사용자`라고합니다. 14 | 15 | [RFC 2119]: http://tools.ietf.org/html/rfc2119 16 | 17 | ## 1. 명세서 18 | 19 | ### 1.1 기본 20 | 21 | #### 1.1.1 엔트리 식별자 22 | 23 | 엔트리 식별자는 컨테이너 내의 항목을 고유하게 식별하는 적어도 하나의 문자로 구성된 PHP에서 유효한 문자열입니다. 24 | 엔트리 식별자는 불투명 한 문자열이므로 호출자는 문자열의 구조가 의미를 전달한다고 가정해서는 안됩니다(SHOULD NOT). 25 | 26 | #### 1.1.2 컨테이너에서 읽어오기 27 | 28 | - `Psr\Container\ContainerInterface`는 `get`과 `has` 두가지 메서드를 제공합니다. 29 | 30 | - `get` 은 하나의 필수 매개 변수를 가집니다. 엔트리 식별자는 반드시 문자열이어야 합니다 (MUST). 31 | `get` 은 어떤 값이든 (하나의 *mixed* 값) 반환 할 수 있고 식별자가 컨테이너에 알려지지 않은 경우에는 `NotFoundExceptionInterface` 예외를 던집니다. 32 | 동일한 식별자를 가진 `get` 에 대한 두 번의 연속적인 호출은 동일한 값을 반환해야합니다 (SHOULD). 33 | 그러나 `implementor` 디자인 또는 `user` 설정에 따라 다른 값들이 반환 될 수 있습니다. 그래서 `user`는 2번의 연속적인 호출에서 같은 값을 얻는 것에 의존하지 않아야합니다 (SHOULD NOT). 34 | 35 | - `has` 는 하나의 고유 한 매개 변수를 가집니다. 엔트리 식별자는 반드시 문자열이어야 합니다(MUST). 36 | `has` 는 엔트리 식별자가 컨테이너에 알려지면 `true` 를 리턴하고 그렇지 않으면 `false` 를 리턴해야합니다 (MUST). 37 | `has($id)` 가 false 를 반환하면 `get($id)` 는 `NotFoundExceptionInterface` 예외를 던져야합니다. 38 | 39 | ### 1.2 Exceptions 40 | 41 | 컨테이너에 의해 직접 던져진 예외는 42 | [`Psr\Container\ContainerExceptionInterface`](#container-exception)을 상속해야한다(SHOULD). 43 | 44 | 존재하지 않는 id를 가진 `get` 메서드에 대한 호출은 45 | [`Psr\Container\NotFoundExceptionInterface`](#not-found-exception) 예외를 던져야 한다(MUST). 46 | 47 | ### 1.3 권장 사용법 48 | 49 | 사용자는 객체가 *자신의 의존성*을 검색 할 수 있도록 컨테이너에 객체를 넘겨서는 안됩니다(SHOULD NOT). 50 | 즉, 컨테이너는 [Service Locator](https://en.wikipedia.org/wiki/Service_locator_pattern)로 사용됩니다. 51 | 이런 행동은 일반적으로 방해가 됩니다 52 | 53 | 자세한 내용은 META 문서의 섹션 4를 참조하십시오. 54 | 55 | ## 2. Package 56 | 57 | 설명한 인터페이스와 클래스 및 예외 사항은 [psr/container](https://packagist.org/packages/psr/container) 패키지의 일부로 제공됩니다. 58 | 59 | PSR 컨테이너 구현체를 제공하는 패키지는 `psr/container-implementation` 을 제공한다고 선언해야합니다. 60 | 61 | 구현이 필요한 프로젝트에는 `psr/container-implementation`의 `1.0.0` 을 요구합니다. 62 | 63 | ## 3. Interfaces 64 | 65 | 66 | ### 3.1. `Psr\Container\ContainerInterface` 67 | 68 | ~~~php 69 | 105 | ### 3.2. `Psr\Container\ContainerExceptionInterface` 106 | 107 | ~~~php 108 | 120 | ### 3.3. `Psr\Container\NotFoundExceptionInterface` 121 | 122 | ~~~php 123 | 역자주: 위의 키워드는 아래의 번역문에 괄호안에 표시하였습니다 10 | 11 | ## 목표 12 | 13 | 이 PSR의 목표는 개발자가 HTTP 클라이언트 구현에서 분리 된 라이브러리를 만들 수있게하는 것입니다. 14 | 이렇게하면 종속성 수가 줄어들고 버전 충돌의 가능성이 줄어들기 때문에 라이브러리를 더 많이 재사용 할 수 있습니다. 15 | 16 | 두 번째 목표는 HTTP 클라이언트가 [Liskov 치환 원칙][Liskov]에 따라 대체 될 수 있다는 것입니다. 17 | 즉, 요청을 보낼 때 모든 클라이언트가 동일한 방식으로 작동해야합니다. 18 | 19 | ## 정의 20 | 21 | * **클라이언트** - 클라이언트는 PSR-7 호환 HTTP 요청 메시지를 보내고 PSR-7 호환 HTTP 응답 메시지를 호출 라이브러리에 반환하기 위해 이 사양을 구현하는 라이브러리입니다. 22 | * **호출 라이브러리** - 호출 라이브러리는 클라이언트를 사용하는 모든 코드입니다. 이 문서에 존재하는 인터페이스를 구현하지 않지만 이를 구현하는 객체 (클라이언트)를 사용합니다. 23 | 24 | ## 클라이언트 25 | 26 | 클라이언트는 `ClientInterface`를 구현 한 객체입니다. 27 | 28 | 클라이언트는 다음과 같은 것을 할 수 있습니다.(MAY) : 29 | 30 | * 제공된 HTTP 요청을 변경하여 보낼지 선택합니다. 예를 들어, 보내는 메시지 본문을 압축 할 수 있습니다. 31 | * 수신 된 HTTP 응답을 호출 라이브러리로 되돌리기 전에 변경할 것인지 선택합니다. 예를 들어 들어오는 메시지 본문의 압축을 풀 수 있습니다. 32 | 33 | 클라이언트가 HTTP 요청이나 HTTP 응답을 변경하기로 결정한 경우, 객체가 내부적으로 일관성을 유지하는지 확인해야합니다 (MUST). 34 | 예를 들어, 클라이언트가 메시지 본문을 압축 해제하기로 선택한 경우, 반드시 `Content-Encoding` 헤더를 제거하고`Content-Length` 헤더를 조정해야합니다. 35 | 36 | 결과적으로 [PSR-7 객체는 불변이므로](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-7-http-message-meta.md#why-value-objects), 호출 라이브러리는 `ClientInterface::sendRequest()`에 전달 된 객체가 실제로 전송 된 것과 동일한 PHP 객체가 될 것이라고 가정해서는 안됩니다. 37 | 예를 들어, 예외에 의해 반환 된 Request 객체는 `sendRequest()`에 전달 된 것과 다른 객체 일 수 있기 때문에 참조 (===)로 비교할 수 없습니다. 38 | 39 | 클라이언트는 반드시 다음을 지켜야합니다.(MUST) : 40 | 41 | * 호출 라이브러리에 반환되는 내용이 상태 코드 200 이상의 유효한 HTTP 응답이 되도록 여러개의 HTTP 1xx 응답 자체를 재구성하십시오 42 | 43 | ## 오류 처리 44 | 45 | 클라이언트는 올바른 형식의 HTTP 요청이나 HTTP 응답을 오류 조건으로 취급해서는 안됩니다 (MUST NOT). 46 | 47 | 예를 들어 400 및 500 범위의 응답 상태 코드는 예외를 발생시키지 않아야하며 정상적으로 호출 라이브러리에 반환되어야합니다 (MUST). 48 | 49 | 클라이언트가 HTTP 요청을 전혀 보낼 수 없거나 HTTP 응답을 PSR-7 응답 객체로 구문 분석을 할 수없는 경우에만 클라이언트는 `Psr\Http\Client\ClientExceptionInterface` 인스턴스를 던져야합니다. 50 | 51 | 요청 메시지가 올바른 형식의 HTTP 요청이 아니거나 일부 중요한 정보 (예 : 호스트 또는 메서드)가 없어서 요청을 보낼 수없는 경우, 클라이언트는 `Psr\Http\Client\RequestExceptionInterface`의 인스턴스를 던져야만 합니다.(MUST) 52 | 53 | 타임 아웃을 포함하여 어떤 종류의 네트워크 장애로 인해 요청을 보낼 수없는 경우, 클라이언트는 `Psr\Http\Client\NetworkExceptionInterface`의 인스턴스를 던져야만 합니다 (MUST). 54 | 55 | 클라이언트는 위에서 정의된 인터페이스를 적합하게 구현한다면 여기에 정의 된 것보다 더 구체적인 예외 (예 :`TimeOutException` 또는 `HostNotFoundException`)를 던질 수도 있습니다 (MAY). 56 | 57 | ## Interfaces 58 | 59 | ### ClientInterface 60 | 61 | ```php 62 | namespace Psr\Http\Client; 63 | 64 | use Psr\Http\Message\RequestInterface; 65 | use Psr\Http\Message\ResponseInterface; 66 | 67 | interface ClientInterface 68 | { 69 | /** 70 | * Sends a PSR-7 request and returns a PSR-7 response. 71 | * 72 | * @param RequestInterface $request 73 | * 74 | * @return ResponseInterface 75 | * 76 | * @throws \Psr\Http\Client\ClientExceptionInterface If an error happens while processing the request. 77 | */ 78 | public function sendRequest(RequestInterface $request): ResponseInterface; 79 | } 80 | ``` 81 | 82 | ### ClientExceptionInterface 83 | 84 | ```php 85 | namespace Psr\Http\Client; 86 | 87 | /** 88 | * Every HTTP client related exception MUST implement this interface. 89 | */ 90 | interface ClientExceptionInterface extends \Throwable 91 | { 92 | } 93 | ``` 94 | 95 | ### RequestExceptionInterface 96 | 97 | ```php 98 | namespace Psr\Http\Client; 99 | 100 | use Psr\Http\Message\RequestInterface; 101 | 102 | /** 103 | * Exception for when a request failed. 104 | * 105 | * Examples: 106 | * - Request is invalid (e.g. method is missing) 107 | * - Runtime request errors (e.g. the body stream is not seekable) 108 | */ 109 | interface RequestExceptionInterface extends ClientExceptionInterface 110 | { 111 | /** 112 | * Returns the request. 113 | * 114 | * The request object MAY be a different object from the one passed to ClientInterface::sendRequest() 115 | * 116 | * @return RequestInterface 117 | */ 118 | public function getRequest(): RequestInterface; 119 | } 120 | ``` 121 | 122 | ### NetworkExceptionInterface 123 | 124 | ```php 125 | namespace Psr\Http\Client; 126 | 127 | use Psr\Http\Message\RequestInterface; 128 | 129 | /** 130 | * Thrown when the request cannot be completed because of network issues. 131 | * 132 | * There is no response object as this exception is thrown when no response has been received. 133 | * 134 | * Example: the target host name can not be resolved or the connection failed. 135 | */ 136 | interface NetworkExceptionInterface extends ClientExceptionInterface 137 | { 138 | /** 139 | * Returns the request. 140 | * 141 | * The request object MAY be a different object from the one passed to ClientInterface::sendRequest() 142 | * 143 | * @return RequestInterface 144 | */ 145 | public function getRequest(): RequestInterface; 146 | } 147 | ``` 148 | 149 | [Liskov]: https://en.wikipedia.org/wiki/Liskov_substitution_principle 150 | -------------------------------------------------------------------------------- /accepted/PSR-17-http-factory.md: -------------------------------------------------------------------------------- 1 | HTTP Factories 2 | ============== 3 | 4 | 이 문서는 [PSR-7][psr7]에 호환하는 HTTP 객체를 만드는 팩토리의 공통 표준을 설명합니다. 5 | 6 | PSR-7은 HTTP 객체를 만드는 방법에 대한 권장 사항을 포함하지 않았기 때문에 PSR-7의 특정 구현과 관련되지 않은 구성 요소 내에 새로운 HTTP 객체를 생성해야 할 때 어려움을 겪습니다. 7 | 8 | 이 문서에 설명 된 인터페이스는 PSR-7 객체를 인스턴스화 할 수 있는 방법을 설명합니다. 9 | 10 | 이 문서에서 핵심이 되는 단어는 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", "OPTIONAL" 입니다. 11 | 이것은 [RFC 2119][rfc2119]에 설명 된대로 해석해야 합니다. 12 | 13 | > 역자주: 위의 키워드는 아래의 번역문에 괄호안에 표시하였습니다 14 | 15 | [psr7]: https://www.php-fig.org/psr/psr-7/ 16 | [rfc2119]: https://tools.ietf.org/html/rfc2119 17 | 18 | ## 1. 명세서 19 | 20 | HTTP 팩토리는 PSR-7에 정의 된대로 새 HTTP 객체를 만드는 방법입니다. 21 | HTTP 팩토리는 패키지가 제공하는 각 객체 유형에 대해 이러한 인터페이스를 구현해야합니다 (MUST). 22 | 23 | ## 2. Interfaces 24 | 25 | 다음 인터페이스들은 단일 클래스 내에서 또는 별도의 클래스들 내에서 함께 구현 될 수있습니다 (MAY). 26 | 27 | ### 2.1 RequestFactoryInterface 28 | 29 | 클라이언트 요청을 생성하는 기능 30 | 31 | ```php 32 | namespace Psr\Http\Message; 33 | 34 | use Psr\Http\Message\RequestInterface; 35 | use Psr\Http\Message\UriInterface; 36 | 37 | interface RequestFactoryInterface 38 | { 39 | /** 40 | * Create a new request. 41 | * 42 | * @param string $method The HTTP method associated with the request. 43 | * @param UriInterface|string $uri The URI associated with the request. 44 | */ 45 | public function createRequest(string $method, $uri): RequestInterface; 46 | } 47 | ``` 48 | 49 | ### 2.2 ResponseFactoryInterface 50 | 51 | 응답을 생성하는 하는 기능 52 | 53 | ```php 54 | namespace Psr\Http\Message; 55 | 56 | use Psr\Http\Message\ResponseInterface; 57 | 58 | interface ResponseFactoryInterface 59 | { 60 | /** 61 | * Create a new response. 62 | * 63 | * @param int $code The HTTP status code. Defaults to 200. 64 | * @param string $reasonPhrase The reason phrase to associate with the status code 65 | * in the generated response. If none is provided, implementations MAY use 66 | * the defaults as suggested in the HTTP specification. 67 | */ 68 | public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface; 69 | } 70 | ``` 71 | 72 | ### 2.3 ServerRequestFactoryInterface 73 | 74 | 서버 요청을 생성하는 기능 75 | 76 | ```php 77 | namespace Psr\Http\Message; 78 | 79 | use Psr\Http\Message\ServerRequestInterface; 80 | use Psr\Http\Message\UriInterface; 81 | 82 | interface ServerRequestFactoryInterface 83 | { 84 | /** 85 | * Create a new server request. 86 | * 87 | * Note that server parameters are taken precisely as given - no parsing/processing 88 | * of the given values is performed. In particular, no attempt is made to 89 | * determine the HTTP method or URI, which must be provided explicitly. 90 | * 91 | * @param string $method The HTTP method associated with the request. 92 | * @param UriInterface|string $uri The URI associated with the request. 93 | * @param array $serverParams An array of Server API (SAPI) parameters with 94 | * which to seed the generated request instance. 95 | */ 96 | public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface; 97 | } 98 | ``` 99 | 100 | ### 2.4 StreamFactoryInterface 101 | 102 | 요청 및 응답을 위한 스트림을 생성하는 기능 103 | 104 | ```php 105 | namespace Psr\Http\Message; 106 | 107 | use Psr\Http\Message\StreamInterface; 108 | 109 | interface StreamFactoryInterface 110 | { 111 | /** 112 | * Create a new stream from a string. 113 | * 114 | * The stream SHOULD be created with a temporary resource. 115 | * 116 | * @param string $content String content with which to populate the stream. 117 | */ 118 | public function createStream(string $content = ''): StreamInterface; 119 | 120 | /** 121 | * Create a stream from an existing file. 122 | * 123 | * The file MUST be opened using the given mode, which may be any mode 124 | * supported by the `fopen` function. 125 | * 126 | * The `$filename` MAY be any string supported by `fopen()`. 127 | * 128 | * @param string $filename The filename or stream URI to use as basis of stream. 129 | * @param string $mode The mode with which to open the underlying filename/stream. 130 | * 131 | * @throws \RuntimeException If the file cannot be opened. 132 | * @throws \InvalidArgumentException If the mode is invalid. 133 | */ 134 | public function createStreamFromFile(string $filename, string $mode = 'r'): StreamInterface; 135 | 136 | /** 137 | * Create a new stream from an existing resource. 138 | * 139 | * The stream MUST be readable and may be writable. 140 | * 141 | * @param resource $resource The PHP resource to use as the basis for the stream. 142 | */ 143 | public function createStreamFromResource($resource): StreamInterface; 144 | } 145 | ``` 146 | 147 | 이 인터페이스의 구현은 문자열에서 리소스를 만들 때 임시 스트림을 사용해야합니다 (SHOULD). 148 | 이렇게하는 권장 방법은 다음과 같습니다 (RECOMMENDED). 149 | 150 | ```php 151 | $resource = fopen('php://temp', 'r+'); 152 | ``` 153 | 154 | ### 2.5 UploadedFileFactoryInterface 155 | 156 | 업로드 된 파일의 스트림을 만들 수 있는 기능 157 | 158 | ```php 159 | namespace Psr\Http\Message; 160 | 161 | use Psr\Http\Message\StreamInterface; 162 | use Psr\Http\Message\UploadedFileInterface; 163 | 164 | interface UploadedFileFactoryInterface 165 | { 166 | /** 167 | * Create a new uploaded file. 168 | * 169 | * If a size is not provided it will be determined by checking the size of 170 | * the stream. 171 | * 172 | * @link http://php.net/manual/features.file-upload.post-method.php 173 | * @link http://php.net/manual/features.file-upload.errors.php 174 | * 175 | * @param StreamInterface $stream The underlying stream representing the 176 | * uploaded file content. 177 | * @param int $size The size of the file in bytes. 178 | * @param int $error The PHP file upload error. 179 | * @param string $clientFilename The filename as provided by the client, if any. 180 | * @param string $clientMediaType The media type as provided by the client, if any. 181 | * 182 | * @throws \InvalidArgumentException If the file resource is not readable. 183 | */ 184 | public function createUploadedFile( 185 | StreamInterface $stream, 186 | int $size = null, 187 | int $error = \UPLOAD_ERR_OK, 188 | string $clientFilename = null, 189 | string $clientMediaType = null 190 | ): UploadedFileInterface; 191 | } 192 | ``` 193 | 194 | ### 2.6 UriFactoryInterface 195 | 196 | 클라이언트 및 서버 요청에 대한 URI를 생성하는 기능 197 | 198 | ```php 199 | namespace Psr\Http\Message; 200 | 201 | use Psr\Http\Message\UriInterface; 202 | 203 | interface UriFactoryInterface 204 | { 205 | /** 206 | * Create a new URI. 207 | * 208 | * @param string $uri The URI to parse. 209 | * 210 | * @throws \InvalidArgumentException If the given URI cannot be parsed. 211 | */ 212 | public function createUri(string $uri = '') : UriInterface; 213 | } 214 | ``` 215 | -------------------------------------------------------------------------------- /accepted/PSR-14-event-dispatcher.md: -------------------------------------------------------------------------------- 1 | Event Dispatcher 2 | ================ 3 | 4 | Event Dispatching은 개발자가 어플리케이션에 로직을 쉽고 일관되게 주입 할 수있게 해주는 일반적이며 잘 테스트 된 메커니즘입니다. 5 | 6 | 이 PSR의 목표는 라이브러리와 컴포넌트가가 다양한 어플리케이션과 프레임워크간에 보다 자유롭게 재사용 될 수 있도록 Event 기반 확장 및 협업을 위한 공통 메커니즘을 확립하는 것입니다. 7 | 8 | 이 문서에서 핵심이 되는 단어는 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", "OPTIONAL" 입니다. 9 | 이것은 [RFC 2119]에 설명 된대로 해석해야 합니다. 10 | 11 | > 역자주: 위의 키워드는 아래의 번역문에 괄호안에 표시하였습니다 12 | 13 | [RFC 2119]: http://tools.ietf.org/html/rfc2119 14 | 15 | ## 목표 16 | 17 | Event 발송 및 처리를 위한 공통 인터페이스를 사용하면 개발자가 공통된 방식으로 여러 프레임워크 및 기타 라이브러리와 상호 작용할 수 있는 라이브러리를 만들 수 있습니다. 18 | 19 | 몇 가지 예 : 20 | 21 | * 사용자가 권한이 없을 때 데이터에 저장/액세스를 방지하는 보안 프레임워크. 22 | * 일반적인 전체 페이지 캐싱 시스템. 23 | * 다른 라이브러리를 확장하는 라이브러리. 프레임워크가 둘 다 통합되어 있는지 여부와 관계 없음. 24 | * 어플리케이션 내에서 수행 된 모든 작업을 추적하는 로깅 패키지 25 | 26 | ## 정의 27 | 28 | * **Event** - Event는 *Emitter*가 생성 한 메시지입니다. 임의의 PHP 객체 일 수 있습니다. 29 | * **Listener** - Listener는 Event를 전달할 실행가능한 어떠한 PHP 입니다. 동일한 Event를 0 개 이상의 Listener에 전달할 수 있습니다. Listener는 원할 경우 다른 비동기 동작을 큐에 넣을 수 있습니다 (MAY). 30 | * **Emitter** - Emitter는 Event를 보내고자 하는 임의의 코드입니다. 이것은 "호출 코드"라고도합니다. 이것은 특정 데이터 구조로 표현되지 않고 유스케이스를 가르킵니다. 31 | * **Dispatcher** - Dispatcher는 Emitter에 의해 Event 객체를 전달하는 서비스 객체입니다. Dispatcher는 Event가 관련된 모든 Listener에게 전달되도록 보장하지만, 실행할 Listener를 결정하는 것은 Listener Provider에게 위임해야합니다.(MUST) 32 | * **Listener Provider** - Listener Provider는 주어진 Event와 관련이있는 Listener를 결정할 책임이 있지만 Listener 자신을 호출해서는 안됩니다(MUST NOT). Listener Provider는 0 개 이상의 관련 Listener를 지정할 수 있습니다. 33 | 34 | ## 이벤트 35 | 36 | Event는 Emitter와 해당하는 Listener 간의 통신 단위 역할을 하는 객체입니다. 37 | 38 | Emitter에 정보를 다시 돌려주는 Listener를 호출하는 경우 Event 객체는 변경 될 수 있습니다(MAY). 39 | 40 | 그러나 그러한 양방향 통신이 필요하지 않은 경우 Event는 변경 불가능한 것으로 정의하는 것이 좋습니다(RECOMMENDED). 즉, 뮤 테이터 (mutator) 메소드가 존재하지 않도록 정의합니다. 41 | 42 | 구현체는 동일한 객체가 모든 Listener에게 반드시 전달된다고 가정해야합니다 (MUST). 43 | 44 | Event 객체가 무손실 직렬화 및 비 직렬화를 지원한다는 것이 권장되지만(RECOMMENDED) 필수적이지는 않습니다(NOT REQUIRED). `$event == unserialize(serialize($event))`는 참이어야합니다 (SHOULD). 객체는 PHP의 `Serializable` 인터페이스, `__sleep()` 또는 `__wakeup()` 매직 메소드 또는 적절한 경우 언어(PHP) 내 유사한 기능을 활용 할 수 있습니다 (MAY). 45 | 46 | ## 멈출수 있는 Event-Stoppable Event 47 | 48 | **Stoppable Event**는 더 많은 Listener가 호출되는 것을 방지하는 방법을 추가한, Event의 특별한 케이스입니다. 이것은 `StoppableEventInterface`를 구현하여 표현합니다. 49 | 50 | `StoppableEventInterface`를 구현 한 Event는 해당하는 Event가 완료되면 `isPropagationStopped()`로부터 `true`를 리턴해야합니다 (MUST). 그것이 언제인지를 결정하는 것은 클래스를 구현하는 자의 몫입니다. 예를 들어, PSR-7의 `RequestInterface` 객체가 대응하는 `ResponseInterface` 객체와 일치하도록 요청하는 Event는 Listener가 호출 할 `setResponse(ResponseInterface $res)`메소드를 가질 수 있습니다. 이것은 `isPropagationStopped()` 가 `true`를 반환합니다. 51 | 52 | ## 리스너-Listener 53 | 54 | Listener는 실행가능한 어떤 PHP 일 것입니다. Listener는 하나의 매개 변수만을 가져야하며(MUST), 이것은 리스너가 반응해야하는 Event입니다. 55 | 56 | Listener는 해당 유즈 케이스와 관련하여 파라메터에 구체적으로 타입 힌트를 입력해야합니다 (SHOULD). 57 | 58 | 즉, Listener는 인터페이스에 대해 타입 힌트를 입력하여 해당 인터페이스를 구현하는 모든 Event 유형 또는 해당 인터페이스의 특정 구현과 호환 가능하다는 것을 표현합니다. 59 | 60 | Listener는 `void`리턴을 가져야하고 (SHOULD), 명시 적으로 리턴하는 타입 힌트를 입력해야합니다 (SHOULD). Dispatcher는 Listener의 리턴 값을 무시해야합니다 (MUST). 61 | 62 | Listener는 다른 코드에 행동을 위임 할 수 있습니다(MAY). 이것은 실제 비즈니스 로직을 실행하는 객체 둘러싼 얇은 래퍼(wrapper) 인 Listener가 포함됩니다. 63 | 64 | Listener는 cron, 큐 서버 또는 유사한 기술을 사용하는 보조 프로세스를 통해 나중에 처리하기 위해 Event로부터 정보를 큐에 넣을 수 있습니다(MAY). 65 | 그러기 위해 Event 객체 자체를 직렬화 할 수있습니다. 그러나 모든 Event 객체가 안전하게 직렬화 될 수 있는 것은 아니므로주의해야합니다. 66 | 보조 프로세스는 Event 객체에 대한 모든 변경 사항이 다른 Listener에 전파되지 않는다고 가정해야합니다 (MUST). 67 | 68 | ## 발송자-Dispatcher 69 | 70 | Dispatcher는 `EventDispatcherInterface`를 구현 한 서비스 객체입니다. Listener Provider로부터 전달 된 Event에 대한 Listener를 찾아서 해당 Event와 함께 각 Listener를 호출합니다. 71 | 72 | Dispatcher는 : 73 | 74 | * ListenerProvider에서 반환 된 순서대로 Listener를 동기적으로 호출해야합니다(MUST). 75 | * Listener를 호출 한 후 전달 된 것과 동일한 Event 객체를 반환해야합니다(MUST). 76 | * 모든 Listener가 실행완료될 때까지 Emitter로 돌아 가지 않아야합니다(MUST NOT). 77 | 78 | Dispatcher는 Stoppable Event가 전달되면 79 | 80 | * 각 Listener가 호출되기 전에 Event에 대해 반드시 `isPropagationStopped()`를 호출해야합니다 (MUST). 그 메소드가 `true`를 리턴하면, 반드시 Event를 Emitter에게 즉시 반환해야하고 더 이상의 Listener를 호출해서는 안됩니다. 이것은 `isPropagationStopped()`에서 항상 `true`를 반환하는 Event가 Dispatcher에 전달되면 0개의 Listener가 호출됨을 의미합니다. 81 | 82 | Dispatcher는 Listener 제공자로부터 리턴 된 Listener가 type-safe하다고 가정해야합니다 (SHOULD). 즉, Dispatcher는 `$listener($event)`호출이 `TypeError`를 생성하지 않아야한다고 가정해야합니다 (SHOULD). 83 | 84 | [Promise object]: https://promisesaplus.com/ 85 | 86 | ### Error handling 87 | 88 | Listener가 던진 예외 또는 오류는 이후의 모든 Listener의 실행을 차단해야합니다(MUST). Listener에 의해 던져진 오류 또는 예외는 Emitter로 전달 되야합니다(MUST). 89 | 90 | Dispatcher는 던져진 객체를 잡아서 기록 할 수 있고(MAY), 추가적인 조치가 행동을 하도록 허용하지만 반드시 원래의 Throwable을 다시 던져야합니다 (MUST). 91 | 92 | ## Listener Provider 93 | 94 | Listener Provider는, Listener가 어느 Event에 관련이 있는지, 어떤 Listener가 호출되어야 하는지를 결정하는 서비스 객체입니다. Listener가 무엇을 의미하는지 그리고 Listener가 선택하는 방법에 따라 Listener를 돌려주는 순서를 결정할 수 있습니다. 다음이 포함될 수 있습니다(MAY): 95 | 96 | * 구현자가 고정 된 순서로 Event에 Listener를 할당 할 수 있도록 일부 등록 메커니즘을 허용합니다. 97 | * Event 유형 과 구현 된 인터페이스를 기반으로 리플렉션을 통해 해당 Listener 목록을 만듭니다. 98 | * 런타임에 참조 될 수 있는 미리 컴파일 된 Listener의 목록 생성합니다. 99 | * 현재 사용자에게 특정 권한이 있는 경우에만 특정 Listener가 호출되도록 액세스 제어 형식을 구현합니다. 100 | * 엔티티와 같이 Event에 의해 참조되는 객체에서 일부 정보를 추출하고 해당 객체에 대해 미리 정의 된 라이프 사이클 메소드를 호출합니다. 101 | * 임의의 로직를 사용하여 하나 이상의 다른 Listener Provider에게 책임을 위임합니다. 102 | 103 | 위의 메커니즘이나 다른 메커니즘을 원하는대로 사용할 수 있습니다(MAY). 104 | 105 | Listener Provider는 Event의 클래스 이름을 사용하여 Event를 다른 Event와 구별해야합니다 (SHOULD). 또한 Event에 대한 다른 정보를 적절하게 고려할 수 있습니다(MAY). 106 | 107 | Listener Provider는 Listener 적용 가능 여부를 결정할 때 부모 유형을 Event의 자체 유형과 동일하게 처리해야합니다(MUST). 108 | 109 | 다음과 같은 경우 : 110 | 111 | ```php 112 | class A {} 113 | 114 | class B extends A {} 115 | 116 | $b = new B(); 117 | 118 | function listener(A $event): void {}; 119 | ``` 120 | 121 | Listener Provider는 리스너의 다른 조건에 의해 타입이 호환되지 않는 한 호환성이 유효하므로, `$b`의 Listener로서 `listener()`를 처리 해야합니다 (MUST). 122 | 123 | ## 오브젝트 구성-Object composition 124 | 125 | Dispatcher는 관련된 Listener를 판별하기 위해 Listener Provider를 구성해야합니다 (SHOULD). Listener Provider가 Dispatcher와는 별개의 오브젝트로 구현되지만 반드시 요구되지는 않는 것이 좋습니다 (RECOMMENDED). 126 | 127 | ## Interfaces 128 | 129 | ```php 130 | namespace Psr\EventDispatcher; 131 | 132 | /** 133 | * Defines a dispatcher for events. 134 | */ 135 | interface EventDispatcherInterface 136 | { 137 | /** 138 | * Provide all relevant listeners with an event to process. 139 | * 140 | * @param object $event 141 | * The object to process. 142 | * 143 | * @return object 144 | * The Event that was passed, now modified by listeners. 145 | */ 146 | public function dispatch(object $event); 147 | } 148 | ``` 149 | 150 | ```php 151 | namespace Psr\EventDispatcher; 152 | 153 | /** 154 | * Mapper from an event to the listeners that are applicable to that event. 155 | */ 156 | interface ListenerProviderInterface 157 | { 158 | /** 159 | * @param object $event 160 | * An event for which to return the relevant listeners. 161 | * @return iterable[callable] 162 | * An iterable (array, iterator, or generator) of callables. Each 163 | * callable MUST be type-compatible with $event. 164 | */ 165 | public function getListenersForEvent(object $event) : iterable; 166 | } 167 | ``` 168 | 169 | ```php 170 | namespace Psr\EventDispatcher; 171 | 172 | /** 173 | * An Event whose processing may be interrupted when the event has been handled. 174 | * 175 | * A Dispatcher implementation MUST check to determine if an Event 176 | * is marked as stopped after each listener is called. If it is then it should 177 | * return immediately without calling any further Listeners. 178 | */ 179 | interface StoppableEventInterface 180 | { 181 | /** 182 | * Is propagation stopped? 183 | * 184 | * This will typically only be used by the Dispatcher to determine if the 185 | * previous listener halted propagation. 186 | * 187 | * @return bool 188 | * True if the Event is complete and no further listeners should be called. 189 | * False to continue calling listeners. 190 | */ 191 | public function isPropagationStopped() : bool; 192 | } 193 | ``` 194 | -------------------------------------------------------------------------------- /accepted/PSR-3-logger-interface.md: -------------------------------------------------------------------------------- 1 | 로거 인터페이스 2 | ================ 3 | 4 | 이 문서는 로깅 라이브러리에 대한 공통 인터페이스를 설명합니다. 5 | 6 | 가장 중요한 목표는 라이브러리가 `Psr\Log\LoggerInterface` 객체를 받아서 간단하고 보편적인 방법으로 로그를 쓸 수있게하는 것입니다. 7 | 커스텀 할 필요가 있는 프레임워크와 CMS는 자체적인 목적을 위해 인터페이스를 확장 할 수 있지만 이 문서와 호환 가능해야합니다 (SHOULD). 8 | 이렇게하면 프로그램에서 사용하는 타사 라이브러리가 프로그램의 중앙 집중식 로그에 쓸 수 있습니다. 9 | 10 | > 역자주: 타 벤더의 로그를 중앙집중형으로 모아서 남길 수 있다는 의미 11 | 12 | 이 문서에서 핵심이 되는 단어는 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", "OPTIONAL" 입니다. 13 | 이것은 [RFC 2119]에 설명 된대로 해석해야 합니다. 14 | 15 | > 역자주: 위의 키워드는 아래의 번역문에 괄호안에 표시하였습니다 16 | 17 | 이 문서에서 `구현자(implementor)` 라는 단어는 로그 관련 라이브러리 또는 프레임워크에서 `LoggerInterface` 를 구현하는 누군가로 해석되어야합니다. 18 | 로거 사용자는 `사용자(user)`라고합니다. 19 | 20 | [RFC 2119]: http://tools.ietf.org/html/rfc2119 21 | 22 | ## 1. 명세서 23 | 24 | ### 1.1 기본 25 | 26 | - `LoggerInterface`는 로그를 8 개의 [RFC 5424] 레벨 (debug, info, notice, warning, error, critical, alert, emergency)에 맞게 쓸 수 있는 8 가지 method를 제공해야 합니다. 27 | 28 | - 9 번째 method 인`log`는 첫 번째 인자로 로그 수준(level)을 입력받습니다. 29 | 로그 수준 상수 중 하나를 사용하여 이 메서드를 호출하면 수준별 메서드를 호출 할 때와 동일한 결과를 가져야합니다. 30 | 알지 못하는 수준(level)이거나 이 스펙에 정의되지 않은 수준(level)로 이 메소드를 호출하면 반드시 `Psr\Log\InvalidArgumentException` 을 던져야합니다 (MUST). 31 | 사용자는 현재 구현이 이를 지원하는지 모른 채 사용자 지정 수준(level)을 사용해서는 안됩니다(SHOULD NOT). 32 | 33 | 34 | [RFC 5424]: http://tools.ietf.org/html/rfc5424 35 | 36 | ### 1.2 메세지 37 | 38 | - 모든 method는 문자열을 메시지로 받거나 `__toString ()` method를 가진 객체를 받아들입니다. 39 | 구현자는 전달 된 객체를 특별한 형태로 처리 할 수도있다 (MAY). 40 | 그렇지 않은 경우, 구현자는 그것을 문자열로 변환해야한다 (MUST). 41 | 42 | 43 | - 메시지는 구현자가 문맥 배열의 값으로 대체 할 수 있는(MAY) Placeholder를 포함 할 수있습니다(MAY). 44 | Placeholder 이름은 컨텍스트 배열의 키와 일치해야합니다. 45 | Placeholder 이름은 하나의 여는 중괄호 `{` 와 하나의 닫는 중괄호 `}`로 구분해야합니다. 46 | 구분 기호와 Placeholder 이름 사이에 공백이 없어야합니다 (MUST NOT). 47 | Placeholder 이름은 `A-Z`, `a-z`, `0-9`, 밑줄 `_` 및 마침표 `.` 만으로 구성되어야합니다 (SHOULD). 48 | 다른 문자의 사용은 Placeholder 사양(specification)의 향후 수정을 위해 예약됩니다. 49 | 구현자는 Placeholder를 사용하여 다양한 이스케이프 전략을 구현하고 표시를 위해 로그를 변환 할 수 있습니다 (MAY). 50 | 사용자는 데이터가 표시 될 컨텍스트를 알 수 없으므로 Placeholder 값을 미리 이스케이프해서는 안됩니다. 51 | 52 | 다음은 참조용으로만 제공되는 Placeholder 보간법의 구현 예입니다. 53 | 54 | ~~~php 55 | $val) { 65 | // check that the value can be casted to string 66 | if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) { 67 | $replace['{' . $key . '}'] = $val; 68 | } 69 | } 70 | 71 | // interpolate replacement values into the message and return 72 | return strtr($message, $replace); 73 | } 74 | 75 | // a message with brace-delimited placeholder names 76 | $message = "User {username} created"; 77 | 78 | // a context array of placeholder names => replacement values 79 | $context = array('username' => 'bolivar'); 80 | 81 | // echoes "User bolivar created" 82 | echo interpolate($message, $context); 83 | ~~~ 84 | 85 | ### 1.3 문맥(Context) 86 | 87 | - 모든 메소드는 배열을 컨텍스트 데이터로 허용합니다. 88 | 이것은 문자열에 잘 맞지 않는 불필요한 정보를 보유하기위한 것입니다. 89 | 배열은 무엇이든 포함 할 수 있습니다. 90 | 구현자는 가능한 한 많은 관용으로 컨텍스트 데이터를 처리해야합니다 (MUST). 91 | 문맥에서 주어진 값은 예외를 던지거나 PHP error, warning 또는 notice를 발생시켜서는 안됩니다(MUST NOT). 92 | 93 | - `Exception` 객체가 컨텍스트 데이터에 전달되면, 그것은 `'exception'` 키에 있어야합니다 (MUST). 94 | 로깅 예외(exceptios)는 일반적인 패턴이며, 이로 인해 구현자가 로그 백엔드가 지원할 때 예외에서 스택 추적을 추출 할 수 있습니다. 95 | 구현자들은 무엇이든 포함 할 수 있기 때문에`'exception'` 키가 실제로 그것을 사용하기 전에 실제로 `Exception` 인지를 반드시 확인해야합니다 (MUST). 96 | 97 | 98 | ### 1.4 헬퍼 클래스와 인터페이스 99 | 100 | - `Psr\Log\AbstractLogger` Class를 확장하고 일반적인 `log` 메소드를 구현함으로써 `LoggerInterface`를 매우 쉽게 구현할 수있게합니다. 101 | 다른 8 가지 method는 메시지와 컨텍스트를 전달하는 것입니다. 102 | 103 | - 마찬가지로 `Psr\Log\LoggerTrait` 만 사용하면 일반적으로 `log` 메소드를 구현해야합니다. 104 | 이 trait은 인터페이스를 구현하지 않으므로 이 경우에는 여전히 `LoggerInterface`를 구현해야합니다. 105 | 106 | - `Psr\Log\NullLogger`는 인터페이스와 함께 제공됩니다. 107 | 로거가 제공되지 않으면 폴백 (back-back) "블랙홀"구현을 제공하기 위해 인터페이스 사용자가 이를 사용할 수 있습니다 (MAY). 108 | 그러나 컨텍스트 데이터 작성 비용면에서 조건부 로깅이 더 나은 접근 방법 일 수 있습니다. 109 | 110 | > 역자주: 아무것도 저장하지 않는 로거를 사용하는 것 보다 경우에 따라 로거를 호출 하도록 하는 편이 더 효율적 111 | 112 | 113 | - `Psr\Log\LoggerAwareInterface` 는 `setLogger(LoggerInterface $logger)` method만을 포함하고 있으며, 임의의 인스턴스를 로거로 자동으로 연결하기 위해 프레임워크에서 사용할 수 있습니다. 114 | 115 | - `Psr\Log\LoggerAwareTrait` trait은 모든 클래스에서 쉽게 동일한 인터페이스를 구현하는 데 사용할 수 있습니다. 116 | `$this->logger`에 접근 할 수 있습니다. 117 | 118 | - `Psr\Log\LogLevel` 클래스는 8 개의 로그 레벨에 대한 상수를 가지고 있습니다. 119 | 120 | ## 2. Package 121 | 122 | 설명한 인터페이스와 클래스는 물론 관련 예외 클래스 및 구현을 확인하는 테스트가 [psr/log](https://packagist.org/packages/psr/log) 패키지의 일부로 제공됩니다. 123 | 124 | ## 3. `Psr\Log\LoggerInterface` 125 | 126 | ~~~php 127 | 역자주: 위의 키워드는 아래의 번역문에 괄호안에 표시하였습니다 10 | 11 | 최종 구현체는 제시된 것보다 더 많은 기능을 가진 객체로 만들 수 있지만(MAY) 반드시 지정한 인터페이스/기능을 먼저 구현해야합니다(MUST). 12 | 13 | [RFC 2119]: http://tools.ietf.org/html/rfc2119 14 | 15 | # 1. 명세서 16 | 17 | ## 1.1 소개 18 | 19 | 캐싱은 모든 프로젝트의 성능을 향상시키는 일반적인 방법이며, 캐싱 라이브러리를 많은 프레임 워크 및 라이브러리의 가장 일반적인 기능 중 하나로 만듭니다. 20 | 여기서 말하는 상호 운용성은 라이브러리가 자체 캐싱 구현을 중단하고 프레임 워크 또는 다른 캐시 전용 라이브러리에 의해 제공되는 구현에 쉽게 의지 할 수 있음을 의미합니다. 21 | 22 | PSR-6은 이미 이 문제를 해결했지만 단순한 유스 케이스에 필요한 이상으로 공식적이고 장황한 방법으로 해결합니다. 23 | 이 간단한 접근 방식은 일반적인 경우에 대해 표준화와 간소화 된 인터페이스를 구축하는 것을 목표로합니다. 24 | 이것은 PSR-6과 독립적이지만 PSR-6과의 호환성을 가진채 가능한 한 간단하게 만들도록 설계되었습니다. 25 | 26 | ## 1.2 정의 27 | 28 | 호출 라이브러리, 구현 라이브러리, TTL, 만료 및 키에 대한 정의는 PSR-6에서 복사 한 것과 동일한 것으로 가정합니다 29 | 30 | * **호출 라이브러리(Calling Library)** - 실제로 캐시 서비스가 필요한 라이브러리 또는 코드. 31 | 이 라이브러리는이 표준의 인터페이스를 구현하는 캐싱 서비스를 활용할 것이며, 그렇지 않으면 이러한 캐싱 서비스의 구현에 대한 알지 못합니다. 32 | > 역자주: 인터페이스를 구현한 캐싱 서비스를 사용만하고 구현을 하지 않는다. 33 | 34 | * **구현 라이브러리(Implementing Library)** - 이 라이브러리는 모든 호출 라이브러리에 캐싱 서비스를 제공하기 위해이 표준을 구현합니다. 35 | 구현 라이브러리는 `Cache\CacheItemPoolInterface` 및 `Cache\CacheItemInterface` 인터페이스를 구현하는 클래스를 제공해야합니다(MUST). 36 | 라이브러리 구현은 전체 초 단위로 아래에 설명 된 최소 TTL 기능을 지원해야만 합니다 (MUST). 37 | 38 | * **TTL** - TTL (Time To Live)은 해당 항목이 저장하고 보관하는 것으로 간주되는 시간입니다. 39 | TTL은 일반적으로 초 단위의 시간을 나타내는 정수 또는 DateInterval 개체로 정의됩니다. 40 | 41 | * **만료(Expiration)** - 항목이 만료로 설정되는 실제 시간입니다. 42 | 이것은 일반적으로 개체가 저장된 시간에 TTL을 추가하여 계산됩니다. 43 | 이것은 일반적으로 개체가 저장된 시간에 TTL을 추가하여 계산되지만 DateTime 개체로 명시 적으로 설정할 수도 있습니다. 44 | 1:30:00에 저장된 300 초 TTL을 가진 항목의 만료 시간은 1:35:00입니다. 45 | 구현 라이브러리는 요청한 만료 시간 전에 항목을 만료시킬 수도 있지만(MAY) 만료 시간에 도달하면 만료 된 것으로 간주해야합니다(MUST). 46 | 호출 라이브러리가 항목을 저장요청을 하지만 만료 시간을 지정하지 않거나 만료 시간 또는 TTL을 null로 지정되어 있다면 구현 라이브러리는 설정한 기본 기간을 사용할 수 있습니다 (MAY). 47 | 기본 기간이 설정되지 않은 경우 구현 라이브러리는 해당 항목을 영원히 캐시하는 요청으로 해석하거나 기본 구현이 지원하는 동안 저장하는 것으로 해석해야합니다(MUST). 48 | 49 | * **Key** - 캐시 된 항목을 고유하게 식별하는 적어도 하나의 문자로 구성된 문자열입니다. 50 | 구현 라이브러리는`A-Z`,`a-z`,`0-9`,`_` 및`.` 문자로 구성된 키를 UTF-8 인코딩과 길이가 64 문자 이하의 순서로 지원해야합니다 (MUST). 51 | 구현 라이브러리은 추가 문자와 인코딩 또는 더 긴 길이를 지원할 수 있지만(MAY) 최소한 그 최소값을 지원해야합니다(MUST). 52 | 라이브러리는 적절하게 키 문자열을 이스케이프 처리해야하지만 원래의 수정되지 않은 키 문자열을 반환 할 수 있어야합니다(MUST). 53 | 다음 문자는 미래의 확장을 위해 예약되어 있으며, 구현 라이브러리에서 지원해서는 안됩니다(MUST NOT) :`{} () / \ @ :` 54 | 55 | * **Cache** - `Psr\SimpleCache\CacheInterface` 인터페이스를 구현하는 객체. 56 | 57 | * **Cache Misses** - 캐시 미스 (cache miss)는 널(null)을 리턴 할 것이고 따라서 `null`이 하나만 저장된 경우 구별이 불가능합니다. 58 | 이것은 PSR-6와 가장 큰 차이입니다. 59 | 60 | ## 1.3 Cache 61 | 62 | 구현체는 특정 캐시 항목에 대해 TTL을 지정되지 않은 경우 사용자가 기본 TTL을 지정하는 메커니즘을 제공 할 수 있습니다 (MAY). 63 | 사용자 지정 기본값도 제공되지 않으면 구현체은 기본 구현체에서 허용되는 최대 유효 값으로 기본 설정되어야합니다(MUST). 64 | 기본 구현체가 TTL을 지원하지 않으면 사용자 지정 TTL을 자동으로 무시해야합니다 (MUST). 65 | 66 | ## 1.4 Data 67 | 68 | 라이브러리를 구현할 때 다음을 포함하여 모든 직렬화 가능한 PHP 데이터 유형을 지원해야합니다 (MUST). 69 | 70 | * **Strings** - PHP 호환 인코딩의 임의의 크기를 갖는 문자열. 71 | * **Integers** - PHP가 지원하는 모든 크기의 정수 (최대 64 비트). 72 | * **Floats** - 부호가 있는(signed) 모든 부동소수점 값. 73 | * **Booleans** - True 와 False. 74 | * **Null** - null값 (캐시미스와 구별이 되지 않습니다). 75 | * **Arrays** - 인덱스된 임의의 깊이를 가진 연관 및 다차원 배열 76 | * **Objects** - `$o == unserialize(serialize($o))` 와 같이 무손실 직렬화 및 직렬화 해제를 지원하는 객체. 77 | 객체는 PHP의 Serializable 인터페이스, 적절한 경우 `__sleep()` 또는 `__wakeup()` 매직 메서드 또는 유사한 언어 기능을 활용할 수 있습니다(MAY). 78 | 79 | 구현 라이브러리에 전달 된 모든 데이터는 전달 된 그대로 정확하게 반환되어야합니다(MUST). 80 | 여기에는 가변 유형이 포함됩니다. 81 | 즉, 만약 (int) 5가 저장된 값이었던 경우 (string) 5를 반환하는 것은 오류입니다. 82 | 구현 라이브러리는 PHP의 serialize()/unserialize() 함수를 내부적으로 사용할 수 있지만 꼭 그렇게 할 필요는 없습니다(MAY). 83 | 이들과의 호환성은 수용 가능한 객체 값의 기준선으로 사용됩니다. 84 | 85 | 어떠한 이유로든 저장된 정확한 값을 반환 할 수없는 경우 구현 라이브러리는 데이터가 손상되지 않게 캐시 미스로 응답해야합니다(MUST). 86 | 87 | # 2. Interfaces 88 | 89 | ## 2.1 CacheInterface 90 | 91 | 캐시 인터페이스는 각 캐시 항목의 기본 읽기, 쓰기 및 삭제를 수반하는 캐시 항목 모음에 대한 가장 기본적인 작업을 정의합니다. 92 | 93 | 또한 한 번에 여러 캐시 항목을 쓰거나, 읽거나 삭제하는 것과 같은 캐시 항목의 여러 세트를 처리하기위한 방법을 제공합니다. 94 | 이는 수행 할 캐시 읽기 / 쓰기가 많을 때 유용하며 대기 시간을 대폭 줄이는 캐시 서버에 대한 단일 호출로 작업을 수행 할 수 있습니다. 95 | 96 | CacheInterface의 인스턴스는 단일 키 네임 스페이스가있는 캐시 항목의 단일 모음에 해당하며 PSR-6의 "풀"과 동일합니다. 97 | 서로 다른 CacheInterface 인스턴스는 동일한 데이터 저장소에 의해 백업 될 수 있지만 (MAY) 반드시 논리적으로 독립적이어야합니다 (MUST). 98 | 99 | ~~~php 100 | value pairs. Cache keys that do not exist or are stale will have $default as value. 161 | * 162 | * @throws \Psr\SimpleCache\InvalidArgumentException 163 | * MUST be thrown if $keys is neither an array nor a Traversable, 164 | * or if any of the $keys are not a legal value. 165 | */ 166 | public function getMultiple($keys, $default = null); 167 | 168 | /** 169 | * Persists a set of key => value pairs in the cache, with an optional TTL. 170 | * 171 | * @param iterable $values A list of key => value pairs for a multiple-set operation. 172 | * @param null|int|\DateInterval $ttl Optional. The TTL value of this item. If no value is sent and 173 | * the driver supports TTL then the library may set a default value 174 | * for it or let the driver take care of that. 175 | * 176 | * @return bool True on success and false on failure. 177 | * 178 | * @throws \Psr\SimpleCache\InvalidArgumentException 179 | * MUST be thrown if $values is neither an array nor a Traversable, 180 | * or if any of the $values are not a legal value. 181 | */ 182 | public function setMultiple($values, $ttl = null); 183 | 184 | /** 185 | * Deletes multiple cache items in a single operation. 186 | * 187 | * @param iterable $keys A list of string-based keys to be deleted. 188 | * 189 | * @return bool True if the items were successfully removed. False if there was an error. 190 | * 191 | * @throws \Psr\SimpleCache\InvalidArgumentException 192 | * MUST be thrown if $keys is neither an array nor a Traversable, 193 | * or if any of the $keys are not a legal value. 194 | */ 195 | public function deleteMultiple($keys); 196 | 197 | /** 198 | * Determines whether an item is present in the cache. 199 | * 200 | * NOTE: It is recommended that has() is only to be used for cache warming type purposes 201 | * and not to be used within your live applications operations for get/set, as this method 202 | * is subject to a race condition where your has() will return true and immediately after, 203 | * another script can remove it, making the state of your app out of date. 204 | * 205 | * @param string $key The cache item key. 206 | * 207 | * @return bool 208 | * 209 | * @throws \Psr\SimpleCache\InvalidArgumentException 210 | * MUST be thrown if the $key string is not a legal value. 211 | */ 212 | public function has($key); 213 | } 214 | ~~~ 215 | 216 | ## 2.2 CacheException 217 | 218 | ~~~php 219 | 220 | 역자주: 완전히 표준화되지 못했다는 의미 7 | 8 | 이 스펙은 PHP 개발자에게 사용되는 직렬화 형식과는 별도로 하이퍼 미디어 링크를 표현하는 간단하고 일반적인 방법을 제공하는 것을 목표로 합니다. 9 | 그래서 시스템은 하이퍼 미디어 링크를 사용하여 하나 이상의 연결된 포맷으로 응답을 직렬화 할 수 있습니다. 10 | 11 | 이 문서에서 핵심이 되는 단어는 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", "OPTIONAL" 입니다. 12 | 이것은 [RFC 2119]에 설명 된대로 해석해야 합니다. 13 | 14 | > 역자주: 위의 키워드는 아래의 번역문에 괄호안에 표시하였습니다 15 | 16 | ### References 17 | 18 | - [RFC 2119](http://tools.ietf.org/html/rfc2119) 19 | - [RFC 4287](https://tools.ietf.org/html/rfc4287) 20 | - [RFC 5988](https://tools.ietf.org/html/rfc5988) 21 | - [RFC 6570](https://tools.ietf.org/html/rfc6570) 22 | - [IANA Link Relations Registry](http://www.iana.org/assignments/link-relations/link-relations.xhtml) 23 | - [Microformats Relations List](http://microformats.org/wiki/existing-rel-values#HTML5_link_type_extensions) 24 | 25 | ## 1. 명세서 26 | 27 | ### 1.1 Basic links 28 | 29 | 하이퍼 미디어 링크는 최소한 다음으로 구성됩니다. 30 | - 참조되는 대상 자원을 나타내는 URI입니다. 31 | - 대상 자원과 관련된 소스의 관계를 정의합니다. 32 | 33 | 사용 된 형식에 따라 링크의 다양한 다른 속성이 존재할 수 있습니다. 34 | 추가 속성(additional attributes)은 표준화되거나 보편화되지 않았기 때문에 이 표준은 표준화하려고하지 않습니다. 35 | 36 | 이 명세서는 목정상 다음의 정의가 적용됩니다. 37 | 38 | * **Implementing Object** - 이 명세에 정의 된 인터페이스 중 하나를 구현하는 객체. 39 | * **Serializer** - 하나 이상의 Link 객체를 사용하고 정의 된 형식으로 직렬화 된 표현을 생성하는 라이브러리 또는 기타 시스템입니다. 40 | 41 | ### 1.2 Attributes 42 | 43 | 모든 링크는 URI와 관계를 넘어 0개 이상의 추가 속성을 포함 할 수있습니다(MAY). 44 | 여기에 허용되는 값의 정식 등록된 것이 없으며 값의 유효성은 컨텍스트 및 종종 특정 직렬화 형식에 따라 다릅니다. 45 | 일반적으로 지원되는 값에는 'hreflang', 'title'및 'type'이 포함됩니다. 46 | 47 | 직렬화 포맷에 의해 필요한 경우 링크 객체의 속성을 생략 할 수 있습니다(MAY). 48 | 그러나 serializers는 serialization 형식의 정의에 의해 방지되지 않는 한 사용자 확장을 허용하기 위해 가능한 모든 제공된 속성을 인코딩해야합니다 (SHOULD). 49 | 50 | 일부 속성 (일반적으로 `hreflang`)은 그들의 문맥에 두 번 이상 나타날 수 있습니다. 51 | 따라서 속성 값은 단순한 값이 아닌 값의 배열 일 수 있습니다(MAY). 52 | Serializers는 직렬화 된 형식 (공백으로 구분 된 목록, 쉼표로 구분 된 목록 등)에 적합한 형식으로 배열을 인코딩 할 수 있습니다 (MAY). 53 | 특정 속성이 특정 컨텍스트에서 다중 값을 가질 수 없는 경우, 직렬자는 제공된 첫 번째 값을 사용하고 모든 후속 값을 무시해야합니다 (MUST). 54 | 55 | 속성 값이 부울 `true`이면, serializers는 적절한 경우 축약형을 사용할 수 있고 직렬화 형식으로 지원할 수 있습니다 (MAY). 56 | 예를 들어, HTML은 속성의 존재가 부울 의미를 가질 때 속성이 값을 갖지 못하게합니다. 57 | 이 규칙은 속성이 부울 `true`인 경우에만 적용되며 정수 1과 같은 PHP의 "truthy"값은 적용되지 않습니다. 58 | 59 | 속성 값이 부울 `false` 인 경우, serializer는 속성의 의미를 변경하지 않는 한 속성을 완전히 생략해서는 안됩니다 (SHOULD). 60 | 이 규칙은 속성이 부울 `false` 인 경우에만 적용되며, 정수 0과 같은 PHP의 다른 "falsey"값에는 적용되지 않습니다. 61 | 62 | ### 1.3 Relationships 63 | 64 | 링크 관계는 문자열로 정의되며 공개적으로 정의 된 관계의 경우 간단한 키워드이고 비공개인 관계의 경우 절대 URI를 사용합니다. 65 | 66 | 간단한 키워드가 사용되는 경우 [IANA 레지스트리](http://www.iana.org/assignments/link-relations/link-relations.xhtml)의 키워드와 일치해야합니다(SHOULD). 67 | 68 | 선택적으로 [microformats.org](http://microformats.org/wiki/existing-rel-values) 레지스트리를 사용할 수도 있지만(MAY) 모든 컨텍스트에서 유효하지 않을 수 있습니다. 69 | 70 | 위의 레지스트리 중 하나 또는 이와 유사한 공개 레지스트리에 정의되지 않은 관계는 "비공개"으로 간주됩니다. 즉 특정 응용 프로그램 또는 유스 케이스에 한정됩니다. 71 | 그러한 관계는 반드시 절대 URI를 사용해야 합니다(MUST). 72 | 73 | ## 1.4 Link Templates 74 | 75 | [RFC 6570](https://tools.ietf.org/html/rfc6570)은 URI 템플릿의 형식, 즉 클라이언트에서 제공 한 값으로 채워질 것으로 예상되는 URI의 패턴을 정의합니다. 76 | 일부 하이퍼 미디어 형식은 템플릿 링크를 지원하지만 다른 링크는 템플릿이 아니라는 것을 나타내는 특별한 방법이 있을 수 있습니다. 77 | URI 템플릿을 지원하지 않는 형식의 Serializer는 템플릿 기반 링크가 발견되면 이를 무시해야 합니다 (MUST). 78 | 79 | ## 1.5 Evolvable providers 80 | 81 | 어떤 경우에는 링크 공급자가 추가 링크를 추가해야 할 수도 있습니다. 82 | 어떤 경우에는 링크 공급자가 반드시 읽기 전용이며 링크는 런타임시 다른 데이터 소스에서 파생됩니다. 83 | 이러한 이유로 수정 가능한 공급자는 선택적으로 구현 될 수 있는 보조 인터페이스입니다. 84 | 85 | 또한 PSR-7 응답 객체 같은 일부 링크 공급자 객체는 의도적으로 변경할 수 없습니다. 86 | 이것은 메소드를 해당 링크에 추가하는 방법은 맞지 않는 다는 것을 의미합니다 87 | 따라서 `EvolvableLinkProviderInterface` 의 단일 메소드는 원본과 동일하지만 추가 링크 객체가 포함 된 새로운 객체가 반환되어야 합니다. 88 | 89 | ## 1.6 Evolvable link objects 90 | 91 | 링크 오브젝트는 대부분의 경우 값 오브젝트입니다. 92 | 따라서 PSR-7 값 객체와 동일한 방식으로 처리하도록 하는 것이 좋은 방식입니다. 93 | 94 | > 역자주: 원문은 evolve이지만 의역하였습니다 95 | 96 | 이러한 이유 때문에, 단일 변경으로 새 객체 인스턴스를 생성하는 메소드인 `EvolvableLinkInterface`가 추가적으로 제공됩니다. 97 | 같은 방식이 PSR-7에서 사용되었고, PHP의 copy-on-write 동작 덕분에 여전히 CPU와 메모리가 효율적입니다. 98 | 99 | 그러나 링크의 templated 된 값은 href 값에 기반하므로 templated 된 값에 대한 확장 가능한 방법은 없습니다. 100 | 101 | > 역자주: evolvable지만 좀 더 좋은 단어를 찾지 못하였습니다 102 | 103 | 이것은 독립적으로 설정하면 안되지만(MUST NOT), href 값이 RFC 6570 링크 템플릿인지에 따라서 결정됩니다. 104 | 105 | ## 2. Package 106 | 107 | 설명 한 인터페이스와 클래스는 [psr/link](https://packagist.org/packages/psr/link) 패키지의 일부로 제공됩니다. 108 | 109 | ## 3. Interfaces 110 | 111 | ### 3.1 `Psr\Link\LinkInterface` 112 | 113 | ~~~php 114 | 역자주: 사실상 오토로더는 컴포저로 대동단결 되었기 때문에 직접 구현하시기 보다는 컴포저를 사용하시는 것을 추천합니다 7 | 8 | Closure 예제 9 | --------------- 10 | 11 | ~~~php 12 | register(); 91 | * 92 | * // register the base directories for the namespace prefix 93 | * $loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/src'); 94 | * $loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/tests'); 95 | * 96 | * The following line would cause the autoloader to attempt to load the 97 | * \Foo\Bar\Qux\Quux class from /path/to/packages/foo-bar/src/Qux/Quux.php: 98 | * 99 | * prefixes[$prefix]) === false) { 149 | $this->prefixes[$prefix] = array(); 150 | } 151 | 152 | // retain the base directory for the namespace prefix 153 | if ($prepend) { 154 | array_unshift($this->prefixes[$prefix], $base_dir); 155 | } else { 156 | array_push($this->prefixes[$prefix], $base_dir); 157 | } 158 | } 159 | 160 | /** 161 | * Loads the class file for a given class name. 162 | * 163 | * @param string $class The fully-qualified class name. 164 | * @return mixed The mapped file name on success, or boolean false on 165 | * failure. 166 | */ 167 | public function loadClass($class) 168 | { 169 | // the current namespace prefix 170 | $prefix = $class; 171 | 172 | // work backwards through the namespace names of the fully-qualified 173 | // class name to find a mapped file name 174 | while (false !== $pos = strrpos($prefix, '\\')) { 175 | 176 | // retain the trailing namespace separator in the prefix 177 | $prefix = substr($class, 0, $pos + 1); 178 | 179 | // the rest is the relative class name 180 | $relative_class = substr($class, $pos + 1); 181 | 182 | // try to load a mapped file for the prefix and relative class 183 | $mapped_file = $this->loadMappedFile($prefix, $relative_class); 184 | if ($mapped_file) { 185 | return $mapped_file; 186 | } 187 | 188 | // remove the trailing namespace separator for the next iteration 189 | // of strrpos() 190 | $prefix = rtrim($prefix, '\\'); 191 | } 192 | 193 | // never found a mapped file 194 | return false; 195 | } 196 | 197 | /** 198 | * Load the mapped file for a namespace prefix and relative class. 199 | * 200 | * @param string $prefix The namespace prefix. 201 | * @param string $relative_class The relative class name. 202 | * @return mixed Boolean false if no mapped file can be loaded, or the 203 | * name of the mapped file that was loaded. 204 | */ 205 | protected function loadMappedFile($prefix, $relative_class) 206 | { 207 | // are there any base directories for this namespace prefix? 208 | if (isset($this->prefixes[$prefix]) === false) { 209 | return false; 210 | } 211 | 212 | // look through base directories for this namespace prefix 213 | foreach ($this->prefixes[$prefix] as $base_dir) { 214 | 215 | // replace the namespace prefix with the base directory, 216 | // replace namespace separators with directory separators 217 | // in the relative class name, append with .php 218 | $file = $base_dir 219 | . str_replace('\\', '/', $relative_class) 220 | . '.php'; 221 | 222 | // if the mapped file exists, require it 223 | if ($this->requireFile($file)) { 224 | // yes, we're done 225 | return $file; 226 | } 227 | } 228 | 229 | // never found it 230 | return false; 231 | } 232 | 233 | /** 234 | * If a file exists, require it from the file system. 235 | * 236 | * @param string $file The file to require. 237 | * @return bool True if the file exists, false if not. 238 | */ 239 | protected function requireFile($file) 240 | { 241 | if (file_exists($file)) { 242 | require $file; 243 | return true; 244 | } 245 | return false; 246 | } 247 | } 248 | ~~~ 249 | 250 | ### Unit Tests 251 | 252 | 다음 예제는 위의 클래스 로더를 단위 테스트하는 방법의 한 가지입니다. 253 | 254 | ~~~php 255 | files = $files; 265 | } 266 | 267 | protected function requireFile($file) 268 | { 269 | return in_array($file, $this->files); 270 | } 271 | } 272 | 273 | class Psr4AutoloaderClassTest extends \PHPUnit_Framework_TestCase 274 | { 275 | protected $loader; 276 | 277 | protected function setUp() 278 | { 279 | $this->loader = new MockPsr4AutoloaderClass; 280 | 281 | $this->loader->setFiles(array( 282 | '/vendor/foo.bar/src/ClassName.php', 283 | '/vendor/foo.bar/src/DoomClassName.php', 284 | '/vendor/foo.bar/tests/ClassNameTest.php', 285 | '/vendor/foo.bardoom/src/ClassName.php', 286 | '/vendor/foo.bar.baz.dib/src/ClassName.php', 287 | '/vendor/foo.bar.baz.dib.zim.gir/src/ClassName.php', 288 | )); 289 | 290 | $this->loader->addNamespace( 291 | 'Foo\Bar', 292 | '/vendor/foo.bar/src' 293 | ); 294 | 295 | $this->loader->addNamespace( 296 | 'Foo\Bar', 297 | '/vendor/foo.bar/tests' 298 | ); 299 | 300 | $this->loader->addNamespace( 301 | 'Foo\BarDoom', 302 | '/vendor/foo.bardoom/src' 303 | ); 304 | 305 | $this->loader->addNamespace( 306 | 'Foo\Bar\Baz\Dib', 307 | '/vendor/foo.bar.baz.dib/src' 308 | ); 309 | 310 | $this->loader->addNamespace( 311 | 'Foo\Bar\Baz\Dib\Zim\Gir', 312 | '/vendor/foo.bar.baz.dib.zim.gir/src' 313 | ); 314 | } 315 | 316 | public function testExistingFile() 317 | { 318 | $actual = $this->loader->loadClass('Foo\Bar\ClassName'); 319 | $expect = '/vendor/foo.bar/src/ClassName.php'; 320 | $this->assertSame($expect, $actual); 321 | 322 | $actual = $this->loader->loadClass('Foo\Bar\ClassNameTest'); 323 | $expect = '/vendor/foo.bar/tests/ClassNameTest.php'; 324 | $this->assertSame($expect, $actual); 325 | } 326 | 327 | public function testMissingFile() 328 | { 329 | $actual = $this->loader->loadClass('No_Vendor\No_Package\NoClass'); 330 | $this->assertFalse($actual); 331 | } 332 | 333 | public function testDeepFile() 334 | { 335 | $actual = $this->loader->loadClass('Foo\Bar\Baz\Dib\Zim\Gir\ClassName'); 336 | $expect = '/vendor/foo.bar.baz.dib.zim.gir/src/ClassName.php'; 337 | $this->assertSame($expect, $actual); 338 | } 339 | 340 | public function testConfusion() 341 | { 342 | $actual = $this->loader->loadClass('Foo\Bar\DoomClassName'); 343 | $expect = '/vendor/foo.bar/src/DoomClassName.php'; 344 | $this->assertSame($expect, $actual); 345 | 346 | $actual = $this->loader->loadClass('Foo\BarDoom\ClassName'); 347 | $expect = '/vendor/foo.bardoom/src/ClassName.php'; 348 | $this->assertSame($expect, $actual); 349 | } 350 | } 351 | ~~~ 352 | -------------------------------------------------------------------------------- /accepted/PSR-6-cache.md: -------------------------------------------------------------------------------- 1 | # Caching Interface 2 | 3 | 캐싱은 모든 프로젝트의 성능을 향상시키는 일반적인 방법이며, 많은 프레임워크 및 라이브러리는 캐싱 라이브러리를 기본 기능 중 하나로 만들게 됩니다. 4 | 이로 인해 많은 라이브러리가 다양한 수준의 기능을 갖춘 자체 캐싱 라이브러리를 사용하게 되었습니다. 5 | 이러한 상황으로 인해 개발자는 필요한 기능을 제공 할 수도 있고 제공하지 못할 수도 있는 여러 시스템을 배워야합니다. 6 | 또한 라이브러리를 캐싱하는 개발자는 제한된 수의 프레임워크 만 지원하거나 많은 수의 어댑터 클래스를 만드는 것 중에서 선택해야합니다. 7 | 8 | 캐싱 시스템을 위한 공통 인터페이스는 이러한 문제를 해결할 것 입니다. 9 | 라이브러리 및 프레임워크 개발자는 의도한대로 동작하는 캐싱 시스템에 의존 할 수 있습니다. 10 | 캐싱 시스템의 개발자는 전체 어댑터 모음보다는 단일 인터페이스 세트 만 구현하면됩니다. 11 | 12 | 이 문서에서 핵심이 되는 단어는 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", "OPTIONAL" 입니다. 13 | 이것은 [RFC 2119]에 설명 된대로 해석해야 합니다. 14 | 15 | > 역자주: 위의 키워드는 아래의 번역문에 괄호안에 표시하였습니다 16 | 17 | [RFC 2119]: http://tools.ietf.org/html/rfc2119 18 | 19 | ## 목표 20 | 21 | 이 PSR의 목표는 개발자가 빈틈없는 캐시 라이브러리를 만들 수 있도록 하여 맞춤 개발이 필요없이 기존 프레임 워크와 시스템에 통합 될 수 있도록 하는 것입니다. 22 | 23 | ## 정의 24 | 25 | * **호출 라이브러리(Calling Library)** - 실제로 캐시 서비스가 필요한 라이브러리 또는 코드. 26 | 이 라이브러리는이 표준의 인터페이스를 구현하는 캐싱 서비스를 활용할 것이며, 그렇지 않으면 이러한 캐싱 서비스의 구현에 대한 알지 못합니다. 27 | > 역자주: 인터페이스를 구현한 캐싱 서비스를 사용만하고 구현을 하지 않는다. 28 | 29 | * **구현 라이브러리(Implementing Library)** - 이 라이브러리는 모든 호출 라이브러리에 캐싱 서비스를 제공하기 위해이 표준을 구현합니다. 30 | 구현 라이브러리는 `Cache\CacheItemPoolInterface` 및 `Cache\CacheItemInterface` 인터페이스를 구현하는 클래스를 제공해야합니다. 31 | 라이브러리 구현은 전체 초 단위로 아래에 설명 된 최소 TTL 기능을 지원해야만 합니다 (MUST). 32 | 33 | * **TTL** - TTL (Time To Live)은 해당 항목이 저장하고 보관하는 것으로 간주되는 시간입니다. 34 | TTL은 일반적으로 초 단위의 시간을 나타내는 정수 또는 DateInterval 개체로 정의됩니다. 35 | 36 | 37 | * **만료(Expiration)** - 항목이 만료로 설정되는 실제 시간입니다. 38 | 이것은 일반적으로 개체가 저장된 시간에 TTL을 추가하여 계산됩니다. 39 | 이것은 일반적으로 개체가 저장된 시간에 TTL을 추가하여 계산되지만 DateTime 개체로 명시 적으로 설정할 수도 있습니다. 40 | 1:30:00에 저장된 300 초 TTL을 가진 항목의 만료 시간은 1:35:00입니다. 41 | 구현 라이브러리는 요청한 만료 시간 전에 항목을 만료시킬 수도 있지만(MAY) 만료 시간에 도달하면 만료 된 것으로 간주해야합니다(MUST). 42 | 호출 라이브러리가 항목을 저장요청을 하지만 만료 시간을 지정하지 않거나 만료 시간 또는 TTL을 null로 지정되어 있다면 구현 라이브러리는 설정한 기본 기간을 사용할 수 있습니다 (MAY). 43 | 기본 기간이 설정되지 않은 경우 구현 라이브러리는 해당 항목을 영원히 캐시하는 요청으로 해석하거나 기본 구현이 지원하는 동안 저장하는 것으로 해석해야합니다(MUST). 44 | 45 | * **Key** - 캐시 된 항목을 고유하게 식별하는 적어도 하나의 문자로 구성된 문자열입니다. 46 | 구현 라이브러리는`A-Z`,`a-z`,`0-9`,`_` 및`.` 문자로 구성된 키를 UTF-8 인코딩과 길이가 64 문자 이하의 순서로 지원해야합니다 (MUST). 47 | 구현 라이브러리은 추가 문자와 인코딩 또는 더 긴 길이를 지원할 수 있지만 최소한 그 최소값을 지원해야합니다(MAY). 48 | 라이브러리는 적절하게 키 문자열을 이스케이프 처리해야하지만 원래의 수정되지 않은 키 문자열을 반환 할 수 있어야합니다(MUST). 49 | 다음 문자는 미래의 확장을 위해 예약되어 있으며, 구현 라이브러리에서 지원해서는 안됩니다(MUST NOT) :`{} () / \ @ :` 50 | 51 | 52 | * **Hit** - 호출 라이브러리가 키로 Item을 요청하고 해당 키에 대해 일치하는 값이 발견되고 그 값이 만료되지 않았으며 값이 다른 이유로 무효하지 않은 경우 캐시 히트(Hit)가 발생합니다. 53 | 호출 라이브러리는 모든 `get()` 호출에 대해 `isHit()`를 확인해야합니다 (SHOULD). 54 | 55 | 56 | * **Miss** - 캐시 미스는 캐시 히트와 반대입니다. 57 | 호출 라이브러리가 키로 항목을 요청하고 해당 키에 해당 값이 없거나 값이 발견되었지만 만료되었거나 값이 다른 이유로 유효하지 않은 경우 캐시 미스가 발생합니다. 58 | 만료 된 값은 항상 캐시 미스로 간주되어야합니다 (MUST). 59 | 60 | 61 | * **지연됨(Deferred)** - 지연된 캐시 저장은 캐시 항목이 풀에 의해 즉시 유지되지 않을 수 있음을 나타냅니다. 62 | 풀 객체는 일부 저장소 엔진에서 지원하는 대량 세트 연산을 이용하기 위해 지연된 캐시 항목을 유지하는 것을 지연시킬 수 있습니다. 63 | 풀은 지연 캐시 항목이 결국 유지되고 데이터가 손실되지 않도록 보장해야하며 호출 라이브러리가 지속되도록 요청하기 전에이를 유지해야합니다. 64 | 호출 라이브러리가 `commit()` 메소드를 호출 할 때 모든 미해결 지연 항목을 유지해야합니다 (MUST). 65 | 구현 라이브러리는 객체 소멸자, `save()`, timeout 또는 max-items check 또는 다른 적절한 논리에서 모두 지속되는 것과 같이 지연된 항목을 언제 유지할 것인지를 결정하는 데 적합한 논리를 사용할 수 있습니다 (MAY). 66 | 지연된 캐시 항목에 대한 요청은 지연되었지만 아직 지속되지 않은 항목을 반환해야합니다 (MUST). 67 | 68 | 69 | ## Data 70 | 71 | 구현 라이브러리는 다음을 포함하여 모든 직렬화 가능한 PHP 데이터 유형을 지원해야합니다. 72 | 73 | * **Strings** - PHP 호환 인코딩의 임의의 크기를 갖는 문자열. 74 | * **Integers** - PHP가 지원하는 모든 크기의 정수 (최대 64 비트). 75 | * **Floats** - 부호가 있는(signed) 모든 부동소수점 값. 76 | * **Boolean** - True 와 False. 77 | * **Null** - 진짜 Null 값. `역자주: 진짜라는 표현을 하는 이유는 PSR-16의 Null과는 다른 의미라서 입니다` 78 | * **Arrays** - 인덱스된 임의의 깊이를 가진 연관 및 다차원 배열 79 | * **Object** - `$o == unserialize(serialize($o))` 와 같이 무손실 직렬화 및 직렬화 해제를 지원하는 객체. 80 | 객체는 PHP의 Serializable 인터페이스, 적절한 경우 `__sleep()` 또는 `__wakeup()` 매직 메서드 또는 유사한 언어 기능을 활용할 수 있습니다(MAY). 81 | 82 | 구현 라이브러리에 전달 된 모든 데이터는 전달 된 그대로 정확하게 반환되어야합니다(MUST). 83 | 여기에는 가변 유형이 포함됩니다. 즉, 만약 (int) 5가 저장된 값이었던 경우 (string) 5를 반환하는 것은 오류입니다. 84 | 구현 라이브러리는 PHP의 `serialize()`/`unserialize()` 함수를 내부적으로 사용할 수 있지만 꼭 그렇게 할 필요는 없습니다(MAY). 85 | 이들과의 호환성은 수용 가능한 객체 값의 기준선으로 사용됩니다. 86 | 87 | 88 | 어떠한 이유로든 저장된 정확한 값을 반환 할 수없는 경우 구현 라이브러리는 데이터가 손상되지 않게 캐시 미스로 응답해야합니다(MUST). 89 | 90 | ## Key Concepts 91 | 92 | ### Pool 93 | 94 | 풀은 캐싱 시스템의 항목 모음을 나타냅니다. 95 | 풀은 포함 된 모든 항목의 논리적 저장소입니다. 96 | 캐시 가능한 모든 항목은 풀에서 항목 객체로 검색되고 캐시 된 객체의 전체 유니버스와의 모든 상호 작용은 풀을 통해 발생합니다. 97 | 98 | ### Items 99 | 100 | Item은 풀 내의 단일 키 / 값 쌍을 나타냅니다. 101 | 키는 Item에 대한 주요 고유 식별자이며 변경할 수 없어야합니다 (MUST). 102 | 언제든지 값을 변경할 수 있습니다 (MAY). 103 | 104 | ## Error handling 105 | 106 | 캐싱은 종종 애플리케이션 성능의 중요한 부분이지만 애플리케이션 기능의 중요한 부분이되어서는 안됩니다. 107 | 따라서 캐시 시스템의 오류로 인해 프로그램이 실패(failure)하지 않아야합니다 (SHOULD NOT). 108 | 이런 이유로, 구현 라이브러리는 인터페이스에 의해 정의 된 것과 다른 예외를 던져서는 안되며, 기본 데이터 저장소에 의해 발생된 된 오류나 예외를 버리고 문제를 일으키지 않아야합니다 (SHOULD). 109 | 110 | 구현 라이브러리는 그러한 오류를 기록하거나 적절한 경우 이를 관리자에게 보고해야합니다 (SHOULD). 111 | 112 | 호출 라이브러리가 하나 이상의 항목을 삭제하도록 요청하거나 풀을 지우도록 요청한 경우 지정된 키가 존재하지 않으면 오류 상태로 간주해서는 안됩니다(MUST NOT). 113 | 다음의 조건(키가 존재하지 않거나 풀이 비어 있음)도 동일하며 오류 조건은 없습니다. 114 | 115 | ## Interfaces 116 | 117 | ### CacheItemInterface 118 | 119 | `CacheItemInterface`는 캐시 시스템 내부의 항목을 정의합니다. 120 | 각 Item 객체는 구현 시스템에 따라 설정 될 수 있는 특정 키와 연결되어야하며(MUST) 일반적으로 `Cache\CacheItemPoolInterface` 객체에 의해 전달됩니다. 121 | 122 | `Cache\CacheItemInterface` 객체는 캐시 항목의 저장 및 검색을 캡슐화합니다. 123 | 각 `Cache\CacheItemInterface`는 `Cache\CacheItemPoolInterface` 오브젝트에 의해 생성되며, 필요한 모든 설정을 담당 할 뿐만 아니라 오브젝트를 고유 키와 연관시킵니다. 124 | `Cache\CacheItemInterface` 객체는 이 문서의 데이터 섹션에 정의 된 모든 유형의 PHP 값을 저장하고 검색 할 수 있어야 합니다. 125 | 126 | 호출 라이브러리는 Item 객체 자체를 인스턴스화해서는 안됩니다. 127 | `getItem()` 메소드를 통해 Pool 객체에서만 요청할 수 있습니다. 128 | 라이브러리 호출은 하나의 구현 라이브러리에 의해 생성 된 항목이 다른 구현 라이브러리의 풀과 호환 가능하다고 가정해서는 안됩니다 (SHOULD NOT). 129 | 130 | 131 | ~~~php 132 | **사용중단** - 2019-08-10을 기준으로 PSR-2은 사용이 중단되었습니다. 새로운 표준으로 [PSR-12]을 사용하시길 권장합니다. 4 | 5 | [PSR-12]: /accepted/PSR-12-extended-coding-style-guide.md 6 | 7 | 이 가이드는 기본 코딩 표준인 [PSR-1]을 확장입니다. 8 | 9 | 이 가이드의 의도는 다른 저자의 코드를 볼 때 가독성을 해치는 것을 줄이는 것입니다. 10 | PHP 코드의 형식을 지정하는 방법에 대한 여러가지 규칙과 기대 사항을 나열함으로써 이를 달성합니다. 11 | 12 | 이 스타일 규칙은 다양한 회원 프로젝트 간의 공통점에서 파생되었습니다. 13 | 다양한 저자가 여러 프로젝트에서 공동 작업을 수행 할 때 모든 프로젝트 중에서 한 가지의 가이드을 사용하는 것이 도움이 됩니다. 14 | 따라서 이 가이드의 이점은 규칙 자체가 아니라 이러한 규칙을 공유하는 것입니다. 15 | 16 | 이 문서에서 핵심이 되는 단어는 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", "OPTIONAL" 입니다. 17 | 이것은 [RFC 2119]에 설명 된대로 해석해야 합니다. 18 | 19 | > 역자주: 위의 키워드는 아래의 번역문에 괄호안에 표시하였습니다 20 | 21 | [RFC 2119]: http://www.ietf.org/rfc/rfc2119.txt 22 | [PSR-0]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md 23 | [PSR-1]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md 24 | 25 | ## 1. 개요 26 | 27 | - 코드는 반드시(MUST) "코딩 스타일 가이드" PSR [[PSR-1]]을 따라야합니다. 28 | 29 | - 코드는 들여쓰기에 반드시(MUST) 탭이 아니라 스페이스 4칸을 사용해야합니다. 30 | 31 | - 한줄에 들어가는 문자열의 길이에 엄격한 제한이 있으면 안됩니다. 가벼운 제한은 한줄에 120자입니다 (MUST). 가능하다면 한줄은 80자 이하여야 합니다 (SHOULD). 32 | 33 | - `namespace` 선언 다음에 빈 줄이 하나 있어야만 하며(MUST) 그리고 `use` 선언 블록 뒤에 빈 줄이 하나 있어야만 합니다 (MUST). 34 | 35 | - 클래스의 여는 중괄호는 다음 줄로 가야만 하며(MUST), 닫는 중괄호는 본문 뒤의 다음 줄로 가야만 합니다(MUST). 36 | 37 | - 메서드의 여는 중괄호는 다음 줄로 가야만 하며(MUST), 닫는 중괄호는 본문 뒤의 다음 줄로 가야만 합니다(MUST). 38 | 39 | - 모든 속성 및 메서드에서 가시성을 선언해야만 합니다 (MUST). `abstract`와`final`은 가시성 (visibility) 전에 선언되어야만 합니다(MUST). `static`은 가시성 뒤에 선언되어야만 합니다 (MUST). 40 | 41 | - 제어문 키워드는 그 뒤에 하나의 공백을 가져야만 합니다 (MUST). 메서드와 함수에서 해서는 안됩니다(MUST NOT). 42 | > 역자주: if, switch, try, catch, foreach 등 43 | 44 | - 제어문를 여는 중괄호는 같은 줄에 있어야만 하며(MUST), 닫는 중괄호는 반드시 본문 뒤의 다음 줄로 가야만 합니다(MUST). 45 | 46 | - 제어문를 여는 괄호는 그 뒤에 공백이 없어야만 하며(MUST NOT), 제어문에 대한 닫는 괄호는 전에는 공백이 없어야만 합니다(MUST NOT). 47 | 48 | ### 1.1. 예제 49 | 50 | 이 예는 아래의 규칙 중 일부를 간략하게 설명합니다. 51 | 52 | ~~~php 53 | $b) { 67 | $foo->bar($arg1); 68 | } else { 69 | BazClass::bar($arg2, $arg3); 70 | } 71 | } 72 | 73 | final public static function bar() 74 | { 75 | // method body 76 | } 77 | } 78 | ~~~ 79 | 80 | ## 2. General 81 | 82 | ### 2.1. Basic Coding Standard 83 | 84 | 코드는 반드시(MUST) [PSR-1]에 요약 된 모든 규칙을 따라야합니다. 85 | 86 | ### 2.2. Files 87 | 88 | 모든 PHP 파일은 Unix LF (linefeed) 줄 끝을 사용해야합니다. 89 | 90 | 모든 PHP 파일은 하나의 빈 줄을 가진 채로 끝나야합니다. 91 | 92 | 닫는 `?>` 태그는 PHP만 포함 된 파일일 경우 생략해야합니다 (MUST). 93 | 94 | ### 2.3. 라인 (Lines) 95 | 96 | 라인 길이에 엄격한 제한이 있어서는 안됩니다(MUST NOT). 97 | 98 | 라인 길이에 대한 소프트 제한은 120 자여야 합니다(MUST). 자동화 된 스타일 검사기는 반드시(MUST) 경고해야하지만 소프트 한도에서 오류를 표시해서는 안됩니다(MUST NOT). 99 | 100 | 라인은 80자를 넘지 않아야합니다 (SHOULD NOT). 그보다 긴 행은 각각 80 문자 이하의 여러 행으로 나눠 져야합니다 (SHOULD). 101 | 102 | 비어 있지 않은 라인 끝에는 공백 문자가 없어야합니다(MUST NOT). 103 | 104 | 가독성을 높이고 관련 코드 블록을 나타내기 위해 빈 라인을 추가 할 수 있습니다 (MAY). 105 | 106 | 한 라인에 하나 이상의 문장이 있어서는 안됩니다(MUST NOT). 107 | 108 | ### 2.4. 들여쓰기 (Indenting) 109 | 110 | 코드는 반드시(MUST) 4 스페이스의 들여쓰기를 사용해야하며, 들여쓰기에는 탭을 사용하지 않아야합니다(MUST NOT). 111 | 112 | > 공백 만 사용하고 탭과 공백을 섞지 않으면 diff, 패치, 히스토리 및 주석 문제를 피할 수 있습니다. 113 | > 공백을 사용하면 행간 정렬을 위해 세분화 된 하위 들여쓰기를 쉽게 삽입 할 수 있습니다. 114 | 115 | ### 2.5. 예약어(Keywords)와 True/False/Null 116 | 117 | PHP [예약어]는 소문자여야 합니다. 118 | 119 | PHP 상수 `true`,`false` 및 `null`은 반드시(MUST) 소문자여야 합니다. 120 | 121 | [예약어]: http://php.net/manual/en/reserved.keywords.php 122 | 123 | ## 3. 네임 스페이스 및 사용 선언 124 | 125 | 네임스페이스가 존재할 때 `namespace` 선언 다음에 하나의 빈 라인이 있어야 합니다(MUST). 126 | 127 | 네임스페이스가 존재할 때, 모든 `use` 선언은 반드시 `namespace` 선언을 따라야 만합니다(MUST). 128 | 129 | 선언 하나당 하나의 `use` 키워드가 있어야합니다(MUST). 130 | 131 | `use` 블록 뒤에 빈 줄이 하나 있어야합니다(MUST). 132 | 133 | 예제 : 134 | 135 | ~~~php 136 | bar($arg1); 313 | Foo::bar($arg2, $arg3); 314 | ~~~ 315 | 316 | 인수 목록은 여러 줄에 걸쳐 나뉘어 질 수 있으며(MAY), 각 줄은 한 번 들여 쓰일 수 있습니다. 317 | 그렇게 할 때 목록의 첫 번째 항목은 다음 줄에 있어야하며(MUST) 한 줄에 하나의 인수 만 있어야합니다(MUST). 318 | 319 | ~~~php 320 | bar( 322 | $longArgument, 323 | $longerArgument, 324 | $muchLongerArgument 325 | ); 326 | ~~~ 327 | 328 | ## 5. 제어문(Control Structures) 329 | 330 | 제어문의 일반적인 스타일 규칙은 다음과 같습니다. 331 | 332 | - 제어문 키워드 다음에 하나의 공백이 있어야합니다 (MUST). 333 | - 여는 괄호 뒤에 공백이 있으면 안됩니다 (MUST NOT). 334 | - 닫는 괄호 앞에 공백이 없어야합니다 (MUST NOT). 335 | - 닫는 괄호와 여는 중괄호 사이에 하나의 공백이 있어야합니다 (MUST). 336 | - 구조체는 한 번 들여쓰기되어야합니다 (MUST). 337 | - 닫는 중괄호는 제어문의 다음 줄에 있어야합니다 (MUST). 338 | 339 | 각 제어문는 중괄호로 묶어야합니다 (MUST). 340 | 이것은 구조가 어떻게 보이는지를 표준화하고, 새로운 라인이 제어문에 추가 될 때 오류가 발생할 가능성을 줄입니다. 341 | 342 | ### 5.1. `if`, `elseif`, `else` 343 | 344 | `if` 구조는 다음과 같습니다. 괄호, 공백 및 중괄호의 배치에 유의하십시오. 345 | `else`와 `elseif`는 이전 제어문의 닫는 중괄호와 같은 줄에 있습니다. 346 | 347 | ~~~php 348 | $value) { 424 | // foreach body 425 | } 426 | ~~~ 427 | 428 | ### 5.6. `try`, `catch` 429 | 430 | `try catch` 블록은 다음과 같이 보입니다. 괄호, 공백 및 중괄호의 배치에 유의하십시오. 431 | 432 | ~~~php 433 | bar( 527 | $arg1, 528 | function ($arg2) use ($var1) { 529 | // body 530 | }, 531 | $arg3 532 | ); 533 | ~~~ 534 | 535 | ## 7. 결론 536 | 537 | 이 가이드에는 의도적으로 생략 한 스타일과 연습의 많은 요소가 있습니다. 여기에는 다음이 포함되지만 이에 국한되지는 않습니다 : 538 | 539 | - 전역 변수 및 전역 상수 선언 540 | 541 | - 함수 선언 542 | 543 | - 운영자 및 과제 544 | 545 | - 라인 간 정렬 546 | 547 | - 주석 및 문서 블록 548 | 549 | - 클래스 이름 접두사 및 접미사 550 | 551 | - 모범 사례 552 | 553 | 향후 권장 사항은 스타일이나 실습의 요소 또는 기타 요소를 다루기 위해이 가이드를 수정하고 확장 할 수 있습니다. 554 | 555 | ## 부록 A. 설문조사 556 | 557 | 이 스타일 가이드를 작성하면서이 그룹은 공통 실천을 결정하기 위해 회원 프로젝트에 대한 설문 조사를 실시했습니다. 조사는 후일을 위해 여기에 유지됩니다. 558 | 559 | ### A.1. 설문조사 자료 560 | 561 | url,http://www.horde.org/apps/horde/docs/CODING_STANDARDS,http://pear.php.net/manual/en/standards.php,http://solarphp.com/manual/appendix-standards.style,http://framework.zend.com/manual/en/coding-standard.html,https://symfony.com/doc/2.0/contributing/code/standards.html,http://www.ppi.io/docs/coding-standards.html,https://github.com/ezsystems/ezp-next/wiki/codingstandards,http://book.cakephp.org/2.0/en/contributing/cakephp-coding-conventions.html,https://github.com/UnionOfRAD/lithium/wiki/Spec%3A-Coding,http://drupal.org/coding-standards,http://code.google.com/p/sabredav/,http://area51.phpbb.com/docs/31x/coding-guidelines.html,https://docs.google.com/a/zikula.org/document/edit?authkey=CPCU0Us&hgd=1&id=1fcqb93Sn-hR9c0mkN6m_tyWnmEvoswKBtSc0tKkZmJA,http://www.chisimba.com,n/a,https://github.com/Respect/project-info/blob/master/coding-standards-sample.php,n/a,Object Calisthenics for PHP,http://doc.nette.org/en/coding-standard,http://flow3.typo3.org,https://github.com/propelorm/Propel2/wiki/Coding-Standards,http://developer.joomla.org/coding-standards.html 562 | voting,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,no,no,no,?,yes,no,yes 563 | indent_type,4,4,4,4,4,tab,4,tab,tab,2,4,tab,4,4,4,4,4,4,tab,tab,4,tab 564 | line_length_limit_soft,75,75,75,75,no,85,120,120,80,80,80,no,100,80,80,?,?,120,80,120,no,150 565 | line_length_limit_hard,85,85,85,85,no,no,no,no,100,?,no,no,no,100,100,?,120,120,no,no,no,no 566 | class_names,studly,studly,studly,studly,studly,studly,studly,studly,studly,studly,studly,lower_under,studly,lower,studly,studly,studly,studly,?,studly,studly,studly 567 | class_brace_line,next,next,next,next,next,same,next,same,same,same,same,next,next,next,next,next,next,next,next,same,next,next 568 | constant_names,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper 569 | true_false_null,lower,lower,lower,lower,lower,lower,lower,lower,lower,upper,lower,lower,lower,upper,lower,lower,lower,lower,lower,upper,lower,lower 570 | method_names,camel,camel,camel,camel,camel,camel,camel,camel,camel,camel,camel,lower_under,camel,camel,camel,camel,camel,camel,camel,camel,camel,camel 571 | method_brace_line,next,next,next,next,next,same,next,same,same,same,same,next,next,same,next,next,next,next,next,same,next,next 572 | control_brace_line,same,same,same,same,same,same,next,same,same,same,same,next,same,same,next,same,same,same,same,same,same,next 573 | control_space_after,yes,yes,yes,yes,yes,no,yes,yes,yes,yes,no,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes 574 | always_use_control_braces,yes,yes,yes,yes,yes,yes,no,yes,yes,yes,no,yes,yes,yes,yes,no,yes,yes,yes,yes,yes,yes 575 | else_elseif_line,same,same,same,same,same,same,next,same,same,next,same,next,same,next,next,same,same,same,same,same,same,next 576 | case_break_indent_from_switch,0/1,0/1,0/1,1/2,1/2,1/2,1/2,1/1,1/1,1/2,1/2,1/1,1/2,1/2,1/2,1/2,1/2,1/2,0/1,1/1,1/2,1/2 577 | function_space_after,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no 578 | closing_php_tag_required,no,no,no,no,no,no,no,no,yes,no,no,no,no,yes,no,no,no,no,no,yes,no,no 579 | line_endings,LF,LF,LF,LF,LF,LF,LF,LF,?,LF,?,LF,LF,LF,LF,?,,LF,?,LF,LF,LF 580 | static_or_visibility_first,static,?,static,either,either,either,visibility,visibility,visibility,either,static,either,?,visibility,?,?,either,either,visibility,visibility,static,? 581 | control_space_parens,no,no,no,no,no,no,yes,no,no,no,no,no,no,yes,?,no,no,no,no,no,no,no 582 | blank_line_after_php,no,no,no,no,yes,no,no,no,no,yes,yes,no,no,yes,?,yes,yes,no,yes,no,yes,no 583 | class_method_control_brace,next/next/same,next/next/same,next/next/same,next/next/same,next/next/same,same/same/same,next/next/next,same/same/same,same/same/same,same/same/same,same/same/same,next/next/next,next/next/same,next/same/same,next/next/next,next/next/same,next/next/same,next/next/same,next/next/same,same/same/same,next/next/same,next/next/next 584 | 585 | ### A.2. 설문 조사 범례 586 | 587 | `indent_type`: 588 | 들여쓰기의 유형. `tab`= "탭 사용", `2`또는 `4`= "공백 개수" 589 | 590 | `line_length_limit_soft`: 591 | "소프트"줄 길이 제한 (문자 수). `?`= 식별 할 수 없거나 응답이 없으면 `아니오`는 제한이 없음을 의미합니다. 592 | 593 | `line_length_limit_hard`: 594 | "하드"줄 길이 제한 (문자 수). `?`= 식별 할 수 없거나 응답이 없으면 `아니오`는 제한이 없음을 의미합니다. 595 | 596 | `class_names`: 597 | 클래스 이름 지정 방법. `lower` = 소문자 만, `lower_under` = 밑줄 구분 기호가있는 소문자, `studly` = StudlyCase. 598 | 599 | `class_brace_line`: 600 | 클래스의 여는 중괄호가 class 키워드와 `같은` 줄에 있거나, 그 `다음` 줄에 있습니까? 601 | 602 | `constant_names`: 603 | 클래스 상수는 어떻게 명명됩니까? `upper` = 밑줄 구분자가있는 대문자. 604 | 605 | `true_false_null`: 606 | `true`, `false` 및 `null` 키워드는 모두 `lower`또는 모두 `upper`로 철자가 맞습니까? 607 | 608 | `method_names`: 609 | 메소드은 어떻게 명명됩니까? `camel` =`camelCase`,`lower_under` = 밑줄 구분 기호가있는 소문자. 610 | 611 | `method_brace_line`: 612 | 메소드의 여는 중괄호가 메소드 이름과 `같은` 줄 또는 `다음` 줄에 있습니까? 613 | 614 | `control_brace_line`: 615 | 제어문의 여는 중괄호가 `같은` 줄 또는 `다음` 줄에 있습니까? 616 | 617 | `control_space_after`: 618 | 제어문 키워드 다음에 공백이 있습니까? 619 | 620 | `always_use_control_braces`: 621 | 제어문은 항상 중괄호를 사용합니까? 622 | 623 | `else_elseif_line`: 624 | `else` 나`elseif`를 사용할 때, 이전 닫는 중괄호와 `같은` 줄로 가야합니까, 아니면 `다음` 줄로 가나 요? 625 | 626 | `case_break_indent_from_switch`: 627 | `switch` 문에서 `case`와 `break`가 몇 번 들여 쓰여졌습니까? 628 | 629 | `function_space_after`: 630 | 함수 호출은 함수 이름 뒤에 여는 괄호 앞에 공백이 있습니까? 631 | 632 | `closing_php_tag_required`: 633 | PHP 만 포함 된 파일에서 닫는 `?>`태그가 필요합니까? 634 | 635 | `line_endings`: 636 | 어떤 유형의 종료 라인이 사용됩니까? 637 | 638 | `static_or_visibility_first`: 639 | 메서드를 선언 할 때 `static`이 먼저 오는가, 아니면 가시성이 먼저 오는가? 640 | 641 | `control_space_parens`: 642 | 제어 구조 표현식에서 여는 괄호 뒤에 공백이 있고 닫는 괄호 앞에 공백이 있습니까? `yes` =`if ( $expr )`,`no` =`if ($expr)`입니다. 643 | 644 | `blank_line_after_php`: 645 | 여는 PHP 태그 뒤에 빈 줄이 있습니까? 646 | 647 | `class_method_control_brace`: 648 | 클래스, 메서드 및 컨트롤 구조에 대해 여는 중괄호가 어떤 줄로 표시되는지 요약합니다. 649 | 650 | ### A.3. 설문조사 결과 651 | 652 | indent_type: 653 | tab: 7 654 | 2: 1 655 | 4: 14 656 | line_length_limit_soft: 657 | ?: 2 658 | no: 3 659 | 75: 4 660 | 80: 6 661 | 85: 1 662 | 100: 1 663 | 120: 4 664 | 150: 1 665 | line_length_limit_hard: 666 | ?: 2 667 | no: 11 668 | 85: 4 669 | 100: 3 670 | 120: 2 671 | class_names: 672 | ?: 1 673 | lower: 1 674 | lower_under: 1 675 | studly: 19 676 | class_brace_line: 677 | next: 16 678 | same: 6 679 | constant_names: 680 | upper: 22 681 | true_false_null: 682 | lower: 19 683 | upper: 3 684 | method_names: 685 | camel: 21 686 | lower_under: 1 687 | method_brace_line: 688 | next: 15 689 | same: 7 690 | control_brace_line: 691 | next: 4 692 | same: 18 693 | control_space_after: 694 | no: 2 695 | yes: 20 696 | always_use_control_braces: 697 | no: 3 698 | yes: 19 699 | else_elseif_line: 700 | next: 6 701 | same: 16 702 | case_break_indent_from_switch: 703 | 0/1: 4 704 | 1/1: 4 705 | 1/2: 14 706 | function_space_after: 707 | no: 22 708 | closing_php_tag_required: 709 | no: 19 710 | yes: 3 711 | line_endings: 712 | ?: 5 713 | LF: 17 714 | static_or_visibility_first: 715 | ?: 5 716 | either: 7 717 | static: 4 718 | visibility: 6 719 | control_space_parens: 720 | ?: 1 721 | no: 19 722 | yes: 2 723 | blank_line_after_php: 724 | ?: 1 725 | no: 13 726 | yes: 8 727 | class_method_control_brace: 728 | next/next/next: 4 729 | next/next/same: 11 730 | next/same/same: 1 731 | same/same/same: 6 732 | -------------------------------------------------------------------------------- /accepted/PSR-12-extended-coding-style-guide.md: -------------------------------------------------------------------------------- 1 | # Extended Coding Style Guide 2 | 3 | 이 문서에서 핵심이 되는 단어는 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", "OPTIONAL" 입니다. 4 | 이것은 [RFC 2119]에 설명 된대로 해석해야 합니다. 5 | 6 | > 역자주: 위의 키워드는 아래의 번역문에 괄호안에 표시하였습니다 7 | 8 | [RFC 2119]: http://tools.ietf.org/html/rfc2119 9 | 10 | ## 개요 11 | 12 | 이 규칙은 코딩 스타일 가이드인 [PSR-2][]를 확장 및 대체하며, 기본 코딩 표준 인 [PSR-1][]을 준수해야합니다. 13 | 14 | [PSR-2][]와 마찬가지로 이 사양의 목적은 다른 작성자의 코드를 읽을 때 이해하기 어려운 것을 줄이는 것입니다. 15 | 이것은 PHP 코드의 형식을 지정하는 방법에 대한 규칙과 기대 사항을 공유하여 열거합니다. 16 | 이 PSR은 코딩 스타일 도구가 구현할 수 있는 설정 방법을 제공하기 위해 노력하고, 프로젝트에서 이 PSR의 준수를 선언함을 통해 개발자는 서로 다른 프로젝트와 쉽게 연동 할 수 있습니다. 17 | 다양한 저자가 여러 프로젝트에서 협업을 할 때, 모든 프로젝트에서 한가지의 가이드라인을 사용하는 것이 도움이 됩니다. 18 | 따라서 이 가이드로 얻는 혜택은 규칙 자체가 아니라 이러한 규칙을 공유하는 것을 통해 얻을 수 있습니다. 19 | 20 | [PSR-2][]는 2012 년에 승인되었으며 그 이후로 PHP에 많은 발전이 있었으므로 코딩 스타일 지침에 영향을 미쳤습니다. 21 | [PSR-2]는 문서 작성 당시 존재했던 PHP 기능은 대부분 포함하고 있지만, 새로운 기능들은 매우 다양하게 해석 될 수 있습니다. 22 | 따라서 이 PSR은 새로운 기능을 사용하여 보다 현대적인 관점에서 PSR-2의 내용을 명확하게 하고 PSR-2에 관한 오류의 개정본을 만듭니다. 23 | 24 | 25 | ### 이전 버전 26 | 27 | 이 문서 전체의 내용 중, 프로젝트에서 사용하는 PHP 버전에 없는 지침은 무시할 수 있습니다 (MAY). 28 | 29 | ### 예제 30 | 31 | 이 예제는 아래의 규칙 중 일부를 간략하게 설명합니다. 32 | 33 | ~~~php 34 | $b) { 54 | $foo->bar($arg1); 55 | } else { 56 | BazClass::bar($arg2, $arg3); 57 | } 58 | } 59 | 60 | final public static function bar() 61 | { 62 | // method body 63 | } 64 | } 65 | ~~~ 66 | 67 | ## 2. 일반 68 | 69 | ### 2.1 기본 코딩 표준 70 | 71 | 코드는 [PSR-1]에 요약 된 모든 규칙을 따라야합니다. 72 | 73 | PSR-1의 '*StudlyCaps*'라는 용어는 *PascalCase*로 해석해야하며(MUST) 첫 단어가 첫 문자를 포함하여 대문자로 표시해야합니다. 74 | 75 | ### 2.2 Files 76 | 77 | 모든 PHP 파일은 Unix LF (linefeed) 줄만 사용해야합니다 (MUST). 78 | 79 | 모든 PHP 파일은 단일 LF로 끝나는 비어 있지 않은 라인으로 끝나야합니다 (MUST). 80 | 81 | PHP code만 존재하는 파일에서는 닫는 `?>`태그를 생략해야합니다 (MUST). 82 | 83 | ### 2.3 Lines 84 | 85 | 라인 길이에 엄격한 제한이 있어서는 안됩니다(MUST NOT). 86 | 87 | 한줄에 들어가는 글자수에 대한 가벼운 제한은 120자여야 합니다. (MUST). 88 | 89 | 한줄은 80자를 넘지 않아야합니다 (SHOULD NOT). 그보다 긴 줄은 각각 80자 이하의 여러 줄으로 나눠야합니다 (SHOULD). 90 | 91 | HEREDOC/NOWDOC 구문을 제외하고 줄의 끝에 공백이 있으면 안됩니다(MUST NOT). 92 | 93 | 명시적으로 금지 된 경우를 제외하고 가독성을 높이고 관련 코드 블록을 표시하기 위해 빈 줄을 추가 할 수 있습니다 (MAY). 94 | 95 | 한 줄에 하나 이상의 문장이 있어서는 안됩니다 (MUST NOT). 96 | 97 | ### 2.4 들여쓰기 98 | 99 | 코드는 4개의 스페이스로 들여쓰기를 사용해야만하며(MUST), 탭을 사용하지 않아야만 합니다 (MUST NOT). 100 | 101 | ### 2.5 Keyword와 Type 102 | 103 | 모든 PHP 예약 키워드와 타입 [[1]][keywords][[2]][types]은 소문자 여야만합니다 (MUST). 104 | 105 | 향후 PHP 버전에 추가되는 모든 새로운 유형과 키워드는 반드시 소문자 여야만합니다 (MUST). 106 | 107 | 반드시 `boolean` 대신 `bool`, `integer` 대신 `int` 등 짧은 형태의 타입 키워드를 사용해야합니다 (MUST). 108 | 109 | ## 3. Declare 선언문, 네임 스페이스 및 Import 선언문 110 | 111 | PHP 파일의 머릿글은 여러 블록으로 구성 될 수 있습니다. 112 | 이미 존재한다면, 아래의 각 블록은 하나의 빈 행으로 분리해야하며 빈 행을 포함해서는 안됩니다 (MUST NOT). 113 | 관련이 없는 블록은 생략 할 수 있지만(MUST) 각 블록은 아래에 나열된 순서여야 합니다. 114 | 115 | 1. ` 역자주: 설명이 어려우니 그냥 아래에 나오는 예제를 참고하세요 130 | 131 | Import 문은 항상 정규화된 형식이어야 하므로 백 슬래시로 시작해서는 안됩니다 (MUST). 132 | 133 | 다음은 모든 블록의 전체 목록의 예제를 보여줍니다. 134 | 135 | ~~~php 136 | 198 | 199 | 200 | 203 | 204 | 205 | ~~~ 206 | 207 | Declare 문은 공백을 포함하지 않아야하며(MUST) `declare(strict_types=1)` (선택 항목 인 세미콜론 종결자 포함)이어야합니다(MUST). 208 | 209 | 블록 선언문은 허용되며 반드시 아래와 같은 형식이여야합니다(MUST). 중괄호와 간격의 위치 참고 : 210 | 211 | ~~~php 212 | declare(ticks=1) { 213 | // some code 214 | } 215 | ~~~ 216 | 217 | ## 4. 클래스, 프로퍼티, 메소드 218 | 219 | "클래스"라는 용어는 모든 클래스, 인터페이스 및 특성-trait을 나타냅니다. 220 | 221 | 닫는 중괄호는 같은 줄의 주석이나 명령문 다음에 와서는 안됩니다(MUST NOT). 222 | 223 | 새 클래스를 인스턴스화 할 때 생성자에 전달 된 인수가 없는 경우에도 항상 괄호가 있어야합니다(MUST). 224 | 225 | > 역자주 : new Foo; 같은걸 하지 말라는 의미 226 | 227 | ~~~php 228 | new Foo(); 229 | ~~~ 230 | 231 | ### 4.1 확장과 구현 232 | 233 | `extends`와 `implements` 키워드는 클래스 이름과 같은 줄에 선언해야합니다 (MUST). 234 | 235 | 해당 클래스의 여는 중괄호는 바로 다음 줄에 있어야만 합니다(MUST). 클래스의 닫는 중괄호는 본문 뒤의 다음 줄로 가야만 합니다(MUST). 236 | 237 | 여는 중괄호는 반드시(MUST) 바로 다음 줄에 있어야하며 중간에 빈 줄이 있어서는 안됩니다. 238 | 239 | 닫는 중괄호는 반드시(MUST) 바로 다음 줄에 있어야하며 빈 줄이 앞에 있어서는 안됩니다(MUST NOT). 240 | 241 | 242 | ~~~php 243 | 역자주: 가시성은 다른 언어에서 접근제어자 등으로 부르는 public, protected, private 를 의미합니다 366 | 367 | 프로젝트의 PHP 최소 버전이 상수의 가시성 (PHP 7.1.0 이상)을 지원하는 경우 모든 상수에 대한 가시성을 반드시(MUST) 선언해야합니다. 368 | 369 | `var` 키워드는 속성-property를 선언하는데 사용해서는 안됩니다 (MUST NOT). 370 | 371 | 선언문마다 하나 이상의 속성-property이 선언해서는 안됩니다(MUST NOT). 372 | 373 | protected나 private 가시성을 나타내기 위해 속성 이름 앞에 하나의 밑줄을 사용해서는 안됩니다 (MUST NOT). 즉, 밑줄 접두사는 명시적인 의미가 없습니다. 374 | 375 | 형식 선언과 속성-property 이름 사이에 공백이 있어야합니다(MUST). 376 | 377 | 속성-property 선언은 다음과 같아야 합니다. 378 | 379 | ~~~php 380 | bar($arg1); 567 | Foo::bar($arg2, $arg3); 568 | ~~~ 569 | 570 | 인수 목록은 여러 줄에 걸쳐 나뉘어 질 수 있으며(MAY), 각 줄은 한 번 들여쓰기를 합니다. 571 | 그렇게 할 때 목록의 첫 번째 항목은 다음 줄에 있어야하며(MUST) 한 줄에 하나의 인수 만 있어야합니다(MUST). 572 | (익명함수나 배열의 경우처럼) 여러 줄로 분할되는 단일 인수는 인수 목록 자체를 분할하는 이것에는 해당하지 않습니다. 573 | 574 | ~~~php 575 | bar( 578 | $longArgument, 579 | $longerArgument, 580 | $muchLongerArgument 581 | ); 582 | ~~~ 583 | 584 | ~~~php 585 | get('/hello/{name}', function ($name) use ($app) { 592 | return 'Hello ' . $app->escape($name); 593 | }); 594 | ~~~ 595 | 596 | ## 5. 제어구조 597 | 598 | 제어 구조의 일반적인 스타일 규칙은 다음과 같습니다. 599 | 600 | - 제어 구조 키워드 다음에 하나의 공백이 있어야합니다(MUST). 601 | - 여는 괄호 뒤에 공백이 있으면 안됩니다(MUST NOT). 602 | - 닫는 괄호 앞에 공백이 없어야 합니다(MUST NOT). 603 | - 닫는 괄호와 여는 중괄호 사이에 하나의 공백이 있어야 합니다(MUST). 604 | - 본문은 한 번 들여쓰기해야합니다(MUST). 605 | - 닫는 중괄호는 몸체 뒤의 다음 줄에 있어야합니다(MUST). 606 | 607 | 각 구조의 본문은 중괄호로 묶어야합니다(MUST). 이것은 구조가 어떻게 보이는지 표준화하고 새로운 라인을 본문에 추가 할 때 오류가 발생할 가능성을 줄입니다. 608 | 609 | ### 5.1 `if`, `elseif`, `else` 610 | 611 | `if` 구조는 다음과 같습니다. 괄호, 공백 및 중괄호의 배치에 유의하십시오. `else`와 `elseif`는 이전 본문의 닫는 중괄호와 같은 줄에 있습니다. 612 | 613 | ~~~php 614 | 역자주: phpstorm과 같은 ide에서 else if로 사용하고 코드 자동정렬을 할 경우 else { if(){} } 같은 형태로 분할 해버리기도 합니다. 이때는 설정을 수정할 수도 있지만 저는 elseif 로 사용하시는 것을 권장합니다 628 | 629 | 괄호 안의 표현은 여러 줄에 걸쳐 나뉘어 질 수 있으며(MAY), 그 다음 줄은 적어도 한 번 들여 쓰일 수 있습니다. 630 | 그렇게 할 때 첫 번째 조건은 반드시(MUST) 다음 줄에 있어야합니다. 631 | 닫는 괄호와 여는 중괄호는 한개 공백과 함께 한 줄에 함께 있어야합니다 (MUST). 632 | 조건 사이의 부울-boolean 연산자는 항상 줄의 시작 또는 끝에 있어야하며 둘 다를 혼합해서는 안됩니다(MUST). 633 | 634 | ~~~php 635 | $value) { 782 | // foreach body 783 | } 784 | ~~~ 785 | 786 | ### 5.6 `try`, `catch`, `finally` 787 | 788 | `try-catch-finally` 블록은 다음과 같이 보입니다. 괄호, 공백 및 중괄호의 배치에 유의하십시오. 789 | 790 | ~~~php 791 | $b) { 838 | $foo = $a + $b * $c; 839 | } elseif ($a <=> $c) { 840 | $foo += $bar % $a & $b ** $c; 841 | } 842 | ~~~ 843 | 844 | ### 6.3. 삼항-Ternary 연산자 845 | 846 | 삼항 연산자라고도하는 조건부 연산자 `?` 및 `:`문자 앞뒤에는 하나 이상의 공백이 와야합니다(MUST). 847 | 848 | ~~~php 849 | $variable = $foo ? 'foo' : 'bar'; 850 | ~~~ 851 | 852 | 조건부 연산자의 중간 피연산자가 생략되면 연산자는 다른 이진 [비교-comparison][] 연산자와 동일한 스타일 규칙을 따라야합니다(MUST). 853 | 854 | ~~~php 855 | $variable = $foo ?: 'bar'; 856 | ~~~ 857 | 858 | ## 7. 클로저-Closures 859 | 860 | 클로저는 `function` 키워드 뒤의 공백과 `use` 키워드 앞뒤에 공백으로 선언해야합니다 (MUST). 861 | 862 | 여는 중괄호는 반드시(MUST) 같은 줄에 있어야하며 닫는 중괄호는 반드시(MUST) 그 다음 줄에 있어야합니다. 863 | 864 | 인수 목록이나 변수 목록의 여는 괄호 다음에 공백이 있으면 안되며(MUST NOT), 인수 목록이나 변수 목록의 닫는 괄호 앞에 공백이 있으면 안됩니다(MUST NOT). 865 | 866 | 인수 목록과 변수 목록에는 각 쉼표 앞에 공백이 있어서는 안되며(MUST NOT) 각 쉼표 뒤에 하나의 공백이 있어야합니다(MUST). 867 | 868 | 기본값을 가진 클로저 인수는 인수 목록의 끝에 와야합니다 (MUST). 869 | 870 | 반환유형(return type)이 있는 경우 일반 함수 및 메소드와 동일한 규칙을 따라야 하며 `use` 키워드가 존재한다면, 콜론은 두 문자 사이에 공백없이 `use` 리스트의 닫는 괄호에 따라와야합니다 (MUST). 871 | 872 | 클로저 선언은 다음과 같습니다. 괄호, 쉼표, 공백 및 중괄호의 배치에 유의하십시오. 873 | 874 | ~~~php 875 | bar( 952 | $arg1, 953 | function ($arg2) use ($var1) { 954 | // body 955 | }, 956 | $arg3 957 | ); 958 | ~~~ 959 | 960 | ## 8. 익명 클래스 961 | 962 | 익명 클래스는 위 섹션의 클로저와 동일한 지침과 원칙을 따라야합니다(MUST). 963 | 964 | ~~~php 965 |