- •Пособие по работе в среде программирования php 4
- •1.Установка php
- •Настройка Apache для работы с php
- •Тестирование php
- •Установка дополнительных модулей
- •2. Характеристика языка php
- •Интерпретатор или компилятор?
- •Достоинства и недостатки интерпретатора
- •Использование php в Web
- •3. Переменные, константы, выражения
- •Переменные
- •Integer
- •Действия с переменными
- •1.Присвоение значения.
- •2.Проверка существования.
- •3.Уничтожение.
- •4.Определение типа переменной.
- •Константы
- •Выражения
- •Операции
- •4. Работа с данными формы
- •5. Конструкции языка
- •6. Ассоциативные массивы
- •Операции над массивами
- •1.Одинаковые ключи
- •2.Нулевой ключ
- •7. Функции и области видимости
- •8. Строковые функции
- •9. Работа с массивами
- •10. Математические функции
- •11. Работа с файлами
- •12. Работа с каталогами
- •13. Каналы и символические ссылки
Операции над массивами
Существует довольно много операций, которые можно выполнять с массивами (в дополнение к общим операциям над переменными). Давайте перечислим их, а заодно и подытожим все сказанное выше.
Доступ по ключу
Как мы уже знаем, ассоциативные массивы – объекты, которые наиболее приспособлены для выборки из них данных путем указания нужного ключа. В PHP и для всех массивов, и для списков (которые, еще раз напомню, также являются массивами) используется один и тот же синтаксис, что является очень большим достоинством. Вот как это выглядит:
echo $Arr["anykey"]; // выводит элемент массива $Arr с ключом anykey
echo $Arr["first"]["second"]; // так используются двумерные массивы
echo (SomeFuncThatReturnsArray())[5]; // ОШИБКА! Так нельзя!
// Вот так правильно:
$Arr= SomeFuncThatReturnsArray();
echo $Arr[5];
Последний пример показывает, что PHP сильно отличается от Си с точки зрения работы с массивами: в нем нет такого понятия, как "контекст массива", а значит, мы не можем применить [] непосредственно к значению, возвращенному функцией. Величина $Arr[ключ] является полноценным "левым значением", т. е. может стоять в левой части оператора присваивания, от нее можно брать ссылку с помощью оператора &, и т. д. Например:
$Arr["anykey"]=array(100,200); // присваиваем элементу массива 100
$ref=&$Arr["first"]["second"]; // $ref — синоним элемента массива
$Arr[]="for add"; // добавляем новый элемент
Функция count()
Мы можем определить размер (число элементов) в массиве при помощи стандартной функции count():
$num=count($Names); // теперь в $num — число элементов в массиве
Сразу отмечу, что count() работает не только с массивами, но и с объектами и даже с обычными переменными (для последних count() всегда равен 1, как будто переменная – это массив с одним элементом). Впрочем, ее очень редко применяют для чего-либо, отличного от массива – разве что по-ошибке.
Слияние массивов
Еще одна фундаментальная операция – слияние массивов, т. е. создание массива, содержащего как элементы одного, так и другого массива. Реализуется это при помощи оператора +. Например:
$a=array("a"=>"aa", "b"=>"bb");
$b=array("c"=>"cc", "d"=>"dd");
$c=$a+$b;
В результате в $c окажется ассоциативный массив, содержащий все 4 элемента, а именно: array("a"=>"aa", "b"=>"bb", "c"=>"cc", "d"=>"dd"), причем именно в указанном порядке. Если бы мы написали $c=$b+$a, результат бы был немного другой, а именно: array("c"=>"cc", "d"=>"dd", "a"=>"aa", "b"=>"bb"), т. е. элементы расположены в другом порядке. Видите, как проявляется направленность массивов? Она заставляет оператор + стать некоммутативным, т. е. $a+$b не равно $b+$a, если $a и $b – массивы.
Будьте особенно внимательны при слиянии таким образом списков. Рассмотрим следующие операторы:
$a=array(10,20,30);
$b=array(100,200);
$c=$a+$b;
Возможно, вы рассчитываете, что в $c будет array(10,20,30,100,200)? Это неверно: там окажется array(10,20,30). Вот почему так происходит. При конкатенации массивов с некоторыми одинаковыми элементами (то есть, элементами с одинаковыми ключами) в результирующем массиве останется только один элемент с таким же ключом – тот, который был в первом массиве, и на том же самом месте. Последний факт может слегка озадачить. Казалось бы, элементы массива $b по логике должны заменить элементы из $a. Однако все происходит наоборот. Окончательно выбивает из колеи следующий пример:
$a=array('a'=>10, 'b'=>20);
$b=array('c'=>30, 'b'=>'new?');
$a+=$b;
Мы-то ожидали, что оператор += обновит элементы $a при помощи элементов $b. А напрасно. В результате этих операций значение $a не изменится. Так как же нам все-таки обновить элементы в массиве $a? Получается, только прямым способом – с помощью цикла:
foreach ($b as $k=>$v) $a[$k]=$v;
Что поделать, так уж распорядились разработчики PHP. В массиве никогда не может быть двух элементов с одинаковыми ключами, потому что все операции, применимые к массивам, всегда контролируют, чтобы этого не произошло. Впрочем, на мой взгляд, данное свойство вовсе не достоинство, а недостаток – вполне можно было бы позволить оператору + оставлять одинаковые ключи, а всем остальным – запретить это делать. Что ж, разработчики PHP "пошли другим путем"...
Так как списки являются тоже ассоциативными массивами, оператор + будет работать с ними неправильно! Например, в результате слияния списков array(10,20) и array(100,200,300) получится список array(10,20,300) – всего из трех элементов!
Косвенный перебор элементов массива
Довольно часто при программировании на PHP нам приходится перебирать все без исключения элементы некоторого массива. Если наш массив – список, то эта задача, как мы уже знаем, не будет особенно обременительной:
// Пусть $Names – список имен. Распечатаем их в столбик
for($i=0; $i<count($Names); $i++)
echo $Names[$i]."\n";
Я стараюсь везде, где можно, избегать помещения имени переменной-массива в кавычки – например, предыдущий пример я не пишу вот так:
for($i=0; $i<count($Names); $i++)
echo "$Names[$i]\n";
Дело в том, что это, пожалуй, единственный способ, который совместим с PHP версии 3. А что касается четвертой версии, то мы спокойно можем помещать массивы в строки, заключив их в фигурные скобки вместе с символом $:
$Names=array(
array(’name’=>’Вася’, ’age’=>20),
array(’name’=>’Билл’, ’age’=>40)
);
for($i=0; $i<count($Names); $i++)
echo "{$Names[$i][’age’]}\n";
Давайте теперь предположим, что массив $Names ассоциативный: его ключи – имена людей, а значения, сопоставленные ключам – например, возраст этих людей. Для перебора такого массива можно воспользоваться конструкцией наподобие следующей:
for(Reset($Names); ($k=key($Names)); Next($Names))
echo "Возраст $k – { $Names[$k]} лет\n";
Эта конструкция опирается на еще одно свойство ассоциативных массивов в PHP. А именно, мало того, что массивы являются направленными, в них есть еще и такое понятие, как текущий элемент. Функция Reset() просто устанавливает этот элемент на первую позицию в массиве. Функция key() возвращает ключ, который имеет текущий элемент (если он указывает на конец массива, возвращается пустая строка, что позволяет использовать вызов key() в контексте второго выражения for). Ну а функция Next() просто перемещает текущий элемент на одну позицию вперед. На самом деле, две простейшие функции, – Reset() и Next(), – помимо выполнения своей основной задачи, еще и возвращают некоторые значения, а именно:
●функция Reset() возвращает значение первого элемента массива (или пустую строку, если массив пуст);
●функция Next() возвращает значение элемента, следующего за текущим (или пустую строку, если такого элемента нет).
Иногда (кстати, гораздо реже) бывает нужно перебрать массив с конца, а не с начала. Для этого воспользуйтесь такой конструкцией:
for(End($Names); ($k=key($Names)); Prev($Names))
echo "Возраст $k – {$Names[$k]} лет\n";
По контексту несложно сообразить, как это работает. Функция End() устанавливает позицию текущего элемента в конец массива, а Prev() передвигает ее на один элемент назад. И еще. В PHP имеется функция current(). Она очень напоминает key(), только возвращает не ключ, а величину текущего элемента (если он не указывает на конец массива).
Недостатки косвенного перебора
Давайте теперь поговорим о достоинствах и недостатках такого вида перебора массивов. Основное достоинство – "читабельность" и ясность кода, а также то, что массив мы можем перебрать как в одну, так и в другую сторону. Однако существуют и недостатки.