Что такое ссылки php

Что такое ссылки php

Unlike in C, PHP references are not treated as pre-dereferenced pointers, but as complete aliases.

The data that they are aliasing ("referencing") will not become available for garbage collection until all references to it have been removed.

"Regular" variables are themselves considered references, and are not treated differently from variables assigned using =& for the purposes of garbage collection.

The following examples are provided for clarification.

1) When treated as a variable containing a value, references behave as expected. However, they are in fact objects that *reference* the original data.

<?php
var = "foo" ;
$ref1 =& $var ; // new object that references $var
$ref2 =& $ref1 ; // references $var directly, not $ref1.

echo $ref1 ; // >Notice: Undefined variable: ref1
echo $ref2 ; // >foo
echo $var ; // >foo
?>

2) When accessed via reference, the original data will not be removed until *all* references to it have been removed. This includes both references and "regular" variables assigned without the & operator, and there are no distinctions made between the two for the purpose of garbage collection.

echo $var ; // >Notice: Undefined variable: var
echo $ref ; // >foo
?>

3) To remove the original data without removing all references to it, simply set it to null.

echo $var ; // Value is NULL, so nothing prints
echo $ref ; // Value is NULL, so nothing prints
?>

4) Placing data in an array also counts as adding one more reference to it, for the purposes of garbage collection.

Ссылки в PHP — как они работают и когда их использовать?

Доброго времени суток, уважаемые читатели блога SoftMaker.kz. На этом сайте уже есть статья о том что такое PHP . А сегодня мы поговорим, о ссылках в языке программирование PHP, так как ссылки являются весьма полезной частью языка программирования PHP. Это утверждение касается так же и большинства других языков программирования. Тем не менее, тема ссылок может быть не вполне понятной при первом знакомстве с ней.

Эта статья поможет устранить всё, что может быть непонятно при первом знакомстве с темой ссылок в PHP . Вы узнаете, что такое ссылки в PHP и как они работают. Также в этой статье вы узнаете, как создавать и удалять ссылки, а также как передавать и возвращать переменную по ссылке в функцию и из неё. Вы также изучите некоторые другие виды ссылок, и узнаете о ситуациях, когда PHP создаёт ссылки автоматически.

Что же такое ссылки в PHP?

Ссылка — это способ обратиться к переменной с помощью другого имени. PHP-ссылки не похожи на указатели языка программирования C и не являются псевдонимами таблицы символов. Во многих отношениях они похожи на ярлык в Windows, файл псевдоним в Mac OS X и символические ссылки в Linux.

Присвоение ссылки в PHP

Здесь мы создали переменную $myVar со значением «Привет!». Затем мы присвоили значение другой переменной $anotherVar. Это копия значения первой переменной во вторую. Затем мы изменим значение, сохраненное в $anotherVar на «Увидимся позже».

Поскольку две переменные являются независимыми, $myVar по-прежнему сохраняет свою первоначальное значение ( «Привет!» ), которое будет выедено на странице. Пока всё идёт хорошо. А теперь давайте изменим пример, чтобы присвоить переменной $myVar значение $anotherVar, используя ссылку, а не значение. Чтобы сделать это, мы просто напишем знак амперсанда («&» ) после знака равенства :

Теперь вы можете видеть, что $myVar также изменен на «Увидимся позже»! Почему это произошло? Вместо того, чтобы присвоить значение переменной $myVar переменной $anotherVar — которые просто создают две независимых копии одного и того же значения — мы сделали переменную $anotherVar ссылкой на значение $myVar. Другими словами, $myVar и $anotherVarоба указывают на одно и то же значение. Таким образом, когда мы присвоили новое значение переменной, $anotherVarзначение переменной $myVar также изменилось.

Обратите внимание на то, что мы могли бы изменить значение переменной $myVar на «Увидимся позже» вместо изменения переменной $anotherVar и результат был бы точно такой же. Две переменных, по сути, являются идентичными.

Удаление ссылки в PHP

Вы можете удалить ссылку с помощью функции PHP unset() также как вы удаляете обычную переменную. Когда вы удаляете ссылку, вы просто удаляете саму ссылку, а не значение ссылки:

Значение остается в памяти, пока вы не удалите все ссылки на него, в том числе в исходной переменной:

Передача переменных в функцию по ссылке

Ссылки действительно работают, если вы передаёте их как аргументы функций. Как правило, когда вы передаете переменную в функцию,
функция получает копию значения этой переменной. Передавая ссылку на переменную функция может сослаться на эту переменную,
но что еще важнее, изменить исходную переменную.

Чтобы передать аргумент в качестве ссылки установите знак амперсанда перед именем параметра функции:

Теперь, каждый раз при вызове myFunc() и передаче переменной PHP передаёт ссылку на переменную, а не на значение переменной. Рассмотрим простой пример передачи по ссылке:

goodbye( $myVar); echo $myVar; // Выведет «Увидимся позже»

Здесь мы создали функцию goodbye() , которая принимает ссылку на переменную. Ссылка хранится в параметре $greeting. Функция присваивает новое значение («Увидимся позже») переменной $greeting, которая изменяет значение сохранённое в переменной, которая была передана в функцию.

Мы это проверим, путем создания переменной $myVar, с первоначальным значением «Привет!», вызвав функцию goodbye() с параметром $myVar , переданным по ссылке. Функция goodbye( изменяет значение, сохраненное в $myVar на «Увидимся позже».

Таким образом, используйте передачу по ссылке всякий раз, когда вы хотите изменять переменную, которая передаётся в качестве аргумента функции. Просто не правда ли?! Кстати, не поддавайтесь искушению записать знак амперсанда перед аргументом при вызове функции:

Запись знака амперсанда перед параметром в определении функции является достаточным для того, чтобы передать переменную путем ссылки. Много функций, встроенных в PHP используют передачу аргументов по ссылке. Например, функция sort() принимает ссылку для сортировки массива, так что эта функция может изменить порядок элементов в массиве.

Возвращение по ссылке из функций

Если можно передавать переменные по ссылке в функцию, то так же можно возвращать ссылки из функции. Для этого нужно записать знак амперсанда перед названием функции в её определении. Вы также должны записать знак амперсанда (=&) при присвоении функции переменной, в противном случае вы просто присвоите значение, а не ссылку.

В этом примере функция getNumWidgets() находит глобальную переменную $numWidgets и возвращает ссылку на неё. Затем мы вызываем getNumWidgets() , которая сохраняет возвращенные ссылки в $numWidgetsRef, и уменьшает значение в переменной, на которую указывает $numWidgetsRef. Это то же самое значение, на которое указывает переменная $numWidgets, как можно увидеть из результата работы функции echo.

Возможно, вы не так часто пользуетесь возвращением по ссылке, как передачей по ссылке, но этот метод может быть полезен в некоторых ситуациях, например, когда вы хотите создать функцию поиска (или метод класса), которая находит переменную (или свойство класса) и возвращает ссылку на переменную или свойство, так чтобы вызываемый код мог управлять переменной или свойством.

Изменение значений в предложении foreach с помощью ссылок в PHP

Ещё один полезный пример использования ссылок для изменения значений в массиве с помощью цикла foreach. С помощью обычного циклаforeach, вы работаете скопией значений массива, так что, если вы измените её значения вы не затронете исходного массива. Например, попробуйте перевести в верхний регистр названия музыкальных групп в массиве с помощью цикла foreach:

Будет выведено следующее:

Как вы можете видеть, исходный массив не был изменён в результате работы цикла foreach. Вместе с тем, если мы ставим знак амперсанда до $band в операторе foreach $band становится ссылкой на исходный элемент массива, а не на его копию. Затем мы можем преобразовать элементы массива в верхний регистр:

Наш код теперь работает как и предполагалось, следующим образом:

Другой способ изменить значения массива в цикле является использование цикла for вместо foreach.

Когда ссылки используются автоматически

Итак, вы узнали четыре пути создания ссылки напрямую:

  • Присваивание ссылки
  • Передача по ссылке
  • Возвращение по ссылке
  • Создание ссылки в цикле foreach

Кроме того, есть случаи, когда PHP автоматически создает ссылки. В большинстве случаев это вам не понадобится, но знать об этой возможности будет полезно!

Ссылки в PHP при использовании ключевого слова global

Когда вы используете ключевое слово global внутри функции, чтобы иметь доступ к глобальной переменной, тогда, на самом деле, вы создаёте ссылку в глобальной переменной массива $GLOBALS.

Не одно и то же, что следующий пример:

Ссылки в PHP, когда используется ключевое слово $this

При написании объектно-ориентированного кода часто используется ключевое слово $this. При использовании $this в пределах метода объекта, выполняется указание на текущий объект. Стоит запомнить, что $this всегда ссылается на объект, а не на его копию.

В примере приведенном выше $this — это ссылка на объект. Метод может изменять свойство объекта на новое значение в пределах этого объекта.

При передаче объектов

В отличие от других типов переменной, всякий раз, когда вы присваиваете, передаёте или возвращаете объект, вы возвращаете ссылку на объект, а не на его копию. Как правило, передавая функцию или метод вы работаете с самим объектом, а не с его копией.

В некоторых ситуациях, когда вы действительно хотите сделать копию объекта, вы можете использовать ключевое слово
clone. В сущности, всё намного тоньше. При создании переменной объекта, она содержит указатель на объект в памяти, а не на сам объект. При присвоении или передаче переменной вы на самом деле создаёте копию переменной. Но копия, также является просто указателем на объект — обе копии по-прежнему указывают на тот же объект. Таким образом, в большинстве случаев вы создаёте ссылки.

Краткий обзор статьи о ссылках в PHP

В этой статье были объяснены основы работы со ссылками в PHP. Вы изучили присвоение, передачу по ссылке, и возвращение по ссылке; научились использовать ссылки для изменения элементов массива в цикле foreach; и увидели ситуации, когда PHP создает ссылки автоматически.

Читайте также

Стандартные библиотеки PHP умеют генерировать только целые случайные числа. Однако, возникают задачи где нужно не целое рандомное число с максимально…

Казалось бы http_build_query — простая функция, однако, имеет некоторые особенности. Нельзя однозначно сказать что это баг, скорее просто недокументированная фича,…

Что такое ссылки php

Есть три основных операции с использованием ссылок: присвоение по ссылке, передача по ссылке и возврат по ссылке. Данный раздел познакомит вас с этими операциями и предоставит ссылки для дальнейшего изучения.

Присвоение по ссылке

Первая из них — ссылки PHP позволяют создать две переменные указывающие на одно и то же значение. Таким образом, когда выполняется следующее:

Замечание:

$a и $b здесь абсолютно эквивалентны, но это не означает, что $a указывает на $b или наоборот. Это означает, что $a и $b указывают на одно и то же значение.

Замечание:

При присвоении, передаче или возврате неинициализированной переменной по ссылке, происходит её создание.

Пример #1 Использование ссылок с неинициализированными переменными

foo ( $a ); // $a создана и равна null

$b = array();
foo ( $b [ ‘b’ ]);
var_dump ( array_key_exists ( ‘b’ , $b )); // bool(true)

$c = new StdClass ;
foo ( $c -> d );
var_dump ( property_exists ( $c , ‘d’ )); // bool(true)
?>

Такой же синтаксис может использоваться в функциях, возвращающими ссылки, и с оператором new :

Использование того же синтаксиса с функцией, которая не возвращает по ссылке, приведёт к ошибке, так же как и её использование с результатом оператора new. Хотя объекты передаются как указатели, это не то же самое, что ссылки, как описано в разделе Объекты и ссылки.

Если переменной, объявленной внутри функции как global , будет присвоена ссылка, она будет видна только в функции. Чтобы избежать этого, используйте массив $GLOBALS .

Пример #2 Присвоение ссылок глобальным переменным внутри функции

<?php
$var1 = "Пример переменной" ;
$var2 = "" ;

function global_references ( $use_globals )
<
global $var1 , $var2 ;
if (! $use_globals ) <
$var2 =& $var1 ; // только локально
> else <
$GLOBALS [ "var2" ] =& $var1 ; // глобально
>
>

global_references ( false );
echo "значение var2: ‘ $var2 ‘\n" ; // значение var2: »
global_references ( true );
echo "значение var2: ‘ $var2 ‘\n" ; // значение var2: ‘Пример переменной’
?>

Замечание:

При использовании переменной-ссылки в foreach, изменяется содержание, на которое она ссылается.

Пример #3 Ссылки и foreach

Хотя в выражениях, создаваемых с помощью конструкции array() , нет явного присвоения по ссылке, тем не менее они могут вести себя как таковые, если указать префикс & для элементов массива. Пример:

Однако следует отметить, что ссылки в массивах являются потенциально опасными. При обычном (не по ссылке) присвоении массива, ссылки внутри этого массива сохраняются. Это также относится и к вызовам функций, когда массив передаётся по значению. Пример:

<?php
/* Присвоение скалярных переменных */
$a = 1 ;
$b =& $a ;
$c = $b ;
$c = 7 ; //$c не ссылка и не изменяет значений $a и $b

/* Присвоение массивов */
$arr = array( 1 );
$a =& $arr [ 0 ]; // $a и $arr[0] ссылаются на одно значение
$arr2 = $arr ; // присвоение не по ссылке!
$arr2 [ 0 ]++;
/* $a == 2, $arr == array(2) */
/* Содержимое $arr изменилось, хотя было присвоено не по ссылке! */
?>

Передача по ссылке

Второе, что делают ссылки — передача параметров по ссылке. При этом локальная переменная в функции и переменная в вызывающей области видимости ссылаются на одно и то же содержимое. Пример:

Возврат по ссылке

Третье, что могут делать ссылки — это возврат по ссылке.

User Contributed Notes 23 notes

I ran into something when using an expanded version of the example of pbaltz at NO_SPAM dot cs dot NO_SPAM dot wisc dot edu below.
This could be somewhat confusing although it is perfectly clear if you have read the manual carfully. It makes the fact that references always point to the content of a variable perfectly clear (at least to me).

<?php
$a = 1 ;
$c = 2 ;
$b =& $a ; // $b points to 1
$a =& $c ; // $a points now to 2, but $b still to 1;
echo $a , " " , $b ;
// Output: 2 1
?>

Watch out for this:

foreach ($somearray as &$i) <
// update some $i.
>
.
foreach ($somearray as $i) <
// last element of $somearray is mysteriously overwritten!
>

Problem is $i contians reference to last element of $somearray after the first foreach, and the second foreach happily assigns to it!

It appears that references can have side-effects. Below are two examples. Both are simply copying one array to another. In the second example, a reference is made to a value in the first array before the copy. In the first example the value at index 0 points to two separate memory locations. In the second example, the value at index 0 points to the same memory location.

I won’t say this is a bug, because I don’t know what the designed behavior of PHP is, but I don’t think ANY developers would expect this behavior, so look out.

An example of where this could cause problems is if you do an array copy in a script and expect on type of behavior, but then later add a reference to a value in the array earlier in the script, and then find that the array copy behavior has unexpectedly changed.

<?php
// Example one
$arr1 = array( 1 );
echo "\nbefore:\n" ;
echo "\$arr1[0] == < $arr1 [ 0 ]>\n" ;
$arr2 = $arr1 ;
$arr2 [ 0 ]++;
echo "\nafter:\n" ;
echo "\$arr1[0] == < $arr1 [ 0 ]>\n" ;
echo "\$arr2[0] == < $arr2 [ 0 ]>\n" ;

// Example two
$arr3 = array( 1 );
$a =& $arr3 [ 0 ];
echo "\nbefore:\n" ;
echo "\$a == $a \n" ;
echo "\$arr3[0] == < $arr3 [ 0 ]>\n" ;
$arr4 = $arr3 ;
$arr4 [ 0 ]++;
echo "\nafter:\n" ;
echo "\$a == $a \n" ;
echo "\$arr3[0] == < $arr3 [ 0 ]>\n" ;
echo "\$arr4[0] == < $arr4 [ 0 ]>\n" ;
?>

Something that might not be obvious on the first look:
If you want to cycle through an array with references, you must not use a simple value assigning foreach control structure. You have to use an extended key-value assigning foreach or a for control structure.

A simple value assigning foreach control structure produces a copy of an object or value. The following code

which means $v in foreach is not a reference to $v1 but a copy of the object the actual element in the array was referencing to.

and therefor cycle through the original objects (both $v1), which is, in terms of our aim, what we have been looking for.

(tested with php 4.1.3)

in PHP you don’t really need pointer anymore if you want to share an object across your program

<?php
class foo <
protected $name ;
function __construct ( $str ) <
$this -> name = $str ;
>
function __toString () <
return ‘my name is "’ . $this -> name . ‘" and I live in "’ . __CLASS__ . ‘".’ . "\n" ;
>
function setName ( $str ) <
$this -> name = $str ;
>
>

class MasterOne <
protected $foo ;
function __construct ( $f ) <
$this -> foo = $f ;
>
function __toString () <
return ‘Master: ‘ . __CLASS__ . ‘ | foo: ‘ . $this -> foo . "\n" ;
>
function setFooName ( $str ) <
$this -> foo -> setName ( $str );
>
>

class MasterTwo <
protected $foo ;
function __construct ( $f ) <
$this -> foo = $f ;
>
function __toString () <
return ‘Master: ‘ . __CLASS__ . ‘ | foo: ‘ . $this -> foo . "\n" ;
>
function setFooName ( $str ) <
$this -> foo -> setName ( $str );
>
>

$bar = new foo ( ‘bar’ );

print( "\n" );
print( "Only Created \$bar and printing \$bar\n" );
print( $bar );

print( "\n" );
print( "Now \$baz is referenced to \$bar and printing \$bar and \$baz\n" );
$baz =& $bar ;
print( $bar );

print( "\n" );
print( "Now Creating MasterOne and Two and passing \$bar to both constructors\n" );
$m1 = new MasterOne ( $bar );
$m2 = new MasterTwo ( $bar );
print( $m1 );
print( $m2 );

print( "\n" );
print( "Now changing value of \$bar and printing \$bar and \$baz\n" );
$bar -> setName ( ‘baz’ );
print( $bar );
print( $baz );

print( "\n" );
print( "Now printing again MasterOne and Two\n" );
print( $m1 );
print( $m2 );

print( "\n" );
print( "Now changing MasterTwo’s foo name and printing again MasterOne and Two\n" );
$m2 -> setFooName ( ‘MasterTwo\’s Foo’ );
print( $m1 );
print( $m2 );

print( "Also printing \$bar and \$baz\n" );
print( $bar );
print( $baz );
?>

points to post below me.
When you’re doing the references with loops, you need to unset($var).

I think a correction to my last post is in order.

When there is a constructor, the strange behavior mentioned in my last post doesn’t occur. My guess is that php was treating reftest() as a constructor (maybe because it was the first function?) and running it upon instantiation.

<?php
class reftest
<
public $a = 1 ;
public $c = 1 ;

public function __construct ()
<
return 0 ;
>

public function reftest ()
<
$b =& $this -> a ;
$b ++;
>

$reference = new reftest ();

$reference -> reftest ();
$reference -> reftest2 ();

echo $reference -> a ; //Echoes 2.
echo $reference -> c ; //Echoes 2.
?>

The order in which you reference your variables matters.

<?php
$a1 = "One" ;
$a2 = "Two" ;
$b1 = "Three" ;
$b2 = "Four" ;

echo $a1 ; //Echoes "One"
echo $b1 ; //Echoes "One"

echo $a2 ; //Echoes "Four"
echo $b2 ; //Echoes "Four"
?>

In reply to lars at riisgaardribe dot dk,

When a variable is copied, a reference is used internally until the copy is modified. Therefore you shouldn’t use references at all in your situation as it doesn’t save any memory usage and increases the chance of logic bugs, as you discoved.

Solution to post "php at hood dot id dot au 04-Mar-2007 10:56":

foreach ( $a1 as $k =>& $v )
$v = ‘x’ ;

echo $a1 [ ‘a’ ]; // will echo x

unset( $GLOBALS [ ‘v’ ]);

foreach ( $a2 as $k => $v )
<>

echo $a1 [ ‘a’ ]; // will echo x

About the example on array references.
I think this should be written in the array chapter as well.
Indeed if you are new to programming language in some way, you should beware that arrays are pointers to a vector of Byte(s).

<?php $arr = array( 1 ); ?>
$arr here contains a reference to which the array is located.
Writing :
<?php echo $arr [ 0 ]; ?>
dereferences the array to access its very first element.

Now something that you should also be aware of (even you are not new to programming languages) is that PHP use references to contains the different values of an array. And that makes sense because the type of the elements of a PHP array can be different.

Consider the following example :

$arr = array( 1 , ‘test’ );

$point_to_test =& $arr [ 1 ];

$arr [ 1 ] =& $new_ref ;

echo $arr [ 1 ]; // echo ‘new’;
echo $point_to_test ; // echo ‘test’ ! (still pointed somewhere in the memory)

If you set a variable before passing it to a function that takes a variable as a reference, it is much harder (if not impossible) to edit the variable within the function.

Example:
<?php
function foo (& $bar ) <
$bar = "hello\n" ;
>

foo ( $unset );
echo( $unset );
foo ( $set = "set\n" );
echo( $set );

It baffles me, but there you have it.

It matters if you are playing with a reference or with a value

Here we are working with values so working on a reference updates original variable too;

$b = & $a;
echo "$a, $b"; //Output: 1, 1

$b++;
echo "$a, $b";//Output: 2, 2 both values are updated

$b = 10;
echo "$a, $b";//Output: 10, 10 both values are updated

$b =$c; //This assigns value 2 to $b which also updates $a
echo "$a, $b";//Output: 22, 22

But, if instead of $b=$c you do
$b = &$c; //Only value of $b is updated, $a still points to 10, $b serves now reference to variable $c

echo "$a, $b"//Output: 10, 22

In this example class name is different from its first function and however there is no construction function. In the end as you guess "a" and "c" are equal. So if there is no construction function at same time class and its first function names are the same, "a" and "c" doesn’t equal forever. In my opinion php doesn’t seek any function for the construction as long as their names differ from each others.

<?php
class reftest_new
<
public $a = 1 ;
public $c = 1 ;

public function reftest ()
<
$b =& $this -> a ;
$b ++;
>

$reference = new reftest_new ();

$reference -> reftest ();
$reference -> reftest2 ();

echo $reference -> a ; //Echoes 2.
echo $reference -> c ; //Echoes 2.
?>

In reply to Drewseph using foo($a = ‘set’); where $a is a reference formal parameter.

$a = ‘set’ is an expression. Expressions cannot be passed by reference, don’t you just hate that, I do. If you turn on error reporting for E_NOTICE, you will be told about it.

Resolution: $a = ‘set’; foo($a); this does what you want.

Here’s a good little example of referencing. It was the best way for me to understand, hopefully it can help others.

When using references in a class, you can reference $this-> variables.

<?php
class reftest
<
public $a = 1 ;
public $c = 1 ;

public function reftest ()
<
$b =& $this -> a ;
$b = 2 ;
>

$reference = new reftest ();

$reference -> reftest ();
$reference -> reftest2 ();

echo $reference -> a ; //Echoes 2.
echo $reference -> c ; //Echoes 2.
?>

However, this doesn’t appear to be completely trustworthy. In some cases, it can act strangely.

<?php
class reftest
<
public $a = 1 ;
public $c = 1 ;

public function reftest ()
<
$b =& $this -> a ;
$b ++;
>

$reference = new reftest ();

$reference -> reftest ();
$reference -> reftest2 ();

echo $reference -> a ; //Echoes 3.
echo $reference -> c ; //Echoes 2.
?>

In this second code block, I’ve changed reftest() so that $b increments instead of just gets changed to 2. Somehow, it winds up equaling 3 instead of 2 as it should.

I discovered something today using references in a foreach

foreach ( $a1 as $k =>& $v )
$v = ‘x’ ;

echo $a1 [ ‘a’ ]; // will echo x

foreach ( $a2 as $k => $v )
<>

echo $a1 [ ‘a’ ]; // will echo b (!)
?>

After reading the manual this looks like it is meant to happen. But it confused me for a few days!

(The solution I used was to turn the second foreach into a reference too)

An interesting if offbeat use for references: Creating an array with an arbitrary number of dimensions.

For example, a function that takes the result set from a database and produces a multidimensional array keyed according to one (or more) columns, which might be useful if you want your result set to be accessible in a hierarchial manner, or even if you just want your results keyed by the values of each row’s primary/unique key fields.

<?php
function array_key_by ( $data , $keys , $dupl = false )
/*
* $data — Multidimensional array to be keyed
* $keys — List containing the index/key(s) to use.
* $dupl — How to handle rows containing the same values. TRUE stores it as an Array, FALSE overwrites the previous row.
*
* Returns a multidimensional array indexed by $keys, or NULL if error.
* The number of dimensions is equal to the number of $keys provided (+1 if $dupl=TRUE).
*/
<
// Sanity check
if (! is_array ( $data )) return null ;

// Allow passing single key as a scalar
if ( is_string ( $keys ) or is_integer ( $keys )) $keys = Array( $keys );
elseif (! is_array ( $keys )) return null ;

// Our output array
$out = Array();

// Loop through each row of our input $data
foreach( $data as $cx => $row ) if ( is_array ( $row ))
<

// Loop through our $keys
foreach( $keys as $key )
<
$value = $row [ $key ];

if (!isset( $last )) // First $key only
<
if (!isset( $out [ $value ])) $out [ $value ] = Array();
$last =& $out ; // Bind $last to $out
>
else // Second and subsequent $key.
<
if (!isset( $last [ $value ])) $last [ $value ] = Array();
>

// Bind $last to one dimension ‘deeper’.
// First lap: was &$out, now &$out[. ]
// Second lap: was &$out[. ], now &$out[. ][. ]
// Third lap: was &$out[. ][. ], now &$out[. ][. ][. ]
// (etc.)
$last =& $last [ $value ];
>

if (isset( $last ))
<
// At this point, copy the $row into our output array
if ( $dupl ) $last [ $cx ] = $row ; // Keep previous
else $last = $row ; // Overwrite previous
>
unset( $last ); // Break the reference
>
else return NULL ;

// A sample result set to test the function with
$data = Array(Array( ‘name’ => ‘row 1’ , ‘foo’ => ‘foo_a’ , ‘bar’ => ‘bar_a’ , ‘baz’ => ‘baz_a’ ),
Array( ‘name’ => ‘row 2’ , ‘foo’ => ‘foo_a’ , ‘bar’ => ‘bar_a’ , ‘baz’ => ‘baz_b’ ),
Array( ‘name’ => ‘row 3’ , ‘foo’ => ‘foo_a’ , ‘bar’ => ‘bar_b’ , ‘baz’ => ‘baz_c’ ),
Array( ‘name’ => ‘row 4’ , ‘foo’ => ‘foo_b’ , ‘bar’ => ‘bar_c’ , ‘baz’ => ‘baz_d’ )
);

// First, let’s key it by one column (result: two-dimensional array)
print_r ( array_key_by ( $data , ‘baz’ ));

// Or, key it by two columns (result: 3-dimensional array)
print_r ( array_key_by ( $data , Array( ‘baz’ , ‘bar’ )));

// We could also key it by three columns (result: 4-dimensional array)
print_r ( array_key_by ( $data , Array( ‘baz’ , ‘bar’ , ‘foo’ )));

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *