Supponendo che sia possibile, come si passerebbero gli argomenti facendo riferimento a una funzione variadica senza generare un avviso in PHP? Non possiamo più usare l'operatore '&' in una chiamata di funzione, altrimenti lo accetterei (anche se sarebbe soggetto a errori, se un programmatore lo dimentica).Come possono essere passati argomenti in variabili alle funzioni variadiche in PHP?
Ciò che ha ispirato sono le vecchie classi wrapper MySQLi che ho scoperto (in questi giorni, userei solo PDO). L'unica differenza tra i wrapper e le classi MySQLi è che i wrapper generano eccezioni piuttosto che restituire 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;
}
}
La difficoltà sta nel chiamare metodi come bind_result
nel wrapper. È possibile definire in modo esplicito le funzioni di aritmetica costante (ad esempio bind_param
), consentendo il passaggio per riferimento. bind_result
, tuttavia, tutti gli argomenti devono essere pass-by-reference. Se si chiama bind_result
su un'istanza di MySQLi_stmt_throwing
così com'è, gli argomenti vengono passati per valore e l'associazione non verrà eseguita.
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) {
...
}
Poiché le classi di cui sopra non sono più in uso, questa domanda è solo una questione di curiosità. Approcci alternativi alle classi wrapper non sono rilevanti. La definizione di un metodo con un gruppo di argomenti che richiede valori predefiniti Null
non è corretta (cosa succede se si definiscono 20 argomenti, ma la funzione viene chiamata con 21?). Le risposte non hanno nemmeno bisogno di essere scritte in termini di MySQL_stmt_throwing
; esiste semplicemente per fornire un esempio concreto.
Ops ... appena trovato la domanda che questo dups: http://stackoverflow.com/questions/1925253/php-variable-length-argument-list-by-reference , anche se preferisco la risposta di magro sotto alla risposta accettata per l'altra domanda. – outis