| ||
|
Референции в PHP.Много спорове за референциите в PHP започват с „референциите са объркващи”. Всъщност , референциите са много елементарна концепция за схващане. Референциите в PHP са средство за достигане до съдържанието на променлива чрез различни имена. Тези имена ще са псевдоними на базовата променлива и ще сочат към нея. Освен това те могат да бъдат използвани за по-кратко записване на имена на променливи. Така те ще бъдат достъпни по-удобно и по-практично до съдържанието на техните базови променливи, ако имената на базовите променливи е дълго и сложно. Тези разработчици , които са запознати с езици за програмиране, като C++ или Java ще забележат, че референциите в PHP не са аналогични с указателите. Всички имена на променливи в PHP са автоматично свързани със стойности в паметта. Използвайки референции, ние може да свържем две имена на променлива към същата стойност в паметта. Трябва да знаем , че име на променлива и съдържание на променлива са две различни неща. За да разберем как работят референциите трябва да знаем първо как PHP работи с променливите, които не са достъпни като референции, а по стойност. Взимане на стойност от друга променлива Пример 1 : <?php $a = 1; $b = $a; $b++; еcho $a; // ще изведе 1 еcho $b; // ще изведе 2 ?> Предаване на стойност като аргумент на функция Пример 2 : <?php function addFive( $num ) { $num += 5; } $original_num = 10; addFive( $original_num); print( $original_num); // Ще изведе 10 ?> Предаване на стойност като аргумент на метод от обект Пример 3 : <?php class DefensiveAttack { /** * My IP address * * @access protected * @var string */ var $mMyIpAddress = '127.0.0.1'; /** * Set my IP address * * @access public * @param string $ip */ function SetMyIpAddress($ip) { $this->mMyIpAddress = $ip; } /** * Clear my ip * * @access public */ function ClearMyIP() { $this->mMyIpAddress = ''; } } $my_ip = '212.116.142.*'; $object = new DefensiveAttack(); $object->SetMyIpAddress($my_ip); echo $object->mMyIpAddress;// Ще изведе 212.116.142.* echo $my_ip;// Ще изведе 212.116.142.* $object->ClearMyIP(); //Изтриваме съдържанието на $mMyIpAddress echo $object->mMyIpAddress;// Няма да изведе нищо echo $my_ip;// Ще изведе 212.116.142.* ?> Сега започнем да разглеждаме предаването на стойности като референция. Достъп до стойност на друга променлива като референция към нея. Пример 1: <?php $a = 1; $b = &$a; $b++; еcho $a; // ще изведе 2. При увеличаването на стойността на $b променяме стойността на $a еcho $b; // ще изведе 2 ?> Пример 2: <?php $A=array('a' => 'aaa', 'b' => 'bbb'); $b=&$A['b']; // $b сочи към елемент “b” от масив $A $b=0; // $A['b']=0; echo $A['b']; // изкарва на екрана 0 ?> За да се създаде референция , не е нужно да съществува стойност към която да сочи. <?php $A=array('a' => 'aaa', 'b' => 'bbb'); $b=&$A['c']; // $b сочи към 'c' индекса на масива $A // Сега масива $A съдържа ‘c’ индекс, но той е празен. echo " Съдържанието на 'c' индекса от масива $A : (".$A['c'].")"; ?> Когато дадена променлива съдържа име на друга променлива, това се нарича символна референция. Пример 3: <?php $a=10; $b=20; $c=30; $p="a"; // съдържа името на друга променлива (в случая на ‘a’) echo $$p; // това е референция към $a и ще изведе 10 $$p=100; // тука задаваме стойност не на $p, а на $a. Задаваме 100. echo $a; // ще изведе 100 вместо 10 ?> Предаване на аргумент като референция към функция Пример1 : <?php function addFive( &$num ) { // Увеличаваме $original_num с 5 $num += 5; } $original_num = 10; // Увеличаваме $original_num с 5 addFive( $original_num ); // $original_num е вече 15 print( $original_num ); ?> Връщане на референция от функция <?php //Връща референция function &addFive( &$num ) { $num+=5; return $num; } $original_num = 10; //референция , която сочи към върнатата стойност от addFive $returned_num = & addFive( $original_num ); //Променяме $original_num и в същото време променяме върнатата стойност от addFive. //В този случай $returned_num $original_num += 10; print( $returned_num ); // показва на екрана 25 ?> Предаване на референция като аргумент на метод от обект Тука това е почти същото, както при предаването на референция като аргумент или връщане на референция при функциите. Пример : <?php class DefensiveAttack { /** * My IP address * * @access protected * @var string */ var $mMyIpAddress = '127.0.0.1'; /** * Set my IP address by reference * * @access public * @param string $ip */ function SetMyIpAddress(&$rIp) { $this->mMyIpAddress = &$rIp; } /** * Clear my ip * * @access public */ function ClearMyIP() { $this->mMyIpAddress = ''; } /** * Get My IP * * @access public */ function &GetIp() { return $this->mMyIpAddress; } } $my_ip = '212.116.142.*'; $object = new DefensiveAttack(); //Предаваме променлива като референция $object->SetMyIpAddress($my_ip); //Връща референция към mMyIpAddress, която сочи към $my_ip $i_will_get_ip =& $object->GetIp(); echo ('Съдържанието на $i_will_get_ip:') . $i_will_get_ip . '<br />';// Ще изведе 212.116.142.* echo ('Съдържанието на $object->mMyIpAddress:') . $object->mMyIpAddress . '<br />';// Ще изведе 212.116.142.* echo ('Съдържанието на $my_ip:') . $my_ip . '<br />';// Ще изведе 212.116.142.* $object->ClearMyIP(); //Изтриваме съдържанието на $mMyIpAddress echo ('Съдържанието на $object->mMyIpAddress след $object->ClearMyIP():') . $object->mMyIpAddress . '<br />';// Няма да изведе нищо echo ('Съдържанието на $my_ip след $object->ClearMyIP():') . $my_ip . '<br />';// Няма да изведе нищо echo ('Съдържанието на $i_will_get_ip след $object->ClearMyIP():') . $i_will_get_ip . '<br />';// // Няма да изведе нищо ?> Особености при обектите в PHP5 В PHP5 обектите се предават като референция. За да направите две различни инстанции на даден обект е нужно да го клонирате . В противен случай , при промяна на инстанцията от обекта вие ще променяте базовия обект. Това става много лесно. Пример: $object = new DefensiveAttack(); $object->mMyIpAddress = '212.116.142.*'; echo ('Съдържанието на $object->mMyIpAddress:') . $object->mMyIpAddress . '<br />';// Ще изведе 212.116.142.* //Предава се чрез референция $object1 = $object; //Променяме $object->mMyIpAddress $object1->mMyIpAddress = '127.0.0.1'; echo ('Съдържанието на $object->mMyIpAddress:') . $object->mMyIpAddress . '<br />';// Ще изведе 127.0.0.1 echo ('Съдържанието на $object1->mMyIpAddress:') . $object1->mMyIpAddress . '<br />';// Ще изведе 127.0.0.1 Клонирането става със запазената дума на PHP “clone” Пример : $object = new DefensiveAttack(); $object->mMyIpAddress = '212.116.142.*'; echo ('Съдържанието на $object->mMyIpAddress:') . $object->mMyIpAddress . '<br />';// Ще изведе 212.116.142.* //Клонираме обекта $object1 = clone $object; //Не променяме $object->mMyIpAddress, а само $object1->mMyIpAddress $object1->mMyIpAddress = '127.0.0.1'; echo ('Съдържанието на $object->mMyIpAddress:') . $object->mMyIpAddress . '<br />';// Ще изведе 127.0.0.1 echo ('Съдържанието на $object1->mMyIpAddress:') . $object1->mMyIpAddress . '<br />';// Ще изведе 212.116.142.* Референцията като удобство Споменах , че също така референциите може да се използват и за удобство, като заменим именуваните вече с дълги имена на променливи с техни по-къси псевдоними. Пример : <?php // Създаваме масив от стойности $arrNamesThatAreFairlyCommon = Array("Joe", "Bob", "Sarah", "Bill", "Suzy"); // Показваме съдържанието на масива print_r($arrNamesThatAreFairlyCommon); // Референция към $arrNamesThatAreFairlyCommon $arrNames =& $arrNamesThatAreFairlyCommon; // Показваме съдържанието на масива достъпен от $arrNames print_r($arrNames); ?> Премахване на променлива Какво става когато се премахне променливата съдържаща референция, която сочи към някакви данни? Ако унищожим такава променлива ще прекъснем единствено връзката към данните, а те си остават. Пример : <?php $a = 1; $b =& $a; unset($a); print $b; ?> Добри и лоши практики Понякога , когато използваме референции, кода може да стане много объркан, труден за четене и разбиране. Пример 1 - Лоша практика: <?php function msg($message) { echo $message; } $my_message = 'Hello World!'; // Задаването на аргумент като референция по този начин е лоша практика и може да ни обърка msg(&$my_message); ?> Предвидена е една директива в конфигурационния файл на PHP „allow_call_time_pass_reference = Off” за да ни пази от такъв вид програмиране. По подразбиране стойността и е Off . Пример 2 - Добра практика: <?php // Приемането на референция от функцията е добра практика function msg(&$message) { echo $message; } $my_message = 'Hello World!'; msg($my_message); ?> Кога да използваме референции и кога не? В зависимост от приложението , вие трябва внимателно да прецените кога и къде да използвате референции. Примерно , когато желаете да спестите ненужно изразходване на памет и увеличите бързодействието на приложението си. Това става тогава, когато вместо да копирате една променлива(масиви,...) в друга, вие само задавате референция , която сочи към базовата променлива. Има смисъл да се използват за големи по обем данни(масиви, обекти,..) , но не е нужно да се употребяват референциите за нищожни данни. Примерно: $a = ‘Няма бира!’; $b = $a; // Няма нужда от $b =& $a;
|
|