Cách truyền số lượng đối số biến cho hàm PHP


115

Tôi có một hàm PHP có số lượng đối số (sử dụng func_num_args()func_get_args()) thay đổi, nhưng số lượng đối số tôi muốn truyền hàm phụ thuộc vào độ dài của một mảng. Có cách nào để gọi một hàm PHP với số lượng đối số thay đổi không?


1
Kiểm tra câu trả lời của tôi để tìm hiểu về toán tử splat trong php5.6 mới: stackoverflow.com/a/23163963/1090562
Salvador Dali

Câu trả lời:


132

Nếu bạn có các đối số của mình trong một mảng, bạn có thể quan tâm đến call_user_func_arrayhàm.

Nếu số lượng đối số bạn muốn vượt qua phụ thuộc vào độ dài của một mảng, điều đó có thể có nghĩa là bạn có thể tự đóng gói chúng thành một mảng - và sử dụng đối số đó cho tham số thứ hai call_user_func_array.

Các phần tử của mảng mà bạn vượt qua sau đó sẽ được hàm của bạn nhận dưới dạng các tham số riêng biệt.


Chẳng hạn, nếu bạn có chức năng này:

function test() {
  var_dump(func_num_args());
  var_dump(func_get_args());
}

Bạn có thể đóng gói các tham số của mình thành một mảng, như thế này:

$params = array(
  10,
  'glop',
  'test',
);

Và, sau đó, gọi hàm:

call_user_func_array('test', $params);

Mã này sẽ xuất ra:

int 3

array
  0 => int 10
  1 => string 'glop' (length=4)
  2 => string 'test' (length=4)

tức là 3 tham số; chính xác như iof, hàm được gọi theo cách này:

test(10, 'glop', 'test');

1
Vâng, cảm ơn. call_user_func_array () chính xác là chức năng mà tôi đang tìm kiếm.

Có thể sử dụng call_user_func_array () với một cuộc gọi phương thức đối tượng không?

6
@nohat: bạn được chào đón :-) ;; về việc sử dụng một phương thức của một đối tượng: có, bạn có thể, sử dụng một cái gì đó như mảng ($ obj, 'methodName') làm tham số đầu tiên ;; thực tế, bạn có thể vượt qua bất kỳ "cuộc gọi lại" nào bạn muốn cho chức năng đó. Để biết thêm thông tin về các cuộc gọi lại, hãy xem php.net/callback#lingu.types.callback
Pascal MARTIN

58

Điều này hiện có thể với PHP 5.6.x , sử dụng toán tử ... (còn được gọi là toán tử splat trong một số ngôn ngữ):

Thí dụ:

function addDateIntervalsToDateTime( DateTime $dt, DateInterval ...$intervals )
{
    foreach ( $intervals as $interval ) {
        $dt->add( $interval );
    }
    return $dt;
}

addDateIntervaslToDateTime( new DateTime, new DateInterval( 'P1D' ), 
        new DateInterval( 'P4D' ), new DateInterval( 'P10D' ) );

1
Các đánh máy danh sách đối số biến là một tính năng được giới thiệu trong PHP 7 .
Daniele Orlando

46

Trong Php 5.6 mới , bạn có thể sử dụng ... operatorthay vì sử dụng func_get_args().

Vì vậy, bằng cách sử dụng này, bạn có thể nhận được tất cả các tham số bạn vượt qua:

function manyVars(...$params) {
   var_dump($params);
}

3
Xem thêm thông tin ở đây: php.net/manual/en/...
fracz

Từ liên kết @fracz, OP đang cố gắng tạo ra một "hàm biến đổi".
Nathan Arthur

40

Kể từ PHP 5.6 , một danh sách đối số biến có thể được chỉ định với ...toán tử.

function do_something($first, ...$all_the_others)
{
    var_dump($first);
    var_dump($all_the_others);
}

do_something('this goes in first', 2, 3, 4, 5);

#> string(18) "this goes in first"
#>
#> array(4) {
#>   [0]=>
#>   int(2)
#>   [1]=>
#>   int(3)
#>   [2]=>
#>   int(4)
#>   [3]=>
#>   int(5)
#> }

Như bạn có thể thấy, ...toán tử thu thập danh sách các đối số biến trong một mảng.

Nếu bạn cần chuyển các đối số biến sang hàm khác, ...vẫn có thể giúp bạn.

function do_something($first, ...$all_the_others)
{
    do_something_else($first, ...$all_the_others);
    // Which is translated to:
    // do_something_else('this goes in first', 2, 3, 4, 5);
}

Kể từ PHP 7 , danh sách biến của các đối số có thể bị buộc phải tất cả cùng loại quá.

function do_something($first, int ...$all_the_others) { /**/ }

11

Đối với những người tìm kiếm một cách để làm điều này với $object->method:

call_user_func_array(array($object, 'method_name'), $array);

Tôi đã thành công với điều này trong một hàm xây dựng gọi một phương thức tên biến với các tham số biến.


2
Bạn cũng có thể sử dụng$object->method_name(...$array);
Yoann Kergall

Đi xa hơn, nếu bạn muốn vượt qua bằng cách tham khảo, hãy sử dụng$object->method_name(&...$args);
Fabien Haddadi

4

Bạn chỉ có thể gọi nó.

function test(){        
     print_r(func_get_args());
}

test("blah");
test("blah","blah");

Đầu ra:

Mảng ([0] => blah) Mảng ([0] => blah [1] => blah)


Nếu tôi hiểu OP chính xác, vấn đề không phải là nhận các tham số, mà là gọi hàm với số lượng tham số thay đổi.
Pascal MARTIN

1
Tôi đã không hiểu chính xác về OP. Một mảng chắc chắn sẽ là con đường để đi, sau đó. Sau đó, một lần nữa, anh ta có thể chuyển mảng trực tiếp vào test (), không?
Donnie C

1
Vượt qua một mảng cũng có thể là một giải pháp - Nếu tôi hiểu đúng ^^
Pascal MARTIN

1
Câu hỏi cũ nhưng fyi, một mảng hoạt động tốt nhưng việc truyền các đối số thực tế cho phép bạn sử dụng các giá trị mặc định của PHP cho các đối số null giúp tiết kiệm rất nhiều kiểm tra xấu xí để xem liệu mảng có chứa các giá trị cụ thể không.
Endophage

2

Tôi ngạc nhiên không ai ở đây đã đề cập chỉ đơn giản là vượt qua và trích xuất một mảng. Ví dụ:

function add($arr){
    extract($arr, EXTR_REFS);
    return $one+$two;
}
$one = 1;
$two = 2;
echo add(compact('one', 'two')); // 3

Tất nhiên, điều này không cung cấp xác nhận đối số . Vì thế, bất cứ ai cũng có thể sử dụng chức năng mong đợi của tôi: https://gist.github.com/iautomation/8063fc78e9508ed427d5


1

Một câu hỏi cũ, tôi biết, tuy nhiên, không có câu trả lời nào ở đây thực sự làm tốt công việc chỉ đơn giản là trả lời câu hỏi.

Tôi chỉ chơi xung quanh với php và giải pháp trông như thế này:

function myFunction($requiredArgument, $optionalArgument = "default"){
   echo $requiredArgument . $optionalArgument;
}

Hàm này có thể làm hai việc:

Nếu nó được gọi chỉ với tham số bắt buộc: myFunction("Hi") Nó sẽ in "Hi default"

Nhưng nếu nó được gọi với tham số tùy chọn: myFunction("Hi","me") Nó sẽ in "Hi me";

Tôi hy vọng điều này sẽ giúp bất cứ ai đang tìm kiếm điều này trên đường.


2
Bạn không hiểu câu hỏi. OP đã hỏi về các đối số mà anh ta không phải xác định rõ ràng trong chữ ký hàm - tuy nhiên anh ta vẫn có thể chuyển các giá trị dưới dạng đối số cho hàm. Ví dụ, chữ ký hàm không có bất kỳ đối số nào được xác định (tùy chọn hoặc không), nhưng khi anh ta yêu cầu, OP có thể gửi 45 giá trị khác nhau làm đối số cho hàm.
a20

0

Đây là một giải pháp sử dụng phương thức ma thuật __invoke

(Có sẵn từ php 5.3)

class Foo {
    public function __invoke($method=null, $args=[]){
        if($method){
            return call_user_func_array([$this, $method], $args);
        }
        return false;
    }

    public function methodName($arg1, $arg2, $arg3){

    }
}

Từ trong cùng một lớp:

$this('methodName', ['arg1', 'arg2', 'arg3']);

Từ một thể hiện của một đối tượng:

$obj = new Foo;
$obj('methodName', ['arg1', 'arg2', 'arg3'])

Điều này về cơ bản là sử dụng call_user_func_arraynhư đã nêu bởi câu trả lời được bình chọn hàng đầu trong năm 2009. Có thể có một điểm để gói thêm một phần __invokexung quanh nó - nhưng tôi không thấy nó.
a20
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.