Object, closures a předávání pole odkazem
- jasir
- Člen | 746
S PHP5.3 se tak nějak pomalu sžívám.
Mám zajímavý(?) problém:
<?php
abstract class EntityPresenter extends BasePresenter
{
public $onSave = array();
public function handleSave($form) {
$values = $form->values;
$this->onSave($values);
...
}
}
public class ImagesPresenter extends EntityPresenter
{
public function startup() {
parent::startup();
$this->onSave[] = function(&$values) {
unset($values['image']);
$values['size'] = ...
}
}
}
?>
Toto mi vyhodí chybu ‚Parameter 2 to Closure::__invoke() expected to be a
reference, value given‘. Když se pokusím volání upravit na
$this->onSave(&$values)
, dostanu
chybu ‚Call-time pass-by-reference has been deprecated‘ (mám zapnuté
strictMode a vypínat ho nechci). Jak mám tedy dostat pole odkazem do closure,
abych ho mohl ve funkci
upravit?
Co funguje, je poslat ArrayObject:
$values = new ArrayObject($form->values)
, ale moc se mi to
nelíbí.
Díky za nápady…
Editoval jasir (1. 4. 2010 0:52)
- Majkl578
- Moderator | 1364
Problém je ve třídě Nette\Callback. Tuhle chybu vyvolá použití funkce call_user_func_array na Closure.
Viz toto:
$data = range(1, 10);
$func = function (&$val) {
unset($val[0]);
};
//zde je problém
call_user_func($func, $data);
//popř.
//call_user_func_array($func, array($data));
//pokud se místo toho volá toto, tak funguje jak má:
//$func($data);
var_dump($data);
„Warning: Parameter 1 to {closure}() expected to be a reference, value given“
Otázkou je, jestli je vyhození varování při volání Closure pomocí call_user_func(_array) správné, nebo jestli je to bug. Bug to ale pravděpodobně nebude, jelikož stejné chování nastane i při tomto:
$data = range(1, 10);
function x(&$val) {
unset($val[0]);
};
call_user_func('x', $data);
var_dump($data);
Co funguje správně je tento kód (všimni si použitého & i v předání argumentu):
$data = range(1, 10);
$func = function (&$val) {
unset($val[0]);
};
call_user_func_array($func, array(&$data));
var_dump($data);
Naopak ale použití call_user_func namísto call_user_func_array hodí E_DEPRECATED.
$data = range(1, 10);
$func = function (&$val) {
unset($val[0]);
};
call_user_func($func, &$data);
var_dump($data);
Editoval Majkl578 (1. 4. 2010 2:40)
- Matúš Matula
- Člen | 257
Ahoj, mam rovnaky problem. Pri pokuse spustit callback hodi ladenka warning
Parameter 1 to RssControl::a() expected to be a reference, value given
. Nepomohlo ani pouzitie ArrayObject. Ako sa to da riesit?
<?php
/** @var array */
public $onPrepareProperties;
public function __construct(/*Nette\*/IComponentContainer $parent = NULL, $name = NULL)
{
parent::__construct($parent, $name);
$this->onPrepareProperties[] = callback($this, "a");
}
public function a(&$w) {
echo '1';
}
public function render()
{
$properties = array(2);
// $properties = new ArrayObject($properties);
$this->onPrepareProperties($properties);
}
?>