2010-07-28 34 views
25

Khi bạn định nghĩa một hàm trong một không gian tên,Gọi một hàm PHP được định nghĩa trong namespace khác mà không tiền tố

namespace foo { 
    function bar() { echo "foo!\n"; } 
    class MyClass { } 
} 

bạn phải xác định không gian tên khi gọi nó từ một (hoặc toàn cầu) namespace:

bar();   // call to undefined function \bar() 
foo\bar();  // ok 

với các lớp, bạn có thể sử dụng các "sử dụng" tuyên bố có hiệu quả nhập khẩu một lớp thành các namespace hiện tại [Edit:. tôi nghĩ bạn có thể "sử dụng foo" để có được các lớp học, nhưng dường như không]

use foo\MyClass as MyClass; 
new MyClass(); // ok, instantiates foo\MyClass 

nhưng điều này không làm việc với chức năng [và sẽ trở nên cồng kềnh được bao nhiêu có]:

use foo\bar as bar; 
bar();   // call to undefined function \bar() 

Bạn có thể bí danh không gian tên để làm cho tiền tố ngắn hơn để gõ,

use foo as f; // more useful if "foo" were much longer or nested 
f\bar();  // ok 

nhưng có cách nào để loại bỏ tiền tố hoàn toàn không?

Thông tin cơ bản: Tôi đang làm việc trên thư viện kết hợp Hamcrest xác định rất nhiều chức năng của nhà máy và nhiều trong số chúng được thiết kế để lồng nhau. Có tiền tố không gian tên thực sự giết chết khả năng đọc của các biểu thức. Hãy so sánh

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)) 
    ))); 

Trả lời

28

PHP 5.6 sẽ cho phép nhập khẩu chức năng với use keyword:

namespace foo\bar { 
    function baz() { 
     echo 'foo.bar.baz'; 
    } 
} 

namespace { 
    use function foo\bar\baz; 
    baz(); 
} 

Xem RFC để biết thêm thông tin: https://wiki.php.net/rfc/use_function

+2

Tôi vừa xây dựng 5.6.0-dev trên các cửa sổ và dùng thử.Dường như làm việc tuyệt vời, mặc dù bạn phải nhập từng chức năng riêng lẻ. – b01

+3

Đây là câu trả lời đúng cho câu hỏi này. – user3640967

1

Tôi không biết một giải pháp nhã, nhưng ...

Bạn có thể tạo các chức năng wrapper mà gói gọn các chức năng trong không gian tên bên ngoài. Điều này sẽ cho phép bạn giữ khả năng đọc mã của bạn ...

function assertThat($x, $y) { return h\assertThat($x, $y); }

+0

Các chức năng hiện đã wrappers tiện mà gọi phương pháp nhà máy tĩnh thực sự. Tôi có thể cung cấp bản sao của mô-đun này mà không có không gian tên và cho phép người dùng quyết định họ muốn nhập. Hiệu ứng sẽ giống nhau và tôi đặt cược khá dễ dàng để tự động hóa. –

7

Bằng cách thêm các hacks helper đề cập dưới đây, bạn có thể nhập tất cả mọi thứ từ hamcrest namespace để namespace hiện bằng cách gọi:

import_namespace('Hamcrest', __NAMESPACE__); 

Dưới đây là các hacks, function_alias hoạt động như http://www.php.net/manual/en/function.class-alias.php trừ khi công trình trên các chức năng:

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()); 
     } 
    } 
    "); 

} 

kết hợp với tên không gian nhà nhập khẩu:

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 . '\\'))); 
} 
+19

Sáng tạo, nhưng khủng khiếp! – Evert

Các vấn đề liên quan