Nasıl variadic işlevlerine argümanlar PHP referans olarak kabul edilebilir?

1 Cevap php

Bu mümkün varsayarsak, nasıl bir PHP bir uyarı oluşturmadan bir değişkin işlev başvuruya göre argümanları geçerdi? Biz artık '&' kullanabilirsiniz bir işlev çağrısı operatör, (o hata eğilimli olurdu olsa bile bir kodlayıcı bunu unutmak gerekir), aksi takdirde bunu kabul ediyorum.

Ne bu ilham ben çıkarılan eski MySQLi sarıcı sınıfları (bu gün, ben sadece PDO kullanmak istiyorum) olduğunu. Sarma ve MySQLi sınıflar arasındaki tek fark sarma istisnalar yerine dönen atmak FALSE.

class DBException extends RuntimeException {}
...
class MySQLi_throwing extends mysqli {
    ...
    function prepare($query) {
        $stmt = parent::prepare($query);
        if (!$stmt) {
            throw new DBException($this->error, $this->errno);
        }
        return new MySQLi_stmt_throwing($this, $query, $stmt);
    }
}
// I don't remember why I switched from extension to composition, but
// it shouldn't matter for this question.
class MySQLi_stmt_throwing /* extends MySQLi_stmt */ {
    protected $_link, $_query, $_delegate;

    public function __construct($link, $query, $prepared) {
        //parent::__construct($link, $query);
        $this->_link = $link;
        $this->_query = $query;
        $this->_delegate = $prepared;
    }
    function bind_param($name, &$var) {
        return $this->_delegate->bind_param($name, $var);
    }
    function __call($name, $args) {
        //$rslt = call_user_func_array(array($this, 'parent::' . $name), $args);
        $rslt = call_user_func_array(array($this->_delegate, $name), $args);
        if (False === $rslt) {
            throw new DBException($this->_link->error, $this->errno);
        }
        return $rslt;
    }
}

Zorluk sarıcı böyle bind_result gibi yöntemler arayarak yatıyor. Sabit Arity fonksiyonlar (örneğin bind_param) açıkça pass-by-başvuru için izin tanımlanabilir. bind_result, ancak, pass-by-reference edilecek tüm argümanlar gerekiyor. Eğer bind_result örneğinde çağırırsanız MySQLi_stmt_throwing olarak-ise, argümanlar değer geçirilir ve bağlayıcı almayacağız.

try {
    $id = Null;
    $stmt = $db->prepare('SELECT id FROM tbl WHERE ...');
    $stmt->execute()
    $stmt->bind_result($id);
    // $id is still null at this point
    ...
} catch (DBException $exc) {
   ...
}

Yukarıdaki sınıflar artık kullanımda olduğundan, bu soru sadece merak meselesidir. Sarıcı sınıflar için alternatif yaklaşımlar ilgili değildir. Null varsayılan değerleri alarak argümanlar bir demet bir yöntem tanımlama doğru değil (ne 20 argümanlar tanımlamak, ancak fonksiyon 21 ile çağrılırsa?). Cevaplar bile MySQL_stmt_throwing açısından yazılı olması gerekmez; somut bir örnek vermek için sadece vardır.

1 Cevap

PHP referans değişken uzunluk argümanı listeleri geçen yolu yoktur. Bu dilin temel bir kısıtlamadır.

array(&$var1, &$var2...) sözdizimi ile bir çözüm, ancak var:

<?php

/** raise all our arguments to the power of 2 */
function pow2() {
        $args = &func_get_arg(0);

        for ($i = 0; $i< count($args); ++$i) {
            $args[$i] *= 2;
        }
}


$x = 1; $y = 2; $z = 3;
pow2(array(&$x, &$y, &$z)); // this is the important line

echo "$x, $y, $z"; // output "2, 4, 6"

?>

Test ayrıca ilan function test($args) ama bu fonksiyonların func_get_args() ailesi ile birlikte çalıştığını göstermek istedim olabilir. Bu array(&$x) Bu değişken referans değil işlevi imza tarafından kabul edilmesi neden olur.

Fonksiyon argümanları PHP'nin belgelerine bir yorumun: http://php.net/manual/en/functions.arguments.php