Когда вы определяете функцию в пространстве имен,
namespace foo { function bar() { echo "foo!\n"; } class MyClass { } }
вы должны указать пространство имен при вызове из другого (или глобального) пространства имен:
bar(); // call to undefined function \bar() foo\bar(); // ok
С помощью классов вы можете использовать инструкцию «use», чтобы эффективно импортировать класс в текущее пространство имен [Edit: Я думал, что вы можете «использовать foo» для получения классов, но, по-видимому, нет.]
use foo\MyClass as MyClass; new MyClass(); // ok, instantiates foo\MyClass
но это не работает с функциями [и будет громоздким, учитывая, сколько есть]:
use foo\bar as bar; bar(); // call to undefined function \bar()
Вы можете псевдоним пространства имен, чтобы префикс был короче,
use foo as f; // more useful if "foo" were much longer or nested f\bar(); // ok
но есть ли способ полностью удалить префикс?
Справочная информация. Я работаю над библиотекой соответствия Hamcrest, которая определяет множество заводских функций, и многие из них предназначены для вложенности. Наличие префикса пространства имен действительно убивает читаемость выражений. сравнить
assertThat($names, is(anArray( equalTo('Alice'), startsWith('Bob'), anything(), hasLength(atLeast(12)) )));
поassertThat($names, is(anArray( equalTo('Alice'), startsWith('Bob'), anything(), hasLength(atLeast(12)) )));
в
use Hamcrest as h; h\assertThat($names, h\is(h\anArray( h\equalTo('Alice'), h\startsWith('Bob'), h\anything(), h\hasLength(h\atLeast(12)) )));
-use Hamcrest as h; h\assertThat($names, h\is(h\anArray( h\equalTo('Alice'), h\startsWith('Bob'), h\anything(), h\hasLength(h\atLeast(12)) )));
PHP 5.6 позволит импортировать функции с use
ключевого слова use
:
namespace foo\bar { function baz() { echo 'foo.bar.baz'; } } namespace { use function foo\bar\baz; baz(); }
См. RFC для получения дополнительной информации: https://wiki.php.net/rfc/use_function
Добавив вспомогательные хаки, упомянутые ниже, вы можете импортировать все из пространства имен Hamcrest в текущее пространство имен, вызывая:
import_namespace('Hamcrest', __NAMESPACE__);
Вот хаки, function_alias работает как http://www.php.net/manual/en/function.class-alias.php, кроме случаев, когда работает над функциями:
function function_alias ($original, $alias) { $args = func_get_args(); assert('count($args) == 2', 'function_alias(): requires exactly two arguments'); assert('is_string($original) && is_string($alias)', 'function_alias(): requires string arguments'); // valid function name - http://php.net/manual/en/functions.user-defined.php assert('preg_match(\'/^[a-zA-Z_\x7f-\xff][\\\\\\\\a-zA-Z0-9_\x7f-\xff]*$/\', $original) > 0', "function_alias(): '$original' is not a valid function name"); assert('preg_match(\'/^[a-zA-Z_\x7f-\xff][\\\\\\\\a-zA-Z0-9_\x7f-\xff]*$/\', $alias) > 0', "function_alias(): '$alias' is not a valid function name"); $aliasNamespace = substr($alias, 0, strrpos($alias, '\\') !== false ? strrpos($alias, '\\') : 0); $aliasName = substr($alias, strrpos($alias, '\\') !== false ? strrpos($alias, '\\') + 1 : 0); $serializedOriginal = var_export($original, true); eval(" namespace $aliasNamespace { function $aliasName () { return call_user_func_array($serializedOriginal, func_get_args()); } } "); }
В сочетании с импортером пространства имён:
function import_namespace ($source, $destination) { $args = func_get_args(); assert('count($args) == 2', 'import_namespace(): requires exactly two arguments'); assert('is_string($source) && is_string($destination)', 'import_namespace(): requires string arguments'); // valid function name - http://php.net/manual/en/functions.user-defined.php assert('preg_match(\'/^([a-zA-Z_\x7f-\xff][\\\\\\\\a-zA-Z0-9_\x7f-\xff]*)?$/\', $source) > 0', "import_namespace(): '$destination' is not a valid namespace name"); assert('preg_match(\'/^([a-zA-Z_\x7f-\xff][\\\\\\\\a-zA-Z0-9_\x7f-\xff]*)?$/\', $destination) > 0', "import_namespace(): '$source' is not a valid namespace name"); foreach(get_declared_classes() as $class) if (strpos($class, $source . '\\') === 0) class_alias($class, $destination . ($destination ? '\\' : '') . substr($class, strlen($source . '\\'))); $functions = get_defined_functions(); foreach(array_merge($functions['internal'], $functions['user']) as $function) if (strpos($function, $source . '\\') === 0) function_alias($function, $destination . ($destination ? '\\' : '') . substr($function, strlen($source . '\\'))); }
Я не знаю элегантного решения, но …
Вы можете создавать функции-оболочки, которые инкапсулируют функции во внешнем пространстве имен. Это позволит вам сохранить читаемость кода …
function assertThat($x, $y) { return h\assertThat($x, $y); }