====== PHP RFC: Importing namespaced functions ======
* Version: 1.1.1
* Date: 2013-05-02
* Author: Igor Wiedler, igor@wiedler.ch
* Status: Implemented (PHP-5.6)
* First Published at: http://wiki.php.net/rfc/use_function
===== Introduction =====
PHP offers the ability to import namespaces and types (classes/interfaces/traits) via the **use** statement. This capability however does not exist for functions. As a result, working with namespaced functions is rather cumbersome.
A function can only be referenced without fully qualifying it, if the calling code is in the same namespace as the function:
namespace foo\bar {
function baz() {
return 'foo.bar.baz';
}
}
namespace foo\bar {
function qux() {
return baz();
}
}
namespace {
var_dump(foo\bar\qux());
}
It is possible to avoid fully qualifying the name by importing the namespace that the function is defined in. But that namespace must still be referenced when calling the function:
namespace foo\bar {
function baz() {
return 'foo.bar.baz';
}
}
namespace {
use foo\bar as b;
var_dump(b\baz());
}
You cannot import the function directly. PHP does not currently support that.
===== Proposal =====
The proposal is to combine existing keywords to a new sequence that allows importing functions into a namespace. This should make namespaced functions less of a pain to use and discourage placing them in the global namespace.
Since functions and classes are in separate namespaces, it is not feasible to use the **use** keyword for both, as it would likely result in conflicts and overhead.
Instead of introducing a new keyword, it would be possible to combine **use** and **function** to a sequence. This new **use function** combo would work as follows:
namespace foo\bar {
function baz() {
return 'foo.bar.baz';
}
function qux() {
return baz();
}
}
namespace {
use function foo\bar\baz, foo\bar\qux;
var_dump(baz());
var_dump(qux());
}
All of this applies not only to functions, but also to namespaced constants. For consistency, a **use const** sequence should also be introduced, that does the same thing for constants:
namespace foo\bar {
const baz = 42;
}
namespace {
use const foo\bar\baz;
var_dump(baz);
}
Just like classes, it should be possible to alias imported functions and constants:
namespace {
use function foo\bar as foo_bar;
use const foo\BAZ as FOO_BAZ;
var_dump(foo_bar());
var_dump(FOO_BAZ);
}
===== General questions & answers =====
==== Why not just import a namespace? ====
While it's true that you can import a namespace and alias it to a single character, this is not necessary for classes, so it makes no sense to require it for functions.
There are two specific use cases where importing a function can significantly improve the readability of code.
=== Tiny libraries ===
Libraries which are just collections of functions can benefit from this. They can be namespaced under (for example) the author's name, e.g. `igorw\compose()`. This prevents namespace clashes.
The users of that function don't care about who the author is, they just want `compose()`. They don't want to invent a new meaningless alias just to use the function.
=== Domain specific languages ===
Functions can be treated as an extension of the language, or to be used to create a custom meta-language. An example of this is building a HTML tree, but this could be anything, really.
A HTML building DSL:
use function html\div, html\p, html\em;
$html = div(p('Some', em('Text')));
Avoiding noise and clutter is really important to make this usable and readable.
==== Global namespace fallback ====
Currently PHP will search for functions in the local namespace first, then fall back to the global one. For functions imported by a **use function** statement, there should be
no fallback.
namespace foo\bar {
function strlen($str) {
return 4;
}
}
namespace {
use function foo\bar\strlen;
use function foo\bar\non_existent;
var_dump(strlen('x'));
var_dump(non_existent());
}
The call to **strlen** is no longer ambiguous. **non_existent** is no longer looked up in the global namespace.
==== Why is "use function" needed instead of just "use"? ====
In PHP, functions and classes are stored in separate namespaces. A function `foo\bar` and a class `foo\bar` can co-exist, because it is possible to infer from the context if the symbol is used as a class or a function:
namespace foo {
function bar() {}
class bar {}
}
namespace {
foo\bar(); // function call
new foo\bar(); // class instantiation
foo\bar::baz(); // static method call on class
}
If **use** were changed to support functions as well, it would introduce BC breaks.
An example:
namespace {
function bar() {}
}
namespace foo {
function bar() {}
}
namespace {
use foo\bar;
bar();
}
The behaviour changed, when **use** was changed. Depending on your PHP version, a different function will be called.
==== Function autoloading ====
Function autoloading is beyond the scope of this RFC.
===== Backward Incompatible Changes =====
No BC breaks.
===== Proposed PHP Version(s) =====
PHP 5.6.x
===== SAPIs Impacted =====
None.
===== Impact to Existing Extensions =====
None.
===== New Constants =====
None.
===== php.ini Defaults =====
None.
===== Open Issues =====
None yet.
===== Patches and Tests =====
There is a patch against PHP-5.6 (currently master) [[https://github.com/php/php-src/pull/526|as a GitHub pull request]].
===== References =====
* Importing namespaces: http://php.net/manual/en/language.namespaces.importing.php
===== Rejected Features =====
- None.
===== Vote =====
The voting period is 15.08.2013 until 29.08.2013.
* Yes?
* No?
===== Changelog =====
* 2013-08-08 1.1.1 Added example of aliasing
* 2013-07-23 1.1.0 Added support for constants with `use const`
* 2013-07-22 1.0.1 FAQ "why 'use function'?"
* 2013-07-19 1.0.0 First version published for discussion