Передача масиву як аргументи, а не масив, в PHP


148

Здається, я пам’ятаю, що в PHP є спосіб передавати масив як список аргументів для функції, дереференціюючи масив у стандартний func($arg1, $arg2)спосіб. Але зараз я загубився, як це зробити. Я пригадую спосіб проходження посилання, як "глобувати" вхідні параметри ... але не як де-перелічити масив у список аргументів.

Це може бути так просто func(&$myArgs), але я впевнений, що це не так. Але, на жаль, керівництво php.net поки що нічого не розкривало. Не те, що мені довелося користуватися цією особливістю протягом останнього року.

Відповіді:


178

1
Я міг би присягнути, що це теж нефункціональність, як символ префікса чи щось таке. Дякую.
Роберт К

8
Але я не знаю Python! Я повинен бути випадково психічним ...: D
Роберт К

45
Розпакування аргументу, як його називають, буде додано в PHP 5.6 ( wiki.php.net/rfc/argument_unpacking ). Він буде використовувати оператор splat ':' ... '. Його синтаксис: $args = [1,2,3]; function(...$args){}
arothuis

4
але що робити, якщо функція, яку ви хочете викликати, це метод примірника на об’єкті, а не ім'я функції у глобальному просторі?
ahnbizcad

6
@ahnbizcad тоді ви повинні використовувати a callable, який використовує те саме call_user_func_array, тільки з масивом, де перший елемент є об'єктом, а другий - методом. Наприкладcall_user_func_array([$object, 'method'], $myArgs);
SteveB

149

Як уже згадувалося , з PHP 5.6+ ви можете (повинні!) Використовувати ...маркер (він же "оператор splat", частина функцій різноманітних функцій), щоб легко викликати функцію з масивом аргументів:

<?php
function variadic($arg1, $arg2)
{
    // Do stuff
    echo $arg1.' '.$arg2;
}

$array = ['Hello', 'World'];

// 'Splat' the $array in the function call
variadic(...$array);

// 'Hello World'

Примітка: елементи масиву відображаються в аргументах за їхньою позицією в масиві, а не за їх ключами.

Відповідно до коментаря CarlosCarucce , ця форма розпакування аргументів є найшвидшим методом на сьогоднішній день у всіх випадках. У деяких порівняннях це в 5 разів швидше, ніж call_user_func_array.

Убік

Тому що я думаю, що це дійсно корисно (хоча безпосередньо не пов’язано з питанням): ви можете ввести натяк на параметр оператора splat у визначенні своєї функції, щоб переконатися, що всі передані значення відповідають конкретному типу.

(Пам'ятайте лише, що для цього це ОБОВ'ЯЗКОВО бути останнім параметром, який ви визначаєте, і що він зв'язує всі параметри, передані функції в масив.)

Це чудово, щоб переконатися, що масив містить елементи певного типу:

<?php

// Define the function...

function variadic($var, SomeClass ...$items)
{
    // $items will be an array of objects of type `SomeClass`
}

// Then you can call...

variadic('Hello', new SomeClass, new SomeClass);

// or even splat both ways

$items = [
    new SomeClass,
    new SomeClass,
];

variadic('Hello', ...$items);

7
Це значно покращило ефективність роботи call_user_func_array. Тож якщо ви використовуєте php 5.6+, я б рекомендував цей. Ось тест , який був цитований в офіційній вікі-php
CarlosCarucce

2
Це дуже прикро, що це не помічена відповідь. Однозначно краще
непрощено1987

81

Також зауважте, що якщо ви хочете застосувати метод екземпляра до масиву, вам потрібно передати функцію як:

call_user_func_array(array($instance, "MethodName"), $myArgs);

4
@understack $foo->bar()Приклад на пов’язаній сторінці говорить про те, що так і має бути array($instance, "MethodName").
Пол Калкрафт

11
Дивовижно, я використовував це, щоб уникнути дублювання аргументів конструктора в дитячому класі :)call_user_func_array(array(parent, "__construct"), func_get_args());
Джейсон

10

Для повноти, як і в PHP 5.1, це працює:

<?php
function title($title, $name) {
    return sprintf("%s. %s\r\n", $title, $name);
}
$function = new ReflectionFunction('title');
$myArray = array('Dr', 'Phil');
echo $function->invokeArgs($myArray);  // prints "Dr. Phil"
?>

Дивіться: http://php.net/reflectionfunction.invokeargs

Для методів ви використовуєте ReflectionMethod :: invokeArgs замість цього і передаєте об'єкт як перший параметр.


Це насправді те, що я шукав!
Devv
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.