Truyền một mảng dưới dạng đối số, không phải là mảng, trong PHP


148

Tôi dường như nhớ rằng trong PHP có một cách để truyền một mảng dưới dạng một danh sách các đối số cho một hàm, hủy bỏ mảng func($arg1, $arg2)theo cách chuẩn . Nhưng bây giờ tôi không biết làm thế nào để làm điều đó. Tôi nhớ lại cách truyền bằng tham chiếu, cách "toàn cầu" các tham số đến ... nhưng không phải là cách liệt kê lại mảng thành một danh sách các đối số.

Nó có thể đơn giản như func(&$myArgs), nhưng tôi khá chắc chắn rằng nó không phải là nó. Nhưng, thật đáng buồn, hướng dẫn sử dụng php.net đã không tiết lộ bất cứ điều gì cho đến nay. Không phải là tôi đã phải sử dụng tính năng đặc biệt này trong năm ngoái hoặc lâu hơn thế.

Câu trả lời:


178

http://www.php.net/manual/en/feft.call-user-func-array.php

call_user_func_array('func',$myArgs);

1
Tôi có thể đã thề rằng nó cũng không phải là một chức năng, như một nhân vật tiền tố hoặc một cái gì đó. Cảm ơn.
Robert K

8
Nhưng tôi không biết Python! Tôi phải vô tình là nhà ngoại cảm ...: D
Robert K

45
Giải nén đối số, như được gọi, sẽ được thêm vào PHP 5.6 ( wiki.php.net/rfc/argument_unpacking ). Nó sẽ sử dụng 'toán tử splat': '...'. Cú pháp của nó: $args = [1,2,3]; function(...$args){}
arothuis

4
nhưng nếu hàm bạn muốn gọi là một phương thức cá thể trên một đối tượng, không phải là tên hàm trong không gian toàn cầu thì sao?
ahnbizcad

6
@ahnbizcad thì bạn nên sử dụng a callable, sử dụng tương tự call_user_func_array, chỉ với mảng trong đó phần tử đầu tiên là đối tượng và thứ hai là phương thức. Ví dụcall_user_func_array([$object, 'method'], $myArgs);
SteveB

149

Như đã đề cập , kể từ phiên bản PHP 5.6+, bạn có thể (nên!) Sử dụng ...mã thông báo (còn gọi là "toán tử splat", một phần của chức năng hàm matrixdic ) để dễ dàng gọi một hàm với một mảng các đối số:

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

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

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

// 'Hello World'

Lưu ý: các mục mảng được ánh xạ tới các đối số theo vị trí của chúng trong mảng, không phải các khóa của chúng.

Theo nhận xét của CarlosCarucce , hình thức giải nén đối số này là phương pháp nhanh nhất cho đến nay trong mọi trường hợp. Trong một số so sánh, nó nhanh hơn 5x call_user_func_array.

Qua một bên

Bởi vì tôi nghĩ rằng điều này thực sự hữu ích (mặc dù không liên quan trực tiếp đến câu hỏi): bạn có thể gõ gợi ý tham số toán tử splat trong định nghĩa hàm của bạn để đảm bảo tất cả các giá trị được truyền phù hợp với một loại cụ thể.

(Chỉ cần nhớ rằng làm điều này, nó PHẢI là tham số cuối cùng bạn xác định và nó bó tất cả các tham số được truyền cho hàm vào mảng.)

Điều này là tuyệt vời để đảm bảo một mảng chứa các mục thuộc một loại cụ thể:

<?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
Điều này có một cải tiến hiệu suất tuyệt vời hơn call_user_func_array. Vì vậy, nếu bạn đang sử dụng php 5.6+, tôi sẽ giới thiệu cái này. Đây là một bài kiểm tra , được trích dẫn trong wiki php chính thức
CarlosCarucce

2
Thật đáng tiếc đây không phải là câu trả lời được đánh dấu. Chắc chắn là cách tốt hơn
unorgiven1987

81

Cũng lưu ý rằng nếu bạn muốn áp dụng một phương thức cá thể cho một mảng, bạn cần truyền hàm như:

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

4
@understack $foo->bar()Ví dụ trên trang được liên kết cho thấy rằng nó nên như vậy array($instance, "MethodName").
Paul Calcraft

11
Thật tuyệt vời, tôi đã sử dụng điều này để tránh trùng lặp các đối số của hàm tạo trong một lớp con :)call_user_func_array(array(parent, "__construct"), func_get_args());
Jason

10

Để hoàn thiện, kể từ PHP 5.1, điều này cũng hoạt động:

<?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"
?>

Xem: http://php.net/reflectionfeft.invokeargie

Đối với các phương thức, bạn sử dụng ReflectionMethod :: invokeArss thay vào đó và truyền đối tượng làm tham số đầu tiên.


Đây thực sự là những gì tôi đang tìm kiếm!
Dejv 16/2/2015
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.