PHP参数顺序问题:错误或勘误表


PHP Argument Order Issue: Bug or Errata?

我是PHP新手,遇到了一些奇怪的行为,这可能是也可能不是我的PHP版本(5.4.13)中的错误。我发现了一个函数参数顺序在函数声明中很重要的情况。

class Book {
  function __construct() { }
  public static function withDescriptors($isNotOrmObject, $isArray, $isScalar) {
    $instance = new self();
    // initialization here
    return $instance;
  }
}

调用withDescriptors会导致'数组到字符串转换'异常。当调用withDescriptors时抛出错误。withDescriptors永远不会实际执行。但是,将object参数与array参数交换可以解决这个问题。例如

public static function withDescriptors($isArray, $isNotOrmObject, $isScalar){ ....

这是已知的PHP特性还是一个bug?

更明确:

class Book {
  function __construct() { }
  public static function withDescriptors($isNotOrmObject, $isArray, $isScalar) {
    $instance = new self();
    // initialization here
    return $instance;
  }
}
$book = Book::withDescriptors($isNotORMobject, $isArray, $isScalar);

class Book {
  function __construct() { }
  public static function withDescriptors($isArray, $isNotORMobject, $isScalar) {
    $instance = new self();
    // initialization here 
    return $instance;
  }
}
$book = Book::withDescriptors($isArray, $isNotORMobject, $isScalar);
作品

好了。只有的区别是参数序列,"initialization here"代码是相同的。

在第二个示例中没有得到警告的原因是,作为第二个参数传递的Object正在实现一个神奇的__toString()方法。PHP不是一种强类型语言,但是最近的版本有有限的类型提示功能。

说明警告;

function saySomething($shouldBeAString)
{
    echo $shouldBeAString
}
saySomething(array('hello'));

输出"数组"

和警告array to string conversion

class Foo {
   public function __toString() {
       return 'Hi I am Foo';
   }
}
$bar = new Foo();
 saySomething($bar);

将输出

'Hi I am Foo'
毫无预警地

如前所述,PHP提供有限的类型提示。您可以指定所需的'类/对象类型'和'数组'作为可接受的参数,但不能标量类型,如'string', 'int', 'bool'等。
function (array $myarray) {
    // will only accept arrays
    // or something that implements array-access
}
function (Foo $var) {
    // Will only accept 'Foo' objects
}

多态性/函数重载

其他一些语言允许多次定义相同的方法/函数,但使用不同的签名(其他参数类型)。PHP没有明确支持这个

例如,在其他语言中,允许这样做:

function doSomething(string $arg1) { ......}
function doSomething(array $arg1) { .... }
function doSomething(string $arg1, string $arg2) { ... }

在这些语言中,根据参数的类型和数量,将执行变体1、2或3。PHP不支持这个,因为它要求函数/方法有一个唯一的名称。因此,PHP会抱怨函数doSomething()已经定义了。

但是,您可以通过几种方式在PHP中创建类似的东西;

 // rename the functions/methods so that they have a unique name
function _doSomething1(string $arg1) { ......}
function _doSomething2(array $arg1) { .... }
function _doSomething3(string $arg1, string $arg2) { ... }

// create the 'wrapper' function *without arguments specified*
function doSomething() {
    // determin which variant should be executed
    $numargs = func_num_args();
    $args = func_get_args();
    if ($numargs == 2) {
        // 2 arguments -> variant 3
        return call_user_func_array('_doSomething3', $args);
    } else if {$numargs == 1) {
        if (is_array($args[0]) {
            // first argument is an array
            return call_user_func_array('_doSomething2', $args);
        } else {
            return call_user_func_array('_doSomething1', $args);
        }
    }
}

注意:上面的代码是'假'代码,只是为了说明这个想法!

一般来说,函数参数的顺序很重要。唯一不这样做的情况是当参数是相同类型或者你的函数实现了像get opt long这样的东西。

这里有一些很好的答案,但是这个特殊的情况是由于PHP解释器中的一个错误引起的。