Table of Contents

PHP RFC: Namespaces in Core

Introduction

Introduce namespaces to user-level symbols to avoid collisions with user defined symbols, decrease breaking changes due to the introduction of new symbols and thus increase future compatibility. A concrete proposal on how to structure the namespaces is proposed as well.

Proposal

This RFC proposes the definition of a standardized namespace structure for PHP internals by utilizing the reserved PHP namespace as the root for all code that is supplied by the PHP Group, and vendor specific root namespaces for symbols that are contributed to the PHP Group from other vendors.

Coding Standard

An important question to answer, if namespaces are to be used by PHP, is how they should be written. PHP has a long history of inconsistency, it therefore makes sense to define this upfront to ensure that any future effort is not going to introduce new inconsistencies.

There are two possible choices:

  1. snake_case
  2. PascalCase (in accordance with class naming)

Arguments for both approaches exist, however, it is after all a purely cosmetic question:

Another question in this regard is whether to allow plural forms (e.g. collection vs collections) in namespaces or not.

Structure

User-level code provided directly by the PHP Group goes into the PHP vendor namespace. The vendor namespace itself does not contain any code directly, but instead is split into multiple sub-namespaces. This should ensure that we are not creating a new global namespace where everything that cannot be categorized ends up in.

The sub-namespaces are basically endless, anything that makes sense can go there. It is up to the PHP Group to decide on them. Examples for namespaces are:

Extensions which are provided by third-party vendors to the PHP Group for future maintenance and inclusion in the PHP repository go into their own vendor namespace. This should ensure that we can move those extensions to PECL without breaking compatibility on a namespace level. It also clearly communicates that that code is not from the PHP Group directly.

Vendor names must not be random, to ensure that they cannot collide with the names that users choose for their own namespaces. Names of companies or organizations (e.g. MySQL, Oracle, W3C) are always a good choice, because they are protected trademarks and nobody is allowed to actually impersonate them. Widely known software names across programming languages (e.g. curl, PCRE, JSON) are also good choices, as the likelihood of someone using them for their own namespaces is low.

That being said, the decision whether a name is a good root namespace for a vendor or not must be decided on a case-by-case basis by the PHP Group. A search on Packagist for existing users should be the minimum requirement there.

What Goes Where?

This question is actually one that the PHP Group had to ask themselves since modules were introduced to internals. The choice is basically simple, group related things by use-case, reuse, and conceptual cohesion. Hence, this is always something that needs to be decided on a case-by-case basis. The introduction of new namespaces should not be problematic, as long as it is clear that that namespace will contain more than just two classes.

Backward Incompatible Changes

None, this RFC affects future decisions only.

Open Issues

Future Scope

Optimization of the directory structure of php-src to reflect the namespace structure. This could help to avoid those 1,000+ LOC files, and would aid discoverability as well as mapping of a user-level symbol to its actual position in the php-src repository. An optimized directory structure could look as follows:

/
├── bin/
│   ├── appveyor/...
│   ├── travis/...
│   ├── php
│   ├── php-cgi
│   ├── php-dbg
│   ├── php-ext
│   ├── php-fmt
│   ├── php-fpm
│   ├── php-ize
│   ├── php-pkg
│   ├── php-tst
│   └── ...
├── bld/
│   ├── debug/
│   │   ├── x64/...
│   │   └── x86/...
│   ├── debug-ts/
│   │   ├── x64/...
│   │   └── x86/...
│   ├── release/
│   │   ├── x64/...
│   │   └── x86/...
│   └── release-ts/
│       ├── x64/...
│       └── x86/...
├── doc/
│   ├── building/
│   │   ├── supported-platforms.ad
│   │   ├── unix.ad
│   │   ├── windows.ad
│   │   └── ...
│   ├── guidelines/
│   │   ├── coding-standard-c.ad
│   │   ├── coding-standard-php.ad
│   │   ├── git-rules.ad
│   │   ├── mailing-list-rules.ad
│   │   └── ...
│   ├── stubs/...
│   ├── testing/...
│   └── ...
├── etc/
│   ├── php/
│   │   ├── development.ini
│   │   ├── logo.svg
│   │   └── production.ini
│   └── ...
├── lib/...
├── src/
│   ├── mysql/...
│   ├── php/
│   │   ├── engine/...
│   │   ├── locale/...
│   │   ├── logging/...
│   │   ├── reflection/...
│   │   └── ...
│   ├── postgresql/...
│   ├── sapi/
│   │   ├── apache/...
│   │   ├── cgi/...
│   │   ├── cli/...
│   │   ├── fpm/...
│   │   └── ...
│   ├── win32/...
│   ├── zend/...
│   └── ...
├── tst/...
├── var/...
├── README.ad
└── ...

Proposed Voting Choices

Simple 50%+1 majority votes as it does not affect the language’s functionality.

  1. Allow namespaces in Core? Yes/No
  2. Coding Standard? snake_case/PascalCase
  3. Allow plural nouns in namespaces? Yes/No
  4. Use PHP root namespace for PHP Group and vendor specific ones for others? Yes/No
  5. Use namespace for the language itself (in the future)? Yes/No
  6. Name of the language namespace? core/lang
  7. Use namespace for tiny self-encapsulated things (in the future)? Yes/No
  8. Name of that namespace? std/util

References