PHP mysqli sarıcı: (__ () çağrısı ve call_user_func_array ile referans olarak geçen)

3 Cevap php

Ben stackoverflow uzun bir çalışan fan, ilk kez posteri değilim. Birisi bana bu konuda yardımcı olabilir görmek isterdim. Sonra benim sorunu anlatacağım, bana biraz kod ile kazmak sağlar. Ben şu sarıcı sınıfları var:

class mysqli_wrapper
{
    private static $mysqli_obj;
    function __construct() // Recycles the mysqli object
    {
        if (!isset(self::$mysqli_obj))
        {
            self::$mysqli_obj = new mysqli(MYSQL_SERVER, MYSQL_USER, MYSQL_PASS, MYSQL_DBNAME);
        }
    }
    function __call($method, $args)
    {
        return call_user_func_array(array(self::$mysqli_obj, $method), $args);
    }
    function __get($para)
    {
        return self::$mysqli_obj->$para;
    }
    function prepare($query) // Overloaded, returns statement wrapper
    {
        return new mysqli_stmt_wrapper(self::$mysqli_obj, $query);
    }
}

class mysqli_stmt_wrapper
{
    private $stmt_obj;
    function __construct($link, $query)
    {
        $this->stmt_obj = mysqli_prepare($link, $query);
    }
    function __call($method, $args)
    {
        return call_user_func_array(array($this->stmt_obj, $method), $args);
    }
    function __get($para)
    {
        return $this->stmt_obj->$para;
    }
    // Other methods will be added here
}

Benim sorunum bind_result() mysqli_stmt_wrapper sınıfına çağırdığınızda, benim değişkenleri referans olarak kabul edilecek ve hiçbir şey geri alır görünmüyor olmasıdır. Ben bu kod bölümü çalıştırırsanız göstermek için, ben yalnızca NULL en olsun:

$mysqli = new mysqli_wrapper;

$stmt = $mysqli->prepare("SELECT cfg_key, cfg_value FROM config");
$stmt->execute();
$stmt->bind_result($cfg_key, $cfg_value);

while ($stmt->fetch())
{
    var_dump($cfg_key);
    var_dump($cfg_value);
}
$stmt->close();

Ben de bana söyler PHP güzel bir hata alıyorum: PHP Warning: Parameter 1 to mysqli_stmt::bind_result() expected to be a reference, value given in test.php on line 48


Ben bind_param() işlevi aşırı denedim, ama referans olarak bağımsız değişken bir numara almak için nasıl anlamaya olamaz. func_get_args() ya da yardım için mümkün görünmüyor.

I $stmt->bind_result(&$cfg_key, &$cfg_value) çalışması gerektiği gibi referans değişkenleri geçmek, ancak bu davranışı önerilmiyor ve daha hataları atar ise.

Herkes bu etrafında bazı fikirler var mı? Zaman ayırdığınız için çok teşekkür ederiz.

3 Cevap

Eğer mysqli_stmt sınıfından genişletilmesi olacak eğer referans sorununu atlamak olacak. (Ki temiz bir çözümü var)

class mysqli_stmt_wrapper extends mysqli_stmt {
  public function __construct($link, $query) {
    parent::__construct($link, $query);
  }
}

class mysqli_wrapper extends mysqli {
  public function prepare($query) {
    return new mysqli_stmt_wrapper($this, $query);
  }
}

Ben senin __call bunu yapamaz ise orijinal işlevi imza, bu başvurular beklediğini belirtir çünkü bu olduğunu tahmin ediyorum. Bu nedenle, __call kullanarak çalışıyorum ama açıkça orijinal olarak aynı işlevi imza ile bind_result ekledi.

Ben aşağıdaki çözüm ile geldi # php irc kanalından adamlar biraz yardımı ile:

// We have to explicitly declare all parameters as references, otherwise it does not seem possible to pass them on without
// losing the reference property.
public function bind_result (&$v1 = null, &$v2 = null, &$v3 = null, &$v4 = null, &$v5 = null, &$v6 = null, &$v7 = null, &$v8 = null, &$v9 = null, &$v10 = null, &$v11 = null, &$v12 = null, &$v13 = null, &$v14 = null, &$v15 = null, &$v16 = null, &$v17 = null, &$v18 = null, &$v19 = null, &$v20 = null, &$v21 = null, &$v22 = null, &$v23 = null, &$v24 = null, &$v25 = null, &$v26 = null, &$v27 = null, &$v28 = null, &$v29 = null, &$v30 = null, &$v31 = null, &$v32 = null, &$v33 = null, &$v34 = null, &$v35 = null) {
    // debug_backtrace returns arguments by reference, see comments at http://php.net/manual/de/function.func-get-args.php
    $trace = debug_backtrace();
    $args = &$trace[0]['args'];
    return call_user_func_array(array($this->mysqlObj, 'bind_result'), $args);
}