简体   繁体   English

PHP 变量打包解包

[英]PHP variable packing and unpacking

I have a function that is used in Stripe PHP that requires PHP 5.6.我有一个 function,用于需要 PHP 5.6 的 Stripe PHP。 I am running it on a server that has PHP 5.5.9 and giving me some trouble.我在一台有 PHP 5.5.9 的服务器上运行它,给我带来了一些麻烦。 The function is: function 是:

protected function buildPath($basePath, ...$ids)
    {
        foreach ($ids as $id) {
            if (null === $id || '' === \trim($id)) {
                $msg = 'The resource ID cannot be null or whitespace.';

                throw new \Stripe\Exception\InvalidArgumentException($msg);
            }
        }

        return \sprintf($basePath, ...\array_map('\urlencode', $ids));
    }

I understand that the elipses(...) means it is variable packing.我知道 elipses(...) 意味着它是可变包装。 but when I try to convert it to something PHP 5.5.9 can use, using the below, it does not work:但是当我尝试将它转换为 PHP 5.5.9 可以使用的东西时,使用下面的方法,它不起作用:

protected function buildPath($basePath, pack($ids))
    {
        foreach ($ids as $id) {
            if (null === $id || '' === \trim($id)) {
                $msg = 'The resource ID cannot be null or whitespace.';

                throw new \Stripe\Exception\InvalidArgumentException($msg);
            }
        }

        return \sprintf($basePath, ...\array_map('\urlencode', $ids));
    }

... in PHP can be used for two things: ... in PHP 可用于两件事:

  • Array unpacking , when calling a function, or populating another array.数组解包调用function 或填充另一个数组时。 Note that this is not related to the unpack function, which is about handling binary data, but means "turn the items of this array into separate arguments to the function", or "... separate items of the final array".请注意,这与unpack function 无关,它是关于处理二进制数据的,而是意味着“将此数组的项目转换为单独的 arguments 到函数”,或“......最终数组的单独项目”。
  • Collecting variadic arguments - that is, a variable length argument list - when declaring a function. This is close to the reverse of "unpacking", but I've never heard it called "packing".收集可变参数 arguments - 即可变长度参数列表- 当声明一个 function 时。这接近于“解包”的逆向,但我从未听说过它被称为“打包”。 Again, the pack function is completely unrelated (although, by coincidence, it is itself a variadic function).同样,function 是完全不相关的(尽管巧合的是,它本身就是一个可变参数函数)。 The effect is to take any number of arguments passed to the function and turn them into an array.效果是将任意数量的 arguments 传递给 function 并将它们变成一个数组。

The example you show uses both features.您展示的示例同时使用了这两个功能。


For the function signature , it is using variadic arguments .对于 function签名,它使用可变参数 arguments As noted on the manual page linked earlier:如前面链接的手册页所述:

Note: It is also possible to achieve variable-length arguments by using func_num_args(), func_get_arg(), and func_get_args() functions.注意:也可以通过使用 func_num_args()、func_get_arg() 和 func_get_args() 函数来实现可变长度 arguments。

So, in all supported versions of PHP (5.5 has been unsupported for over 5 years ; I hope you're paying someone for long-term-support security patches,): you can define the following function:因此,在 PHP 的所有受支持版本中(5.5 已不受支持超过 5 年;我希望你花钱请人获得长期支持的安全补丁,):你可以定义以下函数:

function example($normalArg, ...$variadicArgs) {
    var_dump($variadicArgs);
}

and call it like this:并这样称呼它:

example('normal'); // $variadicArgs = []
example('normal', 1); // $variadicArgs = [1]
example('normal', 1, 2); // $variadicArgs = [1,2]
example('normal', 1, 2, 3); // $variadicArgs = [1,2,3]

In ancient versions of PHP before the ... notation was added, you had to instead declare the function with only the normal arguments, collect all the passed arguments by calling func_get_args , and skip over the "normal" ones.在添加...符号之前的 PHP 的古代版本中,您必须改为仅使用正常的 arguments 声明 function,通过调用func_get_args收集所有传递的 arguments,并跳过“正常”的。 For example:例如:

function example($normalArg) {
    $allArgs = func_get_args();
    $variadicArgs = array_slice($allArgs, 1);
    var_dump($variadicArgs);
}

So in your case, the function could begin:因此,在您的情况下, function 可以开始:

protected function buildPath($basePath)
{
    $ids = \array_slice(\func_get_args(), 1);

Later in the function, it is using array unpacking .后面的function,就是用数组拆包 The only way to achieve this in ancient versions of PHP is using call_user_func_array , which takes a "callable" (which in simple cases can just be a function name as a string), and an array of arguments to pass to it.在 PHP 的古代版本中实现此目的的唯一方法是使用call_user_func_array ,它采用“可调用”(在简单情况下可以是字符串形式的 function 名称)和传递给它的 arguments 数组。 Again, you'll need to construct the full list of arguments, for instance using array_merge :同样,您需要构建 arguments 的完整列表,例如使用array_merge

$fixedArgs = [$basePath];
$dynamicArgs = \array_map('\urlencode', $ids);
$allArgs = \array_merge($fixedArgs, $dynamicArgs);
return \call_user_func_array('\sprintf', $allArgs);

Or all on one line:或者全部在一条线上:

return \call_user_func_array('\sprintf', \array_merge([$basePath], \array_map('\urlencode', $ids)]);

As it happens, the particular function called here is sprintf , which has a variant called vsprintf ("v" for "vector") which takes an array of parameters instead of multiple separate arguments, so for this particular case you can use that:碰巧,这里调用的特定 function 是sprintf ,它有一个名为vsprintf (“v”代表“向量”)的变体,它采用参数数组而不是多个单独的 arguments,因此对于这种特殊情况,您可以使用它:

return \vsprintf($basePath, \array_map('\urlencode', $ids));

In php 5.5.9 it can be written like this and is called Variadic function :在 php 5.5.9中可以这样写,称为Variadic function

protected function buildPath($basePath)
    {
        $ids = func_get_args();
        array_shift($ids);
        foreach ($ids as $id) {
            if (null === $id || '' === \trim($id)) {
                $msg = 'The resource ID cannot be null or whitespace.';

                throw new \Stripe\Exception\InvalidArgumentException($msg);
            }
        }

        return \sprintf($basePath, ...\array_map('\urlencode', $ids));
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM