Full Code of php-fig/fig-standards for AI

master df5a2b9b37a4 cached
69 files
577.6 KB
138.8k tokens
1 requests
Download .txt
Showing preview only (603K chars total). Download the full file or copy to clipboard to get everything.
Repository: php-fig/fig-standards
Branch: master
Commit: df5a2b9b37a4
Files: 69
Total size: 577.6 KB

Directory structure:
gitextract_dtncyr6s/

├── CODEOWNERS
├── CONTRIBUTING.md
├── LICENSE-CC.md
├── LICENSE-MIT.md
├── LICENSE.md
├── PER.md
├── PSR.md
├── README.md
├── accepted/
│   ├── PSR-0-meta.md
│   ├── PSR-0.md
│   ├── PSR-1-basic-coding-standard-meta.md
│   ├── PSR-1-basic-coding-standard.md
│   ├── PSR-11-container-meta.md
│   ├── PSR-11-container.md
│   ├── PSR-12-extended-coding-style-guide-meta.md
│   ├── PSR-12-extended-coding-style-guide.md
│   ├── PSR-13-links-meta.md
│   ├── PSR-13-links.md
│   ├── PSR-14-event-dispatcher-meta.md
│   ├── PSR-14-event-dispatcher.md
│   ├── PSR-15-request-handlers-meta.md
│   ├── PSR-15-request-handlers.md
│   ├── PSR-16-simple-cache-meta.md
│   ├── PSR-16-simple-cache.md
│   ├── PSR-17-http-factory-meta.md
│   ├── PSR-17-http-factory.md
│   ├── PSR-18-http-client-meta.md
│   ├── PSR-18-http-client.md
│   ├── PSR-2-coding-style-guide-meta.md
│   ├── PSR-2-coding-style-guide.md
│   ├── PSR-20-clock-meta.md
│   ├── PSR-20-clock.md
│   ├── PSR-3-logger-interface-meta.md
│   ├── PSR-3-logger-interface.md
│   ├── PSR-4-autoloader-examples.md
│   ├── PSR-4-autoloader-meta.md
│   ├── PSR-4-autoloader.md
│   ├── PSR-6-cache-meta.md
│   ├── PSR-6-cache.md
│   ├── PSR-7-http-message-meta.md
│   └── PSR-7-http-message.md
├── bylaws/
│   ├── 001-mission-and-structure.md
│   ├── 002-psr-workflow.md
│   ├── 003-per-workflow.md
│   ├── 004-votes.md
│   ├── 005-elections-and-vacancies.md
│   ├── 006-licensing-policies.md
│   ├── 007-psr-amendments.md
│   ├── 008-psr-evolution.md
│   ├── 009-naming-conventions.md
│   ├── 010-funding.md
│   └── 100-implementation.md
├── personnel.md
└── proposed/
    ├── .placeholder
    ├── internationalization-meta.md
    ├── internationalization.md
    ├── phpdoc-meta.md
    ├── phpdoc-tags-meta.md
    ├── phpdoc-tags.md
    ├── phpdoc.md
    ├── psr-8-hug/
    │   ├── PSR-8-hug-meta.md
    │   └── psr-8-hug.md
    ├── security-disclosure-publication-meta.md
    ├── security-disclosure-publication.md
    ├── security-disclosure-publication.xsd
    ├── security-reporting-process-meta.md
    ├── security-reporting-process.md
    ├── tracing-meta.md
    └── tracing.md

================================================
FILE CONTENTS
================================================

================================================
FILE: CODEOWNERS
================================================
* @php-fig/secretaries
/proposed/security* @php-fig/psr-9-10
/proposed/phpdoc* @php-fig/psr-5
/proposed/clock* @php-fig/psr-20
/proposed/internationalization* @php-fig/psr-21
/proposed/tracing* @php-fig/psr-22


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to the PHP-FIG

Anybody who subscribes to the Google Group, is part of the PHP-FIG. As soon as
you subscribe to the [mailing list](http://groups.google.com/group/php-fig/)
and/or join the [Discord Server](https://discord.gg/php-fig) you are a PHP-FIG
Community Member, who can influence standards, make suggestions, give feedback,
etc. Only PHP-FIG Voting Members can start or participate in votes, but the
discussion and formation stages involve everyone.

See the [PHP-FIG FAQ](https://www.php-fig.org/faqs/) for more information.

# Licensing

By contributing code you agree to license your contribution under the MIT
license.

By contributing documentation, examples, or any other non-code assets you agree
to license your contribution under the CC BY 3.0 license. Attribution shall be
given according to the current bylaws of this group.

# Merge & Access Policy

All Editors, Coordinators and Sponsors of specifications in draft & review stage
have access to push to this (php-fig/fig-standards) repository; subject to
secretary discretion

All Editors, Coordinators and Sponsors of specifications have push access to utility
and interface repositories and retrain this even after acceptance; subject to secretary
discretion.

The master branch of all repositories are protected and therefore cannot be forced
pushed to.

Secretaries have, and are the only ones to have, full administrative access to all
repositories and to the GitHub organisation.

## Guidelines for merging

* Never force push to any branch on a repository in the php-fig organisation
* All changes must go through pull requests, a commit should never be pushed
directly (excluding initial commits on new interface/util repositories) to master
* All pull requests relating to a draft PSR must be approved (with a formal +1
comment) or merged by the PSR Editor, except in the review phase when the coordinator
should seek comment from the editor, but merging is at the coordinator's discretion
* You must never merge a pull request that affects any file in the repository
other than those you are on a working group for; you should request a secretary
or member of that working group (mention @php-fig/psr-x) do so
* You should never merge your own pull request
* A change should never be merged to an accepted PSR without approval from
secretaries, who will attempt to seek confirmation from the former Editors
* A change to bylaws shouldn't be merged by anyone other than a secretary
* Pull requests may be triaged (have labels applied) by anyone with push access,
no matter which PSR they are on the working group for or which PSR it affects; but
they cannot close a pull request or issue affecting other PSRs
* After approval of a specification, all merges to an interface or utility repository
must be approved by a secretary; who is required to give suitable notice and seek
comment from the working group team, but it is not required that they approve
* Tags on utility and interface repositories should be created and PGP signed by
Secretaries, who should publish their PGP public keys and register them on GitHub

These guidelines are subject to exceptions and changes at secretaries discretion.
Should you have any questions please contact the secretaries on info [at] php-fig
[dot] org. Failure to comply with guidelines will result in revokation of merge
access. Merge access is a privilege and not a right.

# Tagging

Tagging on utility and interface repository should be done regularly, ideally after
every merge, or every batch of merges after PSR approval.

Versioning should follow semantic versioning and primarily just be simple patch
fix increments (following semantic versioning). The first 1.0.0 tag should be
created on PSR approval.

All tags should be PGP signed.

A changelog should be provided including a list of changes, crediting the
contributor and referencing the pull request/issue.


================================================
FILE: LICENSE-CC.md
================================================
Creative Commons Legal Code

Attribution 3.0 Unported

    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
    LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
    INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
    REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR
    DAMAGES RESULTING FROM ITS USE.

License

THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.

BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
CONDITIONS.

1. Definitions

 a. "Adaptation" means a work based upon the Work, or upon the Work and
    other pre-existing works, such as a translation, adaptation,
    derivative work, arrangement of music or other alterations of a
    literary or artistic work, or phonogram or performance and includes
    cinematographic adaptations or any other form in which the Work may be
    recast, transformed, or adapted including in any form recognizably
    derived from the original, except that a work that constitutes a
    Collection will not be considered an Adaptation for the purpose of
    this License. For the avoidance of doubt, where the Work is a musical
    work, performance or phonogram, the synchronization of the Work in
    timed-relation with a moving image ("synching") will be considered an
    Adaptation for the purpose of this License.
 b. "Collection" means a collection of literary or artistic works, such as
    encyclopedias and anthologies, or performances, phonograms or
    broadcasts, or other works or subject matter other than works listed
    in Section 1(f) below, which, by reason of the selection and
    arrangement of their contents, constitute intellectual creations, in
    which the Work is included in its entirety in unmodified form along
    with one or more other contributions, each constituting separate and
    independent works in themselves, which together are assembled into a
    collective whole. A work that constitutes a Collection will not be
    considered an Adaptation (as defined above) for the purposes of this
    License.
 c. "Distribute" means to make available to the public the original and
    copies of the Work or Adaptation, as appropriate, through sale or
    other transfer of ownership.
 d. "Licensor" means the individual, individuals, entity or entities that
    offer(s) the Work under the terms of this License.
 e. "Original Author" means, in the case of a literary or artistic work,
    the individual, individuals, entity or entities who created the Work
    or if no individual or entity can be identified, the publisher; and in
    addition (i) in the case of a performance the actors, singers,
    musicians, dancers, and other persons who act, sing, deliver, declaim,
    play in, interpret or otherwise perform literary or artistic works or
    expressions of folklore; (ii) in the case of a phonogram the producer
    being the person or legal entity who first fixes the sounds of a
    performance or other sounds; and, (iii) in the case of broadcasts, the
    organization that transmits the broadcast.
 f. "Work" means the literary and/or artistic work offered under the terms
    of this License including without limitation any production in the
    literary, scientific and artistic domain, whatever may be the mode or
    form of its expression including digital form, such as a book,
    pamphlet and other writing; a lecture, address, sermon or other work
    of the same nature; a dramatic or dramatico-musical work; a
    choreographic work or entertainment in dumb show; a musical
    composition with or without words; a cinematographic work to which are
    assimilated works expressed by a process analogous to cinematography;
    a work of drawing, painting, architecture, sculpture, engraving or
    lithography; a photographic work to which are assimilated works
    expressed by a process analogous to photography; a work of applied
    art; an illustration, map, plan, sketch or three-dimensional work
    relative to geography, topography, architecture or science; a
    performance; a broadcast; a phonogram; a compilation of data to the
    extent it is protected as a copyrightable work; or a work performed by
    a variety or circus performer to the extent it is not otherwise
    considered a literary or artistic work.
 g. "You" means an individual or entity exercising rights under this
    License who has not previously violated the terms of this License with
    respect to the Work, or who has received express permission from the
    Licensor to exercise rights under this License despite a previous
    violation.
 h. "Publicly Perform" means to perform public recitations of the Work and
    to communicate to the public those public recitations, by any means or
    process, including by wire or wireless means or public digital
    performances; to make available to the public Works in such a way that
    members of the public may access these Works from a place and at a
    place individually chosen by them; to perform the Work to the public
    by any means or process and the communication to the public of the
    performances of the Work, including by public digital performance; to
    broadcast and rebroadcast the Work by any means including signs,
    sounds or images.
 i. "Reproduce" means to make copies of the Work by any means including
    without limitation by sound or visual recordings and the right of
    fixation and reproducing fixations of the Work, including storage of a
    protected performance or phonogram in digital form or other electronic
    medium.

2. Fair Dealing Rights. Nothing in this License is intended to reduce,
limit, or restrict any uses free from copyright or rights arising from
limitations or exceptions that are provided for in connection with the
copyright protection under copyright law or other applicable laws.

3. License Grant. Subject to the terms and conditions of this License,
Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
perpetual (for the duration of the applicable copyright) license to
exercise the rights in the Work as stated below:

 a. to Reproduce the Work, to incorporate the Work into one or more
    Collections, and to Reproduce the Work as incorporated in the
    Collections;
 b. to create and Reproduce Adaptations provided that any such Adaptation,
    including any translation in any medium, takes reasonable steps to
    clearly label, demarcate or otherwise identify that changes were made
    to the original Work. For example, a translation could be marked "The
    original work was translated from English to Spanish," or a
    modification could indicate "The original work has been modified.";
 c. to Distribute and Publicly Perform the Work including as incorporated
    in Collections; and,
 d. to Distribute and Publicly Perform Adaptations.
 e. For the avoidance of doubt:

     i. Non-waivable Compulsory License Schemes. In those jurisdictions in
        which the right to collect royalties through any statutory or
        compulsory licensing scheme cannot be waived, the Licensor
        reserves the exclusive right to collect such royalties for any
        exercise by You of the rights granted under this License;
    ii. Waivable Compulsory License Schemes. In those jurisdictions in
        which the right to collect royalties through any statutory or
        compulsory licensing scheme can be waived, the Licensor waives the
        exclusive right to collect such royalties for any exercise by You
        of the rights granted under this License; and,
   iii. Voluntary License Schemes. The Licensor waives the right to
        collect royalties, whether individually or, in the event that the
        Licensor is a member of a collecting society that administers
        voluntary licensing schemes, via that society, from any exercise
        by You of the rights granted under this License.

The above rights may be exercised in all media and formats whether now
known or hereafter devised. The above rights include the right to make
such modifications as are technically necessary to exercise the rights in
other media and formats. Subject to Section 8(f), all rights not expressly
granted by Licensor are hereby reserved.

4. Restrictions. The license granted in Section 3 above is expressly made
subject to and limited by the following restrictions:

 a. You may Distribute or Publicly Perform the Work only under the terms
    of this License. You must include a copy of, or the Uniform Resource
    Identifier (URI) for, this License with every copy of the Work You
    Distribute or Publicly Perform. You may not offer or impose any terms
    on the Work that restrict the terms of this License or the ability of
    the recipient of the Work to exercise the rights granted to that
    recipient under the terms of the License. You may not sublicense the
    Work. You must keep intact all notices that refer to this License and
    to the disclaimer of warranties with every copy of the Work You
    Distribute or Publicly Perform. When You Distribute or Publicly
    Perform the Work, You may not impose any effective technological
    measures on the Work that restrict the ability of a recipient of the
    Work from You to exercise the rights granted to that recipient under
    the terms of the License. This Section 4(a) applies to the Work as
    incorporated in a Collection, but this does not require the Collection
    apart from the Work itself to be made subject to the terms of this
    License. If You create a Collection, upon notice from any Licensor You
    must, to the extent practicable, remove from the Collection any credit
    as required by Section 4(b), as requested. If You create an
    Adaptation, upon notice from any Licensor You must, to the extent
    practicable, remove from the Adaptation any credit as required by
    Section 4(b), as requested.
 b. If You Distribute, or Publicly Perform the Work or any Adaptations or
    Collections, You must, unless a request has been made pursuant to
    Section 4(a), keep intact all copyright notices for the Work and
    provide, reasonable to the medium or means You are utilizing: (i) the
    name of the Original Author (or pseudonym, if applicable) if supplied,
    and/or if the Original Author and/or Licensor designate another party
    or parties (e.g., a sponsor institute, publishing entity, journal) for
    attribution ("Attribution Parties") in Licensor's copyright notice,
    terms of service or by other reasonable means, the name of such party
    or parties; (ii) the title of the Work if supplied; (iii) to the
    extent reasonably practicable, the URI, if any, that Licensor
    specifies to be associated with the Work, unless such URI does not
    refer to the copyright notice or licensing information for the Work;
    and (iv) , consistent with Section 3(b), in the case of an Adaptation,
    a credit identifying the use of the Work in the Adaptation (e.g.,
    "French translation of the Work by Original Author," or "Screenplay
    based on original Work by Original Author"). The credit required by
    this Section 4 (b) may be implemented in any reasonable manner;
    provided, however, that in the case of a Adaptation or Collection, at
    a minimum such credit will appear, if a credit for all contributing
    authors of the Adaptation or Collection appears, then as part of these
    credits and in a manner at least as prominent as the credits for the
    other contributing authors. For the avoidance of doubt, You may only
    use the credit required by this Section for the purpose of attribution
    in the manner set out above and, by exercising Your rights under this
    License, You may not implicitly or explicitly assert or imply any
    connection with, sponsorship or endorsement by the Original Author,
    Licensor and/or Attribution Parties, as appropriate, of You or Your
    use of the Work, without the separate, express prior written
    permission of the Original Author, Licensor and/or Attribution
    Parties.
 c. Except as otherwise agreed in writing by the Licensor or as may be
    otherwise permitted by applicable law, if You Reproduce, Distribute or
    Publicly Perform the Work either by itself or as part of any
    Adaptations or Collections, You must not distort, mutilate, modify or
    take other derogatory action in relation to the Work which would be
    prejudicial to the Original Author's honor or reputation. Licensor
    agrees that in those jurisdictions (e.g. Japan), in which any exercise
    of the right granted in Section 3(b) of this License (the right to
    make Adaptations) would be deemed to be a distortion, mutilation,
    modification or other derogatory action prejudicial to the Original
    Author's honor and reputation, the Licensor will waive or not assert,
    as appropriate, this Section, to the fullest extent permitted by the
    applicable national law, to enable You to reasonably exercise Your
    right under Section 3(b) of this License (right to make Adaptations)
    but not otherwise.

5. Representations, Warranties and Disclaimer

UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION
OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.

6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

7. Termination

 a. This License and the rights granted hereunder will terminate
    automatically upon any breach by You of the terms of this License.
    Individuals or entities who have received Adaptations or Collections
    from You under this License, however, will not have their licenses
    terminated provided such individuals or entities remain in full
    compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
    survive any termination of this License.
 b. Subject to the above terms and conditions, the license granted here is
    perpetual (for the duration of the applicable copyright in the Work).
    Notwithstanding the above, Licensor reserves the right to release the
    Work under different license terms or to stop distributing the Work at
    any time; provided, however that any such election will not serve to
    withdraw this License (or any other license that has been, or is
    required to be, granted under the terms of this License), and this
    License will continue in full force and effect unless terminated as
    stated above.

8. Miscellaneous

 a. Each time You Distribute or Publicly Perform the Work or a Collection,
    the Licensor offers to the recipient a license to the Work on the same
    terms and conditions as the license granted to You under this License.
 b. Each time You Distribute or Publicly Perform an Adaptation, Licensor
    offers to the recipient a license to the original Work on the same
    terms and conditions as the license granted to You under this License.
 c. If any provision of this License is invalid or unenforceable under
    applicable law, it shall not affect the validity or enforceability of
    the remainder of the terms of this License, and without further action
    by the parties to this agreement, such provision shall be reformed to
    the minimum extent necessary to make such provision valid and
    enforceable.
 d. No term or provision of this License shall be deemed waived and no
    breach consented to unless such waiver or consent shall be in writing
    and signed by the party to be charged with such waiver or consent.
 e. This License constitutes the entire agreement between the parties with
    respect to the Work licensed here. There are no understandings,
    agreements or representations with respect to the Work not specified
    here. Licensor shall not be bound by any additional provisions that
    may appear in any communication from You. This License may not be
    modified without the mutual written agreement of the Licensor and You.
 f. The rights granted under, and the subject matter referenced, in this
    License were drafted utilizing the terminology of the Berne Convention
    for the Protection of Literary and Artistic Works (as amended on
    September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
    Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996
    and the Universal Copyright Convention (as revised on July 24, 1971).
    These rights and subject matter take effect in the relevant
    jurisdiction in which the License terms are sought to be enforced
    according to the corresponding provisions of the implementation of
    those treaty provisions in the applicable national law. If the
    standard suite of rights granted under applicable copyright law
    includes additional rights not granted under this License, such
    additional rights are deemed to be included in the License; this
    License is not intended to restrict the license of any rights under
    applicable law.

Creative Commons Notice

    Creative Commons is not a party to this License, and makes no warranty
    whatsoever in connection with the Work. Creative Commons will not be
    liable to You or any party on any legal theory for any damages
    whatsoever, including without limitation any general, special,
    incidental or consequential damages arising in connection to this
    license. Notwithstanding the foregoing two (2) sentences, if Creative
    Commons has expressly identified itself as the Licensor hereunder, it
    shall have all rights and obligations of Licensor.

    Except for the limited purpose of indicating to the public that the
    Work is licensed under the CCPL, Creative Commons does not authorize
    the use by either party of the trademark "Creative Commons" or any
    related trademark or logo of Creative Commons without the prior
    written consent of Creative Commons. Any permitted use will be in
    compliance with Creative Commons' then-current trademark usage
    guidelines, as may be published on its website or otherwise made
    available upon request from time to time. For the avoidance of doubt,
    this trademark restriction does not form part of this License.

    Creative Commons may be contacted at http://creativecommons.org/.


================================================
FILE: LICENSE-MIT.md
================================================
Copyright (c) 2013-2017 PHP Framework Interop Group

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.



================================================
FILE: LICENSE.md
================================================
# License

Unless stated otherwise, all content is licensed under the Creative Commons
Attribution License and code licensed under the MIT License.

Copies of all licenses are included in this project's root directory.

================================================
FILE: PER.md
================================================
# PHP Evolving Recommendations

A PHP Evolving Recommendation is a meta document accompanied by one or more artifacts that are set to evolve over time with multiple releases.
Following the [PER Workflow Bylaw][workflow], when a PER has the first release, it will be listed here.

As also described in the [Mission and Structure Bylaw][structure], the Editor of a working group working on a PER is essentially the lead contributor and writer, and they are supported by at least two voting members; the Sponsor, if present, is a Core Committee member that assists the Editor in keeping the evolution process on track.

| Title                            | Editor         | Sponsor          | Last release(s)                              |
|----------------------------------|----------------|------------------|----------------------------------------------|
| [Coding Style][per-coding-style] | Larry Garfield | Chris Tankersley | [PER Coding Style][per-coding-style-release] |


[workflow]: https://github.com/php-fig/fig-standards/blob/master/bylaws/003-per-workflow.md
[structure]: https://github.com/php-fig/fig-standards/blob/master/bylaws/001-mission-and-structure.md
[per-coding-style]: https://github.com/php-fig/per-coding-style/blob/1.0.0/spec.md
[per-coding-style-release]: https://github.com/php-fig/per-coding-style/releases/latest


================================================
FILE: PSR.md
================================================
# PHP Standard Recommendations

According to the [PSR Workflow Bylaw][workflow] each PSR has a status as it is being worked on. Once a proposal has passed the Entrance Vote it will be listed here as "Draft". Unless a PSR is marked as "Accepted" it is subject to change. Draft can change drastically, but Review will only have minor changes.

As also described in the [PSR Workflow Bylaw][workflow]. The Editor, or editors, of a proposal are essentially the lead contributors and writers of the PSRs and they are supported by two voting members. Those voting members are the Coordinator who is responsible for managing the review stage and votes; and a second sponsor.

## Index by Status

### Accepted

| Num | Title                                | Maintainer                     |
|:---:|--------------------------------------|--------------------------------|
| 1   | [Basic Coding Standard][psr1]        | _vacant_                       |
| 3   | [Logger Interface][psr3]             | Jordi Boggiano                 |
| 4   | [Autoloading Standard][psr4]         | _vacant_                       |
| 6   | [Caching Interface][psr6]            | Larry Garfield                 |
| 7   | [HTTP Message Interface][psr7]       | Matthew Weier O'Phinney        |
| 11  | [Container Interface][psr11]         | Matthieu Napoli, David Négrier |
| 12  | [Extended Coding Style Guide][psr12] | Korvin Szanto                  |
| 13  | [Hypermedia Links][psr13]            | Larry Garfield                 |
| 14  | [Event Dispatcher][psr14]            | Larry Garfield                 |
| 15  | [HTTP Handlers][psr15]               | Woody Gilk                     |
| 16  | [Simple Cache][psr16]                | Paul Dragoonis                 |
| 17  | [HTTP Factories][psr17]              | Woody Gilk                     |
| 18  | [HTTP Client][psr18]                 | Tobias Nyholm                  |
| 20  | [Clock][psr20]                       | Chris Seufert                  |

### Draft

| Num | Title                                | Editor(s)                      | Sponsor                        |
|:---:|--------------------------------------|--------------------------------|--------------------------------|
| 5   | [PHPDoc Standard][psr5]              | Chuck Burgess                  | Michael Cullum                 |
| 19  | [PHPDoc tags][psr19]                 | Chuck Burgess                  | Michael Cullum                 |
| 21  | [Internationalization][psr21]        | Navarr Barnier                 | Larry Garfield                 |
| 22  | [Application Tracing][psr22]         | Adam Allport                   | Alessandro Chitolina           |

### Abandoned

| Num | Title                                | Editor(s)                      |
|:---:|--------------------------------------|--------------------------------|
| 8   | [Huggable Interface][psr8]           | Larry Garfield                 |
| 9   | [Security Advisories][psr9]          | Michael Hess                   |
| 10  | [Security Reporting Process][psr10]  | Michael Hess                   |

### Deprecated

| Num | Title                                |     |
|:---:|--------------------------------------|-----|
| 0   | [Autoloading Standard][psr0]         |     |
| 2   | [Coding Style Guide][psr2]           |     |

## Numerical Index

| Num | Title                                | Editor(s) / Maintainers        | Status     |
|:---:|--------------------------------------|--------------------------------|------------|
| 0   | [Autoloading Standard][psr0]         |                                | Deprecated |
| 1   | [Basic Coding Standard][psr1]        | _vacant_                       | Accepted   |
| 2   | [Coding Style Guide][psr2]           |                                | Deprecated |
| 3   | [Logger Interface][psr3]             | Jordi Boggiano                 | Accepted   |
| 4   | [Autoloading Standard][psr4]         | _vacant_                       | Accepted   |
| 5   | [PHPDoc Standard][psr5]              | Chuck Burgess                  | Draft      |
| 6   | [Caching Interface][psr6]            | Larry Garfield                 | Accepted   |
| 7   | [HTTP Message Interface][psr7]       | Matthew Weier O'Phinney        | Accepted   |
| 8   | [Huggable Interface][psr8]           | Larry Garfield                 | Abandoned  |
| 9   | [Security Advisories][psr9]          | Michael Hess                   | Abandoned  |
| 10  | [Security Reporting Process][psr10]  | Michael Hess                   | Abandoned  |
| 11  | [Container Interface][psr11]         | Matthieu Napoli, David Négrier | Accepted   |
| 12  | [Extended Coding Style Guide][psr12] | Korvin Szanto                  | Accepted   |
| 13  | [Hypermedia Links][psr13]            | Larry Garfield                 | Accepted   |
| 14  | [Event Dispatcher][psr14]            | Larry Garfield                 | Accepted   |
| 15  | [HTTP Handlers][psr15]               | Woody Gilk                     | Accepted   |
| 16  | [Simple Cache][psr16]                | Paul Dragoonis                 | Accepted   |
| 17  | [HTTP Factories][psr17]              | Woody Gilk                     | Accepted   |
| 18  | [HTTP Client][psr18]                 | Tobias Nyholm                  | Accepted   |
| 19  | [PHPDoc tags][psr19]                 | Chuck Burgess                  | Draft      |
| 20  | [Clock][psr20]                       | Chris Seufert                  | Accepted   |
| 21  | [Internationalization][psr21]        | Navarr Barnier                 | Draft      |
| 22  | [Application Tracing][psr22]         | Adam Allport                   | Draft      |

[workflow]: https://github.com/php-fig/fig-standards/blob/master/bylaws/002-psr-workflow.md
[psr0]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
[psr1]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md
[psr2]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md
[psr3]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
[psr4]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-meta.md
[psr5]: https://github.com/php-fig/fig-standards/blob/master/proposed/phpdoc.md
[psr6]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-6-cache.md
[psr7]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-7-http-message.md
[psr8]: https://github.com/php-fig/fig-standards/blob/master/proposed/psr-8-hug/
[psr9]: https://github.com/php-fig/fig-standards/blob/master/proposed/security-disclosure-publication.md
[psr10]: https://github.com/php-fig/fig-standards/blob/master/proposed/security-reporting-process.md
[psr11]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-11-container.md
[psr12]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-12-extended-coding-style-guide.md
[psr13]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-13-links.md
[psr14]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-14-event-dispatcher.md
[psr15]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-15-request-handlers.md
[psr16]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-16-simple-cache.md
[psr17]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-17-http-factory.md
[psr18]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-18-http-client.md
[psr19]: https://github.com/php-fig/fig-standards/blob/master/proposed/phpdoc-tags.md
[psr20]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-20-clock.md
[psr21]: https://github.com/php-fig/fig-standards/blob/master/proposed/internationalization.md
[psr22]: https://github.com/php-fig/fig-standards/blob/master/proposed/tracing.md


================================================
FILE: README.md
================================================
PHP Framework Interoperability Group
====================================

The idea behind the group is for project representatives to talk about the
commonalities between our projects and find ways we can work together. Our main
audience is each other, but we’re very aware that the rest of the PHP community
is watching. If other folks want to adopt what we’re doing they are welcome to
do so, but that is not the aim.

Proposing a Standard Recommendation
------------------------------------

To propose a PHP Standard Recommendation (PSR):

- fork this repo, create a branch, checkout that branch, add the PSR in
  `proposed/`, push the branch to GitHub, and send a pull request; or,

- create a ticket to start a discussion on GitHub; or,

- start a conversation on the [mailing list][].

[mailing list]: http://groups.google.com/group/php-fig/

GitHub usage
------------

All discussion regarding a PSR happens on the [mailing list][]. Issues filed
in GitHub are rarely monitored, and PRs are likely to be missed unless a message
is sent to the mailing list regarding them.  Reviews of a proposed PSR should be
conducted on the mailing list, not through PR comments for the same reason.

Please do not simply file an issue or PR and walk-away.  The most likely outcome
is that it will never get seen or addressed.

Requesting Membership
---------------------

You **do not** need to be a voting member to participate in discussion on
the [mailing list][].

To become a voting member, you must send an email to the [mailing list][].

- The subject line should read: `Membership Request: {$your_name} ({$project_name})`

- The body should include your name, the name of (and link to) the project you
  represent, and other details you feel are relevant.

- Current members will vote on your request.

Do not combine separate membership requests in a single thread; one request
per thread, please.

Language & Translations
-----------------------

All PSRs are written in British English or American English (Different specifications
may vary, but it is consistent within the same specification). The PHP FIG does not
offer official translations into other languages but other external entities are free
to translate the specifications in accordance with the license.

Voting Members
--------------

The current list of voting members is available on the [project website][].

[project website]: https://www.php-fig.org/


================================================
FILE: accepted/PSR-0-meta.md
================================================
# PSR-0 Meta Document

## 1. Summary

PSR-0 predates the official FIG structure and describes a standard for 
autoloader interoperability. It is superseded by PSR-4. This meta document
was added after the PSR has been deprecated. 

## 2. People

### 2.1 Editor

* Matthew Weier O'Phinney



================================================
FILE: accepted/PSR-0.md
================================================
Autoloading Standard
====================

> **Deprecated** - As of 2014-10-21 PSR-0 has been marked as deprecated. [PSR-4] is now recommended
as an alternative.

[PSR-4]: https://www.php-fig.org/psr/psr-4/

The following describes the mandatory requirements that must be adhered
to for autoloader interoperability.

Mandatory
---------

* A fully-qualified namespace and class must have the following
  structure `\<Vendor Name>\(<Namespace>\)*<Class Name>`
* Each namespace must have a top-level namespace ("Vendor Name").
* Each namespace can have as many sub-namespaces as it wishes.
* Each namespace separator is converted to a `DIRECTORY_SEPARATOR` when
  loading from the file system.
* Each `_` character in the CLASS NAME is converted to a
  `DIRECTORY_SEPARATOR`. The `_` character has no special meaning in the
  namespace.
* The fully-qualified namespace and class are suffixed with `.php` when
  loading from the file system.
* Alphabetic characters in vendor names, namespaces, and class names may
  be of any combination of lower case and upper case.

Examples
--------

* `\Doctrine\Common\IsolatedClassLoader` => `/path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php`
* `\Symfony\Core\Request` => `/path/to/project/lib/vendor/Symfony/Core/Request.php`
* `\Zend\Acl` => `/path/to/project/lib/vendor/Zend/Acl.php`
* `\Zend\Mail\Message` => `/path/to/project/lib/vendor/Zend/Mail/Message.php`

Underscores in Namespaces and Class Names
-----------------------------------------

* `\namespace\package\Class_Name` => `/path/to/project/lib/vendor/namespace/package/Class/Name.php`
* `\namespace\package_name\Class_Name` => `/path/to/project/lib/vendor/namespace/package_name/Class/Name.php`

The standards we set here should be the lowest common denominator for
painless autoloader interoperability. You can test that you are
following these standards by utilizing this sample SplClassLoader
implementation which is able to load PHP 5.3 classes.

Example Implementation
----------------------

Below is an example function to simply demonstrate how the above
proposed standards are autoloaded.

```php
<?php

function autoload($className)
{
    $className = ltrim($className, '\\');
    $fileName  = '';
    $namespace = '';
    if ($lastNsPos = strrpos($className, '\\')) {
        $namespace = substr($className, 0, $lastNsPos);
        $className = substr($className, $lastNsPos + 1);
        $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
    }
    $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';

    require $fileName;
}
spl_autoload_register('autoload');
```

SplClassLoader Implementation
-----------------------------

The following gist is a sample SplClassLoader implementation that can
load your classes if you follow the autoloader interoperability
standards proposed above. It is the current recommended way to load PHP
5.3 classes that follow these standards.

* [http://gist.github.com/221634](http://gist.github.com/221634)



================================================
FILE: accepted/PSR-1-basic-coding-standard-meta.md
================================================
# PSR-1 Meta Document

## 1. Summary

This section of the standard comprises what should be considered the standard
coding elements that are required to ensure a high level of technical
interoperability between shared PHP code. This meta document is added after the
document was accepted. 

## 2. People

### 2.1 Editor

* Paul M. Jones



================================================
FILE: accepted/PSR-1-basic-coding-standard.md
================================================
# Basic Coding Standard

This section of the standard comprises what should be considered the standard
coding elements that are required to ensure a high level of technical
interoperability between shared PHP code.

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
interpreted as described in [RFC 2119].

[RFC 2119]: http://www.ietf.org/rfc/rfc2119.txt
[PSR-0]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
[PSR-4]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md

## 1. Overview

- Files MUST use only `<?php` and `<?=` tags.

- Files MUST use only UTF-8 without BOM for PHP code.

- Files SHOULD *either* declare symbols (classes, functions, constants, etc.)
  *or* cause side-effects (e.g. generate output, change .ini settings, etc.)
  but SHOULD NOT do both.

- Namespaces and classes MUST follow an "autoloading" PSR: [[PSR-0], [PSR-4]].

- Class names MUST be declared in `StudlyCaps`.

- Class constants MUST be declared in all upper case with underscore separators.

- Method names MUST be declared in `camelCase`.

## 2. Files

### 2.1. PHP Tags

PHP code MUST use the long `<?php ?>` tags or the short-echo `<?= ?>` tags; it
MUST NOT use the other tag variations.

### 2.2. Character Encoding

PHP code MUST use only UTF-8 without BOM.

### 2.3. Side Effects

A file SHOULD declare new symbols (classes, functions, constants,
etc.) and cause no other side effects, or it SHOULD execute logic with side
effects, but SHOULD NOT do both.

The phrase "side effects" means execution of logic not directly related to
declaring classes, functions, constants, etc., *merely from including the
file*.

"Side effects" include but are not limited to: generating output, explicit
use of `require` or `include`, connecting to external services, modifying ini
settings, emitting errors or exceptions, modifying global or static variables,
reading from or writing to a file, and so on.

The following is an example of a file with both declarations and side effects;
i.e, an example of what to avoid:

```php
<?php
// side effect: change ini settings
ini_set('error_reporting', E_ALL);

// side effect: loads a file
include "file.php";

// side effect: generates output
echo "<html>\n";

// declaration
function foo()
{
    // function body
}
```

The following example is of a file that contains declarations without side
effects; i.e., an example of what to emulate:

```php
<?php
// declaration
function foo()
{
    // function body
}

// conditional declaration is *not* a side effect
if (! function_exists('bar')) {
    function bar()
    {
        // function body
    }
}
```

## 3. Namespace and Class Names

Namespaces and classes MUST follow an "autoloading" PSR: [[PSR-0], [PSR-4]].

This means each class is in a file by itself, and is in a namespace of at
least one level: a top-level vendor name.

Class names MUST be declared in `StudlyCaps`.

Code written for PHP 5.3 and after MUST use formal namespaces.

For example:

```php
<?php
// PHP 5.3 and later:
namespace Vendor\Model;

class Foo
{
}
```

Code written for 5.2.x and before SHOULD use the pseudo-namespacing convention
of `Vendor_` prefixes on class names.

```php
<?php
// PHP 5.2.x and earlier:
class Vendor_Model_Foo
{
}
```

## 4. Class Constants, Properties, and Methods

The term "class" refers to all classes, interfaces, and traits.

### 4.1. Constants

Class constants MUST be declared in all upper case with underscore separators.
For example:

```php
<?php
namespace Vendor\Model;

class Foo
{
    const VERSION = '1.0';
    const DATE_APPROVED = '2012-06-01';
}
```

### 4.2. Properties

This guide intentionally avoids any recommendation regarding the use of
`$StudlyCaps`, `$camelCase`, or `$under_score` property names.

Whatever naming convention is used SHOULD be applied consistently within a
reasonable scope. That scope may be vendor-level, package-level, class-level,
or method-level.

### 4.3. Methods

Method names MUST be declared in `camelCase()`.


================================================
FILE: accepted/PSR-11-container-meta.md
================================================
# Container Meta Document

## 1. Introduction

This document describes the process and discussions that led to the Container PSR.
Its goal is to explain the reasons behind each decision.

## 2. Why bother?

There are dozens of dependency injection containers out there, and these
DI containers have very different ways to store entries.

- Some are based on callbacks (Pimple, Laravel, ...)
- Others are based on configuration (Symfony, ZF, ...), with various formats
  (PHP arrays, YAML files, XML files...)
- Some can leverage factories...
- Some have a PHP API to build entries (PHP-DI, ZF, Symfony, Mouf...)
- Some can do auto-wiring (Laravel, PHP-DI, ...)
- Others can wire entries based on annotations (PHP-DI, JMS Bundle...)
- Some have a graphical user interface (Mouf...)
- Some can compile configuration files to PHP classes (Symfony, ZF...)
- Some can do aliasing...
- Some can use proxies to provide lazy loading of dependencies...

So when you look at the big picture, there is a very large number of ways in
which the DI problem can be tackled, and therefore a big number of different
implementations. However, all the DI containers out there are answering the
same need: they offer a way for the application to retrieve a set of
configured objects (usually services).

By standardizing the way entries are fetched from a container, frameworks and
libraries using the Container PSR could work with any compatible container.
That would allow end users to choose their own container based on their own preferences.

## 3. Scope
### 3.1. Goals

The goal set by the Container PSR is to standardize how frameworks and libraries make use of a
container to obtain objects and parameters.

It is important to distinguish the two usages of a container:

- configuring entries
- fetching entries

Most of the time, those two sides are not used by the same party.
While it is often end users who tend to configure entries, it is generally the framework that fetches
entries to build the application.

This is why this interface focuses only on how entries can be fetched from a container.

### 3.2. Non-goals

How entries are set in the container and how they are configured is out of the
scope of this PSR. This is what makes a container implementation unique. Some
containers have no configuration at all (they rely on autowiring), others rely
on PHP code defined via callback, others on configuration files... This standard
only focuses on how entries are fetched.

Also, naming conventions used for entries are not part of the scope of this
PSR. Indeed, when you look at naming conventions, there are 2 strategies:

- the identifier is the class name, or an interface name (used mostly
  by frameworks with an autowiring capability)
- the identifier is a common name (closer to a variable name), which is
  mostly used by frameworks relying on configuration.

Both strategies have their strengths and weaknesses. The goal of this PSR
is not to choose one convention over the other. Instead, the user can simply
use aliasing to bridge the gap between 2 containers with different naming strategies.

## 4. Recommended usage: Container PSR and the Service Locator

The PSR states that:

> "users SHOULD NOT pass a container into an object, so the object
> can retrieve *its own dependencies*. Users doing so are using the container as a Service Locator.
> Service Locator usage is generally discouraged."

```php
// This is not OK, you are using the container as a service locator
class BadExample
{
    public function __construct(ContainerInterface $container)
    {
        $this->db = $container->get('db');
    }
}

// Instead, please consider injecting directly the dependencies
class GoodExample
{
    public function __construct($db)
    {
        $this->db = $db;
    }
}
// You can then use the container to inject the $db object into your $goodExample object.
```

In the `BadExample` you should not inject the container because:

- it makes the code **less interoperable**: by injecting the container, you have
  to use a container compatible with the Container PSR. With the other
  option, your code can work with ANY container.
- you are forcing the developer into naming its entry "db". This naming could
  conflict with another package that has the same expectations for another service.
- it is harder to test.
- it is not directly clear from your code that the `BadExample` class will need
  the "db" service. Dependencies are hidden.

Very often, the `ContainerInterface` will be used by other packages. As a end-user
PHP developer using a framework, it is unlikely you will ever need to use containers
or type-hint on the `ContainerInterface` directly.

Whether using the Container PSR into your code is considered a good practice or not boils down to
knowing if the objects you are retrieving are **dependencies** of the object referencing
the container or not. Here are a few more examples:

```php
class RouterExample
{
    // ...

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    public function getRoute($request)
    {
        $controllerName = $this->getContainerEntry($request->getUrl());
        // This is OK, the router is finding the matching controller entry, the controller is
        // not a dependency of the router
        $controller = $this->container->get($controllerName);
        // ...
    }
}
```

In this example, the router is transforming the URL into a controller entry name,
then fetches the controller from the container. A controller is not really a
dependency of the router. As a rule of thumb, if your object is *computing*
the entry name among a list of entries that can vary, your use case is certainly legitimate.

As an exception, factory objects whose only purpose is to create and return new instances may use
the service locator pattern. The factory must then implement an interface so that it can itself
be replaced by another factory using the same interface.

```php
// ok: a factory interface + implementation to create an object
interface FactoryInterface
{
    public function newInstance();
}

class ExampleFactory implements FactoryInterface
{
    protected $container;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    public function newInstance()
    {
        return new Example($this->container->get('db'));
    }
}
```

## 5. History

Before submitting the Container PSR to the PHP-FIG, the `ContainerInterface` was
first proposed in a project named [container-interop](https://github.com/container-interop/container-interop/).
The goal of the project was to provide a test-bed for implementing the `ContainerInterface`,
and to pave the way for the Container PSR.

In the rest of this meta document, you will see frequent references to
`container-interop.`

## 6. Interface name

The interface name is the same as the one discussed for `container-interop`
(only the namespace is changed to match the other PSRs).
It has been thoroughly discussed on `container-interop` [[4]](#link_naming_discussion) and was decided by a vote [[5]](#link_naming_vote).

The list of options considered with their respective votes are:

- `ContainerInterface`: +8
- `ProviderInterface`: +2
- `LocatorInterface`: 0
- `ReadableContainerInterface`: -5
- `ServiceLocatorInterface`: -6
- `ObjectFactory`: -6
- `ObjectStore`: -8
- `ConsumerInterface`: -9

## 7. Interface methods

The choice of which methods the interface would contain was made after a statistical analysis of existing containers. [[6]](#link_statistical_analysis).

The summary of the analysis showed that:

- all containers offer a method to get an entry by its id
- a large majority name such method `get()`
- for all containers, the `get()` method has 1 mandatory parameter of type string
- some containers have an optional additional argument for `get()`, but it doesn't have the same purpose between containers
- a large majority of the containers offer a method to test if it can return an entry by its id
- a majority name such method `has()`
- for all containers offering `has()`, the method has exactly 1 parameter of type string
- a large majority of the containers throw an exception rather than returning null when an entry is not found in `get()`
- a large majority of the containers don't implement `ArrayAccess`

The question of whether to include methods to define entries has been discussed at the very start of the container-interop project [[4]](#link_naming_discussion).
It has been judged that such methods do not belong in the interface described here because it is out of its scope
(see the "Goal" section).

As a result, the `ContainerInterface` contains two methods:

- `get()`, returning anything, with one mandatory string parameter. Should throw an exception if the entry is not found.
- `has()`, returning a boolean, with one mandatory string parameter.

### 7.1. Number of parameters in `get()` method

While `ContainerInterface` only defines one mandatory parameter in `get()`, it is not incompatible with
existing containers that have additional optional parameters. PHP allows an implementation to offer more parameters
as long as they are optional, because the implementation *does* satisfy the interface.

Difference with container-interop: [The container-interop spec](https://github.com/container-interop/container-interop/blob/master/docs/ContainerInterface.md) stated that:

> While `ContainerInterface` only defines one mandatory parameter in `get()`, implementations MAY accept additional optional parameters.

This sentence was removed from PSR-11 because:

- It is something that stems from OO principles in PHP, so this is not directly related to PSR-11
- We do not want to encourage implementors to add additional parameters as we recommend coding against the interface and not the implementation

However, some implementations have extra optional parameters; that's technically legal. Such implementations are compatible with PSR-11. [[11]](#link_get_optional_parameters)

### 7.2. Type of the `$id` parameter

The type of the `$id` parameter in `get()` and `has()` has been discussed in the container-interop project.

While `string` is used in all the containers that were analyzed, it was suggested that allowing
anything (such as objects) could allow containers to offer a more advanced query API.

An example given was to use the container as an object builder. The `$id` parameter would then be an
object that would describe how to create an instance.

The conclusion of the discussion [[7]](#link_method_and_parameters_details) was that this was beyond the scope of getting entries from a container without
knowing how the container provided them, and it was more fit for a factory.

### 7.3. Exceptions thrown

This PSR provides 2 interfaces meant to be implemented by container exceptions.

#### 7.3.1 Base exception

The `Psr\Container\ContainerExceptionInterface` is the base interface. It SHOULD be implemented by custom exceptions thrown directly by the container.

It is expected that any exception that is part of the domain of the container implements the `ContainerExceptionInterface`. A few examples:

- if a container relies on a configuration file and if that configuration file is flawed, the container might throw an `InvalidFileException` implementing the `ContainerExceptionInterface`.
- if a cyclic dependency is detected between dependencies, the container might throw an `CyclicDependencyException` implementing the `ContainerExceptionInterface`.

However, if the exception is thrown by some code out of the container's scope (for instance an exception thrown while instantiating an entry), the container is not required to wrap this exception in a custom exception implementing the `ContainerExceptionInterface`.

The usefulness of the base exception interface was questioned: it is not an exception one would typically catch [[8]](#link_base_exception_usefulness).

However, most PHP-FIG members considered it to be a best practice. Base exception interface are implemented in previous PSRs and several member projects. The base exception interface was therefore kept.

#### 7.3.2 Not found exception

A call to the `get` method with a non-existing id must throw an exception implementing the `Psr\Container\NotFoundExceptionInterface`.

For a given identifier:

- if the `has` method returns `false`, then the `get` method MUST throw a `Psr\Container\NotFoundExceptionInterface`.
- if the `has` method returns `true`, this does not mean that the `get` method will succeed and throw no exception. It can even throw a `Psr\Container\NotFoundExceptionInterface` if one of the dependencies of the requested entry is missing.

Therefore, when a user catches the `Psr\Container\NotFoundExceptionInterface`, it has 2 possible meanings [[9]](#link_not_found_behaviour):

- the requested entry does not exist (bad request)
- or a dependency of the requested entry does not exist (i.e. the container is misconfigured)

The user can however easily make a distinction with a call to `has`.

In pseudo-code:

```php
if (!$container->has($id)) {
    // The requested instance does not exist
    return;
}
try {
    $entry = $container->get($id);
} catch (NotFoundExceptionInterface $e) {
    // Since the requested entry DOES exist, a NotFoundExceptionInterface means that the container is misconfigured and a dependency is missing.
}
```

## 8. Implementations

At the time of writing, the following projects already implement and/or consume the `container-interop` version of the interface.

### Implementors
- [Acclimate](https://github.com/jeremeamia/acclimate-container)
- [Aura.DI](https://github.com/auraphp/Aura.Di)
- [dcp-di](https://github.com/estelsmith/dcp-di)
- [League Container](https://github.com/thephpleague/container)
- [Mouf](http://mouf-php.com)
- [Njasm Container](https://github.com/njasm/container)
- [PHP-DI](http://php-di.org)
- [PimpleInterop](https://github.com/moufmouf/pimple-interop)
- [XStatic](https://github.com/jeremeamia/xstatic)
- [Zend ServiceManager](https://github.com/zendframework/zend-servicemanager)

### Middleware
- [Alias-Container](https://github.com/thecodingmachine/alias-container)
- [Prefixer-Container](https://github.com/thecodingmachine/prefixer-container)

### Consumers
- [Behat](https://github.com/Behat/Behat)
- [interop.silex.di](https://github.com/thecodingmachine/interop.silex.di)
- [mindplay/middleman](https://github.com/mindplay-dk/middleman)
- [PHP-DI Invoker](https://github.com/PHP-DI/Invoker)
- [Prophiler](https://github.com/fabfuel/prophiler)
- [Silly](https://github.com/mnapoli/silly)
- [Slim](https://github.com/slimphp/Slim)
- [Splash](http://mouf-php.com/packages/mouf/mvc.splash-common/version/8.0-dev/README.md)
- [Zend Expressive](https://github.com/zendframework/zend-expressive)

This list is not comprehensive and should be only taken as an example showing that there is considerable interest in the PSR.

## 9. People

### 9.1 Editors

* [Matthieu Napoli](https://github.com/mnapoli)
* [David Négrier](https://github.com/moufmouf)

### 9.2 Sponsors

* [Matthew Weier O'Phinney](https://github.com/weierophinney) (Coordinator)
* [Korvin Szanto](https://github.com/KorvinSzanto)

### 9.3 Contributors

Are listed here all people that contributed in the discussions or votes (on container-interop and during migration to PSR-11), by alphabetical order:

* [Alexandru Pătrănescu](https://github.com/drealecs)
* [Amy Stephen](https://github.com/AmyStephen)
* [Ben Peachey](https://github.com/potherca)
* [David Négrier](https://github.com/moufmouf)
* [Don Gilbert](https://github.com/dongilbert)
* [Jason Judge](https://github.com/judgej)
* [Jeremy Lindblom](https://github.com/jeremeamia)
* [Larry Garfield](https://github.com/crell)
* [Marco Pivetta](https://github.com/Ocramius)
* [Matthieu Napoli](https://github.com/mnapoli)
* [Nelson J Morais](https://github.com/njasm)
* [Paul M. Jones](https://github.com/pmjones)
* [Phil Sturgeon](https://github.com/philsturgeon)
* [Stephan Hochdörfer](https://github.com/shochdoerfer)
* [Taylor Otwell](https://github.com/taylorotwell)

## 10. Relevant links

1. [Discussion about the container PSR and the service locator](https://groups.google.com/forum/#!topic/php-fig/pyTXRvLGpsw)
1. [Container-interop's `ContainerInterface.php`](https://github.com/container-interop/container-interop/blob/master/src/Interop/Container/ContainerInterface.php)
1. [List of all issues](https://github.com/container-interop/container-interop/issues?labels=ContainerInterface&milestone=&page=1&state=closed)
1. <a name="link_naming_discussion"></a>[Discussion about the interface name and container-interop scope](https://github.com/container-interop/container-interop/issues/1)
1. <a name="link_naming_vote"></a>[Vote for the interface name](https://github.com/container-interop/container-interop/wiki/%231-interface-name:-Vote)
1. <a name="link_statistical_analysis"></a>[Statistical analysis of existing containers method names](https://gist.github.com/mnapoli/6159681)
1. <a name="link_method_and_parameters_details"></a>[Discussion about the method names and parameters](https://github.com/container-interop/container-interop/issues/6)
1. <a name="link_base_exception_usefulness"></a>[Discussion about the usefulness of the base exception](https://groups.google.com/forum/#!topic/php-fig/_vdn5nLuPBI)
1. <a name="link_not_found_behaviour"></a>[Discussion about the `NotFoundExceptionInterface`](https://groups.google.com/forum/#!topic/php-fig/I1a2Xzv9wN8)
1. <a name="link_get_optional_parameters"></a>Discussion about get optional parameters [in container-interop](https://github.com/container-interop/container-interop/issues/6) and on the [PHP-FIG mailing list](https://groups.google.com/forum/#!topic/php-fig/zY6FAG4-oz8)

## 11. Errata

## Type additions

The 1.1 release of the `psr/container` package includes scalar parameter types. The
2.0 release of the package includes return types. This structure leverages PHP
7.2 covariance support to allow for a gradual upgrade process.

Implementers MAY add return types to their own packages at their discretion,
provided that:

- the return types match those in the 2.0 package.
- the implementation specifies a minimum PHP version of 7.2.0 or later.

Implementers MAY add parameter types to their own packages in a new major
release, either at the same time as adding return types or in a subsequent
release, provided that:

- the parameter types match those in the 1.1 package.
- the implementation specifies a minimum PHP version of 7.2.0.
- the implementation depends on `"psr/container": "^1.1 || ^2.0"` so as to exclude
  the untyped 1.0 version.

Implementers are encouraged but not required to transition their packages toward
the 2.0 version of the package at their earliest convenience.


================================================
FILE: accepted/PSR-11-container.md
================================================
# Container interface

This document describes a common interface for dependency injection containers.

The goal set by `ContainerInterface` is to standardize how frameworks and libraries make use of a
container to obtain objects and parameters (called *entries* in the rest of this document).

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
interpreted as described in [RFC 2119][].

The word `implementor` in this document is to be interpreted as someone
implementing the `ContainerInterface` in a dependency injection-related library or framework.
Users of dependency injection containers (DIC) are referred to as `user`.

[RFC 2119]: http://tools.ietf.org/html/rfc2119

## 1. Specification

### 1.1 Basics

#### 1.1.1 Entry identifiers

An entry identifier is any PHP-legal string of at least one character that uniquely identifies an item within a container.  An entry identifier is an opaque string, so callers SHOULD NOT assume that the structure of the string carries any semantic meaning.

#### 1.1.2 Reading from a container

- The `Psr\Container\ContainerInterface` exposes two methods: `get` and `has`.

- `get` takes one mandatory parameter: an entry identifier, which MUST be a string.
  `get` can return anything (a *mixed* value), or throw a `NotFoundExceptionInterface` if the identifier
  is not known to the container. Two successive calls to `get` with the same
  identifier SHOULD return the same value. However, depending on the `implementor`
  design and/or `user` configuration, different values might be returned, so
  `user` SHOULD NOT rely on getting the same value on 2 successive calls.

- `has` takes one unique parameter: an entry identifier, which MUST be a string.
  `has` MUST return `true` if an entry identifier is known to the container and `false` if it is not.
  If `has($id)` returns false, `get($id)` MUST throw a `NotFoundExceptionInterface`.

### 1.2 Exceptions

Exceptions directly thrown by the container SHOULD implement the
[`Psr\Container\ContainerExceptionInterface`](#container-exception).

A call to the `get` method with a non-existing id MUST throw a
[`Psr\Container\NotFoundExceptionInterface`](#not-found-exception).

### 1.3 Recommended usage

Users SHOULD NOT pass a container into an object so that the object can retrieve *its own dependencies*.
This means the container is used as a [Service Locator](https://en.wikipedia.org/wiki/Service_locator_pattern)
which is a pattern that is generally discouraged.

Please refer to section 4 of the META document for more details.

## 2. Package

The interfaces and classes described as well as relevant exceptions are provided as part of the
[psr/container](https://packagist.org/packages/psr/container) package.

Packages providing a PSR container implementation should declare that they provide `psr/container-implementation` `1.0.0`.

Projects requiring an implementation should require `psr/container-implementation` `1.0.0`.

## 3. Interfaces

<a name="container-interface"></a>
### 3.1. `Psr\Container\ContainerInterface`

```php
<?php
namespace Psr\Container;

/**
 * Describes the interface of a container that exposes methods to read its entries.
 */
interface ContainerInterface
{
    /**
     * Finds an entry of the container by its identifier and returns it.
     *
     * @param string $id Identifier of the entry to look for.
     *
     * @throws NotFoundExceptionInterface  No entry was found for **this** identifier.
     * @throws ContainerExceptionInterface Error while retrieving the entry.
     *
     * @return mixed Entry.
     */
    public function get($id);

    /**
     * Returns true if the container can return an entry for the given identifier.
     * Returns false otherwise.
     *
     * `has($id)` returning true does not mean that `get($id)` will not throw an exception.
     * It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`.
     *
     * @param string $id Identifier of the entry to look for.
     *
     * @return bool
     */
    public function has($id);
}
```


Since [psr/container version 1.1](https://packagist.org/packages/psr/container#1.1.0),
the above interface has been updated to add argument type hints.

Since [psr/container version 2.0](https://packagist.org/packages/psr/container#2.0.0),
the above interface has been updated to add return type hints (but only to the
`has()` method).

<a name="container-exception"></a>
### 3.2. `Psr\Container\ContainerExceptionInterface`

```php
<?php
namespace Psr\Container;

/**
 * Base interface representing a generic exception in a container.
 */
interface ContainerExceptionInterface
{
}
```

<a name="not-found-exception"></a>
### 3.3. `Psr\Container\NotFoundExceptionInterface`

```php
<?php
namespace Psr\Container;

/**
 * No entry was found in the container.
 */
interface NotFoundExceptionInterface extends ContainerExceptionInterface
{
}
```


================================================
FILE: accepted/PSR-12-extended-coding-style-guide-meta.md
================================================
Extended Coding Style Guide Meta Document
=========================================

# 1. Summary

This document describes the process and discussions that led to the Extended Coding
Style PSR. Its goal is to explain the reasons behind each decision.

# 2. Why Bother?

PSR-2 was accepted in 2012 and since then a number of changes have been made to PHP,
most notably recent changes for PHP 7, which have implications for coding style
guidelines. Whilst PSR-2 is very comprehensive of PHP functionality that existed at
the time of writing, new functionality is very open to interpretation. PSR-12 seeks
to provide a set way that both coding style tools can implement, projects can declare
adherence to and developers can easily relate on between different projects for these
coding style reducing cognitive friction.

PSR-2 was created based upon the common practices of the PHP-FIG projects at the time
but ultimately this meant it was a compromise of many of the different projects' guidelines.
The repercussions of projects changing their coding guidelines to align with PSR-2 (Almost
all projects do align with PSR-1, even if it is not explicitly stated) were seen to be too
great (losing git history, huge changesets and breaking existing patches/pull requests).

PSR-2 required adopters to reformat large amounts of existing code which stifled adoption.
To help alleviate this issue with PSR-12, we have taken a more prescriptive approach and
defined the standards for new language features as they are released.

However it is for a lack of wanting to be dictatorial that we will aim to apply PSR-2
styling, rationale and stances (Described in Section 4, Approaches) in PSR-12 instead of
establishing new conventions.

# 3. Scope

## 3.1. Goals

This PSR shares the same goals as PSR-2.

> The intent of this guide is to reduce cognitive friction when scanning code from
> different authors. It does so by enumerating a shared set of rules and expectations
> about how to format PHP code.
> When various authors collaborate across multiple projects, it helps to have one set
> of guidelines to be used among all those projects. Thus, the benefit of this guide is
> not in the rules themselves, but in the sharing of those rules.

This PSR is an extension of PSR-2, and therefore also an extension of PSR-1. The basis of
PSR-12 is PSR-2 and therefore a list of differences is provided below to assist with migration
but it should be considered as an independent specification.

This PSR will include coding style guidelines related to new functionality added to PHP
after the publication of PSR-2; this includes PHP 5.5, PHP 5.6 and PHP 7.0. This PSR will
also include clarifications on the text of PSR-2, as described in the PSR-2 Errata.

## 3.2. Non-Goals

It is not the intention of this PSR to add entirely new coding style guidelines. PSR-12 will
also not change anything stipulated in PSR-1 and PSR-2.

# 4. Approaches

The overarching approach is to attempt to apply existing PSR-2 styling and rationale to
new functionality as opposed to establishing new conventions.

## 4.1. Strict Types Declarations

There was a discussion about whether or not strict types should be enforced in the standard
https://github.com/cs-extended/fig-standards/issues/7. All were in agreement we should only
use a MUST or MUST NOT statement and avoid the use of a SHOULD statement and nobody wanted
to say that strict types could not be declared. The discussion was whether it should be
considered a coding style item which should be covered or whether it was out of scope and it
was decided to be out of scope of a coding style guide.

## 4.2. Finally and Return Types Declaration Spacing

Numerous different options were suggested and they can be seen
[here for return type declarations](https://gist.github.com/michaelcullum/c025f3870c9ea1dd2668#file-returntypesspacing-php) or
[here for finally blocks](https://gist.github.com/michaelcullum/c025f3870c9ea1dd2668#file-finallyblocks-php)
and the current implementation was chosen due to consistency with other parts of the PSR-12
specification that came from PSR-2.

## 4.3. Enforcing short form for all type keywords

PHP 7.0 introduced [scalar types declaration](http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration)
which does not support long type aliases. Therefore it makes sense to enforce primary short type forms to be used to
have uniform syntax and prevent possible confusion.

## 4.4. Public Survey

In order to settle things using data, survey was conducted and responses from 142 people
including 17 project representatives were gathered:

### 4.4.1. PHP-FIG Representative Results

| Representative          | Project           | Compound namespaces with a depth of two or more MUST not be used | Header statement grouping and ordering | Declare statements must each be on their own line | Declare statements in PHP files containing markup | Declare statements have no spaces: `declare(strict_types=1);` | Block declare statement formatting | `new` keyword usage, parenthesis required |Return type declaration formatting |Use statement leading slashes disallowed | Block namespace declaration formatting | General operator spacing |Try, Catch, Finally formatting | Anonymous class declaration formatting | Keyword casing, only lower case | Type keywords, short form only |
| --------------          | -------           | ---------------------------------------------------- | ---------------------------------- | ----------------------------------------- | ------------------------------------------- | -------------------------------------------------------- | ------------------------------- | ------------------------------------- |------------------------------- |------------------------------------ | ----------------------------------- | ---------------------- |--------------------------- | ----------------------------------- | --------------------------- | -------------------------- |
| Alexander Makarov       |  Yii framework    | ✓ | ✓ | ✓ | ❌ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Korvin Szanto           | concrete5         | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Leo Feyer               | Contao            | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Larry Garfield          | Drupal            | ✓ | ✓ | ✓ | ✓ | ✓ | ❌ | ✓ | ✓ | ✓ | ❌ | ✓ | ✓ | ❌ | ✓ | ✓ |
| André R.                | eZ                | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Jan Schneider           | Horde             | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Karsten Dambekalns      | Neos and Flow     | ✓ | ✓ | ✓ | ✓ | ❌ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Andres Gutierrez        | Phalcon           | ❌ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Ryan Thompson           | PyroCMS           | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ❌ | ❌ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Matteo Beccati          | Revive Adserver   | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ❌ | ✓ | ✓ | ✓ | ✓ |
| Damian Mooyman          | SilverStripe      | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Brian Retterer          | Stormpath PHP SDK | ✓ | ✓ | ✓ | ❌ | ❌ | ✓ | ❌ | ✓ | ❌ | ✓ | ✓ | ✓ | ✓ | ❌ | ❌ |
| Matthew Weier O'Phinney | Zend Framework    | ❌ | ✓ | ✓ | ❌ | ✓ | ✓ | ✓ | ❌ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Jordi Boggiano          | Composer          | ❌ | ❌ | ❌ | ✓ | ✓ | ✓ | ❌ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Ben Marks               | Magento           | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Chuck Burgess           | PEAR              | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|                         | **Totals**:       |13/3|15/1|15/1|13/3|14/2|15/1|14/2|15/1|14/2|14/2|15/1|16/0|15/1|15/1|15/1|

### 4.4.2. General non-representative voters

| Question | For | Against | Percentage For |
| -------- | --- | ------- | -------------- |
| Compound namespaces required depth | 114 | 12 | 89.47% |
| Header statement grouping and ordering | 113 | 13 | 88.5% |
| Declare statements must each be on their own line | 120 | 6 | 95% |
| Declare statements in PHP files containing markup | 119 | 7 | 94.12% |
| Declare statements have no spaces | 116 | 10 | 91.38% |
| Block declare statement formatting | 118 | 8 | 93.22% |
| `new` keyword usage, parenthesis required | 116 | 10 | 91.38% |
| Return type declaration formatting | 115 | 11 | 90.43% |
| Use statement leading slashes disallowed | 118 | 8 | 93.22% |
| Block namespace declaration formatting | 120 | 6 | 95% |
| General operator spacing | 123 | 3 | 97.56% |
| Try, Catch, Finally formatting | 124 | 2 | 98.39% |
| Anonymous class declaration formatting | 117 | 9 | 92.31% |
| Keyword casing, only lower case | 124 | 2 | 98.39% |
| Type keywords, short form only | 121 | 5 | 95.87% |

## 4.5. Multiline Function Arguments Mixed With Multiline Return

A potential readability issue [was raised on the mailing list](https://groups.google.com/d/msg/php-fig/ULSL4gqK8GY/cgDELuPOCQAJ).
We reviewed options for changes to the specification that could provide better readability and
the floated option was to require a blank line after the opening bracket of a function if the
arguments and the return are both multiline. Instead it was pointed out that this specification
_already_ allows you to decide where you'd like to add blank lines and so we will leave it to
the implementors to decide.

# 5. Changelog from PSR-2

Please note this changelog is not a verbose list of changes from PSR-2 but highlights the most
notable changes. It should be considered a new specification and therefore you should read the
specification for a full understanding of its contents.

## 5.1. New Statements

* Lowercase for all keywords - Section 2.5
* Short form for all type keywords - Section 2.5
* Use statement grouping - Section 3
* Use statement blocks - Section 3
* Declare statement/Strict types declaration usage - Section 3
* Parentheses are always required for class instantiation - Section 4
* Typed properties - Section 4.3
* Return type declarations - Section 4.5
* Variadic and reference argument operators - Section 4.5
* Type hints - Section 4.5
* Add finally block - Section 5.6
* Operators - Section 6
* Unary operators - Section 6.1
* Binary operators - Section 6.2
* Ternary operators - Section 6.3
* Anonymous classes - Section 8

## 5.2. Clarifications and Errata

* Adjust 'methods' to 'methods and functions' in a number of instances - Throughout
* Adjust references to classes and interfaces to also include traits - Throughout
* StudlyCaps meaning clarified as PascalCase - Section 2.1
* The last line should not be blank but contain an EOL character - Section 2.2
* Blank lines may be added for readability except where explicitly forbidden within the PSR - Section 2.3
* PSR-2 errata statement about multi-line arguments - Section 4
* PSR-2 errata statement about extending multiple interfaces - Section 4
* Forbid blank lines before/after closing/opening braces for classes - Section 4

# 6. People

## 6.1.  Editor:
* Korvin Szanto

## 6.2. Sponsor:

* Chris Tankersley

## 6.3. Working Group Members:

* Alessandro Lai
* Alexander Makarov
* Michael Cullum
* Robert Deutz

## 6.4. Special Thanks

* Michael Cullum for drafting the original specification
* Alexandar Makarov for coordinating the draft during PHP-FIG 2.0
* Cees-Jan Kiewiet for moral support

# 7. Votes

* **Entrance Vote:** https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/php-fig/P9atZLOcUBM/_jwkvlYKEAAJ
* **Approval Vote:** https://groups.google.com/forum/#!topic/php-fig/1uaeSMaDGbk

# 8. Relevant Links

_**Note:** Order descending chronologically._

* [Inspiration Mailing List Thread](https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!topic/php-fig/wh9avopSR9k)
* [Initial Mailing List PSR Proposal Thread](https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!topic/php-fig/MkFacLdfGso)


================================================
FILE: accepted/PSR-12-extended-coding-style-guide.md
================================================
# Extended Coding Style Guide

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
interpreted as described in [RFC 2119][].

[RFC 2119]: http://tools.ietf.org/html/rfc2119

## Overview

This specification extends, expands and replaces [PSR-2][], the coding style guide and
requires adherence to [PSR-1][], the basic coding standard.

Like [PSR-2][], the intent of this specification is to reduce cognitive friction when
scanning code from different authors. It does so by enumerating a shared set of rules
and expectations about how to format PHP code. This PSR seeks to provide a set way that
coding style tools can implement, projects can declare adherence to and developers
can easily relate to between different projects. When various authors collaborate
across multiple projects, it helps to have one set of guidelines to be used among
all those projects. Thus, the benefit of this guide is not in the rules themselves
but the sharing of those rules.

[PSR-2][] was accepted in 2012 and since then a number of changes have been made to PHP
which has implications for coding style guidelines. Whilst [PSR-2] is very comprehensive
of PHP functionality that existed at the time of writing, new functionality is very
open to interpretation. This PSR, therefore, seeks to clarify the content of PSR-2 in
a more modern context with new functionality available, and make the errata to PSR-2
binding.

### Previous language versions

Throughout this document, any instructions MAY be ignored if they do not exist in versions
of PHP supported by your project.

### Example

This example encompasses some of the rules below as a quick overview:

```php
<?php

declare(strict_types=1);

namespace Vendor\Package;

use Vendor\Package\{ClassA as A, ClassB, ClassC as C};
use Vendor\Package\SomeNamespace\ClassD as D;

use function Vendor\Package\{functionA, functionB, functionC};

use const Vendor\Package\{ConstantA, ConstantB, ConstantC};

class Foo extends Bar implements FooInterface
{
    public function sampleFunction(int $a, int $b = null): array
    {
        if ($a === $b) {
            bar();
        } elseif ($a > $b) {
            $foo->bar($arg1);
        } else {
            BazClass::bar($arg2, $arg3);
        }
    }

    final public static function bar()
    {
        // method body
    }
}
```

## 2. General

### 2.1 Basic Coding Standard

Code MUST follow all rules outlined in [PSR-1].

The term 'StudlyCaps' in PSR-1 MUST be interpreted as PascalCase where the first letter of
each word is capitalized including the very first letter.

### 2.2 Files

All PHP files MUST use the Unix LF (linefeed) line ending only.

All PHP files MUST end with a non-blank line, terminated with a single LF.

The closing `?>` tag MUST be omitted from files containing only PHP.

### 2.3 Lines

There MUST NOT be a hard limit on line length.

The soft limit on line length MUST be 120 characters.

Lines SHOULD NOT be longer than 80 characters; lines longer than that SHOULD
be split into multiple subsequent lines of no more than 80 characters each.

There MUST NOT be trailing whitespace at the end of lines.

Blank lines MAY be added to improve readability and to indicate related
blocks of code except where explicitly forbidden.

There MUST NOT be more than one statement per line.

### 2.4 Indenting

Code MUST use an indent of 4 spaces for each indent level, and MUST NOT use
tabs for indenting.

### 2.5 Keywords and Types

All PHP reserved keywords and types [[1]][keywords][[2]][types] MUST be in lower case.

Any new types and keywords added to future PHP versions MUST be in lower case.

Short form of type keywords MUST be used i.e. `bool` instead of `boolean`,
`int` instead of `integer` etc.

## 3. Declare Statements, Namespace, and Import Statements

The header of a PHP file may consist of a number of different blocks. If present,
each of the blocks below MUST be separated by a single blank line, and MUST NOT contain
a blank line. Each block MUST be in the order listed below, although blocks that are
not relevant may be omitted.

* Opening `<?php` tag.
* File-level docblock.
* One or more declare statements.
* The namespace declaration of the file.
* One or more class-based `use` import statements.
* One or more function-based `use` import statements.
* One or more constant-based `use` import statements.
* The remainder of the code in the file.

When a file contains a mix of HTML and PHP, any of the above sections may still
be used. If so, they MUST be present at the top of the file, even if the
remainder of the code consists of a closing PHP tag and then a mixture of HTML and
PHP.

When the opening `<?php` tag is on the first line of the file, it MUST be on its
own line with no other statements unless it is a file containing markup outside of PHP
opening and closing tags.

Import statements MUST never begin with a leading backslash as they
must always be fully qualified.

The following example illustrates a complete list of all blocks:

```php
<?php

/**
 * This file contains an example of coding styles.
 */

declare(strict_types=1);

namespace Vendor\Package;

use Vendor\Package\{ClassA as A, ClassB, ClassC as C};
use Vendor\Package\SomeNamespace\ClassD as D;
use Vendor\Package\AnotherNamespace\ClassE as E;

use function Vendor\Package\{functionA, functionB, functionC};
use function Another\Vendor\functionD;

use const Vendor\Package\{CONSTANT_A, CONSTANT_B, CONSTANT_C};
use const Another\Vendor\CONSTANT_D;

/**
 * FooBar is an example class.
 */
class FooBar
{
    // ... additional PHP code ...
}

```

Compound namespaces with a depth of more than two MUST NOT be used. Therefore the
following is the maximum compounding depth allowed:
```php
<?php

use Vendor\Package\SomeNamespace\{
    SubnamespaceOne\ClassA,
    SubnamespaceOne\ClassB,
    SubnamespaceTwo\ClassY,
    ClassZ,
};
```

And the following would not be allowed:

```php
<?php

use Vendor\Package\SomeNamespace\{
    SubnamespaceOne\AnotherNamespace\ClassA,
    SubnamespaceOne\ClassB,
    ClassZ,
};
```

When wishing to declare strict types in files containing markup outside PHP
opening and closing tags, the declaration MUST be on the first line of the file
and include an opening PHP tag, the strict types declaration and closing tag.

For example:
```php
<?php declare(strict_types=1) ?>
<html>
<body>
    <?php
        // ... additional PHP code ...
    ?>
</body>
</html>
```

Declare statements MUST contain no spaces and MUST be exactly `declare(strict_types=1)`
(with an optional semicolon terminator).

Block declare statements are allowed and MUST be formatted as below. Note position of
braces and spacing:
```php
declare(ticks=1) {
    // some code
}
```

## 4. Classes, Properties, and Methods

The term "class" refers to all classes, interfaces, and traits.

Any closing brace MUST NOT be followed by any comment or statement on the
same line.

When instantiating a new class, parentheses MUST always be present even when
there are no arguments passed to the constructor.

```php
new Foo();
```

### 4.1 Extends and Implements

The `extends` and `implements` keywords MUST be declared on the same line as
the class name.

The opening brace for the class MUST go on its own line; the closing brace
for the class MUST go on the next line after the body.

Opening braces MUST be on their own line and MUST NOT be preceded or followed
by a blank line.

Closing braces MUST be on their own line and MUST NOT be preceded by a blank
line.

```php
<?php

namespace Vendor\Package;

use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class ClassName extends ParentClass implements \ArrayAccess, \Countable
{
    // constants, properties, methods
}
```

Lists of `implements` and, in the case of interfaces, `extends` MAY be split
across multiple lines, where each subsequent line is indented once. When doing
so, the first item in the list MUST be on the next line, and there MUST be only
one interface per line.

```php
<?php

namespace Vendor\Package;

use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class ClassName extends ParentClass implements
    \ArrayAccess,
    \Countable,
    \Serializable
{
    // constants, properties, methods
}
```

### 4.2 Using traits

The `use` keyword used inside the classes to implement traits MUST be
declared on the next line after the opening brace.

```php
<?php

namespace Vendor\Package;

use Vendor\Package\FirstTrait;

class ClassName
{
    use FirstTrait;
}
```

Each individual trait that is imported into a class MUST be included
one-per-line and each inclusion MUST have its own `use` import statement.

```php
<?php

namespace Vendor\Package;

use Vendor\Package\FirstTrait;
use Vendor\Package\SecondTrait;
use Vendor\Package\ThirdTrait;

class ClassName
{
    use FirstTrait;
    use SecondTrait;
    use ThirdTrait;
}
```

When the class has nothing after the `use` import statement, the class
closing brace MUST be on the next line after the `use` import statement.

```php
<?php

namespace Vendor\Package;

use Vendor\Package\FirstTrait;

class ClassName
{
    use FirstTrait;
}
```

Otherwise, it MUST have a blank line after the `use` import statement.

```php
<?php

namespace Vendor\Package;

use Vendor\Package\FirstTrait;

class ClassName
{
    use FirstTrait;

    private $property;
}
```

When using the `insteadof` and `as` operators they must be used as follows taking
note of indentation, spacing, and new lines.

```php
<?php

class Talker
{
    use A;
    use B {
        A::smallTalk insteadof B;
    }
    use C {
        B::bigTalk insteadof C;
        C::mediumTalk as FooBar;
    }
}
```

### 4.3 Properties and Constants

Visibility MUST be declared on all properties.

Visibility MUST be declared on all constants if your project PHP minimum
version supports constant visibilities (PHP 7.1 or later).

The `var` keyword MUST NOT be used to declare a property.

There MUST NOT be more than one property declared per statement.

Property names MUST NOT be prefixed with a single underscore to indicate
protected or private visibility. That is, an underscore prefix explicitly has
no meaning.

There MUST be a space between type declaration and property name.

A property declaration looks like the following:

```php
<?php

namespace Vendor\Package;

class ClassName
{
    public $foo = null;
    public static int $bar = 0;
}
```

### 4.4 Methods and Functions

Visibility MUST be declared on all methods.

Method names MUST NOT be prefixed with a single underscore to indicate
protected or private visibility. That is, an underscore prefix explicitly has
no meaning.

Method and function names MUST NOT be declared with space after the method name. The
opening brace MUST go on its own line, and the closing brace MUST go on the
next line following the body. There MUST NOT be a space after the opening
parenthesis, and there MUST NOT be a space before the closing parenthesis.

A method declaration looks like the following. Note the placement of
parentheses, commas, spaces, and braces:

```php
<?php

namespace Vendor\Package;

class ClassName
{
    public function fooBarBaz($arg1, &$arg2, $arg3 = [])
    {
        // method body
    }
}
```

A function declaration looks like the following. Note the placement of
parentheses, commas, spaces, and braces:

```php
<?php

function fooBarBaz($arg1, &$arg2, $arg3 = [])
{
    // function body
}
```

### 4.5 Method and Function Arguments

In the argument list, there MUST NOT be a space before each comma, and there
MUST be one space after each comma.

Method and function arguments with default values MUST go at the end of the argument
list.

```php
<?php

namespace Vendor\Package;

class ClassName
{
    public function foo(int $arg1, &$arg2, $arg3 = [])
    {
        // method body
    }
}
```

Argument lists MAY be split across multiple lines, where each subsequent line
is indented once. When doing so, the first item in the list MUST be on the
next line, and there MUST be only one argument per line.

When the argument list is split across multiple lines, the closing parenthesis
and opening brace MUST be placed together on their own line with one space
between them.

```php
<?php

namespace Vendor\Package;

class ClassName
{
    public function aVeryLongMethodName(
        ClassTypeHint $arg1,
        &$arg2,
        array $arg3 = []
    ) {
        // method body
    }
}
```

When you have a return type declaration present, there MUST be one space after
the colon followed by the type declaration. The colon and declaration MUST be
on the same line as the argument list closing parenthesis with no spaces between
the two characters.

```php
<?php

declare(strict_types=1);

namespace Vendor\Package;

class ReturnTypeVariations
{
    public function functionName(int $arg1, $arg2): string
    {
        return 'foo';
    }

    public function anotherFunction(
        string $foo,
        string $bar,
        int $baz
    ): string {
        return 'foo';
    }
}
```

In nullable type declarations, there MUST NOT be a space between the question mark
and the type.

```php
<?php

declare(strict_types=1);

namespace Vendor\Package;

class ReturnTypeVariations
{
    public function functionName(?string $arg1, ?int &$arg2): ?string
    {
        return 'foo';
    }
}
```

When using the reference operator `&` before an argument, there MUST NOT be
a space after it, like in the previous example.

There MUST NOT be a space between the variadic three dot operator and the argument
name:

```php
public function process(string $algorithm, ...$parts)
{
    // processing
}
```

When combining both the reference operator and the variadic three dot operator,
there MUST NOT be any space between the two of them:

```php
public function process(string $algorithm, &...$parts)
{
    // processing
}
```

### 4.6 `abstract`, `final`, and `static`

When present, the `abstract` and `final` declarations MUST precede the
visibility declaration.

When present, the `static` declaration MUST come after the visibility
declaration.

```php
<?php

namespace Vendor\Package;

abstract class ClassName
{
    protected static $foo;

    abstract protected function zim();

    final public static function bar()
    {
        // method body
    }
}
```

### 4.7 Method and Function Calls

When making a method or function call, there MUST NOT be a space between the
method or function name and the opening parenthesis, there MUST NOT be a space
after the opening parenthesis, and there MUST NOT be a space before the
closing parenthesis. In the argument list, there MUST NOT be a space before
each comma, and there MUST be one space after each comma.

```php
<?php

bar();
$foo->bar($arg1);
Foo::bar($arg2, $arg3);
```

Argument lists MAY be split across multiple lines, where each subsequent line
is indented once. When doing so, the first item in the list MUST be on the
next line, and there MUST be only one argument per line. A single argument being
split across multiple lines (as might be the case with an anonymous function or
array) does not constitute splitting the argument list itself.

```php
<?php

$foo->bar(
    $longArgument,
    $longerArgument,
    $muchLongerArgument
);
```

```php
<?php

somefunction($foo, $bar, [
  // ...
], $baz);

$app->get('/hello/{name}', function ($name) use ($app) {
    return 'Hello ' . $app->escape($name);
});
```

## 5. Control Structures

The general style rules for control structures are as follows:

- There MUST be one space after the control structure keyword
- There MUST NOT be a space after the opening parenthesis
- There MUST NOT be a space before the closing parenthesis
- There MUST be one space between the closing parenthesis and the opening
  brace
- The structure body MUST be indented once
- The body MUST be on the next line after the opening brace
- The closing brace MUST be on the next line after the body

The body of each structure MUST be enclosed by braces. This standardizes how
the structures look and reduces the likelihood of introducing errors as new
lines get added to the body.

### 5.1 `if`, `elseif`, `else`

An `if` structure looks like the following. Note the placement of parentheses,
spaces, and braces; and that `else` and `elseif` are on the same line as the
closing brace from the earlier body.

```php
<?php

if ($expr1) {
    // if body
} elseif ($expr2) {
    // elseif body
} else {
    // else body;
}
```

The keyword `elseif` SHOULD be used instead of `else if` so that all control
keywords look like single words.

Expressions in parentheses MAY be split across multiple lines, where each
subsequent line is indented at least once. When doing so, the first condition
MUST be on the next line. The closing parenthesis and opening brace MUST be
placed together on their own line with one space between them. Boolean
operators between conditions MUST always be at the beginning or at the end of
the line, not a mix of both.

```php
<?php

if (
    $expr1
    && $expr2
) {
    // if body
} elseif (
    $expr3
    && $expr4
) {
    // elseif body
}
```

### 5.2 `switch`, `case`

A `switch` structure looks like the following. Note the placement of
parentheses, spaces, and braces. The `case` statement MUST be indented once
from `switch`, and the `break` keyword (or other terminating keywords) MUST be
indented at the same level as the `case` body. There MUST be a comment such as
`// no break` when fall-through is intentional in a non-empty `case` body.

```php
<?php

switch ($expr) {
    case 0:
        echo 'First case, with a break';
        break;
    case 1:
        echo 'Second case, which falls through';
        // no break
    case 2:
    case 3:
    case 4:
        echo 'Third case, return instead of break';
        return;
    default:
        echo 'Default case';
        break;
}
```

Expressions in parentheses MAY be split across multiple lines, where each
subsequent line is indented at least once. When doing so, the first condition
MUST be on the next line. The closing parenthesis and opening brace MUST be
placed together on their own line with one space between them. Boolean
operators between conditions MUST always be at the beginning or at the end of
the line, not a mix of both.

```php
<?php

switch (
    $expr1
    && $expr2
) {
    // structure body
}
```

### 5.3 `while`, `do while`

A `while` statement looks like the following. Note the placement of
parentheses, spaces, and braces.

```php
<?php

while ($expr) {
    // structure body
}
```

Expressions in parentheses MAY be split across multiple lines, where each
subsequent line is indented at least once. When doing so, the first condition
MUST be on the next line. The closing parenthesis and opening brace MUST be
placed together on their own line with one space between them. Boolean
operators between conditions MUST always be at the beginning or at the end of
the line, not a mix of both.

```php
<?php

while (
    $expr1
    && $expr2
) {
    // structure body
}
```

Similarly, a `do while` statement looks like the following. Note the placement
of parentheses, spaces, and braces.

```php
<?php

do {
    // structure body;
} while ($expr);
```

Expressions in parentheses MAY be split across multiple lines, where each
subsequent line is indented at least once. When doing so, the first condition
MUST be on the next line. Boolean operators between conditions MUST
always be at the beginning or at the end of the line, not a mix of both.

```php
<?php

do {
    // structure body;
} while (
    $expr1
    && $expr2
);
```

### 5.4 `for`

A `for` statement looks like the following. Note the placement of parentheses,
spaces, and braces.

```php
<?php

for ($i = 0; $i < 10; $i++) {
    // for body
}
```

Expressions in parentheses MAY be split across multiple lines, where each
subsequent line is indented at least once. When doing so, the first expression
MUST be on the next line. The closing parenthesis and opening brace MUST be
placed together on their own line with one space between them.

```php
<?php

for (
    $i = 0;
    $i < 10;
    $i++
) {
    // for body
}
```

### 5.5 `foreach`

A `foreach` statement looks like the following. Note the placement of
parentheses, spaces, and braces.

```php
<?php

foreach ($iterable as $key => $value) {
    // foreach body
}
```

### 5.6 `try`, `catch`, `finally`

A `try-catch-finally` block looks like the following. Note the placement of
parentheses, spaces, and braces.

```php
<?php

try {
    // try body
} catch (FirstThrowableType $e) {
    // catch body
} catch (OtherThrowableType | AnotherThrowableType $e) {
    // catch body
} finally {
    // finally body
}
```

## 6. Operators

Style rules for operators are grouped by arity (the number of operands they take).

When space is permitted around an operator, multiple spaces MAY be
used for readability purposes.

All operators not described here are left undefined.

### 6.1. Unary operators

The increment/decrement operators MUST NOT have any space between
the operator and operand.
```php
$i++;
++$j;
```

Type casting operators MUST NOT have any space within the parentheses:
```php
$intValue = (int) $input;
```

### 6.2. Binary operators

All binary [arithmetic][], [comparison][], [assignment][], [bitwise][],
[logical][], [string][], and [type][] operators MUST be preceded and
followed by at least one space:
```php
if ($a === $b) {
    $foo = $bar ?? $a ?? $b;
} elseif ($a > $b) {
    $foo = $a + $b * $c;
}
```

### 6.3. Ternary operators

The conditional operator, also known simply as the ternary operator, MUST be
preceded and followed by at least one space around both the `?`
and `:` characters:
```php
$variable = $foo ? 'foo' : 'bar';
```

When the middle operand of the conditional operator is omitted, the operator
MUST follow the same style rules as other binary [comparison][] operators:
```php
$variable = $foo ?: 'bar';
```

## 7. Closures

Closures MUST be declared with a space after the `function` keyword, and a
space before and after the `use` keyword.

The opening brace MUST go on the same line, and the closing brace MUST go on
the next line following the body.

There MUST NOT be a space after the opening parenthesis of the argument list
or variable list, and there MUST NOT be a space before the closing parenthesis
of the argument list or variable list.

In the argument list and variable list, there MUST NOT be a space before each
comma, and there MUST be one space after each comma.

Closure arguments with default values MUST go at the end of the argument
list.

If a return type is present, it MUST follow the same rules as with normal
functions and methods; if the `use` keyword is present, the colon MUST follow
the `use` list closing parentheses with no spaces between the two characters.

A closure declaration looks like the following. Note the placement of
parentheses, commas, spaces, and braces:

```php
<?php

$closureWithArgs = function ($arg1, $arg2) {
    // body
};

$closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) {
    // body
};

$closureWithArgsVarsAndReturn = function ($arg1, $arg2) use ($var1, $var2): bool {
    // body
};
```

Argument lists and variable lists MAY be split across multiple lines, where
each subsequent line is indented once. When doing so, the first item in the
list MUST be on the next line, and there MUST be only one argument or variable
per line.

When the ending list (whether of arguments or variables) is split across
multiple lines, the closing parenthesis and opening brace MUST be placed
together on their own line with one space between them.

The following are examples of closures with and without argument lists and
variable lists split across multiple lines.

```php
<?php

$longArgs_noVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) {
   // body
};

$noArgs_longVars = function () use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // body
};

$longArgs_longVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // body
};

$longArgs_shortVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use ($var1) {
   // body
};

$shortArgs_longVars = function ($arg) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // body
};
```

Note that the formatting rules also apply when the closure is used directly
in a function or method call as an argument.

```php
<?php

$foo->bar(
    $arg1,
    function ($arg2) use ($var1) {
        // body
    },
    $arg3
);
```

## 8. Anonymous Classes

Anonymous Classes MUST follow the same guidelines and principles as closures
in the above section.

```php
<?php

$instance = new class {};
```

The opening brace MAY be on the same line as the `class` keyword so long as
the list of `implements` interfaces does not wrap. If the list of interfaces
wraps, the brace MUST be placed on the line immediately following the last
interface.

```php
<?php

// Brace on the same line
$instance = new class extends \Foo implements \HandleableInterface {
    // Class content
};

// Brace on the next line
$instance = new class extends \Foo implements
    \ArrayAccess,
    \Countable,
    \Serializable
{
    // Class content
};
```

[PSR-1]: https://www.php-fig.org/psr/psr-1/
[PSR-2]: https://www.php-fig.org/psr/psr-2/
[keywords]: http://php.net/manual/en/reserved.keywords.php
[types]: http://php.net/manual/en/reserved.other-reserved-words.php
[arithmetic]: http://php.net/manual/en/language.operators.arithmetic.php
[assignment]: http://php.net/manual/en/language.operators.assignment.php
[comparison]: http://php.net/manual/en/language.operators.comparison.php
[bitwise]: http://php.net/manual/en/language.operators.bitwise.php
[logical]: http://php.net/manual/en/language.operators.logical.php
[string]: http://php.net/manual/en/language.operators.string.php
[type]: http://php.net/manual/en/language.operators.type.php


================================================
FILE: accepted/PSR-13-links-meta.md
================================================
# Link Definition Meta Document

## 1. Summary

Hypermedia links are becoming an increasingly important part of the web, in both HTML contexts
and various API format contexts. However, there is no single common hypermedia format, nor
is there a common way to represent Links between formats.

This specification aims to provide PHP developers with a simple, common way of representing a
hypermedia link independently of the serialization format that is used. That in turn allows
a system to serialize a response with hypermedia links into one or more wire formats independently
of the process of deciding what those links should be.

## 2. Scope

### 2.1 Goals

* This specification aims to extract and standardize hypermedia link representation between different
formats.

### 2.2 Non-Goals

* This specification does not seek to standardize or favor any particular hypermedia serialization format.

## 3. Design Decisions

### Why no mutator methods?

One of the key targets for this specification is PSR-7 Response objects.  Response objects by design must be
immutable.  Other value-object implementations likely would also require an immutable interface.

Additionally, some Link Provider objects may not be value objects but other objects within a given
domain, which are able to generate Links on the fly, perhaps off of a database result or other underlying
representation.  In those cases a writeable provider definition would be incompatible.

Therefore, this specification splits accessor methods and evolvable methods into separate interfaces,
allowing objects to implement just the read-only or evolvable versions as appropriate to their use case.

### Why is rel on a Link object multi-value?

Different hypermedia standards handle multiple links with the same relationship differently. Some have a single
link that has multiple rel's defined. Others have a single rel entry that then contains multiple links.

Defining each Link uniquely but allowing it to have multiple rels provides a most-compatible-denominator definition.
A single LinkInterface object may be serialized to one or more link entries in a given hypermedia format, as
appropriate.  However, specifying multiple link objects each with a single rel yet the same URI is also legal, and
a hypermedia format can serialize that as appropriate, too.

### Why is a LinkProviderInterface needed?

In many contexts, a set of links will be attached to some other object.  Those objects may be used in situations
where all that is relevant is their links, or some subset of their links. For example, various different value
objects may be defined that represent different REST formats such as HAL, JSON-LD, or Atom.  It may be useful
to extract those links from such an object uniformly for further processing. For instance, next/previous links
may be extracted from an object and added to a PSR-7 Response object as Link headers.  Alternatively, many links
would make sense to represent with a "preload" link relationship, which would indicate to an HTTP 2-compatible
web server that the linked resources should be streamed to a client in anticipation of a subsequent request.

All of those cases are independent of the payload or encoding of the object. By providing a common interface
to access such links, we enable generic handling of the links themselves regardless of the value object or
domain object that is producing them.

## 4. People

### 4.1 Editor(s)

* Larry Garfield

### 4.2 Sponsors

* Matthew Weier O'Phinney (coordinator)
* Marc Alexander

### 4.3 Contributors

* Evert Pot

## 5. Votes

## 6. Relevant links

* [What's in a link?](http://evertpot.com/whats-in-a-link/) by Evert Pot
* [FIG Link Working Group List](https://groups.google.com/forum/#!forum/php-fig-link)

## 7. Errata

### 7.1 Type additions

The 1.1 release of the `psr/link` package includes scalar parameter types.  The 2.0 release of the package includes return types.  This structure leverages PHP 7.2 covariance support to allow for a gradual upgrade process, but requires PHP 8.0 for type compatibility.

Implementers MAY add return types to their own packages at their discretion, provided that:

* the return types match those in the 2.0 package.
* the implementation specifies a minimum PHP version of 8.0.0 or later.

Implementers MAY add parameter types to their own packages in a new major release, either at the same time as adding return types or in a subsequent release, provided that:

* the parameter types match those in the 1.1 package.
* the implementation specifies a minimum PHP version of 8.0.0 or later.
* the implementation depends on `"psr/link": "^1.1 || ^2.0"` so as to exclude the untyped 1.0 version.

Implementers are encouraged but not required to transition their packages toward the 2.0 version of the package at their earliest convenience.

### 7.2 Attribute type handling

The original specification contained an inconsistency regarding array values for attributes.  The text of the specification states in section 1.2 that attribute values (as passed to `EvolvableLinkInterface::withAttribute()`) could be of multiple types, some of which allowed for special handling (such as booleans or arrays).  However, the docblock for that method specified that the `$value` parameter had to be a string, which was incorrect.

To address this issue, the interface has been corrected in later releases to allow `$value` to be of type `string|\Stringable|int|float|bool|array`.  Implementers SHOULD treat a `Stringable` object the same as a `string` parameter.  Implementers MAY serialize `int`, `float`, or `bool` in alternate, type-aware ways for a particular serialization format as appropriate.  Other object types or resources remain disallowed.

Multiple calls to `withAttribute()` with the same `$name` MUST override previously provided values, as the spec already states.  To provide multiple values to a particular attribute, pass an `array` with the desired values.

All other guidelines and requirements in section 1.2 remain valid.


================================================
FILE: accepted/PSR-13-links.md
================================================
# Link definition interfaces

Hypermedia links are becoming an increasingly important part of the web, in both HTML contexts
and various API format contexts. However, there is no single common hypermedia format, nor
is there a common way to represent links between formats.

This specification aims to provide PHP developers with a simple, common way of representing a
hypermedia link independently of the serialization format that is used. That in turn allows
a system to serialize a response with hypermedia links into one or more wire formats independently
of the process of deciding what those links should be.

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
interpreted as described in [RFC 2119](http://tools.ietf.org/html/rfc2119).

### References

- [RFC 2119](http://tools.ietf.org/html/rfc2119)
- [RFC 4287](https://tools.ietf.org/html/rfc4287)
- [RFC 5988](https://tools.ietf.org/html/rfc5988)
- [RFC 6570](https://tools.ietf.org/html/rfc6570)
- [IANA Link Relations Registry](http://www.iana.org/assignments/link-relations/link-relations.xhtml)
- [Microformats Relations List](http://microformats.org/wiki/existing-rel-values#HTML5_link_type_extensions)

## 1. Specification

### 1.1 Basic links

A Hypermedia Link consists of, at minimum:
- A URI representing the target resource being referenced.
- A relationship defining how the target resource relates to the source.

Various other attributes of the Link may exist, depending on the format used. As additional attributes
are not well-standardized or universal, this specification does not seek to standardize them.

For the purposes of this specification, the following definitions apply.

*    **Implementing Object** - An object that implements one of the interfaces defined by this
specification.

*    **Serializer** - A library or other system that takes one or more Link objects and produces
a serialized representation of it in some defined format.

### 1.2 Attributes

All links MAY include zero or more additional attributes beyond the URI and relationship.
There is no formal registry of the values that are allowed here, and validity of values
is dependent on context and often on a particular serialization format. Commonly supported
values include 'hreflang', 'title', and 'type'.

Serializers MAY omit attributes on a link object if required to do so by the serialization
format. However, serializers SHOULD encode all provided attributes possible in order to
allow for user-extension unless prevented by a serialization format's definition.

Some attributes (commonly `hreflang`) may appear more than once in their context. Therefore,
an attribute value MAY be an array of values rather than a simple value. Serializers MAY
encode that array in whatever format is appropriate for the serialized format (such
as a space-separated list, comma-separated list, etc.). If a given attribute is not
allowed to have multiple values in a particular context, serializers MUST use the first
value provided and ignore all subsequent values.

If an attribute value is boolean `true`, serializers MAY use abbreviated forms if appropriate
and supported by a serialization format. For example, HTML permits attributes to
have no value when the attribute's presence has a boolean meaning. This rule applies
if and only if the attribute is boolean `true`, not for any other "truthy" value
in PHP such as integer 1.

If an attribute value is boolean `false`, serializers SHOULD omit the attribute entirely
unless doing so changes the semantic meaning of the result. This rule applies if
and only if the attribute is boolean `false`, not for any other "falsey" value in PHP
such as integer 0.

### 1.3 Relationships

Link relationships are defined as strings, and are either a simple keyword in
case of a publicly defined relationship or an absolute URI in the case of a
private relationships.

In case a simple keyword is used, it SHOULD match one from the IANA registry at:

http://www.iana.org/assignments/link-relations/link-relations.xhtml

Optionally the microformats.org registry MAY be used, but this may not be valid
in every context:

http://microformats.org/wiki/existing-rel-values

A relationship that is not defined in one of the above registries or a similar
public registry is considered "private", that is, specific to a particular
application or use case. Such relationships MUST use an absolute URI.

## 1.4 Link Templates

[RFC 6570](https://tools.ietf.org/html/rfc6570) defines a format for URI templates, that is,
a pattern for a URI that is expected to be filled in with values provided by a client
tool. Some hypermedia formats support templated links while others do not, and may
have a special way to denote that a link is a template. A Serializer for a format
that does not support URI Templates MUST ignore any templated Links it encounters.

## 1.5 Evolvable providers

In some cases, a Link Provider may need the ability to have additional links
added to it. In others, a link provider is necessarily read-only, with links
derived at runtime from some other data source. For that reason, modifiable providers
are a secondary interface that may optionally be implemented.

Additionally, some Link Provider objects, such as PSR-7 Response objects, are
by design immutable. That means methods to add links to them in-place would be
incompatible. Therefore, the `EvolvableLinkProviderInterface`'s single method
requires that a new object be returned, identical to the original but with
an additional Link object included.

## 1.6 Evolvable link objects

Link objects are in most cases value objects. As such, allowing them to evolve
in the same fashion as PSR-7 value objects is a useful option. For that reason,
an additional EvolvableLinkInterface is included that provides methods to
produce new object instances with a single change. The same model is used by PSR-7
and, thanks to PHP's copy-on-write behavior, is still CPU and memory efficient.

There is no evolvable method for templated values, however, as the templated value of a
link is based exclusively on the href value. It MUST NOT be set independently, but
derived from whether or not the href value is an RFC 6570 link template.

## 2. Package

The interfaces and classes described are provided as part of the
[psr/link](https://packagist.org/packages/psr/link) package.

## 3. Interfaces

### 3.1 `Psr\Link\LinkInterface`

```php
<?php

namespace Psr\Link;

/**
 * A readable link object.
 */
interface LinkInterface
{
    /**
     * Returns the target of the link.
     *
     * The target link must be one of:
     * - An absolute URI, as defined by RFC 5988.
     * - A relative URI, as defined by RFC 5988. The base of the relative link
     *     is assumed to be known based on context by the client.
     * - A URI template as defined by RFC 6570.
     *
     * If a URI template is returned, isTemplated() MUST return True.
     *
     * @return string
     */
    public function getHref();

    /**
     * Returns whether or not this is a templated link.
     *
     * @return bool
     *   True if this link object is templated, False otherwise.
     */
    public function isTemplated();

    /**
     * Returns the relationship type(s) of the link.
     *
     * This method returns 0 or more relationship types for a link, expressed
     * as an array of strings.
     *
     * @return string[]
     */
    public function getRels();

    /**
     * Returns a list of attributes that describe the target URI.
     *
     * @return array
     *   A key-value list of attributes, where the key is a string and the value
     *  is either a PHP primitive or an array of PHP strings. If no values are
     *  found an empty array MUST be returned.
     */
    public function getAttributes();
}
```

### 3.2 `Psr\Link\EvolvableLinkInterface`

```php
<?php

namespace Psr\Link;

/**
 * An evolvable link value object.
 */
interface EvolvableLinkInterface extends LinkInterface
{
    /**
     * Returns an instance with the specified href.
     *
     * @param string $href
     *   The href value to include. It must be one of:
     *     - An absolute URI, as defined by RFC 5988.
     *     - A relative URI, as defined by RFC 5988. The base of the relative link
     *       is assumed to be known based on context by the client.
     *     - A URI template as defined by RFC 6570.
     *     - An object implementing __toString() that produces one of the above
     *       values.
     *
     * An implementing library SHOULD evaluate a passed object to a string
     * immediately rather than waiting for it to be returned later.
     *
     * @return static
     */
    public function withHref($href);

    /**
     * Returns an instance with the specified relationship included.
     *
     * If the specified rel is already present, this method MUST return
     * normally without errors, but without adding the rel a second time.
     *
     * @param string $rel
     *   The relationship value to add.
     * @return static
     */
    public function withRel($rel);

    /**
     * Returns an instance with the specified relationship excluded.
     *
     * If the specified rel is already not present, this method MUST return
     * normally without errors.
     *
     * @param string $rel
     *   The relationship value to exclude.
     * @return static
     */
    public function withoutRel($rel);

    /**
     * Returns an instance with the specified attribute added.
     *
     * If the specified attribute is already present, it will be overwritten
     * with the new value.
     *
     * @param string $attribute
     *   The attribute to include.
     * @param string $value
     *   The value of the attribute to set.
     * @return static
     */
    public function withAttribute($attribute, $value);

    /**
     * Returns an instance with the specified attribute excluded.
     *
     * If the specified attribute is not present, this method MUST return
     * normally without errors.
     *
     * @param string $attribute
     *   The attribute to remove.
     * @return static
     */
    public function withoutAttribute($attribute);
}
```

#### 3.2 `Psr\Link\LinkProviderInterface`

```php
<?php

namespace Psr\Link;

/**
 * A link provider object.
 */
interface LinkProviderInterface
{
    /**
     * Returns an iterable of LinkInterface objects.
     *
     * The iterable may be an array or any PHP \Traversable object. If no links
     * are available, an empty array or \Traversable MUST be returned.
     *
     * @return LinkInterface[]|\Traversable
     */
    public function getLinks();

    /**
     * Returns an iterable of LinkInterface objects that have a specific relationship.
     *
     * The iterable may be an array or any PHP \Traversable object. If no links
     * with that relationship are available, an empty array or \Traversable MUST be returned.
     *
     * @return LinkInterface[]|\Traversable
     */
    public function getLinksByRel($rel);
}
```

#### 3.3 `Psr\Link\EvolvableLinkProviderInterface`

```php
<?php

namespace Psr\Link;

/**
 * An evolvable link provider value object.
 */
interface EvolvableLinkProviderInterface extends LinkProviderInterface
{
    /**
     * Returns an instance with the specified link included.
     *
     * If the specified link is already present, this method MUST return normally
     * without errors. The link is present if $link is === identical to a link
     * object already in the collection.
     *
     * @param LinkInterface $link
     *   A link object that should be included in this collection.
     * @return static
     */
    public function withLink(LinkInterface $link);

    /**
     * Returns an instance with the specified link removed.
     *
     * If the specified link is not present, this method MUST return normally
     * without errors. The link is present if $link is === identical to a link
     * object already in the collection.
     *
     * @param LinkInterface $link
     *   The link to remove.
     * @return static
     */
    public function withoutLink(LinkInterface $link);
}
```

Since [psr/link version 1.1](https://packagist.org/packages/psr/link#1.1.0), the above interfaces have been updated to add argument type hints.
Since [psr/link version 2.0](https://packagist.org/packages/psr/link#2.0.0), the above interfaces have been updated to add return type hints.  References to `array|\Traversable` have been replaced with `iterable`.


================================================
FILE: accepted/PSR-14-event-dispatcher-meta.md
================================================
Event Dispatcher Meta Document
==============================

## 1. Summary

The purpose of this document is to describe the rationale and logic behind the Event Dispatcher specification.

## 2. Why Bother?

Many libraries, components, and frameworks have long supported mechanisms for allowing arbitrary third party code to interact with them.  Most are variations on the classic Observer pattern, often mediated through an intermediary object or service.  Others take a more Aspect-Oriented Programming (AOP) approach.  Nonetheless all have the same basic concept: interrupt program flow at a fixed point to provide information to arbitrary third party libraries with information about the action being performed and allow them to either react or influence the program behavior.

This is a well-established model, but a standard mechanism by which libraries do so will allow them to interoperate with more and more varied third party libraries with less effort by both the original developer and extension developers.

## 3. Scope

### 3.1 Goals

* Simplify and standardize the process by which libraries and components may expose themselves to extension via "events" so that they may be more easily incorporated into applications and frameworks.
* Simplify and standardize the process by which libraries and components may register an interest in responding to an Event so that they may be more easily incorporated into arbitrary applications and frameworks.
* To the extent feasible, ease the process for existing code bases to transition toward this specification.

### 3.2 Non-Goals

* Asynchronous systems often have a concept of an "event loop" to manage interleaving coroutines.  That is an unrelated matter and explicitly irrelevant to this specification.
* Storage systems implementing an "Event Source" pattern also have a concept of an "event".  That is unrelated to the Events discussed here and explicitly out of scope.
* Strict backward compatibility with existing event systems is not a priority and is not expected.
* While this specification will undoubtedly suggest implementation patterns, it does not seek to define One True Event Dispatcher Implementation, only how callers and Listeners communicate with that Dispatcher.

## 4. Approaches

### 4.1 Use cases considered

The Working Group identified four possible workflows for event passing, based on use cases seen in the wild in various systems.

* One-way notification.  ("I did a thing, if you care.")
* Object enhancement.  ("Here's a thing, please modify it before I do something with it.")
* Collection.  ("Give me all your things, that I may do something with that list.")
* Alternative chain.  ("Here's a thing; the first one of you that can handle it do so, then stop.")

On further review, the Working Goup determined that:

* Collection was a special case of object enhancement (the collection being the object that is enhanced).
* Alternative chain is similarly a special case of object enhancement, as the signature is identical and the dispatch workflow is nearly identical, albeit with an extra check included.
* One-way notification is a degenerate case of the others, or can be represented as such.

Although in concept one-way notification can be done asynchronously (including delaying it through a queue), in practice, few explicit implementations of that model exist, providing fewer places from which to draw guidance on details (such as proper error handling).  After much consideration, the Working Group elected not to provide an explicitly separate workflow for one-way notification as it could be adequately represented as a degenerate case of the others.

### 4.2 Example applications

* Indicating that some change in system configuration or some user action has occurred and allowing other systems to react in ways that do not affect program flow (such as sending an email or logging the action).
* Passing an object to a series of Listeners to allow it to be modified before it is saved to a persistence system.
* Passing a collection to a series of Listeners to allow them to register values with it or modify existing values so that the Emitter may act on all of the collected information.
* Passing some contextual information to a series of Listeners so that all of them may "vote" on what action to take, with the Emitter deciding based on the aggregate information provided.
* Passing an object to a series of Listeners and allowing any Listener to terminate the process early before other Listeners have completed.

### 4.3 Immutable events

Initially the Working Group wished to define all Events as immutable message objects, similar to PSR-7.  However, that proved problematic in all but the one-way notification case.  In the other scenarios, Listeners needed a way to return data to the caller.  In concept, there were three possible avenues:

* Make the Event mutable and modify it in place.
* Require that Events be evolvable (immutable but with `with*()` methods like PSR-7 and PSR-13) and that Listeners return the Event to pass along.
* Make the Event immutable, but aggregate and return the return value from each Listener.

However, Stoppable Events (the alternative chain case) also needed to have a channel by which to indicate that further Listeners should not be called.  That could be done either by:

* Modifying the Event (e.g., calling a `stopPropagation()` method)
* Returning a sentinel value from the Listener (`true` or `false`) to indicate that propagation should terminate.
* Evolving the Event to be stopped (`withPropagationStopped()`)

Each of these alternatives have drawbacks. The first means that, at least for the purposes of indicating propagation status, Events must be mutable. The second requires that Listeners return a value, at least when they intend to halt event propagation; this could have ramifications with existing libraries, and potential issues in terms of documentation. The third requires that Listeners return the Event or mutated Event in all cases, and would require Dispatchers to test to ensure that the returned value is of the same type as the value passed to the Listener; it effectively puts an onus both on consumers and implementers, thus raising more potential integration issues.

Additionally, a desired feature was the ability to derive whether or not to stop propagation based on values collected from the Listeners.  (For example, to stop when one of them has provided a certain value, or after at least three of them have indicated a "reject this request" flag, or similar.)  While technically possible to implement as an evolvable object, such behavior is intrinsically stateful, so would be highly cumbersome for both implementers and users.

Having Listeners return evolvable Events also posed a challenge.  That pattern is not used by any known implementations in PHP or elsewhere.  It also relies on the Listener to remember to return the Event (additional work for the Listener author) and to not return some other, new object that might not be fully compatible with later Listeners (such as a subclass or superclass of the Event).

Immutable Events also rely on the Event author to respect the admonition to be immutable.  Events are, by nature, very loosely designed, and the potential for implementers to ignore that part of the spec, even inadvertently, is high.

That left two possible options:

* Allow Events to be mutable.
* Require, but be unable to enforce, immutable Events with a high-ceremony interface, more work for Listener authors, and a higher potential for breakage that may not be detectable at compile time.

By "high-ceremony", we imply that verbose syntax and/or implementations would be required.  In the former case, Listener authors would need to (a) create a new Event instance with the propagation flag toggled, and (b) return the new Event instance so that the Dispatcher could examine it:

```php
function (SomeEvent $event) : SomeEvent
{
    // do some work
    return $event->withPropagationStopped();
}
```

The latter case, Dispatcher implementations, would require checks on the return value:

```php
foreach ($provider->getListenersForEvent($event) as $listener) {
    $returnedEvent = $listener($event);
    
    if (! $returnedEvent instanceof $event) {
        // This is an exceptional case!
        // 
        // We now have an event of a different type, or perhaps nothing was
        // returned by the listener. An event of a different type might mean:
        // 
        // - we need to trigger the new event
        // - we have an event mismatch, and should raise an exception
        // - we should attempt to trigger the remaining listeners anyway
        // 
        // In the case of nothing being returned, this could mean any of:
        // 
        // - we should continue triggering, using the original event
        // - we should stop triggering, and treat this as a request to
        //   stop propagation
        // - we should raise an exception, because the listener did not
        //   return what was expected
        //
        // In short, this becomes very hard to specify, or enforce.
    }

    if ($returnedEvent instanceof StoppableEventInterface
        && $returnedEvent->isPropagationStopped()
    ) {
        break;
    }
}
```

In both situations, we would be introducing more potential edge cases, with little benefit, and few language-level mechanisms to guide developers to correct implementation.

Given these options, the Working Group felt mutable Events were the safer alternative.

That said, *there is no requirement that an Event be mutable*.  Implementers should provide mutator methods on an Event object *if and only if it is necessary* and appropriate to the use case at hand.

### 4.4 Listener registration

Experimentation during development of the specification determined that there were a wide range of viable, legitimate means by which a Dispatcher could be informed of a Listener.  A Listener:

* could be registered explicitly;
* could be registered explicitly based on reflection of its signature;
* could be registered with a numeric priority order;
* could be registered using a before/after mechanism to control ordering more precisely;
* could be registered from a service container;
* could use a pre-compile step to generate code;
* could be based on method names on objects in the Event itself;
* could be limited to certain situations or contexts based on arbitrarily complex logic (only for certain users, only on certain days, only if certain system settings are present, etc).

These and other mechanisms all exist in the wild today in PHP, all are valid use cases worth supporting, and few if any can be conveniently represented as a special case of another.  That is, standardizing one way, or even a small set of ways, to inform the system of a Listener turned out to be impractical if not impossible without cutting off many use cases that should be supported.

The Working Group therefore chose to encapsulate the registration of Listeners behind the `ListenerProviderInterface`.  A Provider object may have an explicit registration mechanism available, or multiple such mechanisms, or none.  It could also be generated code produced by some compile step.  However, that also splits the responsibility of managing the process of dispatching an Event from the process of mapping an Event to Listeners.  That way different implementations may be mixed-and-matched with different Provider mechanisms as needed.

It is even possible, and potentially advisable, to allow libraries to include their own Providers that get aggregated into a common Provider that aggregates their Listeners to return to the Dispatcher.  That is one possible way to handle arbitrary Listener registration within an arbitrary framework, although the Working Group is clear that is not the only option.

While combining the Dispatcher and Provider into a single object is a valid and permissible degenerate case, it is NOT RECOMMENDED as it reduces the flexibility of system integrators.  Instead, the Provider SHOULD be composed as a dependent object.

### 4.5 Deferred listeners

The specification requires that the callables returned by a Provider MUST all be invoked (unless propagation is explicitly stopped) before the Dispatcher returns.  However, the specification also explicitly states that Listeners may enqueue Events for later processing rather than taking immediate action.  It is also entirely permissible for a Provider to accept registration of a callable, but then wrap it in another callable before returning it to the Dispatcher.  (In that case, the wrapper is the Listener from the Dispatcher's point of view.)  That allows all of the following behaviors to be legal:

* Providers return callable Listeners that were provided to them.
* Providers return callables that create an entry in a queue that will react to the Event with another callable at some later point in time.
* Listeners may themselves create an entry in a queue that will react to the Event at some later point in time.
* Listeners or Providers may trigger an asynchronous task, if running in an environment with support for asynchronous behavior (assuming that the result of the asynchronous task is not needed by the Emitter.)
* Providers may perform such delay or wrapping on Listeners selectively based on arbitrary logic.

The net result is that Providers and Listeners are responsible for determining when it is safe to defer a response to an Event until some later time.  In that case, the Provider or Listener is explicitly opting out of being able to pass meaningful data back to the Emitter, but the Working Group determined that they were in the best position to know if it was safe to do so.

While technically a side effect of the design, it is essentially the same approach used by Laravel (as of Laravel 5) and has been proven in the wild.

### 4.6 Return values

Per the spec, a Dispatcher MUST return the Event passed by the Emitter.  This is specified to provide a more ergonomic experience for users, allowing short-hands similar to the following:

```php
$event = $dispatcher->dispatch(new SomeEvent('some context'));

$items = $dispatcher->dispatch(new ItemCollector())->getItems();
```

The `EventDispatcher::dispatch()` interface, however, has no return type specified.  That is primarily for backward compatibility with existing implementations to make it easier for them to adopt the new interface.  Additionally, as Events can be any arbitrary object the return type could only have been `object`, which would provide only minimal (albeit non-zero) value, as that type declaration would not provide IDEs with any useful information nor would it effectively enforce that the same Event is returned.  The method return was thus left syntactically untyped.  However, returning the same Event object from `dispatch()` is still a requirement and failure to do so is a violation of the specification.

## 5. People

The Event Manager Working Group consisted of:

### 5.1 Editor

* Larry Garfield

### 5.2 Sponsor

* Cees-Jan Kiewiet

### 5.3 Working Group Members

* Benjamin Mack
* Elizabeth Smith
* Ryan Weaver
* Matthew Weier O'Phinney

## 6. Votes

* [Entrance vote](https://groups.google.com/d/topic/php-fig/6kQFX-lhuk4/discussion)
* [Review Period Initiation](https://groups.google.com/d/topic/php-fig/sR4oEQC3Gz8/discussion)
* [Acceptance](https://groups.google.com/d/topic/php-fig/o4ZSu7vJi2w/discussion)

## 7. Relevant Links

* [Inspiration Mailing List Thread][]
* [Entrance vote][]
* [Informal poll on package structure][]
* [Informal poll on naming structure][]

[Inspiration Mailing List Thread]: https://groups.google.com/forum/#!topic/php-fig/-EJOStgxAwY
[Entrance vote]: https://groups.google.com/d/topic/php-fig/6kQFX-lhuk4/discussion
[Informal poll on package structure]: https://docs.google.com/forms/d/1fvhYUH6xvPgJ1UW9I-3pMGPUtxkt5_Ph6_x_3qXHIuM/edit#responses
[Informal poll on naming structure]: https://docs.google.com/forms/d/1Rs6APuwNx4k2VzJbTgieeNvN48kLu7CG8qn6Dd2FhTw/edit#responses


================================================
FILE: accepted/PSR-14-event-dispatcher.md
================================================
Event Dispatcher
================

Event Dispatching is a common and well-tested mechanism to allow developers to inject logic into an application easily and consistently.

The goal of this PSR is to establish a common mechanism for event-based extension and collaboration so that libraries and components may be reused more freely between various applications and frameworks.

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119][].

[RFC 2119]: http://tools.ietf.org/html/rfc2119

## Goal

Having common interfaces for dispatching and handling events allows developers to create libraries that can interact with many frameworks and other libraries in a common fashion.

Some examples:

* A security framework that will prevent saving/accessing data when a user doesn't have permission.
* A common full page caching system.
* Libraries that extend other libraries, regardless of what framework they are both integrated into.
* A logging package to track all actions taken within the application

## Definitions

* **Event** - An Event is a message produced by an *Emitter*.  It may be any arbitrary PHP object.
* **Listener** - A Listener is any PHP callable that expects to be passed an Event.  Zero or more Listeners may be passed the same Event.  A Listener MAY enqueue some other asynchronous behavior if it so chooses.
* **Emitter** - An Emitter is any arbitrary code that wishes to dispatch an Event.  This is also known as the "calling code".  It is not represented by any particular data structure but refers to the use case.
* **Dispatcher** - A Dispatcher is a service object that is given an Event object by an Emitter.  The Dispatcher is responsible for ensuring that the Event is passed to all relevant Listeners, but MUST defer determining the responsible listeners to a Listener Provider.
* **Listener Provider** - A Listener Provider is responsible for determining what Listeners are relevant for a given Event, but MUST NOT call the Listeners itself.  A Listener Provider may specify zero or more relevant Listeners.

## Events

Events are objects that act as the unit of communication between an Emitter and appropriate Listeners.

Event objects MAY be mutable should the use case call for Listeners providing information back to the Emitter.  However, if no such bidirectional communication is needed then it is RECOMMENDED that the Event be defined as immutable; i.e., defined such that it lacks mutator methods.

Implementers MUST assume that the same object will be passed to all Listeners.

It is RECOMMENDED, but NOT REQUIRED, that Event objects support lossless serialization and deserialization; `$event == unserialize(serialize($event))` SHOULD hold true.  Objects MAY leverage PHP’s `Serializable` interface, `__sleep()` or `__wakeup()` magic methods, or similar language functionality if appropriate.

## Stoppable Events

A **Stoppable Event** is a special case of Event that contains additional ways to prevent further Listeners from being called.  It is indicated by implementing the `StoppableEventInterface`.

An Event that implements `StoppableEventInterface` MUST return `true` from `isPropagationStopped()` when whatever Event it represents has been completed.  It is up to the implementer of the class to determine when that is.  For example, an Event that is asking for a PSR-7 `RequestInterface` object to be matched with a corresponding `ResponseInterface` object could have a `setResponse(ResponseInterface $res)` method for a Listener to call, which causes `isPropagationStopped()` to return `true`.

## Listeners

A Listener may be any PHP callable.  A Listener MUST have one and only one parameter, which is the Event to which it responds.  Listeners SHOULD type hint that parameter as specifically as is relevant for their use case; that is, a Listener MAY type hint against an interface to indicate it is compatible with any Event type that implements that interface, or to a specific implementation of that interface.

A Listener SHOULD have a `void` return, and SHOULD type hint that return explicitly.  A Dispatcher MUST ignore return values from Listeners.

A Listener MAY delegate actions to other code. That includes a Listener being a thin wrapper around an object that runs the actual business logic.

A Listener MAY enqueue information from the Event for later processing by a secondary process, using cron, a queue server, or similar techniques.  It MAY serialize the Event object itself to do so; however, care should be taken that not all Event objects may be safely serializable. A secondary process MUST assume that any changes it makes to an Event object will NOT propagate to other Listeners.

## Dispatcher

A Dispatcher is a service object implementing `EventDispatcherInterface`.  It is responsible for retrieving Listeners from a Listener Provider for the Event dispatched, and invoking each Listener with that Event.

A Dispatcher:

* MUST call Listeners synchronously in the order they are returned from a ListenerProvider.
* MUST return the same Event object it was passed after it is done invoking Listeners.
* MUST NOT return to the Emitter until all Listeners have executed.

If passed a Stoppable Event, a Dispatcher

* MUST call `isPropagationStopped()` on the Event before each Listener has been called.  If that method returns `true` it MUST return the Event to the Emitter immediately and MUST NOT call any further Listeners.  This implies that if an Event is passed to the Dispatcher that always returns `true` from `isPropagationStopped()`, zero listeners will be called.

A Dispatcher SHOULD assume that any Listener returned to it from a Listener Provider is type-safe.  That is, the Dispatcher SHOULD assume that calling `$listener($event)` will not produce a `TypeError`.

### Error handling

An Exception or Error thrown by a Listener MUST block the execution of any further Listeners.  An Exception or Error thrown by a Listener MUST be allowed to propagate back up to the Emitter.

A Dispatcher MAY catch a thrown object to log it, allow additional action to be taken, etc., but then MUST rethrow the original throwable.

## Listener Provider

A Listener Provider is a service object responsible for determining what Listeners are relevant to and should be called for a given Event.  It may determine both what Listeners are relevant and the order in which to return them by whatever means it chooses.  That MAY include:

* Allowing for some form of registration mechanism so that implementers may assign a Listener to an Event in a fixed order.
* Deriving a list of applicable Listeners through reflection based on the type and implemented interfaces of the Event.
* Generating a compiled list of Listeners ahead of time that may be consulted at runtime.
* Implementing some form of access control so that certain Listeners will only be called if the current user has a certain permission.
* Extracting some information from an object referenced by the Event, such as an Entity, and calling pre-defined lifecycle methods on that object.
* Delegating its responsibility to one or more other Listener Providers using some arbitrary logic.

Any combination of the above, or other mechanisms, MAY be used as desired.

Listener Providers SHOULD use the class name of an Event to differentiate one event from another.  They MAY also consider any other information on the event as appropriate.

Listener Providers MUST treat parent types identically to the Event's own type when determining listener applicability.  In the following case:

```php
class A {}

class B extends A {}

$b = new B();

function listener(A $event): void {};
```

A Listener Provider MUST treat `listener()` as an applicable listener for `$b`, as it is type compatible, unless some other criteria prevents it from doing so.

## Object composition

A Dispatcher SHOULD compose a Listener Provider to determine relevant listeners.  It is RECOMMENDED that a Listener Provider be implemented as a distinct object from the Dispatcher but that is NOT REQUIRED.

## Interfaces

```php
namespace Psr\EventDispatcher;

/**
 * Defines a dispatcher for events.
 */
interface EventDispatcherInterface
{
    /**
     * Provide all relevant listeners with an event to process.
     *
     * @param object $event
     *   The object to process.
     *
     * @return object
     *   The Event that was passed, now modified by listeners.
     */
    public function dispatch(object $event);
}
```

```php
namespace Psr\EventDispatcher;

/**
 * Mapper from an event to the listeners that are applicable to that event.
 */
interface ListenerProviderInterface
{
    /**
     * @param object $event
     *   An event for which to return the relevant listeners.
     * @return iterable<callable>
     *   An iterable (array, iterator, or generator) of callables.  Each
     *   callable MUST be type-compatible with $event.
     */
    public function getListenersForEvent(object $event): iterable;
}
```

```php
namespace Psr\EventDispatcher;

/**
 * An Event whose processing may be interrupted when the event has been handled.
 *
 * A Dispatcher implementation MUST check to determine if an Event
 * is marked as stopped after each listener is called.  If it is then it should
 * return immediately without calling any further Listeners.
 */
interface StoppableEventInterface
{
    /**
     * Is propagation stopped?
     *
     * This will typically only be used by the Dispatcher to determine if the
     * previous listener halted propagation.
     *
     * @return bool
     *   True if the Event is complete and no further listeners should be called.
     *   False to continue calling listeners.
     */
    public function isPropagationStopped(): bool;
}
```


================================================
FILE: accepted/PSR-15-request-handlers-meta.md
================================================
HTTP Server Request Handlers Meta Document
==========================================

## 1. Summary

The purpose of this PSR is to define formal interfaces for HTTP server request
handlers ("request handlers") and HTTP server request middleware ("middleware")
that are compatible with HTTP messages as defined in [PSR-7][psr7] or subsequent
replacement PSRs.

_Note: All references to "request handlers" and "middleware" are specific to
**server request** processing._

[psr7]: https://www.php-fig.org/psr/psr-7/

## 2. Why Bother?

The HTTP messages specification does not contain any reference to request
handlers or middleware.

Request handlers are a fundamental part of any web application. The handler is
the component that receives a request and produces a response. Nearly all code
that works with HTTP messages will have some kind of request handler.

[Middleware][middleware] has existed for many years in the PHP ecosystem. The
general concept of reusable middleware was popularized by [StackPHP][stackphp].
Since the release of HTTP messages as a PSR, many frameworks have adopted
middleware that use HTTP message interfaces.

Agreeing on formal request handler and middleware interfaces eliminates several
problems and has a number of benefits:

* Provides a formal standard for developers to commit to.
* Enables any middleware component to run in any compatible framework.
* Eliminates duplication of similar interfaces defined by various frameworks.
* Avoids minor discrepancies in method signatures.

[middleware]: https://en.wikipedia.org/wiki/Middleware
[stackphp]: http://stackphp.com/

## 3. Scope

### 3.1 Goals

* Create a request handler interface that uses HTTP messages.
* Create a middleware interface that uses HTTP messages.
* Implement request handler and middleware signatures that are based on
  best practices.
* Ensure that request handlers and middleware will be compatible with any
  implementation of HTTP messages.

### 3.2 Non-Goals

* Attempting to define the mechanism by which HTTP responses are created.
* Attempting to define interfaces for client/asynchronous middleware.
* Attempting to define how middleware is dispatched.

## 4. Request Handler Approaches

There are many approaches to request handlers that use HTTP messages. However,
the general process is the same in all of them:

Given an HTTP request, produce an HTTP response for that request.

The internal requirements of that process will vary from framework to framework
and application to application. This proposal makes no effort to determine what
that process should be.

## 5. Middleware Approaches

There are currently two common approaches to middleware that use HTTP messages.

### 5.1 Double Pass

The signature used by most middleware implementations has been mostly the same
and is based on [Express middleware][express], which is defined as:

```
fn(request, response, next): response
```

[express]: http://expressjs.com/en/guide/writing-middleware.html

Based on the middleware implementations already used by frameworks that have
adopted this signature, the following commonalities are observed:

* The middleware is defined as a [callable][php-callable].
* The middleware is passed 3 arguments during invocation:
  1. A `ServerRequestInterface` implementation.
  2. A `ResponseInterface` implementation.
  3. A `callable` that receives the request and response to delegate to the next middleware.

[php-callable]: http://php.net/manual/language.types.callable.php

A significant number of projects provide and/or use exactly the same interface.
This approach is often referred to as "double pass" in reference to both the
request and response being passed to the middleware.

#### 5.1.1 Projects Using Double Pass

* [mindplay/middleman v1](https://github.com/mindplay-dk/middleman/blob/1.0.0/src/MiddlewareInterface.php#L24)
* [relay/relay v1](https://github.com/relayphp/Relay.Relay/blob/1.0.0/src/MiddlewareInterface.php#L24)
* [slim/slim v3](https://github.com/slimphp/Slim/blob/3.4.0/Slim/MiddlewareAwareTrait.php#L66-L75)
* [zendframework/zend-stratigility v1](https://github.com/zendframework/zend-stratigility/blob/1.0.0/src/MiddlewarePipe.php#L69-L79)

#### 5.1.2 Middleware Implementing Double Pass

* [bitexpert/adroit](https://github.com/bitExpert/adroit)
* [akrabat/rka-ip-address-middleware](https://github.com/akrabat/rka-ip-address-middleware)
* [akrabat/rka-scheme-and-host-detection-middleware](https://github.com/akrabat/rka-scheme-and-host-detection-middleware)
* [bear/middleware](https://github.com/bearsunday/BEAR.Middleware)
* [los/api-problem](https://github.com/Lansoweb/api-problem)
* [los/los-rate-limit](https://github.com/Lansoweb/LosRateLimit)
* [monii/monii-action-handler-psr7-middleware](https://github.com/monii/monii-action-handler-psr7-middleware)
* [monii/monii-nikic-fast-route-psr7-middleware](https://github.com/monii/monii-nikic-fast-route-psr7-middleware)
* [monii/monii-response-assertion-psr7-middleware](https://github.com/monii/monii-response-assertion-psr7-middleware)
* [mtymek/blast-base-url](https://github.com/mtymek/blast-base-url)
* [ocramius/psr7-session](https://github.com/Ocramius/PSR7Session)
* [oscarotero/psr7-middlewares](https://github.com/oscarotero/psr7-middlewares)
* [php-middleware/block-robots](https://github.com/php-middleware/block-robots)
* [php-middleware/http-authentication](https://github.com/php-middleware/http-authentication)
* [php-middleware/log-http-messages](https://github.com/php-middleware/log-http-messages)
* [php-middleware/maintenance](https://github.com/php-middleware/maintenance)
* [php-middleware/phpdebugbar](https://github.com/php-middleware/phpdebugbar)
* [php-middleware/request-id](https://github.com/php-middleware/request-id)
* [relay/middleware](https://github.com/relayphp/Relay.Middleware)

The primary downside of this interface is that the while the interface itself is
a callable, there is currently no way to strictly type a closure.

### 5.2 Single Pass (Lambda)

The other approach to middleware is much closer to [StackPHP][stackphp] style
and is defined as:

```
fn(request, next): response
```

Middleware taking this approach generally has the following commonalities:

* The middleware is defined with a specific interface with a method that takes
  the request for processing.
* The middleware is passed 2 arguments during invocation:
  1. An HTTP request message.
  2. A request handler to which the middleware can delegate the responsibility
     of producing an HTTP response message.

In this form, middleware has no access to a response until one is generated by
the request handler. Middleware can then modify the response before returning it.

This approach is often referred to as "single pass" or "lambda" in reference to
only the request being passed to the middleware.

#### 5.2.1 Projects Using Single Pass

There are fewer examples of this approach within projects using HTTP messages,
with one notable exception.

[Guzzle middleware][guzzle-middleware] is focused on outgoing (client) requests
and uses this signature:

```php
function (RequestInterface $request, array $options): ResponseInterface
```

#### 5.2.2 Additional Projects Using Single Pass

There are also significant projects that predate HTTP messages using this approach.

[StackPHP][stackphp] is based on [Symfony HttpKernel][httpkernel] and supports
middleware with this signature:

```php
function handle(Request $request, $type, $catch): Response
```

_Note: While Stack has multiple arguments, a response object is not included._

[Laravel middleware][laravel-middleware] uses Symfony components and supports
middleware with this signature:

```php
function handle(Request $request, callable $next): Response
```

[guzzle-middleware]: http://docs.guzzlephp.org/en/latest/handlers-and-middleware.html
[httpkernel]: https://symfony.com/doc/2.0/components/http_kernel/introduction.html
[laravel-middleware]: https://laravel.com/docs/master/middleware

### 5.3 Comparison of Approaches

The single pass approach to middleware has been well established in the PHP
community for many years. This is most evident with the large number of packages
that are based around StackPHP.

The double pass approach is much newer but has been almost universally used by
early adopters of HTTP messages (PSR-7).

### 5.4 Chosen Approach

Despite the nearly universal adoption of the double-pass approach, there are
significant issues regarding implementation.

The most severe is that passing an empty response has no guarantees that the
response is in a usable state. This is further exacerbated by the fact that a
middleware may modify the response before passing it for further processing.

Further compounding the problem is that there is no way to ensure that the
response body has not been written to, which can lead to incomplete output or
error responses being sent with cache headers attached. It is also possible
to end up with [corrupted body content][rob-allen-filtering] when writing over
existing body content if the new content is shorter than the original. The most
effective way to resolve these issues is to always provide a fresh stream when
modifying the body of a message.

[rob-allen-filtering]: https://akrabat.com/filtering-the-psr-7-body-in-middleware/

Some have argued that passing the response helps ensure dependency inversion.
While it is true that it helps avoid depending on a specific implementation of
HTTP messages, the problem can also be resolved by injecting factories into the
middleware to create HTTP message objects, or by injecting empty message instances.
With the creation of HTTP Factories in [PSR-17][psr17], a standard approach to
handling dependency inversion is possible.

[psr17]: https://github.com/php-fig/fig-standards/blob/master/proposed/http-factory/http-factory-meta.md

A more subjective, but also important, concern is that existing double-pass
middleware typically uses the `callable` type hint to refer to middleware.
This makes strict typing impossible, as there is no assurance that the `callable`
being passed implements a middleware signature, which reduces runtime safety.

**Due to these significant issues, the lambda approach has been chosen for this proposal.**

## 6. Design Decisions

### 6.1 Request Handler Design

The `RequestHandlerInterface` defines a single method that accepts a request and
MUST return a response. The request handler MAY delegate to another handler.

#### Why is a server request required?

To make it clear that the request handler can only be used in a server side context.
In an client side context, a [promise][promises] would likely be returned instead
of a response.

[promises]: https://promisesaplus.com/

#### Why the term "handler"?

The term "handler" means something designated to manage or control. In terms of
request processing, a request handler is the point where the request must be
acted upon to create a response.

As opposed to the term "delegate", which was used in a previous version of this
specification, the internal behavior of this interface is not specified.
As long as the request handler ultimately produces a response, it is valid.

#### Why doesn't request handler use `__invoke`?

Using `__invoke` is less transparent than using a named method. It also makes
it easier to call the request handler when it is assigned to a class variable,
without using `call_user_func` or other less common syntax.

_See [PHP-FIG discussion of FrameInterface][] for
 additional information._

### 6.2 Middleware Design

The `MiddlewareInterface` defines a single method that accepts an HTTP request
and a request handler and must return a response. The middleware may:

- Evolve the request before passing it to the request handler.
- Evolve the response received from the request handler before returning it.
- Create and return a response without passing the request to the request handler,
  thereby handling the request itself.

When delegating from one middleware to another in a sequence, one approach for
dispatching systems is to use an intermediary request handler composing the
middleware sequence as a way to link middleware together. The final or innermost
middleware will act as a gateway to application code and generate a response
from its results; alternately, the middleware MAY delegate this responsibility
to a dedicated request handler.

#### Why doesn't middleware use `__invoke`?

Doing so would conflict with existing middleware that implements the double-pass
approach and may want to implement the middleware interface for purposes of
forward compatibility with this specification.

#### Why the name `process()`?

We reviewed a number of existing monolithic and middleware frameworks to
determine what method(s) each defined for processing incoming requests. We found
the following were commonly used:

- `__invoke` (within middleware systems, such as Slim, Expressive, Relay, etc.)
- `handle` (in particular, software derived from Symfony's [HttpKernel][HttpKernel])
- `dispatch` (Zend Framework's [DispatchableInterface][DispatchableInterface])

[HttpKernel]: https://symfony.com/doc/current/components/http_kernel.html
[DispatchableInterface]: https://github.com/zendframework/zend-stdlib/blob/980ce463c29c1a66c33e0eb67961bba895d0e19e/src/DispatchableInterface.php

We chose to allow a forward-compatible approach for such classes to repurpose
themselves as middleware (or middleware compatible with this specification),
and thus needed to choose a name not in common usage. As such, we chose
`process`, to indicate _processing_ a request.

#### Why is a server request required?

To make it clear that the middleware can only be used in a synchronous, server
side context.

While not all middleware will need to use the additional methods defined by the
server request interface, outbound requests are typically processed asynchronously
and would typically return a [promise][promises] of a response. (This is primarily
due to the fact that multiple requests can be made in parallel and processed as
they are returned.) It is outside the scope of this proposal to address the needs
of asynchronous request/response life cycles.

Attempting to define client middleware would be premature at this point. Any future
proposal that is focused on client side request processing should have the opportunity
to define a standard that is specific to the nature of asynchronous middleware.

_See [PHP-FIG discussion about client vs server side middleware][] for additional information._

#### What is the role of the request handler?

Middleware has the following roles:

- Producing a response on its own. If specific request conditions are met, the
  middleware can produce and return a response.

- Returning the result of the request handler. In cases where the middleware
  cannot produce its own response, it can delegate to the request handler to
  produce one; sometimes this may involve providing a transformed request (e.g.,
  to inject a request attribute, or the results of parsing the request body).

- Manipulating and returning the response produced by the request handler. In
  some cases, the middleware may be interested in manipulating the response
  the request handler returns (e.g., to gzip the response body, to add CORS
  headers, etc.). In such cases, the middleware will capture the response
  returned by the request handler, and return a transformed response on
  completion.

In these latter two cases, the middleware may have code such as the following:

```php
// Straight delegation:
return $handler->handle($request);

// Capturing the response to manipulate:
$response = $handler->handle($request);
```

How the handler acts is entirely up to the developer, so long as it produces a
response.

In one common scenario, the handler implements a _queue_ or a _stack_ of
middleware instances internally. In such cases, calling
`$handler->handle($request)` will advance the internal pointer, pull the
middleware associated with that pointer, and call it using
`$middleware->process($request, $this)`. If no more middleware exists, it will
generally either raise an exception or return a canned response.

Another possibility is for  _routing middleware_ that matches the incoming
server request to a specific handler, and then returns the response generated by
executing that handler. If unable to route to a handler, it would instead
execute the handler provided to the middleware. (This sort of mechanism can even
be used in conjunction with middleware queues and stacks.)

### 6.3 Example Interface Interactions

The two interfaces, `RequestHandlerInterface` and `MiddlewareInterface`, were
designed to work in conjunction with one another. Middleware gains flexibility
when de-coupled from any over-arching application layer, and instead only
relying on the provided request handler to produce a response.

Two approaches to middleware dispatch systems that the Working Group observed
and/or implemented are demonstrated below. Additionally, examples of re-usable
middleware are provided to demonstrate how to write middleware that is
loosely-coupled.

Please note that these are not suggested as definitive or exclusive approaches
to defining middleware dispatch systems.

#### Queue-based request handler

In this approach, a request handler maintains a queue of middleware, and a
fallback response to return if the queue is exhausted without returning a
response. When executing the first middleware, the queue passes itself as a
request handler to the middleware.

```php
class QueueRequestHandler implements RequestHandlerInterface
{
    private $middleware = [];
    private $fallbackHandler;
    
    public function __construct(RequestHandlerInterface $fallbackHandler)
    {
        $this->fallbackHandler = $fallbackHandler;
    }
    
    public function add(MiddlewareInterface $middleware)
    {
        $this->middleware[] = $middleware;
    }
    
    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        // Last middleware in the queue has called on the request handler.
        if (0 === count($this->middleware)) {
            return $this->fallbackHandler->handle($request);
        }
        
        $middleware = array_shift($this->middleware);
        return $middleware->process($request, $this);
    }
}
```

An application bootstrap might then look like this:

```php
// Fallback handler:
$fallbackHandler = new NotFoundHandler();

// Create request handler instance:
$app = new QueueRequestHandler($fallbackHandler);

// Add one or more middleware:
$app->add(new AuthorizationMiddleware());
$app->add(new RoutingMiddleware());

// execute it:
$response = $app->handle(ServerRequestFactory::fromGlobals());
```

This system has two request handlers: one that will produce a response if the
last middleware delegates to the request handler, and one for dispatching the
middleware layers. (In this example, the `RoutingMiddleware` will likely execute
composed handlers on a successful route match; see more on that below.)

This approach has the following benefits:

- Middleware does not need to know anything about any other middleware or how it
  is composed in the application.
- The `QueueRequestHandler` is agnostic of the PSR-7 implementation in use.
- Middleware is executed in the order it is added to the application, making the
  code explicit.
- Generation of the "fallback" response is delegated to the application
  developer. This allows the developer to determine whether that should be a
  "404 Not Found" condition, a default page, etc.

#### Decoration-based request handler

In this approach, a request handler implementation decorates both a middleware
instance and a fallback request handler to pass to it. The application is built
from the outside-in, passing each request handler "layer" to the next outer one.

```php
class DecoratingRequestHandler implements RequestHandlerInterface
{
    private $middleware;
    private $nextHandler;

    public function __construct(MiddlewareInterface $middleware, RequestHandlerInterface $nextHandler)
    {
        $this->middleware = $middleware;
        $this->nextHandler = $nextHandler;
    }

    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        return $this->middleware->process($request, $this->nextHandler);
    }
}

// Create a response prototype to return if no middleware can produce a response
// on its own. This could be a 404, 500, or default page.
$responsePrototype = (new Response())->withStatus(404);
$innerHandler = new class ($responsePrototype) implements RequestHandlerInterface {
    private $responsePrototype;

    public function __construct(ResponseInterface $responsePrototype)
    {
        $this->responsePrototype = $responsePrototype;
    }

    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        return $this->responsePrototype;
    }
};

$layer1 = new DecoratingRequestHandler(new RoutingMiddleware(), $innerHandler);
$layer2 = new DecoratingRequestHandler(new AuthorizationMiddleware(), $layer1);

$response = $layer2->handle(ServerRequestFactory::fromGlobals());
```

Similar to the queue-based middleware, request handlers serve two purposes in
this system:

- Producing a fallback response if no other layer does.
- Dispatching middleware.

#### Reusable Middleware Examples

In the examples above, we have two middleware composed in each. In order for
these to work in either situation, we need to write them such that they interact
appropriately.

Implementors of middleware striving for maximum interoperability may want to
consider the following guidelines:

- Test the request for a required condition. If it does not satisfy that
  condition, use a composed prototype response or a composed response factory
  to generate and return a response.

- If pre-conditions are met, delegate creation of the response to the provided
  request handler, optionally providing a "new" request by manipulating the
  provided request (e.g., `$handler->handle($request->withAttribute('foo',
  'bar')`).

- Either pass the response returned by the request handler unaltered, or provide
  a new response by manipulating the one returned (e.g., `return
  $response->withHeader('X-Foo-Bar', 'baz')`).

The `AuthorizationMiddleware` is one that will exercise all three of these guidelines:

- If authorization is required, but the request is not authorized, it will use a
  composed prototype response to produce an "unauthorized" response.
- If authorization is not required, it will delegate the request to the handler
  without changes.
- If authorization is required and the request is authorized, it will delegate
  the request to the handler, and sign the response returned based on the request.

```php
class AuthorizationMiddleware implements MiddlewareInterface
{
    private $authorizationMap;

    public function __construct(AuthorizationMap $authorizationMap)
    {
        $this->authorizationMap = $authorizationMap;
    }

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        if (! $this->authorizationMap->needsAuthorization($request)) {
            return $handler->handle($request);
        }

        if (! $this->authorizationMap->isAuthorized($request)) {
            return $this->authorizationMap->prepareUnauthorizedResponse();
        }

        $response = $handler->handle($request);
        return $this->authorizationMap->signResponse($response, $request);
    }
}
```

Note that the middleware is not concerned with how the request handler is
implemented; it merely uses it to produce a response when pre-conditions have
been met.

The `RoutingMiddleware` implementation described below follows a similar
process: it analyzes the request to see if it matches known routes. In this
particular implementation, routes map to request handlers, and the middleware
essentially delegates to them in order to produce a response. However, in the
case that no route is matched, it will execute the handler passed to it to
produce the response to return.

```php
class RoutingMiddleware implements MiddlewareInterface
{
    private $router;

    public function __construct(Router $router)
    {
        $this->router = $router;
    }

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        $result = $this->router->match($request);

        if ($result->isSuccess()) {
            return $result->getHandler()->handle($request);
        }

        return $handler->handle($request);
    }
}
```

## 7. People

This PSR was produced by a FIG Working Group with the following members:

* Matthew Weier O'Phinney (sponsor), <mweierophinney@gmail.com>
* Woody Gilk (editor), <woody.gilk@gmail.com>
* Glenn Eggleton
* Matthieu Napoli
* Oscar Otero
* Korvin Szanto
* Stefano Torresi

The working group would also like to acknowledge the contributions of:

* Jason Coward, <jason@opengeek.com>
* Paul M. Jones, <pmjones88@gmail.com>
* Rasmus Schultz, <rasmus@mindplay.dk>

## 8. Votes

* [Working Group Formation](https://groups.google.com/d/msg/php-fig/rPFRTa0NODU/tIU9BZciAgAJ)
* [Review Period Initiation](https://groups.google.com/d/msg/php-fig/mfTrFinTvEM/PiYvU2S6BAAJ)
* [Acceptance](https://groups.google.com/d/msg/php-fig/bhQmHt39hJE/ZCYrK_O2AQAJ)

## 9. Relevant Links

_**Note:** Order descending chronologically._

* [PHP-FIG mailing list thread][]
* [The PHP League middleware proposal][]
* [PHP-FIG discussion of FrameInterface][]
* [PHP-FIG discussion about client vs server side middleware][]

## 10. Errata

...

[PHP-FIG mailing list thread]: https://groups.google.com/d/msg/php-fig/vTtGxdIuBX8/NXKieN9vDQAJ
[The PHP League middleware proposal]: https://groups.google.com/d/msg/thephpleague/jyztj-Nz_rw/I4lHVFigAAAJ
[PHP-FIG discussion of FrameInterface]: https://groups.google.com/d/msg/php-fig/V12AAcT_SxE/aRXmNnIVCwAJ
[PHP-FIG discussion about client vs server side middleware]: https://groups.google.com/d/topic/php-fig/vBk0BRgDe2s/discussion


================================================
FILE: accepted/PSR-15-request-handlers.md
================================================
HTTP Server Request Handlers
============================

This document describes common interfaces for HTTP server request handlers
("request handlers") and HTTP server middleware components ("middleware")
that use HTTP messages as described by [PSR-7][psr7] or subsequent
replacement PSRs.

HTTP request handlers are a fundamental part of any web application. Server-side
code receives a request message, processes it, and produces a response message.
HTTP middleware is a way to move common request and response processing away from
the application layer.

The interfaces described in this document are abstractions for request handlers
and middleware.

_Note: All references to "request handlers" and "middleware" are specific to
**server request** processing._

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
interpreted as described in [RFC 2119][rfc2119].

[psr7]: https://www.php-fig.org/psr/psr-7/
[rfc2119]: http://tools.ietf.org/html/rfc2119

### References

- [PSR-7][psr7]
- [RFC 2119][rfc2119]

## 1. Specification

### 1.1 Request Handlers

A request handler is an individual component that processes a request and
produces a response, as defined by PSR-7.

A request handler MAY throw an exception if request conditions prevent it from
producing a response. The type of exception is not defined.

Request handlers using this standard MUST implement the following interface:

- `Psr\Http\Server\RequestHandlerInterface`

### 1.2 Middleware

A middleware component is an individual component participating, often together
with other middleware components, in the processing of an incoming request and
the creation of a resulting response, as defined by PSR-7.

A middleware component MAY create and return a response without delegating to
a request handler, if sufficient conditions are met.

Middleware using this standard MUST implement the following interface:

- `Psr\Http\Server\MiddlewareInterface`

### 1.3 Generating Responses

It is RECOMMENDED that any middleware or request handler that generates a response
will either compose a prototype of a PSR-7 `ResponseInterface` or a factory capable
of generating a `ResponseInterface` instance in order to prevent dependence on a
specific HTTP message implementation.

### 1.4 Handling Exceptions

It is RECOMMENDED that any application using middleware includes a component
that catches exceptions and converts them into responses. This middleware SHOULD
be the first component executed and wrap all further processing to ensure that
a response is always generated.

## 2. Interfaces

### 2.1 Psr\Http\Server\RequestHandlerInterface

The following interface MUST be implemented by request handlers.

```php
namespace Psr\Http\Server;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

/**
 * Handles a server request and produces a response.
 *
 * An HTTP request handler process an HTTP request in order to produce an
 * HTTP response.
 */
interface RequestHandlerInterface
{
    /**
     * Handles a request and produces a response.
     *
     * May call other collaborating code to generate the response.
     */
    public function handle(ServerRequestInterface $request): ResponseInterface;
}
```

### 2.2 Psr\Http\Server\MiddlewareInterface

The following interface MUST be implemented by compatible middleware components.

```php
namespace Psr\Http\Server;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

/**
 * Participant in processing a server request and response.
 *
 * An HTTP middleware component participates in processing an HTTP message:
 * by acting on the request, generating the response, or forwarding the
 * request to a subsequent middleware and possibly acting on its response.
 */
interface MiddlewareInterface
{
    /**
     * Process an incoming server request.
     *
     * Processes an incoming server request in order to produce a response.
     * If unable to produce the response itself, it may delegate to the provided
     * request handler to do so.
     */
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface;
}
```


================================================
FILE: accepted/PSR-16-simple-cache-meta.md
================================================
# PSR-16 Meta Document

## 1. Summary

Caching is a common way to improve the performance of any project, and many
libraries make use or could make use of it. Interoperability at this level
means libraries can drop their own caching implementations and easily rely
on the one given to them by the framework, or another dedicated cache
library the user picked.

## 2. Why Bother?

PSR-6 solves this problem already, but in a rather formal and verbose way for
what the most simple use cases need. This simpler approach aims to build a
standardized layer of simplicity on top of the existing PSR-6 interfaces.

## 3. Scope

### 3.1 Goals

* A simple interface for cache operations.
* Basic support for operations on multiple keys for performance (round-trip-time)
  reasons.
* Providing an adapter class that turns a PSR-6 implementation into a
  PSR-Simple-Cache one.
* It should be possible to expose both caching PSRs from a caching library.

### 3.2 Non-Goals

* Solving all possible edge cases, PSR-6 does this well already.

## 4. Approaches

The approach chosen here is very barebones by design, as it is to be used
only by the most simple cases. It does not have to be implementable by all
possible cache backends, nor be usable for all usages. It is merely a layer
of convenience on top of PSR-6.

## 5. People

### 5.1 Editor(s)

* Paul Dragoonis (@dragoonis)

### 5.2 Sponsors

* Jordi Boggiano (@seldaek) - Composer (Coordinator)
* Fabien Potencier (@fabpot) - Symfony

### 5.3 Contributors

For their role in the writing the initial version of this cache PSR:

* Evert Pot (@evert)
* Florin Pățan (@dlsniper)

For being an early reviewer

* Daniel Messenger (@dannym87)

## 6. Votes

* **Entrance Vote:**  https://groups.google.com/d/topic/php-fig/vyQTKHS6pJ8/discussion
* **Acceptance Vote:**  https://groups.google.com/d/msg/php-fig/A8e6GvDRGIk/HQBJGEhbDQAJ

## 7. Relevant Links

* [Survey of existing cache implementations][1], by @dragoonis

[1]: https://docs.google.com/spreadsheet/ccc?key=0Ak2JdGialLildEM2UjlOdnA4ekg3R1Bfeng5eGlZc1E#gid=0

## 8. Errata

### 8.1 Throwable

The 2.0 release of the `psr/simple-cache` package updates `Psr\SimpleCache\CacheException` to extend `\Throwable`.  This is considered a backwards compatible change for implementing libraries as of PHP 7.4.

### 8.2 Type additions

The 2.0 release of the `psr/simple-cache` package includes scalar parameter types and increases the minimum PHP version to 8.0.  This is considered a backwards compatible change for implementing libraries as PHP 7.2 introduces covariance for parameters.  Any implementation of 1.0 is compatible with 2.0. For calling libraries, however, this reduces the types that they may pass (as previously any parameter that could be cast to string could be accepted) and as such requires incrementing the major version.

The 3.0 release includes return types.  Return types break backwards compatibility for implementing libraries as PHP does not support return type widening.

Implementing libraries **MAY** add return types to their own packages at their discretion, provided that:

* the return types match those in the 3.0 package.
* the implementation specifies a minimum PHP version of 8.0.0 or later
* the implementation depends on `"psr/simple-cache": "^2 || ^3"` so as to exclude the untyped 1.0 version.

Implementing libraries **MAY** add parameter types to their own package in a new minor release, either at the same time as adding return types or in a subsequent release, provided that:

* the parameter types match or widen those in the 2.0 package
* the implementation specifies a minimum PHP version of 8.0 if using mixed or union types or later.
* the implementation depends on `"psr/simple-cache": "^2 || ^3"` so as to exclude the untyped 1.0 version.

Implementing libraries are encouraged, but not required to transition their packages toward the 3.0 version of the package at their earliest convenience.

Calling libraries are encouraged to ensure they are sending the correct types and to update their requirement to `"psr/simple-cache": "^1 || ^2 || ^3"` at their earliest convenience.


================================================
FILE: accepted/PSR-16-simple-cache.md
================================================
Common Interface for Caching Libraries
======================================

This document describes a simple yet extensible interface for a cache item and
a cache driver.

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
interpreted as described in [RFC 2119][].

The final implementations MAY decorate the objects with more
functionality than the one proposed but they MUST implement the indicated
interfaces/functionality first.

[RFC 2119]: http://tools.ietf.org/html/rfc2119

# 1. Specification

## 1.1 Introduction

Caching is a common way to improve the performance of any project, making
caching libraries one of the most common features of many frameworks and
libraries. Interoperability at this level means libraries can drop their
own caching implementations and easily rely on the one given to them by the
framework, or another dedicated cache library.

PSR-6 solves this problem already, but in a rather formal and verbose way for
what the most simple use cases need. This simpler approach aims to build a
standardized streamlined interface for common cases. It is independent of
PSR-6 but has been designed to make compatibility with PSR-6 as straightforward
as possible.

## 1.2 Definitions

Definitions for Calling Library, Implementing Library, TTL, Expiration and Key
are copied from PSR-6 as the same assumptions are true.

*    **Calling Library** - The library or code that actually needs the cache
services. This library will utilize caching services that implement this
standard's interfaces, but will otherwise have no knowledge of the
implementation of those caching services.

*    **Implementing Library** - This library is responsible for implementing
this standard in order to provide caching services to any Calling Library. The
Implementing Library MUST provide a class implementing the Psr\SimpleCache\CacheInterface interface.
Implementing Libraries MUST support at minimum TTL functionality as described
below with whole-second granularity.

*    **TTL** - The Time To Live (TTL) of an item is the amount of time between
when that item is stored and it is considered stale. The TTL is normally defined
by an integer representing time in seconds, or a DateInterval object.

* **Expiration** - The actual time when an item is set to go stale. This is
  calculated by adding the TTL to the time when an object is stored.

  An item with a 300 second TTL stored at 1:30:00 will have an expiration of 1:35:00.

  Implementing Libraries MAY expire an item before its requested Expiration Time,
  but MUST treat an item as expired once its Expiration Time is reached. If a calling
  library asks for an item to be saved but does not specify an expiration time, or
  specifies a null expiration time or TTL, an Implementing Library MAY use a configured
  default duration. If no default duration has been set, the Implementing Library
  MUST interpret that as a request to cache the item forever, or for as long as the
  underlying implementation supports.

  If a negative or zero TTL is provided, the item MUST be deleted from the cache
  if it exists, as it is expired already.

*    **Key** - A string of at least one character that uniquely identifies a
cached item. Implementing libraries MUST support keys consisting of the
characters `A-Z`, `a-z`, `0-9`, `_`, and `.` in any order in UTF-8 encoding and a
length of up to 64 characters. Implementing libraries MAY support additional
characters and encodings or longer lengths, but MUST support at least that
minimum. Libraries are responsible for their own escaping of key strings
as appropriate, but MUST be able to return the original unmodified key string.
The following characters are reserved for future extensions and MUST NOT be
supported by implementing libraries: `{}()/\@:`

*    **Cache** - An object that implements the `Psr\SimpleCache\CacheInterface` interface.

*    **Cache Misses** - A cache miss will return null and therefore detecting
if one stored `null` is not possible. This is the main deviation from PSR-6's
assumptions.

## 1.3 Cache

Implementations MAY provide a mechanism for a user to specify a default TTL
if one is not specified for a specific cache item. If no user-specified default
is provided implementations MUST default to the maximum legal value allowed by
the underlying implementation. If the underlying implementation does not
support TTL, the user-specified TTL MUST be silently ignored.

## 1.4 Data

Implementing libraries MUST support all serializable PHP data types, including:

*    **Strings** - Character strings of arbitrary size in any PHP-compatible encoding.
*    **Integers** - All integers of any size supported by PHP, up to 64-bit signed.
*    **Floats** - All signed floating point values.
*    **Booleans** - True and False.
*    **Null** - The null value (although it will not be distinguishable from a
cache miss when reading it back out).
*    **Arrays** - Indexed, associative and multidimensional arrays of arbitrary depth.
*    **Objects** - Any object that supports lossless serialization and
deserialization such that $o == unserialize(serialize($o)). Objects MAY
leverage PHP's Serializable interface, `__sleep()` or `__wakeup()` magic methods,
or similar language functionality if appropriate.

All data passed into the Implementing Library MUST be returned exactly as
passed. That includes the variable type. That is, it is an error to return
(string) 5 if (int) 5 was the value saved. Implementing Libraries MAY use PHP's
serialize()/unserialize() functions internally but are not required to do so.
Compatibility with them is simply used as a baseline for acceptable object values.

If it is not possible to return the exact saved value for any reason, implementing
libraries MUST respond with a cache miss rather than corrupted data.

# 2. Interfaces

## 2.1 CacheInterface

The cache interface defines the most basic operations on a collection of cache-entries, which
entails basic reading, writing and deleting individual cache items.

In addition, it has methods for dealing with multiple sets of cache entries such as writing, reading or
deleting multiple cache entries at a time. This is useful when you have lots of cache reads/writes
to perform, and lets you perform your operations in a single call to the cache server cutting down latency
times dramatically.

An instance of CacheInterface corresponds to a single collection of cache items with a single key namespace,
and is equivalent to a "Pool" in PSR-6. Different CacheInterface instances MAY be backed by the same
datastore, but MUST be logically independent.

```php
<?php

namespace Psr\SimpleCache;

interface CacheInterface
{
    /**
     * Fetches a value from the cache.
     *
     * @param string $key     The unique key of this item in the cache.
     * @param mixed  $default Default value to return if the key does not exist.
     *
     * @return mixed The value of the item from the cache, or $default in case of cache miss.
     *
     * @throws \Psr\SimpleCache\InvalidArgumentException
     *   MUST be thrown if the $key string is not a legal value.
     */
    public function get($key, $default = null);

    /**
     * Persists data in the cache, uniquely referenced by a key with an optional expiration TTL time.
     *
     * @param string                 $key   The key of the item to store.
     * @param mixed                  $value The value of the item to store. Must be serializable.
     * @param null|int|\DateInterval $ttl   Optional. The TTL value of this item. If no value is sent and
     *                                      the driver supports TTL then the library may set a default value
     *                                      for it or let the driver take care of that.
     *
     * @return bool True on success and false on failure.
     *
     * @throws \Psr\SimpleCache\InvalidArgumentException
     *   MUST be thrown if the $key string is not a legal value.
     */
    public function set($key, $value, $ttl = null);

    /**
     * Delete an item from the cache by its unique key.
     *
     * @param string $key The unique cache key of the item to delete.
     *
     * @return bool True if the item was successfully removed. False if there was an error.
     *
     * @throws \Psr\SimpleCache\InvalidArgumentException
     *   MUST be thrown if the $key string is not a legal value.
     */
    public function delete($key);

    /**
     * Wipes clean the entire cache's keys.
     *
     * @return bool True on success and false on failure.
     */
    public function clear();

    /**
     * Obtains multiple cache items by their unique keys.
     *
     * @param iterable $keys    A list of keys that can obtained in a single operation.
     * @param mixed    $default Default value to return for keys that do not exist.
     *
     * @return iterable A list of key => value pairs. Cache keys that do not exist or are stale will have $default as value.
     *
     * @throws \Psr\SimpleCache\InvalidArgumentException
     *   MUST be thrown if $keys is neither an array nor a Traversable,
     *   or if any of the $keys are not a legal value.
     */
    public function getMultiple($keys, $default = null);

    /**
     * Persists a set of key => value pairs in the cache, with an optional TTL.
     *
     * @param iterable               $values A list of key => value pairs for a multiple-set operation.
     * @param null|int|\DateInterval $ttl    Optional. The TTL value of this item. If no value is sent and
     *                                       the driver supports TTL then the library may set a default value
     *                                       for it or let the driver take care of that.
     *
     * @return bool True on success and false on failure.
     *
     * @throws \Psr\SimpleCache\InvalidArgumentException
     *   MUST be thrown if $values is neither an array nor a Traversable,
     *   or if any of the $values are not a legal value.
     */
    public function setMultiple($values, $ttl = null);

    /**
     * Deletes multiple cache items in a single operation.
     *
     * @param iterable $keys A list of string-based keys to be deleted.
     *
     * @return bool True if the items were successfully removed. False if there was an error.
     *
     * @throws \Psr\SimpleCache\InvalidArgumentException
     *   MUST be thrown if $keys is neither an array nor a Traversable,
     *   or if any of the $keys are not a legal value.
     */
    public function deleteMultiple($keys);

    /**
     * Determines whether an item is present in the cache.
     *
     * NOTE: It is recommended that has() is only to be used for cache warming type purposes
     * and not to be used within your live applications operations for get/set, as this method
     * is subject to a race condition where your has() will return true and immediately after,
     * another script can remove it, making the state of your app out of date.
     *
     * @param string $key The cache item key.
     *
     * @return bool
     *
     * @throws \Psr\SimpleCache\InvalidArgumentException
     *   MUST be thrown if the $key string is not a legal value.
     */
    public function has($key);
}
```

## 2.2 CacheException

```php

<?php

namespace Psr\SimpleCache;

/**
 * Interface used for all types 
Download .txt
gitextract_dtncyr6s/

├── CODEOWNERS
├── CONTRIBUTING.md
├── LICENSE-CC.md
├── LICENSE-MIT.md
├── LICENSE.md
├── PER.md
├── PSR.md
├── README.md
├── accepted/
│   ├── PSR-0-meta.md
│   ├── PSR-0.md
│   ├── PSR-1-basic-coding-standard-meta.md
│   ├── PSR-1-basic-coding-standard.md
│   ├── PSR-11-container-meta.md
│   ├── PSR-11-container.md
│   ├── PSR-12-extended-coding-style-guide-meta.md
│   ├── PSR-12-extended-coding-style-guide.md
│   ├── PSR-13-links-meta.md
│   ├── PSR-13-links.md
│   ├── PSR-14-event-dispatcher-meta.md
│   ├── PSR-14-event-dispatcher.md
│   ├── PSR-15-request-handlers-meta.md
│   ├── PSR-15-request-handlers.md
│   ├── PSR-16-simple-cache-meta.md
│   ├── PSR-16-simple-cache.md
│   ├── PSR-17-http-factory-meta.md
│   ├── PSR-17-http-factory.md
│   ├── PSR-18-http-client-meta.md
│   ├── PSR-18-http-client.md
│   ├── PSR-2-coding-style-guide-meta.md
│   ├── PSR-2-coding-style-guide.md
│   ├── PSR-20-clock-meta.md
│   ├── PSR-20-clock.md
│   ├── PSR-3-logger-interface-meta.md
│   ├── PSR-3-logger-interface.md
│   ├── PSR-4-autoloader-examples.md
│   ├── PSR-4-autoloader-meta.md
│   ├── PSR-4-autoloader.md
│   ├── PSR-6-cache-meta.md
│   ├── PSR-6-cache.md
│   ├── PSR-7-http-message-meta.md
│   └── PSR-7-http-message.md
├── bylaws/
│   ├── 001-mission-and-structure.md
│   ├── 002-psr-workflow.md
│   ├── 003-per-workflow.md
│   ├── 004-votes.md
│   ├── 005-elections-and-vacancies.md
│   ├── 006-licensing-policies.md
│   ├── 007-psr-amendments.md
│   ├── 008-psr-evolution.md
│   ├── 009-naming-conventions.md
│   ├── 010-funding.md
│   └── 100-implementation.md
├── personnel.md
└── proposed/
    ├── .placeholder
    ├── internationalization-meta.md
    ├── internationalization.md
    ├── phpdoc-meta.md
    ├── phpdoc-tags-meta.md
    ├── phpdoc-tags.md
    ├── phpdoc.md
    ├── psr-8-hug/
    │   ├── PSR-8-hug-meta.md
    │   └── psr-8-hug.md
    ├── security-disclosure-publication-meta.md
    ├── security-disclosure-publication.md
    ├── security-disclosure-publication.xsd
    ├── security-reporting-process-meta.md
    ├── security-reporting-process.md
    ├── tracing-meta.md
    └── tracing.md
Condensed preview — 69 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (612K chars).
[
  {
    "path": "CODEOWNERS",
    "chars": 210,
    "preview": "* @php-fig/secretaries\n/proposed/security* @php-fig/psr-9-10\n/proposed/phpdoc* @php-fig/psr-5\n/proposed/clock* @php-fig/"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 3907,
    "preview": "# Contributing to the PHP-FIG\n\nAnybody who subscribes to the Google Group, is part of the PHP-FIG. As soon as\nyou subscr"
  },
  {
    "path": "LICENSE-CC.md",
    "chars": 19465,
    "preview": "Creative Commons Legal Code\n\nAttribution 3.0 Unported\n\n    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT P"
  },
  {
    "path": "LICENSE-MIT.md",
    "chars": 1077,
    "preview": "Copyright (c) 2013-2017 PHP Framework Interop Group\n\nPermission is hereby granted, free of charge, to any person obtaini"
  },
  {
    "path": "LICENSE.md",
    "chars": 218,
    "preview": "# License\n\nUnless stated otherwise, all content is licensed under the Creative Commons\nAttribution License and code lice"
  },
  {
    "path": "PER.md",
    "chars": 1344,
    "preview": "# PHP Evolving Recommendations\n\nA PHP Evolving Recommendation is a meta document accompanied by one or more artifacts th"
  },
  {
    "path": "PSR.md",
    "chars": 7884,
    "preview": "# PHP Standard Recommendations\n\nAccording to the [PSR Workflow Bylaw][workflow] each PSR has a status as it is being wor"
  },
  {
    "path": "README.md",
    "chars": 2424,
    "preview": "PHP Framework Interoperability Group\n====================================\n\nThe idea behind the group is for project repr"
  },
  {
    "path": "accepted/PSR-0-meta.md",
    "chars": 289,
    "preview": "# PSR-0 Meta Document\n\n## 1. Summary\n\nPSR-0 predates the official FIG structure and describes a standard for \nautoloader"
  },
  {
    "path": "accepted/PSR-0.md",
    "chars": 3034,
    "preview": "Autoloading Standard\n====================\n\n> **Deprecated** - As of 2014-10-21 PSR-0 has been marked as deprecated. [PSR"
  },
  {
    "path": "accepted/PSR-1-basic-coding-standard-meta.md",
    "chars": 338,
    "preview": "# PSR-1 Meta Document\n\n## 1. Summary\n\nThis section of the standard comprises what should be considered the standard\ncodi"
  },
  {
    "path": "accepted/PSR-1-basic-coding-standard.md",
    "chars": 4112,
    "preview": "# Basic Coding Standard\n\nThis section of the standard comprises what should be considered the standard\ncoding elements t"
  },
  {
    "path": "accepted/PSR-11-container-meta.md",
    "chars": 18888,
    "preview": "# Container Meta Document\n\n## 1. Introduction\n\nThis document describes the process and discussions that led to the Conta"
  },
  {
    "path": "accepted/PSR-11-container.md",
    "chars": 4995,
    "preview": "# Container interface\n\nThis document describes a common interface for dependency injection containers.\n\nThe goal set by "
  },
  {
    "path": "accepted/PSR-12-extended-coding-style-guide-meta.md",
    "chars": 12029,
    "preview": "Extended Coding Style Guide Meta Document\n=========================================\n\n# 1. Summary\n\nThis document describ"
  },
  {
    "path": "accepted/PSR-12-extended-coding-style-guide.md",
    "chars": 26110,
    "preview": "# Extended Coding Style Guide\n\nThe key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL NOT\", \"SHOULD\",\n\"SHOULD NOT"
  },
  {
    "path": "accepted/PSR-13-links-meta.md",
    "chars": 6027,
    "preview": "# Link Definition Meta Document\n\n## 1. Summary\n\nHypermedia links are becoming an increasingly important part of the web,"
  },
  {
    "path": "accepted/PSR-13-links.md",
    "chars": 12565,
    "preview": "# Link definition interfaces\n\nHypermedia links are becoming an increasingly important part of the web, in both HTML cont"
  },
  {
    "path": "accepted/PSR-14-event-dispatcher-meta.md",
    "chars": 16100,
    "preview": "Event Dispatcher Meta Document\n==============================\n\n## 1. Summary\n\nThe purpose of this document is to describ"
  },
  {
    "path": "accepted/PSR-14-event-dispatcher.md",
    "chars": 9847,
    "preview": "Event Dispatcher\n================\n\nEvent Dispatching is a common and well-tested mechanism to allow developers to inject"
  },
  {
    "path": "accepted/PSR-15-request-handlers-meta.md",
    "chars": 26131,
    "preview": "HTTP Server Request Handlers Meta Document\n==========================================\n\n## 1. Summary\n\nThe purpose of thi"
  },
  {
    "path": "accepted/PSR-15-request-handlers.md",
    "chars": 4270,
    "preview": "HTTP Server Request Handlers\n============================\n\nThis document describes common interfaces for HTTP server req"
  },
  {
    "path": "accepted/PSR-16-simple-cache-meta.md",
    "chars": 4122,
    "preview": "# PSR-16 Meta Document\n\n## 1. Summary\n\nCaching is a common way to improve the performance of any project, and many\nlibra"
  },
  {
    "path": "accepted/PSR-16-simple-cache.md",
    "chars": 11809,
    "preview": "Common Interface for Caching Libraries\n======================================\n\nThis document describes a simple yet exte"
  },
  {
    "path": "accepted/PSR-17-http-factory-meta.md",
    "chars": 16873,
    "preview": "HTTP Factories Meta\n===================\n\n## 1. Summary\n\nThe purpose of this PSR is to provide factory interfaces that de"
  },
  {
    "path": "accepted/PSR-17-http-factory.md",
    "chars": 6754,
    "preview": "HTTP Factories\n==============\n\nThis document describes a common standard for factories that create [PSR-7][psr7]\ncomplia"
  },
  {
    "path": "accepted/PSR-18-http-client-meta.md",
    "chars": 6695,
    "preview": "HTTP Client Meta Document\n=========================\n\n## Summary\n\nHTTP requests and responses are the two fundamental obj"
  },
  {
    "path": "accepted/PSR-18-http-client.md",
    "chars": 5749,
    "preview": "HTTP Client\n===========\n\nThis document describes a common interface for sending HTTP requests and receiving HTTP respons"
  },
  {
    "path": "accepted/PSR-2-coding-style-guide-meta.md",
    "chars": 1438,
    "preview": "# PSR-2 Meta Document\n\n## 1. Summary\n\nThe intent of this guide is to reduce cognitive friction when scanning code from d"
  },
  {
    "path": "accepted/PSR-2-coding-style-guide.md",
    "chars": 23063,
    "preview": "# Coding Style Guide\n\n> **Deprecated** - As of 2019-08-10 PSR-2 has been marked as deprecated. [PSR-12] is now recommend"
  },
  {
    "path": "accepted/PSR-20-clock-meta.md",
    "chars": 7625,
    "preview": "# Clock Meta Document\n\n## 1. Summary\n\nGetting the current time in applications is typically achieved using the `\\time()`"
  },
  {
    "path": "accepted/PSR-20-clock.md",
    "chars": 1716,
    "preview": "Common Interface for Accessing the Clock\n========================================\n\nThis document describes a simple inte"
  },
  {
    "path": "accepted/PSR-3-logger-interface-meta.md",
    "chars": 2943,
    "preview": "# Logger Meta Document\n\n## 1. Summary\n\nThe logger interface defines a common interface for logging system messages from "
  },
  {
    "path": "accepted/PSR-3-logger-interface.md",
    "chars": 9626,
    "preview": "Logger Interface\n================\n\nThis document describes a common interface for logging libraries.\n\nThe main goal is t"
  },
  {
    "path": "accepted/PSR-4-autoloader-examples.md",
    "chars": 10153,
    "preview": "Example Implementations of PSR-4\n================================\n\nThe following examples illustrate PSR-4 compliant cod"
  },
  {
    "path": "accepted/PSR-4-autoloader-meta.md",
    "chars": 11089,
    "preview": "# PSR-4 Meta Document\n\n## 1. Summary\n\nThe purpose is to specify the rules for an interoperable PHP autoloader that\nmaps "
  },
  {
    "path": "accepted/PSR-4-autoloader.md",
    "chars": 3583,
    "preview": "# Autoloader\n\nThe key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL NOT\", \"SHOULD\",\n\"SHOULD NOT\", \"RECOMMENDED\","
  },
  {
    "path": "accepted/PSR-6-cache-meta.md",
    "chars": 13145,
    "preview": "# PSR-Cache Meta Document\n\n## 1. Summary\n\nCaching is a common way to improve the performance of any project, making\ncach"
  },
  {
    "path": "accepted/PSR-6-cache.md",
    "chars": 17248,
    "preview": "# Caching Interface\n\nCaching is a common way to improve the performance of any project, making\ncaching libraries one of "
  },
  {
    "path": "accepted/PSR-7-http-message-meta.md",
    "chars": 32947,
    "preview": "# HTTP Message Meta Document\n\n## 1. Summary\n\nThe purpose of this proposal is to provide a set of common interfaces for H"
  },
  {
    "path": "accepted/PSR-7-http-message.md",
    "chars": 70901,
    "preview": "# HTTP message interfaces\n\nThis document describes common interfaces for representing HTTP messages as\ndescribed in [RFC"
  },
  {
    "path": "bylaws/001-mission-and-structure.md",
    "chars": 15998,
    "preview": "# Mission Statement\n\nThe PHP Framework Interoperability Group (The PHP FIG) aims to advance the PHP ecosystem and promot"
  },
  {
    "path": "bylaws/002-psr-workflow.md",
    "chars": 7590,
    "preview": "# PHP Standard Recommendation (PSR) Workflow\n\n## Pre-Draft\n\nThe goal of the Pre-Draft stage is to determine whether a ma"
  },
  {
    "path": "bylaws/003-per-workflow.md",
    "chars": 2950,
    "preview": "# PHP Evolving Recommendation Workflow\n\n## Formation\n\nThe goal of the Formation stage is to determine whether a majority"
  },
  {
    "path": "bylaws/004-votes.md",
    "chars": 8448,
    "preview": "# Votes\n\nThere are a number of different types of vote, each of which has its own rule set and expected threshold. Unles"
  },
  {
    "path": "bylaws/005-elections-and-vacancies.md",
    "chars": 5462,
    "preview": "# Elections\n\n## Election Calendar\n\nBoth Secretaries and Core Committee members are elected for two year terms with votes"
  },
  {
    "path": "bylaws/006-licensing-policies.md",
    "chars": 735,
    "preview": "Licensing Policies\n==================\n\n## 1. Copyright Ownership\n\n1. Anytime the copyright owner of code, documentation "
  },
  {
    "path": "bylaws/007-psr-amendments.md",
    "chars": 3677,
    "preview": "Amendments\n==========\n\nFollowing the rules of the [workflow bylaw], once a PSR has been \"Accepted\" the PSR meaning\ncanno"
  },
  {
    "path": "bylaws/008-psr-evolution.md",
    "chars": 5586,
    "preview": "# PSR evolution\n\n## Scope and objectives\n\nA PSR is often comprised of text and code, generally interfaces. Those interfa"
  },
  {
    "path": "bylaws/009-naming-conventions.md",
    "chars": 1058,
    "preview": "Naming conventions for code released by PHP FIG\n===============================================\n\n1. Interfaces MUST be s"
  },
  {
    "path": "bylaws/010-funding.md",
    "chars": 6685,
    "preview": "# Funding\n\n## Scope and objectives\n\nThe PHP-FIG is an organization composed entirely of unpaid volunteers and community "
  },
  {
    "path": "bylaws/100-implementation.md",
    "chars": 1513,
    "preview": "# Implementation of FIG 3.0 changes\n\nUpon the adoption of these bylaws:\n\nAll currently sitting Secretaries will remain i"
  },
  {
    "path": "personnel.md",
    "chars": 14098,
    "preview": "# Personnel\n\n## Current\n\n### Secretaries\n\n| Name                                              | Term                    "
  },
  {
    "path": "proposed/.placeholder",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "proposed/internationalization-meta.md",
    "chars": 1760,
    "preview": "# Internationalization Meta Document\n\n## 1. Summary\n\nDevelopers of components that are not coupled to any specific frame"
  },
  {
    "path": "proposed/internationalization.md",
    "chars": 554,
    "preview": "# Common Interfaces and Functionality for Interoperability of Message Translation and Formatting\n\nThe key words \"MUST\", "
  },
  {
    "path": "proposed/phpdoc-meta.md",
    "chars": 3502,
    "preview": "# PHPDoc Meta Document\n\n## 1. Summary\n\nPHPDoc as a notation was first presented in 2000 by Ulf Wendel, is heavily inspir"
  },
  {
    "path": "proposed/phpdoc-tags-meta.md",
    "chars": 2092,
    "preview": "# PHPDoc Tags Meta Document\n\n## 1. Summary\n\nThe purpose of this PSR is to document (in a catalog style) the de facto lis"
  },
  {
    "path": "proposed/phpdoc-tags.md",
    "chars": 29861,
    "preview": "PSR-19: PHPDoc tags\n=============\n\n## Table Of Contents\n\n- [1. Introduction](#1-introduction)\n- [2. Conventions Used In "
  },
  {
    "path": "proposed/phpdoc.md",
    "chars": 18125,
    "preview": "PSR-5: PHPDoc\n=============\n\n## Table Of Contents\n\n- [1. Introduction](#1-introduction)\n- [2. Conventions Used In This D"
  },
  {
    "path": "proposed/psr-8-hug/PSR-8-hug-meta.md",
    "chars": 430,
    "preview": "PSR-8 Meta Document\n===================\n\n1. Summary\n----------\n\nThe intent of this spec is to improve the overall amicab"
  },
  {
    "path": "proposed/psr-8-hug/psr-8-hug.md",
    "chars": 2797,
    "preview": "Mutually Assured Hug\n====================\n\nThe key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL NOT\", \"SHOULD\","
  },
  {
    "path": "proposed/security-disclosure-publication-meta.md",
    "chars": 2621,
    "preview": "Security Disclosure Meta Document\n=================================\n\n1. Summary\n----------\n\nThere are two aspects with d"
  },
  {
    "path": "proposed/security-disclosure-publication.md",
    "chars": 4565,
    "preview": "## Introduction\n\nThere are two aspects with dealing with security issues: One is the process\nby which security issues ar"
  },
  {
    "path": "proposed/security-disclosure-publication.xsd",
    "chars": 2493,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<xs:schema\n        xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"\n        targetNam"
  },
  {
    "path": "proposed/security-reporting-process-meta.md",
    "chars": 2956,
    "preview": "Security Disclosure Meta Document\n=================================\n\n1. Summary\n----------\n\nThere are two aspects with d"
  },
  {
    "path": "proposed/security-reporting-process.md",
    "chars": 3575,
    "preview": "## Introduction\n\nThere are two aspects with dealing with security issues: One is the process\nby which security issues ar"
  },
  {
    "path": "proposed/tracing-meta.md",
    "chars": 2725,
    "preview": "# Application Tracing Meta Document\n\n## 1. Summary\n\nApplication performance monitoring (APM) tools are becoming increasi"
  },
  {
    "path": "proposed/tracing.md",
    "chars": 863,
    "preview": "# Application Tracing\n\nThe key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL NOT\", \"SHOULD\",\n\"SHOULD NOT\", \"RECO"
  }
]

About this extraction

This page contains the full source code of the php-fig/fig-standards GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 69 files (577.6 KB), approximately 138.8k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!