Изначально PHP не был объектно-ориентированным (ОО) языком. Но
по мере развития объектно-ориентированные возможности стали в нем
появляться. Сначала можно было определять классы, но не было конструкторов. Затем появились конструкторы, но не было деструкторов.
Медленно, но уверенно, по мере роста количества пользователей, сталкивавшихся с ограничениями синтаксиса PHP, добавлялись новые возможности, призванные удовлетворить требования программистов.
Однако тот, кто хочет, чтобы PHP был настоящим OO языком, возможно, будет разочарован. По своей сути PHP – язык процедурно-ориентированный. Это не Java. Но для тех, кому в программе требуются
некоторые OO возможности, вероятно, PHP как раз то, что нужно.
Класс – это пакет, содержащий, во-первых, данные, а во-вторых, методы
для доступа или модификации данных. Данные состоят из переменных
и известны как свойства. Другую часть класса составляют функции,
которые могут изменять свойства класса, и называются они методами.
Определяя класс, мы не определяем объект, к которому можно получить доступ и которым можно манипулировать. Мы определяем шаблон для объекта. По этому шаблону создаются послушные объекты в
процессе так называемого создания экземпляра класса. Программа
может иметь несколько объектов одного и того же класса, точно так
же, как у человека может быть более одной книги или не один фрукт,
а несколько.
Классы также организованы в определенную иерархию. Вверху цепочки находится родовой класс. В PHP этому классу дано имя stdClass,
«стандартный» класс. Каждый нижележащий класс более специализирован, чем его родитель. Например, родительский класс может быть
зданием. А здания уже могут подразделяться на жилые и промышленные. Жилые здания можно разделить на индивидуальные и многоквартирные и т. д.
И те и другие имеют тот же самый набор свойств, что и жилые здания
вообще, точно так же, как у жилых и коммерческих строений есть что-то общее. О родственных отношениях классов говорят, что дочерний
класс наследует свойства и методы родительского. Это делает возможным повторное использование кода родительского класса, и надо
лишь написать код, адаптирующий новый дочерний класс к его специализации. Это называется наследованием и является одним из главных преимуществ классов перед функциями. Процесс определения дочернего класса известен как создание подкласса, или расширение.
Объекты в PHP, помимо своей обычной OO роли, играют и другую.
PHP не может использовать более одного пространства имен, поэтому
способность класса упаковывать несколько свойств в один объект исключительно полезна. Она позволяет четко разграничивать различные области переменных.
Объявить и создать классы в PHP нетрудно:
class guest_book {
var $comments;
var $last_visitor;
function update($comment , $visitor) {
...
}
}
Ключевое слово class определяет класс точно так же, как слово function определяет функцию. Свойства объявляются с помощью ключевого слова var. Объявление метода идентично объявлению функции.
Ключевое слово new создает экземпляр объекта:
$gb = new guest_book;
Более подробно реализация объекта описывается в примере "Реализация объектов"
Внутри класса можно объявить свойства с помощью ключевого слова
var. Делать это не обязательно, но полезно к этому привыкнуть. Поскольку PHP не требует предварительного объявления всех переменных, то можно создать их внутри класса, и при этом PHP не выдаст
ошибки или какого-либо предупреждения. Поэтому список переменных в начале определения класса может ввести в заблуждение, так
как он может не совпадать с реальным списком переменных класса.
Помимо объявления свойства, можно также присвоить ему значение:
var $last_visitor = ' Donnan ';
Следующая конструкция позволяет присвоить только постоянное значение:
var $last_visitor = ' Donnan '; // правильно
var $last_visitor = 9; // правильно
var $last_visitor = array(' Jesse '); // правильно
var $last_visitor = pick_visitor( ); // неправильно
var $last_visitor = ' Chris ' . ' 9 '; // неправильно
Если вы попытаетесь присвоить что-нибудь еще, то PHP прекратит работу с синтаксической ошибкой.
Для присваивания непостоянного значения применяется внутренний
метод класса.
var $last_visitor;
function update($comment , $visitor) {
if (!empty($comment)) {
array_unshift($this -> comments , $comment);
$this -> last_visitor = $visitor;
}
}
Если посетитель оставил свой комментарий, то вы добавляете его в начало массива комментариев и отмечаете этого посетителя в гостевой
книге как последнего. Переменная $this – это специальная переменная, ссылающаяся на текущий объект. Поэтому, чтобы получить доступ к свойству $size объекта изнутри этого объекта, сошлитесь на
$this -> $size.
Для того чтобы переменная получала значение во время создания экземпляра объекта, его надо присваивать в конструкторе класса. Конструктор класса – это метод, автоматически вызываемый при создании
объекта и имеющий то же самое имя, что и класс:
class guest_book {
var $comments;
var $last_visitor;
function guest_book($user) {
$dbh = mysql_connect(' localhost ' , ' username ' , ' password ');
$db = mysql_select_db(' sites ');
$user = mysql_real_escape_string($user);
$sql = " SELECT comments , last_visitor FROM
guest_books WHERE user=' $user ' ";
$r = mysql_query($sql);
if ($obj = mysql_fetch_object($r)) {
$this -> comments = $obj -> comments;
$this -> last_visitor = $obj -> last_visitor;
}
}
}
$gb = new guest_book(' stewart ');
Конструкторам посвящен пример "Определение конструкторов объектов" Учтите, что функция mysql_real_escape_string() впервые появилась в версии PHP 4.3; в более ранних
версиях следует вызывать функцию mysql_escape_string().
Будьте внимательны, чтобы по ошибке не напечатать $this -> $size. Это допустимо, но не то же самое, что $this -> size. Иначе получится свойство, имя которого представляет значение переменной $size. Скорее всего, переменная $size не определена, поэтому $this -> $size покажет пустое значение. За более подробной информацией о переменных именах свойств обращайтесь к примеру "Создание функции, принимающей
переменное количество аргументов"
Для доступа к методу или члену переменной помимо символа -> можно использовать и символ ::. Этот синтаксис позволяет получить доступ к статическим методам класса. Эти методы одинаковы для каждого экземпляра класса, поскольку они не могут зависеть от данных, характерных только для конкретного экземпляра. Например:
Чтобы реализовать наследование путем расширения существующего класса, применяется ключевое слово extends:
class convert {
// преобразование из градусов по Цельсию в градусы по Фаренгейту
function c2f($degrees) {
return (1.8 * $degrees) + 32;
}
}
$f = convert :: c2f(100); // 212
Чтобы реализовать наследование путем расширения существующего класса, применяется ключевое слово extends:
class xhtml extends xml {
}
Дочерний класс наследует методы родителя и может произвольно создавать свои собственные версии этих методов:
class DB {
var $result;
function getResult() {
return $this -> result;
}
function query($sql) {
error_log(" query() must be overridden by a database - specific child");
return false;
}
}
class MySQL extends DB {
function query($sql) {
$this -> result = mysql_query($sql);
}
}
Приведенный выше класс MySQL наследует неизмененный метод getResult() родительского класса DB, но имеет свою собственную, специфичную для MySQL версию метода query().
Предваряйте имя метода строкой parent:: для явного вызова родительского метода:
function escape($sql) {
$safe_sql = mysql_real_escape_string($sql); // переводим специальные
// символы в escape-последовательности
$safe_sql = parent :: escape($safe_sql); // родительский метод
// добавляет ' ' вокруг $sql
return $safe_sql;
}
Лежащий в основе мощи PHP механизм называется Zend. PHP 4 использует Zend Engine 1; PHP 5 будет основан на усовершенствованной версии – Zend Engine 2 (ZE2). ZE2 имеет совершенно новую объектную модель, которая поддерживает массу новых объектно-ориентированных возможностей: конструкторы и деструкторы, частные методы, обработку исключений и вложенные классы.