PHP | 'use function function_name;'(其中 function 是 PHP 内置函数)有什么作用?

PHP | What does 'use function function_name;' (where function is a PHP built-in function) do?

我遇到了一些使用 use 关键字的 PHP 代码,与我之前看到的略有不同。 居然在Slim框架源码里看到了

use function array_pop;    // --> confusion :/
use function dirname;      // --> confusion :/
use function file_exists;  // --> confusion :/
use function sprintf;      // --> confusion :/
use function is_readable;  // --> confusion :/
use function is_writable;  // --> confusion :/

source code 从行 2429

我知道关键字 use 适用于 ,包括 类

use Psr\Container\ContainerInterface; // --> class
use Psr\Http\Message\ResponseFactoryInterface; // --> class

或者 在函数的闭包中添加外部作用域变量

$array = array('foo', 'bar', 'baz');
$prefix = uniqid();

$array = array_map(function ($elem) use ($prefix) {  // -> here the use keyword is clear
    return $prefix . $elem;
}, $array);

但是在脚本之上和函数前面声明的use关键字真的很奇怪,而且它们都是内置函数? !.

问题

好的其实很简单,主要问题是,我没有正确阅读文档或者我只是错过了部分,尽管 use 关键字在 [=127= 中被广泛使用,但确实如此],除了不同的功能之外。 无论哪种方式,感谢在评论部分帮助我解决问题的 [(@riggsfolly, @peterm, @eis, @david),经过良好的阅读和测试后,我决定 post 我自己的答案。


快速回答

use function [some_function] 是一个 namespace which defines / import that function for a particular place, this place being the namespaced section givin possibility to have same named function from different namespace and even modifying the name with alias,函数和命名空间都在一起。

可以是用户定义的命名空间,也可以是全局命名空间

在这种情况下,以这种方式调用内置函数只是为了风格/清晰,但也可能 PHP Performance Tip: Use fully-qualified function calls when working with namespaces


详细解答

因此 use 关键字分散了这些功能:

  • 命名空间导入/包含:模块(作为包),类,特征,接口,函数,常量
  • 闭包函数中使用变量的外部范围
  • 在 类 中注入特征。

所以我的问题是指第一点导入/包含(函数)。

使用 类 时命名空间在某种程度上更加明显,一旦在脚本上声明了命名空间,该脚本就成为相对于该命名空间的,而不是全局的。因此,如果您随后调用任何未在同一个脚本中定义的 类 而未指定命名空间,将导致错误,example:

<?php    

    namespace A\B\C;
    class Exception extends \Exception
    {
    }
    
    $a = new Exception('hi'); // $a is an object of class A\B\C\Exception
    $b = new \Exception('hi'); // $b is an object of class Exception
    
    $c = new ArrayObject; // fatal error, class A\B\C\ArrayObject not found

?>

但更清楚的例子是:

<?php
namespace A\B\C;
$b = new Exception('hi'); // Uncaught Error: Class "A\B\C\Exception"

通过删除命名空间,它返回到全局上下文

<?php
$b = new Exception('hi'); // no errors..

然而,constfunctions 并没有发生这种情况,这就是为什么 is 不太明显,如果没有找到就会默默地回到外部范围。

For functions and constants, PHP will fall back to global functions or constants if a namespaced function or constant does not exist.

<?php
namespace A\B\C;

const E_ERROR = 45;
function strlen($str)
{
    return \strlen($str) - 1;
}

echo E_ERROR, "\n"; // prints "45"
echo INI_ALL, "\n"; // prints "7" - falls back to global INI_ALL

echo strlen('hi'), "\n"; // prints "1"
if (is_array('hi')) { // prints "is not array"
    echo "is array\n";
} else {
    echo "is not array\n";
}
?>

最后,举一些关于我的问题的例子: 文件functions.php

namespace MyApp\Package;

//use function var_dump;
function var_dump($var)
{
    echo '[', __NAMESPACE__, '] don\'t wnat to do that...<br/>';
}
function explode($separator, $some_string)
{
    echo '[', __NAMESPACE__, '] opps, bomb failed :(...<br/>';
}

文件index.php

<?php

namespace MyApp;
require_once 'functions.php';

use MyApp\Package; // Demostrate that we can 'import' the entire package namespace
use function MyApp\Package\var_dump; // Import the function only

class A
{
    public static function say() {
        $a = "a";
        $b = "b";
        $data = ['a' => $a, 'b' => $b];
        echo var_dump($data); // --> Calling the namespaced function
    }
    public static function sayReal()
    {
        $a = "a";
        $b = "b";
        $data = ['a' => $a, 'b' => $b];
        echo \var_dump($data); // -> with \ we make the lookup fully-qualified and falls back to global
    }
    public static function explodeBadBomb($bomb="something to explode")
    {
        Package\explode(" ",$bomb); // -> demostrate that we can namespaced in withing blocks and statements
    }
    public static function explodeGooodBomb($bomb="something to explode")
    {
        echo print_r(\explode(" ", $bomb)); // again calling the built-in
    }
}
A::say();               // [MyApp\Package] don't wnat to do that...
A::sayReal();           // array(2) { ["a"]=> string(1) "a" ["b"]=> string(1) "b" }
A::explodeBadBomb();    // MyApp\Package] opps, bomb failed :(...
A::explodeGooodBomb();  // Array ( [0] => something [1] => to [2] => explode ) 

文档

有关性能改进的更多信息

相关 Whosebug 问题/答案

  • In PHP, what is a closure and why does it use the "use" identifier?
  • Use keyword in functions - PHP [duplicate]