Php обращение к элементу объекта. Объектно-ориентированное программирование

Поскольку именно классы описывают объекты, мы начнем описание с определения классов.

Определение класса

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

Класс first из приведенного примера - уже полноправный класс, хотя пока и не слишком полезный. Но тем не менее мы сделали нечто очень важное. Мы определили тип, т.е. создали категорию данных, которые мы можем использовать в своих сценариях. Важность этого станет для вас очевидной по мере дальнейшего чтения главы.

Создание объекта

Так как класс - это шаблон для создания объектов, следовательно, объект - это данные, которые создаются и структурируются в соответствии с шаблоном, определенным в классе. Объект также называют экземпляром класса, тип которого определяется классом. Для создания нового экземпляра класса нам понадобится оператор new . Он используется совместно с именем класса следующим образом:

После оператора new указывается имя класса на основе которого будет создан объект. Оператор new создает экземпляр класса и возвращает ссылку на вновь созданный объект. Эта ссылка сохраняется в переменной соответствующего типа. В результате выполнения этого кода будет создано два объект типа first . Хотя функционально они идентичны (т.е. пусты) $obj1 и $obj2 - это два разных объекта одного типа, созданных с помощью одного класса.

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

Давайте сделаем эти объекты немного интереснее, изменив класс first , добавив в него специальные поля данных, называемые свойства.

Определение свойств

В классе можно определить переменные. Переменные, которые определены в классе называются свойствами (или полями данных). Они определяются с одним из ключевых слов protected, public или private , характеризующих управление доступом. Эти ключевые слова мы рассмотрим подробно в следующей главе. А сейчас давайте определим некоторые свойства с помощью ключевого слова public:

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

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

К свойствам объекта можно обращаться с помощь символов " -> ", указав объект и имя свойства. Поскольку свойства объектов были определены как public , мы можем считывать их значения, а также присваивать им новые значения, заменяя тем самым начальные значения, определенные в классе:

str; // присваиваем свойству объекта новое значение $obj->str = "новая строка"; echo "
$obj->str"; ?>

На самом деле в PHP необязательно объявлять все свойства в классе. Свойства можно добавлять к объекту динамически:

newprop = "новое свойство"; echo $obj->newprop; ?>

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

Работа с методами

Методы - это обычные функции, которые определяются внутри класса, они позволяют объектам выполнять различные задачи. Объявление метода напоминает определение обычной функции, за исключением предваряемого одного из ключевых слов protected, public или private . Если в определении метода вы опустите ключевое слово, определяющее видимость, то метод будет объявлен неявно как public . К методам объекта можно обращаться с помощь символов " -> ", указав объект и имя метода. При вызове метода, так же как и при вызове функции нужно использовать круглые скобки.

str; } } $obj = new first(); // вызов метода объекта $obj->getstr(); ?>

Мы добавили метод getstr() к классу first . Обратите внимание на то, что при определении метода мы не использовали ключевое слово, определяющее область видимости. Это означает, что метод getstr() относится к типу public и его можно вызвать за пределами класса.

В определении метода мы воспользовались специальной псевдопеременной $this . Она используется для обращения к методам или свойствам внутри класса и имеет следующий синтаксис:

$this->имя переменной или метода

Class first { public $str = "some text"; // при определении метода в классе, переменная $this не имеет никакого значения function getstr() { echo $this->str; } } // создаем объект $obj = new first(); // созданный нами объект имеет свойство и метод // теперь в методе объекта переменная $this имеет // ссылку на текущий объект, а именно на $obj // т.е. если в методе заменить $this текущим экземпляром объекта $this->str; // это будет выглядеть как простое // обращение к свойству текущего объекта $obj->str;

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

Специальный метод - конструктор

У класса может быть определен специальный метод - конструктор , который вызывается каждый раз при создании нового экземпляра класса (объекта) с целью инициализировать его, например установить значения свойств. Конструктор, как и любой другой метод может иметь параметры. Чтобы определить метод в качестве конструктора его необходимо назвать __construct() . Обратите внимание на то, что имя метода должно начинаться с двух символов подчеркивания. Посмотрим, как это работает:

num1 = $num1; $this->num2 = $num2; } // метод, который складывает два числа function summa() { return $this->num1 + $this->num2; } } // создаем объект и передаем два аргумента $obj = new first(15, 35); // вызываем метод и сразу выводим результат его работы echo $obj->summa(); ?>

Метод __construct вызывается, когда создается объект с помощью оператора new . Указанные в скобках аргументы передаются конструктору. В методе конструктора используется псевдопеременная $this для присвоения значений соответствующим свойствам создаваемого объекта.

Примечание: если конструктор не имеет параметров и при создании новых экземпляров класса не передаются никакие аргументы, круглые скобки () после имени класса можно опустить: $obj = new first;

Указание типа аргумента в методах

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

getobj(new cat()); // здесь будет ошибка: передали в качестве аргумента экземпляр типа wrong $kitty->getobj(new wrong()); ?>

Теперь в качестве аргумента методу getobj() можно передавать только экземпляры типа cat . Поскольку метод getobj() содержит уточнение типа класса, передача ему объекта типа wrong приведет к ошибке.

Указание типа нельзя использовать для определения параметров элементарных типов, таких как строки, числа и т.д. Для этой цели в теле метода следует использовать функции проверки типов, например is_string() . Также есть возможность определить, что передаваемый аргумент является массивом:

my_arr = $some_arr; } } ?>

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

Function getobj(cat $getCat = null) { $this->someVar = $getCat; }

Если вместо NULL указать какое-либо другое значение по умолчанию, будет выдана ошибка.

Объект класса - представитель класса, который имеет свое уникальное состояние и поведение.
Для объявления объекта необходимо использовать оператор new:

Объект = new Имя_класса;

PHP

$myObj = new newClass();

Свойства класса

Свойство – это переменные, хранимые в классе; перед именем свойства ставится один из следующих модификаторов (public , protected , private). Также есть ключевое слово var , но его время ушло (остался в 4-й версии PHP).

Описание свойств

PHP

class newClass { public $property1; protected $property2 = "value2"; private $property3; }

Доступ к свойствам класса

Доступ к свойствам класса за пределами класса реализуется так: объект->

PHP

$myObj = new newClass(); $myObj->property1;

Изменение значения свойств

PHP

$myObj->property2 = "Тут меняем значение";

Методы класса

Метод – это функция, определенная внутри класса. У функции по умолчанию стоит модификатор public (то есть его можно не писать перед функцией).

Описание методов

PHP

class newClass { function myMethod($var1,$var2){ // по умолчанию это // общедоступный метод (public) // операторы } }

Вызов метода

PHP

$myObj = new newClass(); $myObj->myMethod("v1","v2");

$this

Доступ к свойству класса внутри класса реализуется при помощи оператора($this):
$this-> имя_свойства; (знак доллара у свойства не ставится!)

Доступ к методу класса из другого метода класса также осуществляется с помощью ключевого слова $this .

PHP

class newClass { public $property1; function myMethod(){ echo($this->property1); // Вывод значения свойства } function callMethod(){ $this->myMethod(); // Вызов метода } }

Конструкторы и деструкторы

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

Деструктор – специальный метод, который автоматически вызывается при удалении объекта. P.s. Порядок удаления объектов не определен, но стоит отметить, что объекты удалятся по завершении кода (порядок удаления объектов определить нельзя), и вызовется метод __destruct . Объект можно удалить принудительно: unset(имя_объекта) .

PHP

class newClass { public $property; function __construct($var){ $this->property = $var; echo "Вызываем конструктор"; } function __destruct(){ echo "Вызываем деструктор"; } } $obj = new newClass("Значение"); //Вызываем конструктор unset($obj); //Вызываем деструктора (принудительно)

Псевдо-константы __METHOD__ и __CLASS__

Псевдо-константы __METHOD__ и __CLASS__ . Вместо __METHOD__ будет подставлено: имя_класса::имя_метода; __CLASS__ будет подставлено имя_класса.

PHP

class newClass { function myMethod(){ echo __METHOD__; } function getClassName(){ echo __CLASS__; } } $obj = new newClass(); $obj->myMethod();// newClass::myMethod $obj->getClassName();// newClass

Новые принципы работы с объектами

Объекты передаются по ссылке, а не по значению

PHP

class newClass { public $property; } $myObj = new newClass(); $myObj->property = 1; $myObj2 = $myObj; $myObj2->property = 2; print($myObj->property); // Выведет 2 print($myObj2->property); // Выведет 2

Клонирование объекта

При клонировании (clone) конструктор не вызывается. Существует специальный метод __clone , который вызывается при клонировании объекта.

Явное копирование объектов

PHP

class newClass { public $property; } $myObj = new newClass(); $myObj->property = 1; $myObj2 = clone $myObj; // создаем копию объекта, в 4-й версии php было так: $myObj2 = &$myObj; // в 5-й версии PHP & с объектами не работает $myObj2->property = 2; print($myObj->property); // Печатает 1 print($myObj2->property); // Печатает 2

Наследование(полиморфизм)

Один класс может наследовать другой класс. Для этого существует специальное ключевое слово - extends .

PHP

class Machine { public $numWheels = 4; function printWheels() { echo $this->numWheels; } } class Toyota extends Machine { public $country = "Japan"; function printCountry() { echo $this->country; } } $myMachine = new Toyota(); $myMachine->printWheels(); $myMachine->printCountry();

Перегрузка методов

Перегрузка методов – в классе, который наследует другой класс, можно описать такой же метод, который есть в родительском классе, причем вновь описанный метод перезапишет метод родительского класса. Пример:

PHP

class Machine { public $numWheels = 4; function printWheels() { echo $this->numWheels; } } class Toyota extends Machine { public $country = "Japan"; function printCountry() { echo $this->country; } function printWheels() { echo "Перегруженный метод printWheels() "; } } $myMachine = new Toyota(); $myMachine->printWheels();

Parent

parent::имя_метода, данная конструкция позволяет обратиться к родительскому методу.

PHP

class Machine { public $numWheels = 4; function printWheels() { echo $this->numWheels; } } class Toyota extends Machine { public $country = "Japan"; function printWheels() { echo "Перегруженный метод printWheels() "; parent:: printWheels(); } } $myMachine = new Toyota(); $myMachine->printWheels();

Модификаторы доступа: public , protected , private

Модификаторы доступа: как это работает?

PHP

$obj = new newClass(); echo $obj->public; //ДА echo $obj->protected; //НЕТ! echo $obj->private; //НЕТ $obj->myMethod();

PHP

class newClass { public $public = 1; protected $protected = 2; private $private = 3; function myMethod(){ echo $this->public; //ДА echo $this->protected; //ДА echo $this->private; //ДА } }

PHP

$obj1 = new NewClass(); echo $obj1->public; //ДА echo $obj1->protected; //НЕТ! echo $obj1->private; //НЕТ $obj1->newMethod();

PHP

class NewClass extends newClass { function newMethod(){ echo $this->protected; //ДА echo $this->private; //НЕТ $this->myMethod(); } }

Обработка исключений

У нас есть кусок кода, в котором может произойти какая-нибудь ошибка; данный кусок кода помещается в блок под названием try ; в том месте, где-может произойти ошибка, ставится ключевое слово throw ; для отлова произошедшей ошибки описывается блок catch (ловушка), туда приходит ошибка, с которой мы можем работать.

PHP

try { $a = 1; $b = 0; if($b == 0) throw new Exception("Деление на 0!"); echo $a/$b; } catch(Exception $e){ echo "Произошла ошибка - ", $e->getMessage(), // Выводит сообщение " в строке ", $e->getLine(), // Выводит номер строки " файла ", $e->getFile(); // Выводит имя файла }

Создание собственных исключений

PHP

сlass MathException extends Exception { function __construct($message) { parent::__construct($message); } } try { $a = 1; $b = 0; // MathException - имя класса для создания собственного исключения if ($b == 0) throw new MathException("Деление на 0!"); echo $a / $b; } catch (MathException $e) { echo "Произошла математическая ошибка ", $e->getMessage(), " в строке ", $e->getLine(), " файла ", $e->getFile(); }

Перебор свойств объекта

PHP

class Person { public $name; public $yearOfBorn; function __construct($name, $yearOfBorn){ $this->name = $name; $this->yearOfBorn = $yearOfBorn; } } $billGates = new Person(‘Bill Gates’,1955); foreach($billGates as $name=>$value){ print($name.’: ’.$value.’
’); }

Константы класса

Константы – это константы класса, то есть они не принадлежат ни одному объекту. За пределами кода к константе можно обратиться следующим образом: имя_класса::имя_константы. Если мы хотим обратиться к константе в пределах класса, то нужно использовать ключевое слово self: self::имя_константы.

PHP

class Person { const HANDS = 2; function printHands(){ print (self::HANDS);// NOT $this! Обращаемся к константе внутри класса } } print ("Количество рук: ".Person::HANDS); // Обращаемся к константе за пределами класса

Абстрактные методы и классы

Абстрактный класс в php - это так называемый базовый класс, не предназначенный для создания его экземпляров (объектов). Основной смысл и назначение абстрактных классов заключается в расширении возможностей его дочерних классов.

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

В абстрактном классе могут быть абстрактные методы (перед function стоит ключевое слово abstract). Абстрактный метод – это метод без реализации (отсутствуют фигурный скобки).

Абстрактный метод обязательно должен быть описан (перезагружен) в классе-наследнике. Преимущество в использовании абстрактных методов: для каждого класса-наследника можно описать свое уникальное поведение абстрактного метода.

PHP

abstract class Machine { // абстрактный класс public $petrol; function startEngine(){ print("Двигатель зав?лся!"); } abstract function stopEngine(); } class InjectorMachine extends Machine { public function stopEngine(){ print("Двигатель остановился!"); } } $myMegaMachine = new Machine();//Ошибка! $myMegaMachine = new InjectorMachine(); $myMegaMachine->startEngine(); $myMegaMachine->stopEngine();

Интерфейсы

Существует еще один тип абстрактного класса – интерфейс. Интерфейс – это абстрактный класс, который содержит только абстрактные методы. Перед таким классом вместо слова abstract пишется interface . От интерфейса наследование происходит не через ключевое слово extends , а через ключевое слово implements .

PHP

interface Hand { function useKeyboard(); function touchNose(); } interface Foot { function runFast(); function playFootball(); } class Person implements Hand { public function useKeyboard(){ echo "Use keyboard!"; } public function touchNose(){ echo "Touch nose!"; } public function runFast(){ echo "Run fast!"; } public function playFootball(){ echo "Play football!"; } } $vasyaPupkin = new Person(); $vasyaPupkin->touchNose();

Финальные методы и классы

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

PHP

class Mathematics { final function countSum($a,$b){ print("Сумма: " . $a + $b); } } class Algebra extends Mathematics { // Возникнет ошибка public function countSum($a,$b){ $c = $a + $b; print("Сумма $a и $b: $c"); } }

PHP

final class Breakfast { // финальный класс function eatFood($food){ print("Скушали $food!"); } } // Возникнет ошибка class McBreakfast extends Breakfast { // Описание класса }

Статические свойства и методы класса

Статические методы и свойства класса (плюс константы класса) принадлежат классу, то есть они общие для всех объектов класса. К ним нельзя обратиться посредством ‛стрелки‛, а только через:: (внутри класса используется: self::$имя_свойства; за пределами класса: имя_класса::$имя_свойства). Статическое свойство, как и метод, объявляется через ключевое слово static . Как вы догадываетесь, внутри статического метода this использовать нельзя (такие методы не связаны с объектами).

PHP

class CookieLover { static $loversCount = 0; // это статическое свойство, и компилятор не // будет его удалять после завершения работы функции __construct function __construct(){ ++self::$loversCount; } static function welcome(){ echo "Добро пожаловать в клуб любителей булочек!"; //Никаких $this внутри статического метода! } } $vasyaPupkin = new CookieLover(); $frosyaBurlakova = new CookieLover(); print ("Текущее количество любителей булочек: ".CookieLover::$loversCount); print (CookieLover::welcome());

Ключевое слово instanceof

Иногда требуется узнать: является ли текущий объект наследником того или иного класса, или интерфейса. Для этого используется ключевое слово instanceof .

PHP

class Person {} $myBoss = new Person(); if($myBoss instanceOf Person) print("Мой Босс – человек!"); // вернет true, если класс Person есть в предках объекта $myBoss class Woman extends Person {} $englishQueen = new Woman(); if($englishQueen instanceOf Person) print("Английская королева – тоже человек!"); interface LotsOfMoney {} class ReachPeople implements LotsOfMoney {} $billGates = new ReachPeople(); if($billGates instanceOf LotsOfMoney) print("У Билла Гейтса много денег!");

Функция __autoload()

Если PHP натыкается на несуществующий класс, при инициализации объекта, то он ищет функцию __autoload , передавая в функцию __autoload имя неназванного класса. И PHP вызовет эту функцию перед выводом ошибки об отсутствии класса.

PHP

function __autoload($cl_name){ // $cl_name - имя не найденного класса print("Попытка создать объект класса ".$cl_name); } $obj = new undefinedClass();

Методы доступа к свойствам объекта

Метод __set() будет выполнен при записи данных в недоступные свойства (которых нет в классе).

Метод __get() будет выполнен при чтении данных из недоступных свойств (которых нет в классе).

PHP

class newClass { private $properties; function __get($name){ print("Чтение значения свойства $name"); return $this->properties[$name]; } function __set($name,$value){ // в нашем случае $name это property, $value равно 1 print("Задание нового свойства $name = $value"); $this->properties[$name] = $value; } } $obj = new newClass; $obj->property = 1; // Запись нового свойства $a = $obj->property; // Чтение значения свойства print $a; // 1

Перегрузка вызова несуществующих методов

Если мы обращаемся к методу которого нет , то PHP ищет метод __call (1-й параметр – это имя несуществующего метода, 2-й – массив аргументов).

PHP

class newClass { function __call($name, $params){ print("Попытка вызова метода $name со следующими параметрами: "); print_r($params); } } $obj = new newClass(); $obj->megaMethod(1,2,3,"четыре");

Метод __toString()

Метод __toString() позволяет классу решать самостоятельно, как он должен реагировать при преобразовании в строку. Например, что напечатает echo $obj; . Этот метод должен возвращать строку, иначе выдастся неисправимая ошибка E_RECOVERABLE_ERROR .

PHP

class newClass { function __toString(){ return "Вызван метод __toString()"; } } $obj = new newClass(); // Вызван метод __toString() echo $obj;

Добро пожаловать во второй урок из серии, посвященной ООП. В первой статье вы ознакомились с основами ООП в PHP, включая понятия классов, методов, полей и объектов. Также вы узнали, как создать простенький класс и реализовать его.

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

Вот список того, о чем я расскажу вам в этой статье:

  • Конструкторы и деструкторы, которые позволяют назначить определенные действия объекту при его создании и удалении;
  • Статические поля и методы - это такие поля и методы, которые не связаны с конкретными объектами класса;
  • Константы класса, удобные для хранения фиксированных значений, относящихся к определенному классу;
  • Явное указание типа, используемое для задания ограничения типов параметров, которые можно передавать в тот или иной метод;
  • Специальные методы __get() и __set(), которые используются для задания и чтения значений полей классов;
  • Специальный метод __call(), применяемый для вызова метода класса.

Вы готовы? Тогда вперед!

Конструкторы и деструкторы

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

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

На заметку: как удалить объект? PHP автоматически удаляет объект из памяти, когда не остается ни одной переменной, указывающей на него. Например, если вы создадите новый объект и сохраните его в переменной $myObject, а затем удалите ее с помощью метода unset($myObject), то сам объект также удалится. Также, если вы создали локальную переменную в какой-либо функции, она (вместе с объектом) удалится, когда функция завершит работу.

В PHP есть два специальных метода, которые можно применять для совершения определенных действий по созданию и удалению объектов:

  • Конструктор вызывается сразу после того, как вы создали объект;
  • Деструктор вызывается строго перед тем, как объект удаляется из памяти.

Работа с конструкторами

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

Чтобы создать конструктор, добавьте в ваш класс специальный метод __construct() (перед словом construct - два символа подчеркивания). PHP автоматически вызовет этот метод при реализации вашего класса, то есть, при создании объекта этого класса.

Вот пример конструктора:

Class MyClass { public function __construct() { echo "I"ve just been created!"; } } $myObject = new MyClass(); // отобразит "I"ve just been created!"

В классе MyClass есть конструктор, который выводит на страницу строку "I"ve just been created!". Последняя строка кода создает новый объект класса MyClass. Когда это происходит, PHP автоматически вызывает конструктор, и сообщение отображается в браузере. Теперь на практике - инициализация полей класса:

Class Member { private $username; private $location; private $homepage; public function __construct($username, $location, $homepage) { $this->username = $username; $this->location = $location; $this->homepage = $homepage; } public function showProfile() { echo "

"; echo "
Username:
$this->username
"; echo "
Location:
$this->location
"; echo "
Homepage:
$this->homepage
"; echo "
"; } } $aMember = new Member("fred", "Chicago", "http://example.com/"); $aMember->showProfile();

Данный скрипт отобразит на странице следующее:

Username: fred Location: Chicago Homepage: http://example.com/

В нашем классе Member есть три поля и конструктор, который принимает в качестве параметров 3 значения - по одному для каждого поля. Конструктор назначит полям объекта значения, полученные в качестве аргументов. В классе также есть метод для отображения на странице значений полей объекта.

Затем в коде создается объект класса Member, в который мы передаем 3 значения "fred", "Chicago", и "http://example.com/", так как конструктор принимает именно 3 параметра. Конструктор записывает эти значения в поля созданного объекта. В завершение, вызывается метод showProfile() для созданного объекта, чтобы отобразить полученные значения.

Работа с деструкторами

Применяйте деструктор, когда объект удаляется из памяти. Вам может понадобиться сохранить объект в базе данных, закрыть открытые файлы, которые взаимодействовали с объектом. Чтобы создать деструктор, добавьте в класс метод __destruct(). Он вызовется как раз перед удалением объекта автоматически. Вот простой пример:

Class MyClass { public function __destruct() { echo "I"m about to disappear - bye bye!"; // (очистить память) } } $myObject = new MyClass(); unset($myObject); // отобразит "I"m about to disappear - bye bye!"

Мы создали простенький деструктор, который отображает на странице сообщение. Затем мы создали объект нашего класса и сразу же удалили его, вызвав метод unset() для переменной, которая ссылается на объект. Перед самым удалением объекта вызвался деструктор, который отобразил в браузере сообщение "I"m about to disappear - bye bye!".

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

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

Class MyClass { public function __destruct() { echo "I"m about to disappear - bye bye!"; // (очистить память) } } $myObject = new MyClass(); exit; // отобразит "I"m about to disappear - bye bye!"

Также, если работа скрипта прекратится из-за возникшей ошибки, деструктор тоже вызовется.

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

parent::__construct(). То же самое касается деструкторов. Вызвать деструктор родителя можно так: parent:__destruct(). Я расскажу вам о классах-родителях и наследниках в следующем уроке, посвященном наследованию.

Статические поля класса

Мы рассмотрели статические переменные в статье PHP Variable Scope: All You Need to Know. Как обычная локальная переменная, статическая переменная доступна только в пределах функции. Тем не менее, в отличие от обычных локальных, статические переменные сохраняют значения между вызовами функции.

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

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

Чтобы создать статическую переменную, добавьте ключевое слово static в ее задании:

Class MyClass { public static $myProperty; }

Вот пример того, как работают статические переменные:

Class Member { private $username; public static $numMembers = 0; public function __construct($username) { $this->username = $username; self::$numMembers++; } } echo Member::$numMembers . "
"; // отобразит "0" $aMember = new Member("fred"); echo Member::$numMembers . "
"; // отобразит "1" $anotherMember = new Member("mary"); echo Member::$numMembers . "
"; // отобразит "2"

Есть несколько интересных вещей, так что давайте разберем данный скрипт:

  • В классе Member два поля: частное поле $username и статическое $numMembers, которое изначально получает значение 0;
  • Конструктор получает в качестве параметра аргумент $username и устанавливает полю только что созданного объекта значение этого параметра. В то же время, он инкрементирует значение поля $numMembers, тем самым давая понять, что число объектов нашего класса увеличилось на 1.

Отметьте, что конструктор обращается к статическому полю так: self::$numMembers. Ключевое слово self похоже на $this, которое мы рассмотрели в прошлом уроке. Тогда как $this ссылается на текущий объект, self - на текущий класс. Также тогда как для получения доступа к полям и методам объекта вы используете ->, то в этом случае используйте:: для получения доступа к полям и методам класса.

  • В завершении скрипт создает несколько объектов класса Member и отображает на странице их количество, т.е. значение статической переменной $numMembers. Отметьте, что данная переменная сохраняет свое значение на протяжении всей работы скрипта, несмотря на объекты класса.

Итак, чтобы получить доступ к статическому полю класса, применяйте оператор::. Здесь мы не можем воспользоваться ключевым словом self, так как код находится за пределами класса, поэтому мы пишем имя класса, затем::, а затем имя поля (Member::$numMembers). В пределах конструктора тоже нужно использовать именно такую структуру, а не self.

На заметку: нашему скрипту ничего не стоило получить доступ к полю класса $numMembers перед тем, как создался первый объект данного класса. Нет необходимости создавать объекты класса для того, чтобы пользоваться его статическими полями.

Статические методы

Наряду со статическими полями класса, вы также можете создавать статические методы. Статические методы, так же как и поля, связаны с классом, но нет необходимости создавать объект класса, чтобы вызвать статический метод. Это делает такие методы полезными в случае, если вам нужен класс, который не оперирует реальными объектами.

Чтобы создать статический метод, нужно добавить в его объявлении ключевое слово static:

Class MyClass { public static function myMethod() { // (действия) } }

В нашем предыдущем примере, касающемся статических полей, было статическое поле $numMembers. Делать поля частными, а методы для доступа к ним - открытыми, - это хорошая практика. Давайте сделаем наше статическое поле частным и напишем статический метод public для получения значения данного поля:

Class Member { private $username; private static $numMembers = 0; public function __construct($username) { $this->username = $username; self::$numMembers++; } public static function getNumMembers() { return self::$numMembers; } } echo Member::getNumMembers() . "
"; // отобразит "0" $aMember = new Member("fred"); echo Member::getNumMembers() . "
"; // отобразит "1" $anotherMember = new Member("mary"); echo Member::getNumMembers() . "
"; // отобразит "2"

Здесь мы создали статический метод getNumMembers(), который возвращает значение статического поля $numMembers. Мы также сделали это поле частным, чтобы нельзя было получить его значение извне.

Мы также изменили код вызова, применив метод getNumMembers() для получения значения поля $numMembers. Отметьте, можно вызывать данный метод без того, чтобы создавать объект класса, потому что метод - статический.

Константы класса

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

Определить классовую константу можно с помощью ключевого слова const. Например:

Class MyClass { const CONSTANT_NAME = value; }

Обратиться в последствии к классовой константе можно через имя класса и оператор::. Например, так:

MyClass::CONSTANT_NAME

На заметку: как и в случае со статическими полями и методами, вы можете обратиться к константе через ключевое слово self.

Давайте рассмотрим классовые константы на примере. Добавим в класс Member константы, в которых будут храниться значения их роли (участник, модератор или администратор). Применив константы вместо обычных численных значений, мы сделали код более читабельным. Вот скрипт:

Class Member { const MEMBER = 1; const MODERATOR = 2; const ADMINISTRATOR = 3; private $username; private $level; public function __construct($username, $level) { $this->username = $username; $this->level = $level; } public function getUsername() { return $this->username; } public function getLevel() { if ($this->level == self::MEMBER) return "a member"; if ($this->level == self::MODERATOR) return "a moderator"; if ($this->level == self::ADMINISTRATOR) return "an administrator"; return "unknown"; } } $aMember = new Member("fred", Member::MEMBER); $anotherMember = new Member("mary", Member::ADMINISTRATOR); echo $aMember->getUsername() . " is " . $aMember->getLevel() . "
"; // отобразит "fred is a member" echo $anotherMember->getUsername() . " is " . $anotherMember->getLevel() . "
"; // отобразит "mary is an administrator"

Мы создали три классовые константы: MEMBER, MODERATOR и ADMINISTRATOR, и задали им значения 1, 2 и 3 соответственно. Затем мы добавляем поле $level для хранения ролей и немного изменяем конструктор так, чтобы инициализировать еще и это поле. В классе также появился еще один метод - getLevel(), который возвращает определенное сообщение в зависимости от значения поля $level. Он сравнивает это значение с каждой из классовых констант и возвращает нужную строку.

Скрипт создает несколько объектов с разными ролями. Для задания объектам ролей используются именно классовые константы, а не простые численные значения. Затем идут вызовы методов getUsername() и getLevel() для каждого объекта, и результаты отображаются на странице.

Явное указание типов аргументов функций

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

Echo strlen(123); // отобразит"3"

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

Например

Посмотрите на этот код:

Class Member { private $username; public function __construct($username) { $this->username = $username; } public function getUsername() { return $this->username; } } class Topic { private $member; private $subject; public function __construct($member, $subject) { $this->member = $member; $this->subject = $subject; } public function getUsername() { return $this->member->getUsername(); } } $aMember = new Member("fred"); $aTopic = new Topic($aMember, "Hello everybody!"); echo $aTopic->getUsername(); // отобразит "fred"

Данный скрипт работает так:

  • Мы создаем наш класс Member с полем $username, конструктором и методом getUsername();
  • Также создаем класс Topic для управления статьями форума. У него два поля: $member и $subject. $member - это объект класса Member, это будет автор статьи. Поле $subject - это тема статьи.
  • В классе Topic также содержится конструктор, который принимает объект класса Member и строку - тему статьи. Этими значениями он инициализирует поля класса. У него еще есть метод getUsername(), который возвращает имя участника форума. Это достигается через вызов метода getUsername() объекта Member.
  • В завершении создаем объект класса Member со значением поля username “fred”. Затем создаем объект класса Topic, передав ему Фреда и тему статьи “Hello everybody!”. В конце вызываем метод getUsername() класса Topic и отображаем на странице имя пользователя (“fred”).

Это все очень хорошо, но...

Давайте сделаем лучше!

Добавим этот фрагмент кода в конце:

Class Widget { private $colour; public function __construct($colour) { $this->colour = $colour; } public function getColour() { return $this->colour; } } $aWidget = new Widget("blue"); $anotherTopic = new Topic($aWidget, "Oops!"); // отобразит "Fatal error: Call to undefined method Widget::getUsername()" echo $anotherTopic->getUsername();

Здесь мы создаем класс Widget с полем $colour, конструктором и методом getColour(), который возвращает цвет виджета.

Затем мы создадим объект данного класса, а за ним объект Topic с аргументом $aWidget, когда на самом деле нужно передавать автора статьи, т.е. объект класса Member.

Теперь попытаемся вызвать метод getUsername() класса Topic. Этот метод обращается к методу getUsername() класса Widget. И так как в этом классе нет такого метода, мы получаем ошибку:

Fatal error: Call to undefined method Widget::getUsername()

Проблема в том, что причина ошибки не так легко уяснима. Почему объект Topic ищет метод в классе Widget, а не Member? В сложной иерархии классов будет очень сложно найти выход из такого рода ситуации.

Даем подсказку

Было бы лучше ограничить конструктор класса Topic на прием аргументов так, чтобы он мог принимать в качестве первого параметра объекты только класса Member, тем самым предостеречься от фатальных ошибок.

Это как раз то, чем занимается явное указание типов. Чтобы явно указать тип параметра, вставьте имя класса перед названием аргумента в объявлении метода:

Function myMethod(ClassName $object) { // (действия) }

Давайте подкорректируем конструктор класса Topic так, чтобы он принимал только Member:

Class Topic { private $member; private $subject; public function __construct(Member $member, $subject) { $this->member = $member; $this->subject = $subject; } public function getUsername() { return $this->member->getUsername(); } }

Теперь снова попытаемся создать объект Topic, передав ему Widget:

$aWidget = new Widget("blue"); $anotherTopic = new Topic($aWidget, "Oops!");

На этот раз PHP отобразит конкретную ошибку:

Catchable fatal error: Argument 1 passed to Topic::__construct() must be an instance of Member, instance of Widget given, called in script.php on line 55 and defined in script.php on line 24

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

Инициализация и чтение значений полей класса при помощи __get() и __set()

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

Class MyClass { public $aProperty; public $anotherProperty; }

Если поля класса - public, вы можете получить к ним доступ с помощью оператора ->:

$myObject = new MyClass; $myObject->aProperty = "hello";

Тем не менее, PHP позволяет создавать “виртуальные” поля, которых на самом деле нет в классе, но к которым можно получить доступ через оператор ->. Они могут быть полезны в таких случаях:

  • Когда у вас очень много полей, и вы хотите создать для них массив, чтобы не объявлять каждое поле отдельно;
  • Когда вам нужно хранить поле за пределами объекта, например, в другом объекте, или даже в файле или базе данных;
  • Когда вам нужно вычислять значения полей “на лету”, а не хранить их значения где-либо.

Чтобы создать такие “виртуальные” поля, нужно добавить в класс парочку волшебных методов:

  • __get($propName) вызывается автоматически при попытке прочитать значение “невидимого” поля $propName;
  • __set($propName,$propValue) вызывается автоматически при попытке задать “невидимому” полю $propName значение $propValue.

“Невидимый” в данном контексте значит, что на данном участке кода нельзя прямо получить доступ к данным полям. Например, если такого поля вообще нет в классе, или если оно существует, но оно частное, и за пределами класса нет доступа к такому полю.

Перейдем к практике. Изменим наш класс Member так, чтобы в дополнение полю $username были еще и другие случайные поля, которые будут храниться в массиве $data:

Class Member { private $username; private $data = array(); public function __get($property) { if ($property == "username") { return $this->username; } else { if (array_key_exists($property, $this->data)) { return $this->data[$property]; } else { return null; } } } public function __set($property, $value) { if ($property == "username") { $this->username = $value; } else { $this->data[$property] = $value; } } } $aMember = new Member(); $aMember->username = "fred"; $aMember->location = "San Francisco"; echo $aMember->username . "
"; // отобразит "fred" echo $aMember->location . "
"; // отобразит "San Francisco"

Вот, как это работает:

  • В классе Member есть постоянное поле private $username и private массив $data для хранения случайных “виртуальных” полей;
  • Метод __get() принимает единственный параметр $property - имя поля, значение которого нужно вернуть. Если $property = “username”, то метод вернет значение поля $username. В другом случае, метод проверит, встречается ли такой $property в ключах массива $data. Если найдется такой ключ, он вернет значение данного поля, в противном случае - null.
  • Метод __set() принимает 2 параметра: $property - имя поля, которое нужно инициализировать, и $value - значение, которое нужно задать данному полю. Если $property = “username”, метод инициализирует поле $username значением из параметра $value. В противном случае, добавляет в массив $data ключ $property со значением $value.
  • После создания класса Member, создаем объект этого класса и инициализируем его поле $username значением “fred”. Это вызывает метод __set(), который задаст значение $username объекту. Затем устанавливаем значение поля $location в “San Francisco”. Так как такого поля не существует в объекте, метод записывает его в массив $data.
  • В конце, достаем значения $username и $location и выводим их на страницу. Метод __get() достает действительное значение $username из существующего поля $username, а значение $location - из массива $data.

Как видите, с помощью методов __get() и __set() мы создали класс, в котором могут быть как настоящие поля, так и любые “виртуальные”. Из фрагмента кода, где задается значение тому или иному полю, не обязательно знать, существует ли такое поле или нет в объекте. Через обычный оператор -> можно задать полю значение или прочитать его.

В примере также показано, как можно легко создать методы, называемые “геттерами” и “сеттерами”, для доступа к частным полям. Нам не нужно создавать отдельные методы getUsername() и setUsername() для получения доступа к частному полю $username. Вместо этого мы создали методы __get() и __set() для манипулирования данным полем. Это значит, что нам нужно всего 2 метода в общем, а не по 2 метода для каждого частного поля.

На заметку: Слово о инкапсуляции. Использование частных полей класса в комбинации с геттерами и сеттерами - это лучше, чем использование переменных public. Геттеры и сеттеры дополнительно могут обрабатывать данные, задаваемые полям объекта и получаемые из них, например, проверять, в правильном ли формате находится значение, или конвертировать его в нужный формат. Геттеры и сеттеры также скрывают детали того, как имплементируются поля класса, что упрощает процесс модификации внутренней части класса, так как не нужно переписывать код, который оперирует объектами данного класса. Например, вы вдруг захотели хранить значение поля в базе данных. Если у вас уже были геттеры и сеттеры, все, что вам нужно, - это переписать их. А вызывающий код останется таким же. Эта техника называется инкапсуляцией, и это одно из главных преимуществ ООП.

Перегрузка методов с помощью __call()

Геттеры и сеттеры используются для запрета на доступ к частным переменным. В этом же направлении используется метод __call() для запрета доступа к частным методам. Как только из кода вызывается метод класса, который либо не существует, либо он недоступен, автоматически вызывается метод __call(). Вот общий синтаксис метода:

Public function __call($methodName, $arguments) { // (действия) }

Когда производится попытка вызвать недоступный метод класса, PHP автоматически вызывает метод __call(), в который передает строку - имя вызываемого метода и список передаваемых параметров в массиве. Затем ваш метод __call() должен будет определенным способом обработать вызов и, в случае необходимости, вернуть значения.

Метод __call() полезен в ситуациях, когда вам нужно передать некую функциональность класса другому классу. Вот простой пример:

Class Member { private $username; public function __construct($username) { $this->username = $username; } public function getUsername() { return $this->username; } } class Topic { private $member; private $subject; public function __construct($member, $subject) { $this->member = $member; $this->subject = $subject; } public function getSubject() { return $this->subject; } public function __call($method, $arguments) { return $this->member->$method($arguments); } } $aMember = new Member("fred"); $aTopic = new Topic($aMember, "Hello everybody!"); echo $aTopic->getSubject() . "
"; // отобразит "Hello everybody!" echo $aTopic->getUsername() . "
"; // отобразит "fred"

Данный пример похож на тот, что приводился в разделе о явном указании типов. У нас есть класс Member с полем $username и класс Topic с полем - объектом класса Member (автор статьи) и полем $subject - темой статьи. Класс Topic содержит метод getSubject() для получения темы статьи, но в нем нет метода, который возвращал бы имя автора статьи. Вместо него в нем есть метод __call(), который вызывает несуществующий метод и передает аргументы методу класса Member.

Когда в коде вызывается метод $aTopic->getUsername(), PHP понимает, что такого метода в классе Topic не существует. Поэтому вызывается метод __call(), который в свою очередь, вызывает метод getUsername() класса Member. Этот метод возвращает имя автора методу __call(), а тот отправляет полученное значение вызывающему коду.

На заметку: в PHP есть и другие методы, касающиеся перегрузки, например, __isset(), __unset(), и __callStatic().

Заключение

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

  • Конструкторы и деструкторы, полезные для инициализации полей и очистки памяти после удаления объектов;
  • Статические поля и методы, которые работают на уровне класса, а не на уровне объекта;
  • Классовые константы, полезные для хранения фиксированных значений, необходимых на уровне класса;
  • Явное указание типов, с помощью которого можно лимитировать типы аргументов, передаваемых в метод;
  • Волшебные методы __get(), __set() и __call(), которые служат для получения доступа к частным полям и методам класса. Реализация этих методов позволяет вам создавать “виртуальные” поля и методы, которые не существуют в классе, но в то же время, могут быть вызваны.

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

Удачного программирования!

Последнее обновление: 1.11.2015

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

Ключевыми понятиями парадигмы ООП являются понятия "класс" и "объект". Описанием объекта является класс, а объект представляет экземпляр этого класса. Можно провести следующую аналогию: у всех есть некоторое представление о человеке - наличие двух рук, двух ног, головы, пищеварительной, нервной системы, головного мозга и т.д. Есть некоторый шаблон - этот шаблон можно назвать классом. А реально же существующий человек (фактически экземпляр данного класса) является объектом этого класса.

Для создания класса в PHP используется ключевое слово class. Например, новый класс, представляющий пользователя:

Class User {}

Чтобы создать объект класса User, применяется ключевое слово new :

В данном случае переменная $user является объектом класса User . С помощью функции print_r() можно вывести содержимое объекта, как и в случае с массивами.

Свойства и методы

Класс может содержать свойства, которые описывают какие-то признаки объекта, и методы, которые определяют его поведение. Добавим в класс User несколько свойств и методов:

name ; Возраст: $this->age
"; } } $user = new User; $user->name="Tom"; // установка свойства $name $user->age=30; // установка свойства $age $user->getInfo(); // вызов метода getInfo() print_r($user); ?>

Здесь класс User содержит два свойства: $name и $age . Свойства объявляются как обычные переменные, перед которыми стоит модификатор доступа - в данном случае модификатор public .

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

Для обращения к текущему объекту из этого же класса используется выражение $this - оно и представляет текущий объект. Чтобы обратиться к свойствам и методам объекта применяется оператор доступа -> . Например, чтобы получить значение свойства $name, надо использовать выражение $this->name . Причем при обращении к свойствам знак $ не используется.

При использовании объекта класса User также применяется оператор доступа для получения или установки значения свойств, а также для вызова методов.

Конструкторы и деструкторы

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

name = $name; $this->age = $age; } function getInfo() { echo "Имя: $this->name ; Возраст: $this->age
"; } } $user2 = new User("Джон", 33); $user2->getInfo(); ?>

Функция конструктора в данном случае принимает два параметра. Их значения передаются свойствам класса. И теперь чтобы создать объект, нам надо передать значения для соответствующих параметров: $user2 = new User("Джон", 33);

Параметры по умолчанию

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

Function __construct($name="Том", $age=33) { $this->name = $name; $this->age = $age; }

Таким образом, если не будут заданы параметры, вместо них будут использоваться значения "Том" и 33. И теперь мы можем создать объект User несколькими способами:

$user1 = new User("Джон", 25); $user1->getInfo(); $user2 = new User("Джек"); $user2->getInfo(); $user3 = new User(); $user3->getInfo();

Деструкторы

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

Деструктор определяется с помощью функции __destruct (два подчеркивания впереди):

Class User { public $name, $age; function __construct($name, $age) { $this->name = $name; $this->age = $age; } function getInfo() { echo "Имя: $this->name ; Возраст: $this->age
"; } function __destruct() { echo "Вызов деструктора"; } }

Функция деструктора определяется без параметров, и когда на объект не останется ссылок в программе, он будет уничтожен, и при этом будет вызван деструктор.

Переменные, которые являются членами класса, называются "свойства". Также их называют, используя другие термины, такие как "атрибуты" или "поля", но в рамках этой документации, мы будем называть их свойствами. Они определяются с помощью ключевых слов public , protected или private , следуя правилам правильного объявления переменных. Это объявление может содержать инициализацию, но эта инициализация должна быть постоянным значением, то есть значение должно быть вычислено во время компиляции и не должны зависеть от информации, полученной во время выполнения для их вычисления.

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

Пример #1 Определение свойств

class SimpleClass
{
public $var1 = "hello " . "world" ;
public $var2 = <<hello world
EOD;
// правильное определение свойства с PHP 5.6.0:
public $var3 = 1 + 2 ;
// неправильное определение свойств:
public $var4 = self :: myStaticMethod ();
public $var5 = $myVar ;

// правильное определение свойств:
public $var6 = myConstant ;
public $var7 = array(true , false );

// правильное определение свойства с PHP 5.3.0:
public $var8 = <<<"EOD"
hello world
EOD;
}
?>

Замечание :

Начиная с PHP 5.3.0 и nowdocs могут быть использованы в любом статическом контексте данных, включая определение свойств.

Пример #2 Пример использования nowdoc для инициализации свойств

class foo {
// С PHP 5.3.0
public $bar = <<<"EOT"
bar
EOT;
public $baz = <<baz
EOT;
}
?>

Замечание :

Поддержка Nowdoc и Heredoc была добавлена в PHP 5.3.0.

7 years ago

In case this saves anyone any time, I spent ages working out why the following didn"t work:

class MyClass
{
private $foo = FALSE;


{
$this->$foo = TRUE;

Echo($this->$foo);
}
}

$bar = new MyClass();

giving "Fatal error: Cannot access empty property in ...test_class.php on line 8"

The subtle change of removing the $ before accesses of $foo fixes this:

class MyClass
{
private $foo = FALSE;

Public function __construct()
{
$this->foo = TRUE;

Echo($this->foo);
}
}

$bar = new MyClass();

I guess because it"s treating $foo like a variable in the first example, so trying to call $this->FALSE (or something along those lines) which makes no sense. It"s obvious once you"ve realised, but there aren"t any examples of accessing on this page that show that.

4 years ago

You can access property names with dashes in them (for example, because you converted an XML file to an object) in the following way:

$ref = new StdClass ();
$ref ->{ "ref-type" } = "Journal Article" ;
var_dump ($ref );
?>

8 years ago

$this can be cast to array. But when doing so, it prefixes the property names/new array keys with certain data depending on the property classification. Public property names are not changed. Protected properties are prefixed with a space-padded "*". Private properties are prefixed with the space-padded class name...

Class test
{
public $var1 = 1 ;
protected $var2 = 2 ;
private $var3 = 3 ;
static $var4 = 4 ;

Public function toArray ()
{
return (array) $this ;
}
}

$t = new test ;
print_r ($t -> toArray ());

/* outputs:

Array
=> 1
[ * var2] => 2
[ test var3] => 3
)

*/
?>
This is documented behavior when converting any object to an array (see PHP manual page). All properties regardless of visibility will be shown when casting an object to array (with exceptions of a few built-in objects).

To get an array with all property names unaltered, use the "get_object_vars($this)" function in any method within class scope to retrieve an array of all properties regardless of external visibility, or "get_object_vars($object)" outside class scope to retrieve an array of only public properties (see: PHP manual page).

9 years ago

Do not confuse php"s version of properties with properties in other languages (C++ for example). In php, properties are the same as attributes, simple variables without functionality. They should be called attributes, not properties.

Properties have implicit accessor and mutator functionality. I"ve created an abstract class that allows implicit property functionality.

Abstract class PropertyObject
{
public function __get ($name )
{
if (method_exists ($this , ($method = "get_" . $name )))
{
return $this -> $method ();
}
else return;
}

Public function __isset ($name )
{
if (method_exists ($this , ($method = "isset_" . $name )))
{
return $this -> $method ();
}
else return;
}

Public function __set ($name , $value )
{
if (method_exists ($this , ($method = "set_" . $name )))
{
$this -> $method ($value );
}
}

Public function __unset ($name )
{
if (method_exists ($this , ($method = "unset_" . $name )))
{
$this -> $method ();
}
}
}

?>

after extending this class, you can create accessors and mutators that will be called automagically, using php"s magic methods, when the corresponding property is accessed.

5 years ago

Updated method objectThis() to transtypage class array properties or array to stdClass.

Hope it help you.

public function objectThis($array = null) {
if (!$array) {
foreach ($this as $property_name => $property_values) {
if (is_array($property_values) && !empty($property_values)) {
$this->{$property_name} = $this->objectThis($property_values);
} else if (is_array($property_values) && empty($property_values)) {
$this->{$property_name} = new stdClass();
}
}
} else {
$object = new stdClass();
foreach ($array as $index => $values) {
if (is_array($values) && empty($values)) {
$object->{$index} = new stdClass();
} else if (is_array($values)) {
$object->{$index} = $this->objectThis($values);
} else {
$object->{$index} = $values;
}
}
return $object;
}
}



Похожие публикации