РНР программирование

 

 Главная      Программа телепередач, энциклопедии и многие другие справочные материалы

 

стр.  1. 2. 3. 4. 5. 6. 7. 8.

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

Еще одним важным свойством функций в PHP является поддержка функций с переменым числом аргументов, а также задание значений по умолчанию для аргументов функций. Рассмотрим, как это выглядит на примере:

// Вывод текста с заданным цветом. Цвет по-умолчанию - красный.

function printColoredString($text,$color="#FF0000")

{

        echo "$text";

};

 

// Использование этой функции

printColoredString('Немного текста');                // Текст красного цвета

printColoredString('Еще немного текста','#0000FF');    // Текст синего цвета

Как видите - если значение цвета не задано - используется значение по умолчанию, заданное в определении функции.

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

function getAvg()

{

 

        $args = func_get_args();

        return(array_sum($args)/func_num_args());

};

И, наконец, необходимо рассказать еще об одной интересной возможности PHP по работе с функциями. Это т.н. анонимные функции (anonymous functions). Их отличие от обычных функций состоит в том, что они не описываются заранее, а создаются непосредственно во время выполнения PHP скрипта. Подобные функции часто используются, если необходимо использовать какую-нибудь простую функцию, например в качестве callback при сортировке массива. Лучше всего использование такой функции показать на примере. Пусть массив $users содержит информацию о пользователях сайта, и имеет следующую структуру:

array(

        'firstName' => ,

        'lastName'  => ,

        'age'       =>

);

Теперь предположим, что нам необходимо отсортировать этот массив пользователей по их возрасту. Разумеется здесь есть несколько вариантов решения этой задачи, но нас сейчас интересует вариант с использованием анонимной функции:

$callback = create_function('$u1,$u2','return(($u1["age"]==$u2["age"])?0:(($u1["age"]>$u2["age"])?1:-1));');

 

usort($users,$callback);

Как видите, после создания функция присваивается обычной переменной. А это значит, что с ней можно сделать практически все то, что можно сделать и с обычной переменной. Например запихать ее в массив :-) и таким образом создать массив функций, которые можно использовать по мере надобности. Кстати, PHP поддерживает и вот такой способ вызова функций:

function myFunction()

{

        echo "This is my function";

 

};

 

$funcName = 'myFunction';

$funcName();                            // Вызов функции myFunction()

И напоследок хотелось бы заметить еще одну интересную особенность PHP: хотя сам по себе язык является регистрозависимым (т.е. например переменные $var и $Var - это разные переменные), имена функций в нем не являются регистрозависимыми (т.е. функции myFunction, myfunction, MYFUNCTION и mYfUnCtIOn - это одна и та же функция :-) ). Почему это так - покрыто мраком тайны, но об этом нужно помнить, особенно когда читаешь чужой код.

Объекты в PHP

Помимо функций PHP, как и любой уважающий себя современный язык, имеет поддержку объектно-ориентированного программирования. Я должен сразу предупредить вас, что материал, изложенный в этом разделе, будет полезен только людям, знакомым с ООП, всем остальным я настоятельно рекомендую предварительно почитать какую-нибудь хорошую документацию об основах ООП.

Объекты в PHP описываются следующим образом:

class className                 // Определение объекта className

{

        var $property;      // Определение переменной объекта

 

        function className()      // Функция, описанная внутри объекта и имеющая то же имя, что и имя

        {                           // объекта, является конструктором этого объекта (по аналогии с C++)

                $this->property = 0; // Переменная $this внутри методов объекта ссылается на сам объект

        };

 

        function setProperty($property)         // Определение метода объекта

        {

                $this->property = $property; // Обратите внимание, property в

                                                // левой  части выражения - это

                                                // переменная объекта (доступ через

                                                // $this), а в правой части - аргумент

                                                // функции с тем же именем, что

                                                // и переменная объекта.

        };

};

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

// Описание объекта Man

class Man

{

        var $firstName;

        var $lastName;

        var $age;

 

 

        function Man($fName,$lName,$age)

        {

                $this->firstName = $fName;

                $this->lastName = $lName;

                $this->age = $age;

        };

 

        function getName()

        {

                return($this->firstName." ".$this->lastName);

        };

 

        function setAge($newAge)

        {

                $this->age = $newAge;

        };

};

 

// Создание экземпляра объекта

$john = new Man('John','Smith',23);             // Здесь мы передаем параметры непосредственно

                                                // в конструктор объекта

Теперь переменная $john содержит экземпляр объекта Man. К слову сказать, хотя в PHP можно задавать конструкторы объектов, поддержки деструкторов для объектов до сих пор нет. Неясно, чем вызвано подобное ограничение, но это факт.

После того, как переменной присвоен созданный экземпляр объекта - с этой переменной можно делать все , что можно делать с этим объектом:

echo "Hello, my name is ".$john->getName();

echo "I'm ".$john->age." years old";

Кстати, я думаю, вы уже заметили, что имена переменных, являющихся переменными объектов, записываются без символа $ перед ними? Это происходит потому, что PHP рассматривает связку "(переменная-объект)->(переменная объекта)" как одну переменную. Зато это позволит вам очень элегантно делать например вот такие вещи:

$methodName = 'getName';

echo "My name is ".$john->$methodName;

Здорово, не правда ли? :-)

Но объекты как таковые не были бы так интересны, если бы существовали сами по себе. Однако это не так и самым интересным, нужным и полезным свойством объектов является их наследование. Посмотрим, как это выглядит на примере уже описанного выше объекта Man:

// Описание объекта Worker, наследованного от объекта Man

class Worker extends Man

{

        var $profession;

        var $salary = 500;     // Заметьте, переменные объектов могут быть

                               // инициализированы каким-то значением

                               // уже на этапе их описания. Однако это

                               // значение может быть только константой

                               // (не переменной!)

 

        function Worker($fName,$lName,$age,$profession='engineer',$salary=500)

        {

 

// PHP не вызывает конструктор родительского объекта автоматически,

// поэтому вам необходимо делать это самим

                $this->Man($fName,$lName,$age);

                $this->profession = $profession;

                $this->salary = $salary;

        };

};

 

// Создаем экземпляр объекта Worker

$worker = new Worker('Jack','Robertson',29,'programmer');

 

// Только что созданный экземпляр объекта Worker унаследовал все переменные и методы объекта Man

echo "Hello, I'm ".$worker->getName();

Переменные и методы можно не только добавлять, но и переопределять методы родительского объекта:

// Создадим новый вариант объекта Worker, переопределив метод getName()

class Worker extends Man

{

        var $profession;

        var $salary;           

 

        function getName()

        {

                return(parent::getName().", ".$this->profession);

        };

};

 

// Создаем экземпляр объекта Worker и попытаемся получить его имя:

$worker = new Worker('Jack','Robertson',29,'programmer');

echo $worker->getName();

Результатом работы предыдущего примерв будет строка: "Jack Robertson, programmer". Вы заметили использование нового оператора :: ? Этот оператор позволяет вызывать из метода объекта метод одного из родительских объектов, даже если тот уже переопределен при более "поздних" наследованиях. Использование ключевого слова parent в этом выражении позволяет вызвать метод непосредственного предка этого объекта. Однако в более сложных случаях, когда степень наследования объектов выше - можно использовать непосредственно имя объекта, метод которого необходимо вызвать. В нашем случае можно было бы написать: Man::getName().

Заключение

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

Программирование на PHP. Третий выпуск. Более подробно о references.

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

References в PHP

References появились в PHP начиная с четвертой версии, вследствие того, что теперь в качестве ядра PHP используется Zend scripting engine. Для того, чтобы вам стала понятна суть references - необходимо объяснить как Zend engine работает с переменными.

Внутри кода Zend engine существует разделение между именем переменной и ее значением. Это можно представить как две различные таблицы:

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

// Создадим 3 переменные

$a = 2;

$b = 3;

$c = 5;

 

// Выведем их значения

print $a;       // Результат: 2

print $b;       // Результат: 3

print $c;       // Результат: 5

Вот как это будет выглядеть внутри Zend engine:

Так вот, суть механизма references состоит в том, что они позволяет вам изменять связи между элементами этих таблиц. При этом references отличаются от указателей, имеющихся в C/C++ и других языках. Отличие состоит в том, что указатель является отдельной переменной, содержащей указатель, на местоположение в памяти другой переменной. В PHP же механизм references позволит вам создать несколько имен для одной и той же переменной! Важно понять это, чтобы правильно использовать references в своем коде.

Лучше всего рассмотреть то, как это работает на примере:

$b = &$a;              // Знак & перед именем переменной указывает на использование reference

Посмотрим, как в этом случае будут выглядеть внутренние связи между именами переменных и их значениями:

Как видите, имя переменной $b теперь указывает на значение переменной $a. Заметьте, что значение самой переменной $b теперь не имеет ни одного имени, связанного с ней и поэтому больше недоступно из PHP кода. Ядро PHP автоматически уничтожает такие переменные, поэтому значение 3, ранее бывшее значением переменной $b, перестает существовать с этого момента.

Поскольку теперь значение первой переменной в таблице значений имеет два имени ($a и $b), то обращение к любому из этих имен будет рассматриваться как обращение к этой переменной:

print $a;       // Результат: 2

print $b;       // Результат: 2

print $c;       // Результат: 5

Сравните результаты с предыдущими.

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

$a = 1;

$b = 4;

Более того, даже удаления имени переменной, которая изначально была связана с этим значением ничего не изменит, значение переменной будет существовать до тех пор, пока есть хоть одно имя переменной, связанное с ней:

unset($a);              // Удаляем переменную $a

 

print $b;               // Результат: 4

print $c;               // Результат: 5

References могут использоваться не только для переменных. Например в предыдущем выпуске было показано, как использовать references для передачи параметров в функцию. Как вы наверняка знаете - в программировании существует два основных метода передачи параметров в процедуры или функции:

  • передача "по значению" (passing by value) - В процедуру (функцию) передается значение, являющееся копией оригинальной переменной. Все изменения этого значения внутри процедуры (функции) никак не сказываются на оригинальной переменной.
  • передача "по ссылке" (passing by reference) - В процедуру передается ссылка на оригинальную переменную. Все изменения этого значения внутри процедуры (функции) приводят к соответствующим изменениям оригинальной переменной.

Если ранее (до четвертой версии) в PHP можно было использовать только первый метод передачи параметров, то теперь вам доступны оба метода. Посмотрим, как это выглядит, на примере:

// Глобальная переменная, содержащая некоторое значение

$value = 1;

 

// Функция, инкрементирующая значение преданной ей в качестве параметра переменной

function counter(&$var)

{

        $var++;

};

 

// Вызываем функцию, передавая ей в качестве параметра имеющуюся у нас переменную

counter($value);

// Смотрим, как изменилось значение переменной

print $value;           // Результат: 2

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

Конечно, такого же результата можно было бы добиться и другим способом:

$value = 1;

 

 

function counter($var)

{

        $var++;

};

 

 

counter(&$value);

print $value;           // Результат: 2

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

References можно использовать не только для того, чтобы передавать параметры в функции, но и для того, чтобы получать результат. Для этого необходимо поставить знак & перед именем функции:

function &getValue()

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

Но особенно часто references используются при работе с объектами. И это вполне логично, ведь при работе с объектами практически всегда необходимо оперировать именно с самим экземпляром объекта, а не с его копией, создаваемой каждый раз при присваивании или передаче в функцию "по значению".

Использование references зачастую начинается в тот момент, когда создается экземпляр объекта:

$newObj = &new myObject();

Приведенный выше код создает экземпляр объекта myObject() и передает reference на него в переменную $newObj. В этом случае все будет работать нормально. А теперь посмотрим на другой вариант того же кода:

$newObj = new myObject();

Единственное отличие состоит в том, что в переменной $newObj сохраняется не только что созданный экземпляр объекта myObject(), а копия этого экземпляра. При этом оригинал автоматически уничтожается по причинам описанным выше - не будет ни одного имени переменной, связанного с ним.

На первый взгляд разница между двумя этими путями невелика - все равно в результате мы получаем экземпляр необходимого нам объекта. Однако разница есть и она таится в конструкторе объекта. Все дело в том, что конструктор объекта вызывается до того, как завершится работа оператора new. Поэтому, если в конструкторе объекта вы создали какие-либо references в переменных объекта, используя для этого переменную $this, то все эти references будут потеряны! Так что вам необходимо четко следить за тем, как именно вы создаете экземпляры ваших объектов, чтобы избежать подобных, далеко не очевидных, проблем.

Еще один момент, когда использование references просто необходимо - создание связей между объектами и объединение объектов в структуры. Здесь вам вообще не удастся обойтись без помощи references, т.к. здесь необходимо иметь в переменных объекта ссылку именно на экземпляр объекта.

В качестве примера структуры, состоящей из объектов можно привести дерево объектов, каждым листом которого является отдельный объект. В такой структуре references используются как минимум в двух местах:

  • Создание связи с объектом-предком
  • Хранение массива объектов-наследников

И, напоследок, еще один пример кода, который может понадобиться вам довольно часто, но также может привести к ошибкам, которые будет достаточно сложно обнаружить вследствие их неочевидности. Это пример обработки массива объектов, в котором каждый элемент является reference на объект. Для начала код создания подобного массива. Я использовал очень простой объект просто для того, чтобы проиллюстрировать дальнейший код:

// В этом массиве будут храниться объекты.

// Каждый элемент массива - reference на соответствующий объект

$data = array();

 

// Очень простой класс

class myObject

{

    var $id;

 

    function setID($id)

    {

        $this->id = $id;

    }

};

 

// Заполняем массив объектами.

for ($i=0;$i

    $data[] = &new myObject();

Теперь нам, к примеру, необходимо задать идентификатор для каждого объекта в массиве. Первое, что приходит в голову -простой перебор элементов массива и присвоение идентификатора каждому из них:

$id = 1;

foreach($data as $obj)

{

    $obj->setID($id++);

};

Этот код, разумеется не будет работать, потому что здесь references просто не используются и работа ведется с копиями объектов, хранящихся в массиве. Правильным кодом для этого будет следующее:

$id = 0;

// Здесь мы перебираем не сами элементы массива,

// а ключи этого массива с тем, чтобы сохранить references

foreach(array_keys($data) as $key)

{

// Получаем reference на текущий объект

        $obj = &$data[$key];

 

// Выполняем необходимые действия с ним

        $obj->setID($id++);

 

// Уничтожаем созданный reference.

// Если этого не сделать, то на следующем шаге

// мы просто уничтожим объект, с которым работали в прошлый раз

// Почему? См. выше о том, как работают references

        unset($obj);

};

Заключение

Как вы могли убедиться, references - это очень мощный механизм. И иногда без них просто не обойтись. Однако как и каждым мощным средством пользоваться ими надо аккуратно, чтобы избежать множества ошибок.

 

 

1. Что такое PHP?

1. 1. Применение РНР при программировании сайтов

1.2. Программа регистрации и авторизации на вашем сайте

1.3. Программа регистрации и авторизации на сайте с шифрованием пароля

2. Глава посвящена программированию
вообще и программированию в частности
сайтов

3. MySQL элементы управления и взаимодействие с PHP

4. Русский перевод файла "httpd.conf" Для Apache 2.0

5. Русский перевод файла "php.ini"

 

главная                                                                                                                   стр.  1. 2. 3. 4. 5. 6. 7. 8.