PHP
Bibliografia
Szukaj…
Składnia
-
$foo = 1; $bar = &$foo; // both $foo and $bar point to the same value: 1
-
$var = 1; function calc(&$var) { $var *= 15; } calc($var); echo $var;
Uwagi
Przypisując dwie zmienne przez odniesienie, obie zmienne wskazują tę samą wartość. Weź następujący przykład:
$foo = 1;
$bar = &$foo;
$foo
nie wskazuje na $bar
. Zarówno $foo
i $bar
wskazują tę samą wartość $foo
, czyli 1
. Ilustrować:
$baz = &$bar;
unset($bar);
$baz++;
Gdybyśmy mieli points to
relacji, byłoby to zerwane teraz po unset()
; zamiast tego, $foo
i $baz
nadal wskazują na tę samą wartość, czyli 2
.
Przypisz przez odniesienie
To pierwszy etap odwoływania się. Zasadniczo, gdy przypisujesz przez odniesienie , pozwalasz, aby dwie zmienne miały tę samą wartość jako taką.
$foo = &$bar;
$foo
i $bar
są tu równe. Nie wskazują na siebie. Wskazują to samo miejsce ( „wartość” ).
Możesz także przypisać przez odniesienie w konstrukcji języka array()
. Chociaż nie jest to wyłącznie zadanie referencyjne.
$foo = 'hi';
$bar = array(1, 2);
$array = array(&$foo, &$bar[0]);
Należy jednak pamiętać , że odniesienia wewnątrz tablic są potencjalnie niebezpieczne. Wykonanie normalnego (nie referencyjnego) przypisania z referencją po prawej stronie nie zamienia lewej strony w referencję, ale referencje wewnątrz tablic są zachowywane w tych normalnych przypisaniach. Dotyczy to również wywołań funkcji, w których tablica jest przekazywana przez wartość.
Przypisywanie przez odniesienie nie ogranicza się tylko do zmiennych i tablic, są one również obecne dla funkcji i wszystkich powiązań „pass-by-reference”.
function incrementArray(&$arr) {
foreach ($arr as &$val) {
$val++;
}
}
function &getArray() {
static $arr = [1, 2, 3];
return $arr;
}
incrementArray(getArray());
var_dump(getArray()); // prints an array [2, 3, 4]
Przypisanie jest kluczem w definicji funkcji jak wyżej. Nie możesz przekazać wyrażenia przez referencję, tylko wartość / zmienna. Stąd wystąpienie $a
w bar()
.
Wróć przez odniesienie
Czasami przychodzi czas, abyś domyślnie powrócił przez odniesienie.
Zwracanie przez odniesienie jest przydatne, gdy chcesz użyć funkcji do znalezienia, do której zmiennej należy powiązać odniesienie. Nie używaj zwrotu przez odniesienie w celu zwiększenia wydajności. Silnik sam to zoptymalizuje. Zwracaj referencje tylko wtedy, gdy masz ku temu ważny powód techniczny.
Zaczerpnięte z dokumentacji PHP do zwrotu przez odniesienie .
Istnieje wiele różnych formularzy zwracanych przez referencje, w tym następujący przykład:
function parent(&$var) {
echo $var;
$var = "updated";
}
function &child() {
static $a = "test";
return $a;
}
parent(child()); // returns "test"
parent(child()); // returns "updated"
Zwrot przez referencję nie ogranicza się tylko do referencji funkcji. Masz również możliwość niejawnego wywołania funkcji:
function &myFunction() {
static $a = 'foo';
return $a;
}
$bar = &myFunction();
$bar = "updated"
echo myFunction();
Nie można bezpośrednio odwoływać się do wywołania funkcji, należy je przypisać do zmiennej przed jej wykorzystaniem. Aby zobaczyć, jak to działa, po prostu spróbuj echo &myFunction();
.
Notatki
- Musisz podać odniesienie (
&
) w obu miejscach, w których zamierzasz go używać. Oznacza to, dla twojej definicji funkcji (function &myFunction() {...
) oraz w odwołaniu do wywołania (function callFunction(&$variable) {...
lub&myFunction();
). - Możesz zwrócić zmienną tylko przez odniesienie. Stąd wystąpienie
$a
w powyższym przykładzie. Oznacza to, że nie możesz zwrócić wyrażenia, w przeciwnym razie zostanie wygenerowany błąd PHPE_NOTICE
(Notice: Only variable references should be returned by reference in ......
). - Zwrot przez referencję ma uzasadnione przypadki użycia, ale powinienem ostrzec, że należy ich używać oszczędnie, dopiero po zbadaniu wszystkich innych potencjalnych opcji osiągnięcia tego samego celu.
Przekaż przez odniesienie
Umożliwia to przekazanie zmiennej przez odwołanie do funkcji lub elementu, który pozwala zmodyfikować oryginalną zmienną.
Przekazywanie przez odniesienie nie ogranicza się tylko do zmiennych, można również przekazać następujące odniesienia:
- Nowe instrukcje, np.
foo(new SomeClass)
- Referencje zwrócone z funkcji
Tablice
Powszechnym zastosowaniem „przekazywania przez referencję” jest modyfikowanie wartości początkowych w tablicy bez wchodzenia w zakres tworzenia nowych tablic lub zaśmiecania przestrzeni nazw. Przekazywanie przez referencję jest tak proste, jak poprzedzanie / poprzedzanie zmiennej &$myElement
&
=> &$myElement
.
Poniżej znajduje się przykład wykorzystania elementu z tablicy i dodania 1 do jego wartości początkowej.
$arr = array(1, 2, 3, 4, 5);
foreach($arr as &$num) {
$num++;
}
Teraz, gdy użyjesz dowolnego elementu w obrębie $arr
, oryginalny element zostanie zaktualizowany wraz ze wzrostem referencji. Możesz to zweryfikować poprzez:
print_r($arr);
Uwaga
Należy wziąć pod uwagę podczas wykorzystywania przejść przez odniesienie w pętli. Na końcu powyższej pętli
$num
nadal zawiera odwołanie do ostatniego elementu tablicy. Przypisanie go do pętli końcowej spowoduje manipulowanie ostatnim elementem tablicy! Możesz się upewnić, że tak się nie stanie,unset()
wyłączając go po zakończeniu pętli:$myArray = array(1, 2, 3, 4, 5); foreach($myArray as &$num) { $num++; } unset($num);
Powyższe zapewni, że nie napotkasz żadnych problemów. Przykład problemów, które mogą się z tym wiązać, znajduje się w tym pytaniu na StackOverflow .
Funkcje
Innym powszechnym zastosowaniem przekazywania przez odniesienie jest funkcja. Modyfikacja oryginalnej zmiennej jest tak prosta jak:
$var = 5;
// define
function add(&$var) {
$var++;
}
// call
add($var);
Które można zweryfikować, echo
oryginalną zmienną.
echo $var;
Istnieją różne ograniczenia dotyczące funkcji, jak zauważono poniżej w dokumentacji PHP:
Uwaga: W wywołaniu funkcji nie ma znaku odniesienia - tylko w definicjach funkcji. Same definicje funkcji są wystarczające, aby poprawnie przekazać argument przez odwołanie. Począwszy od PHP 5.3.0, pojawi się ostrzeżenie, że „czas przejścia przez referencję” jest przestarzały, gdy używasz & in foo (& $ a) ;. Począwszy od wersji PHP 5.4.0, czas przejścia przez odwołanie został usunięty, więc użycie go spowoduje błąd krytyczny.