PHP call_user_func so với chỉ gọi hàm


90

Tôi chắc rằng có một lời giải thích rất dễ hiểu cho điều này. Sự khác biệt giữa điều này là gì:

function barber($type){
    echo "You wanted a $type haircut, no problem\n";
}
call_user_func('barber', "mushroom");
call_user_func('barber', "shave");

... và điều này (và những lợi ích là gì?):

function barber($type){
    echo "You wanted a $type haircut, no problem\n";
}
barber('mushroom');
barber('shave');

Câu trả lời:


87

Luôn sử dụng tên hàm thực tế khi bạn biết nó.

call_user_func là để gọi các hàm mà bạn không biết trước tên nhưng nó kém hiệu quả hơn nhiều vì chương trình phải tra cứu hàm trong thời gian chạy.


Cảm ơn Kai. call_user_func hóa ra là chính xác những gì tôi cần.
jay

44
call_user_funclà không cần thiết. Bạn luôn có thể gọi một chức năng bằng cách sử dụng chức năng biến: $some_func(). call_user_func_arraylà một trong những thực sự hữu ích.
Ionuț G. Stan

23
php luôn cần "để tra cứu các chức năng trong thời gian chạy"
VolkerK

2
@Pacerier Không chính xác. Các hàm ẩn danh vẫn ở trong các biến, tức là $func = function(){};. Bất kỳ tham số nào có thể có đối với call_user_func đều phải có thể gọi được, có nghĩa là nó chứa đủ dữ liệu để truy cập trực tiếp, cho dù đó là $func(), hoặc $obj->{$func}()hoặc bất cứ điều gì.
Benubird

2
Các "kém hiệu quả" là thực sự rất ít, đặc biệt là kể từ khi php7, đó là khoảng vài ms / triệu cuộc gọi: github.com/fab2s/call_user_func
fab2s

32

Mặc dù bạn có thể gọi tên hàm biến theo cách này:

function printIt($str) { print($str); }

$funcname = 'printIt';
$funcname('Hello world!');

có những trường hợp bạn không biết mình đang chuyển bao nhiêu đối số. Hãy xem xét những điều sau:

function someFunc() {
  $args = func_get_args();
  // do something
}

call_user_func_array('someFunc',array('one','two','three'));

Nó cũng tiện dụng để gọi các phương thức tĩnh và đối tượng, tương ứng:

call_user_func(array('someClass','someFunc'),$arg);
call_user_func(array($myObj,'someFunc'),$arg);

8
Tôi biết điều này đã cũ, nhưng không thể tìm thấy các bài báo ở nơi khác. Có lợi hơn khi sử dụng call_user_func ('customFunction') như được thêm vào $ variableFunction () không? Sự khác biệt là gì? Cảm ơn!
David Hobs

15

các call_user_functùy chọn là có, do đó bạn có thể làm những việc như:

$dynamicFunctionName = "barber";

call_user_func($dynamicFunctionName, 'mushroom');

nơi dynamicFunctionNamechuỗi có thể thú vị hơn và được tạo ra trong thời gian chạy. Bạn không nên sử dụng call_user_func trừ khi phải làm như vậy, vì nó chậm hơn.


1
Có vẻ như bạn có thể sử dụng một hàm biến trong trường hợp này.
Anthony Rutledge,

6

Tôi tưởng tượng nó rất hữu ích khi gọi một hàm mà bạn không biết trước tên ... Một cái gì đó như:

switch($value):
{
  case 7:
  $func = 'run';
  break;
  default:
  $func = 'stop';
  break;
}

call_user_func($func, 'stuff');

5
Không. Chúng tôi vẫn có thể làm$func('stuff');
ankush981

1
Có, nhưng sự khác biệt là việc sử dụng một biến sẽ tạo ra lỗi PHP Fatal so với cảnh báo PHP nếu sử dụng call_user_func.
Robert Brisita

Điều này không phủ định giá trị của các hàm biến call_user_func()trong trường hợp này.
Anthony Rutledge,


3

Không có lợi ích khi gọi hàm như vậy vì tôi nghĩ nó chủ yếu được sử dụng để gọi hàm "người dùng" (như plugin) vì chỉnh sửa tệp lõi không phải là lựa chọn tốt. đây là ví dụ bẩn được sử dụng bởi Wordpress

<?php
/* 
* my_plugin.php
*/

function myLocation($content){
  return str_replace('@', 'world', $content);
}

function myName($content){
  return $content."Tasikmalaya";
}

add_filter('the_content', 'myLocation');
add_filter('the_content', 'myName');

?>

...

<?php
/*
* core.php
* read only
*/

$content = "hello @ my name is ";
$listFunc = array();

// store user function to array (in my_plugin.php)
function add_filter($fName, $funct)
{
  $listFunc[$fName]= $funct;
}

// execute list user defined function
function apply_filter($funct, $content)
{
  global $listFunc;

  if(isset($listFunc))
  {
    foreach($listFunc as $key => $value)
    {
      if($key == $funct)
      {
        $content = call_user_func($listFunc[$key], $content);
      }
    }
  }
  return $content;
}

function the_content()
{
  $content = apply_filter('the_content', $content);
  echo $content;
}

?>

....

<?php
require_once("core.php");
require_once("my_plugin.php");

the_content(); // hello world my name is Tasikmalaya
?>

đầu ra

hello world my name is Tasikmalaya

0

trong ví dụ đầu tiên của bạn, bạn đang sử dụng tên hàm là một chuỗi. nó có thể đến từ bên ngoài hoặc được xác định khi đang bay. nghĩa là, bạn không biết hàm nào sẽ cần được chạy tại thời điểm tạo mã.


-1

Khi sử dụng không gian tên, call_user_func () là cách duy nhất để chạy một hàm mà bạn không biết trước tên của nó, ví dụ:

$function = '\Utilities\SearchTools::getCurrency';
call_user_func($function,'USA');

Nếu tất cả các chức năng của bạn nằm trong cùng một không gian tên, thì đó sẽ không phải là vấn đề như vậy, vì bạn có thể sử dụng một cái gì đó như sau:

$function = 'getCurrency';
$function('USA');

Chỉnh sửa: Sau @Jannis nói rằng tôi đã sai, tôi đã thử nghiệm thêm một chút và không gặp nhiều may mắn:

<?php
namespace Foo {

    class Bar {
        public static function getBar() {
            return 'Bar';
        }
    }
    echo "<h1>Bar: ".\Foo\Bar::getBar()."</h1>";
    // outputs 'Bar: Bar'
    $function = '\Foo\Bar::getBar';
    echo "<h1>Bar: ".$function()."</h1>";
    // outputs 'Fatal error: Call to undefined function \Foo\Bar::getBar()'
    $function = '\Foo\Bar\getBar';
    echo "<h1>Bar: ".$function()."</h1>";
    // outputs 'Fatal error: Call to undefined function \foo\Bar\getBar()'
}

Bạn có thể xem kết quả đầu ra tại đây: https://3v4l.org/iBERh có vẻ như phương pháp thứ hai hoạt động với PHP 7 trở đi, nhưng không phải PHP 5.6.


. vì không phải là sự thật. $ fn = '\ Foo \ Bar \ getCurrency'; $ fn ();
Jan Sverre

Xin chào @Jannis, tôi không thấy điều đó là đúng, có lẽ bạn có thể thấy tôi đang sai ở đâu, tôi đã thêm một ví dụ chi tiết hơn vào câu trả lời của mình.
ThomasRedstone

@ThomasRedstone Bạn có yêu cầu các chức năng đó trước không? php không tự động tải các chức năng từ các tệp khác. Ngoài ra những gì với các chữ cái nhỏ và lớn trong không gian tên. Bar có phải là một lớp học không? thì đó là một usecase khác.
przemo_li

chào @przemo_li, đây là một tệp duy nhất (tất cả đều nằm trong không gian tên), không chắc chắn điều gì đã xảy ra với tên không gian tên, để bào chữa cho tôi, tôi đã viết câu trả lời 4 năm trước, tôi đã cập nhật không gian tên và thêm vào một ghi chú về PHP 7, với một liên kết để xem kết quả thực tế. Tôi vẫn không biết làm thế nào jansverre làm cho nó hoạt động, PHP 7 không nhập alpha cho đến ngày 11 Tháng Sáu 2015
ThomasRedstone
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.