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 从行 24
到 29
。
我知道关键字 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
关键字真的很奇怪,而且它们都是内置函数? !.
问题
- 函数[built-in-function-name]有什么作用;在 PHP (PHP "^7.4 || ^8.0")?
中执行
好的其实很简单,主要问题是,我没有正确阅读文档或者我只是错过了部分,尽管 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..
然而,const
和 functions
并没有发生这种情况,这就是为什么 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 )
文档
- Using namespaces: fallback to global function/constant
- Namespaces
- FAQ: things you need to know about namespaces
有关性能改进的更多信息
相关 Whosebug 问题/答案
- In PHP, what is a closure and why does it use the "use" identifier?
- Use keyword in functions - PHP [duplicate]
我遇到了一些使用 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 从行 24
到 29
。
我知道关键字 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
关键字真的很奇怪,而且它们都是内置函数? !.
问题
- 函数[built-in-function-name]有什么作用;在 PHP (PHP "^7.4 || ^8.0")? 中执行
好的其实很简单,主要问题是,我没有正确阅读文档或者我只是错过了部分,尽管 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..
然而,const
和 functions
并没有发生这种情况,这就是为什么 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 )
文档
- Using namespaces: fallback to global function/constant
- Namespaces
- FAQ: things you need to know about namespaces
有关性能改进的更多信息
相关 Whosebug 问题/答案
- In PHP, what is a closure and why does it use the "use" identifier?
- Use keyword in functions - PHP [duplicate]