Reference
V PHP je možné na jedna data odkazovat více proměnnými, používají se k tomu reference. Osobně reference používám např. tehdy, když chci k datům zanořeným hluboko v poli přistupovat přes jednoduchou proměnnou:
<?php $column = &$table['columns'][$column_name]; ?>
Pak stačí pracovat s proměnnou $column
a všechny změny se projeví v původním poli. Pokud tuto proměnnou následně chci použít k jinému účelu (byť třeba ve foreach cyklu), je nutné referenci zrušit, nejsnáze pomocí unset($column)
.
Reference se dají používat i při předávání parametrů funkcím:
<?php function reference(&$ar) { $ar[0]++; } ?>
V tom případě se všechny změny v proměnné uvnitř funkce projeví i navenek a jako parametr je nutné předat proměnnou. Za normálních okolností se pracuje s kopií dat a předat lze jakýkoliv výraz. Předávání parametrů referencí se dá využít k jejich jednoduché změně. Podle mě to není úplně čistý způsob – funkce by měla mít jasně definovaný vstup a výstup a jakákoliv modifikace vstupních parametrů musí být přinejmenším důkladně popsána. Předávání parametrů referencí se dá použít pro vracení doplňkových informací – např. funkce fsockopen vrací v případě chyby jednoduše false a chybovou hlášku vrací v parametru předaném referencí.
U velkých dat ale může předávání parametrů referencí znamenat značné zrychlení:
<?php // pomalé function setridit($velke_pole) { // setřídění return $velke_pole; } // podstatně rychlejší function setridit_ref(&$velke_pole) { // setřídění } ?>
Dlužno podotknout, že pokud ke změně parametru uvnitř funkce nedochází, nepřinese předávání referencí žádné zrychlení. PHP totiž data fyzicky kopíruje až když to je potřeba.
V PHP 4 se stejným způsobem pracovalo i s objekty, kdy je vytváření kopií potřeba pouze zřídka. Úskalí, na která při tom můžete narazit, pěkně popisuje autor knihovny JpGraph. V PHP 5 došlo k celkem odvážné zpětně nekompatibilní změně a objekty se v něm předávají referencí.
Ve starších verzích PHP bylo možné předání parametru referencí vynutit až v okamžiku volání funkce. Kvůli možným nežádoucím vedlejším efektům byla tato vlastnost naštěstí odstraněna. Pro staré projekty, které jsou na této vlastnosti závislé, to lze povolit direktivou allow_call_time_pass_reference.
Diskuse
dgx:
Pokud bychom měli být zcela přesní, tak se nedá říct, že v PHP5 se objekty předávají referencí, protože reference mají stále svou specifickou funkci, viz http://www.php.net/manual/en/language.oop5.basic.php#AEN5691
<?php
$assigned = $instance;
$reference =& $instance;
$instance->var = 'assigned will have this value';
$instance = null; // $instance and $reference become null
var_dump($instance);
var_dump($reference);
var_dump($assigned);
?>
dává výsledek
NULL
NULL
object(SimpleClass)#1 (1) {
["var"]=>
string(30) "assigned will have this value"
}

martinpav:
$assigned = $instance;priradi referenciu na objekt do premennej
$reference =& $instance;
vytvori referenciu na referenciu ???
Akosi nedokazem prist na dovod preco sa autori PHP rozhodli pre taketo chovanie. Pokial by niekto mal priklad rozumneho vyuzitia, rad sa poucim.
johno:
Nie. Rozdiel je v tom, že v PHP5 sa objekty (IMHO úplne logicky) pri priraďovaní nekopírujú (nedochádza k implicitnému klonovaniu).
Čiže
<?php
$article = new Article();
$theSameArticle = $article;
?>
je v PHP5 to isté ako
<?php
$article = new Article();
$theSameArticle = &$article;
?>
v PHP4 to tak nie je.
dgx:
Právě že to není to stejné. Pokud v PHP5 zavoláš $article = null, tak v první případě bude $theSameArticle obsahovat objekt Article a ve druhém případě bude rovno null.

Jakub Podhorský:
tohle jsem vůbec netušil...to je docela dost podivný chování...každopádně děkuju za upozorněnímartinpav:
Prave priklad od DGX to to porusuje<?php
$instance = new SimpleClass() //nova instancia, v premennej ja referencia na objekt
$assigned = $instance; // priradenie REFERENCIE do druhej premennej, stale ukazuje na tu istu instanciu
$reference =& $instance; // priradenie referencie na premennu $instance
$instance->var = '$assigned will have this value';
print '<hr>';
var_dump($instance);
var_dump($reference);
var_dump($assigned);
print '<hr>';
$instance = null; // $instance aj $reference maju priradene NULL, cize $reference obsahuje len referenciu na premennu instance, nie na instanciu objektu. Toto mi pride ako chore. Logicky by sa mala priradit do $reference referencia na instanciu objektu.
var_dump($instance);
var_dump($reference);
var_dump($assigned);
?>
KKING:
Uz vim proc to tak implementovali a je to uplne uzasne..uplne nadherne se s tim daji udelat vazby mezi objekdy bez pouziti jedineho &.
Diskuse je zrušena z důvodu spamu.

