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

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

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

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

Теперь давайте создадим класс.

Class TestClass { // Это тело класса. }

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

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

Class TestClass { public $message = "Hi!"; function sayHello() { echo "Hello!"; } }

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

Теперь в нашем классе TestClass есть переменная $message со значением "Hi!", эта переменная является свойством класса, и функция sayHello, которая является методом класса.

Итак, мы имеем класс. Теперь на основании этого создадим объект при помощи оператора new .

Class TestClass { public $message = "Hi!"; function sayHello() { echo "Hello!"; } } $govorilka = new TestClass();

Наш объект является как бы копией класса.

Следующий шаг - это использование объекта. Для доступа к свойствам и методам объекта используется оператор -> .

Чтобы получить доступ к свойству $message объекта $govorilka нужно просто написать $govorilka->message. Обратите внимание, что перед названием свойства message мы уже не ставим знак $ .

Доступ к методу осуществляется также, но нужно не забывать о скобках в конце метода, ведь мы имее дело с обычной функцией.

Вот пример обращения к свойству и методу созданного нами объекта:

message; echo "
"; $govorilka->sayHello();

Мы можем менять значения свойств.

message = "Здравствуйте."; echo $govorilka->message; echo "
"; $govorilka->sayHello();

На основании одного класса можно создать сколько угодно объектов.

message = "Здравствуйте."; echo $govorilka->message; echo "
"; $govorilka->sayHello(); echo "
"; // Создаём второй объект $govorilka2 = new TestClass(); echo $govorilka2->message;

Как мы видим, изменение свойтва объекта $govorilka не привело к изменению свойства класса TestClass, и второй объект соответствует классу, экземпляром которого он является.

Стоит отметить, что объекты часто называют экземплярами класса, так что запомните этот термин.

Пока что не совсем понятно, зачем всё это нам надо, эти классы, объекты... Давайте создадим более реалистичный класс и на его примере будем дальше работать.

type \"$this->name\". Описание: $this->description. Цена: $this->price"; } } $Goods = new Goods(); $Goods->printGoods();

Обратите внимание на псевдопеременную $this , это зарезервированная в PHP переменная, которая используется для доступа к свойствам класса внутри его кода.

То есть, чтобы обратиться к свойству $name класса Goods из его же метода мы использовали конструкцию $this->name.

Теперь давайте немного увеличим пример, усложнением это назвать трудно. Итак:

type. Название: \"$this->name\". Описание: $this->description. Цена: $this->price."; } } $Goods = new Goods(); $Goods->type = "книга"; $Goods->name = "Война и мир"; $Goods->description = "Толстая книга из нескольких томов"; $Goods->price = "543.26"; $Goods->printGoods();

Конечно, нет смысла всё делать таким образом. Обычно объект получает уникальный идентификатор товара и берёт все данные из базы MySQL.

id = $id; $this->type = "книга"; $this->name = "Война и мир"; $this->description = "Толстая книга из нескольких томов"; $this->price = "543.26"; } function printGoods() { echo " ID товара: $this->id. Тип товара: $this->type. Название: \"$this->name\". Описание: $this->description. Цена: $this->price."; } } $Goods = new Goods(124); $Goods->printGoods();

В этом примере слишком много нового.

Первое, обратите внимание на название метода __construct() . Это зарезервированное слово в PHP и такой метод запустится автоматически при создании объекта. Такие методы называются конструкторами.

Когда мы создавали новый объект Goods(124), мы передали конструктору число 124. Конструктор, по легенде:), получил из базы данных соответствующий товар и определил свойства объекта в соответствии с информацией из базы данных.

Свойства объекта у нас имеют область видимости protected , то есть защищённую. К такому свойству мы не можем обратиться напрямую из клиентского кода.

Клиентский код - это код, который использует класс, объект или функцию. Это важный термин, запомните его.

Вот пример попытки обратиться из клиентского кода к защещённому свойству:

price;

Этот пример вернёт ошибку: "Cannot access protected property Goods". Так и должно быть, мы обращаемся туда, куда нет доступа.

Резюме

Итак, что мы узнали на этой странице:

  • Что такое класс. Зачем нужен класс. Как создать класс при помощи зарезервированного слова class .
  • Что такое свойства и методы класса.
  • Как при помощи оператора new создать объект какого-то класса.
  • Как из объекта получить доступ к свойствам и методам класса при помощи конструкции -> .
  • Как изменять свойства класса из объекта.
  • Область видимости свойств и методов. Как ограничить область видимости при помощи слова protected .
  • Как обратиться к свойству метода в классе при помощи псевдопеременной $this .
  • Создание конструкторов при помощи метода __construct() .

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

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

Из Зандстры

стр. 51 - проверка передаваемого методу аргумента на соответствие типу класса (можно и проверить на массив).

стр. 56 - оператор instanceof (англ. экземпляр), проверяет соответствие левого аргумента типу объекта в правом аргументе.

У Вас в браузере заблокирован JavaScript. Разрешите JavaScript для работы сайта!

Объектное программирование

Объектно-ориентированное программирование (ООП) на PHP

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

Обращение из метода к свойствам только через служебное слово $this: $this->name; (обратите внимание на отсутствие знака доллара перед name) Обращение внутри метода к другому методу тоже через $this: $this->foo(); Для доступа к свойствам и методам объекта служит оператор "->": $this->name; (обратите внимание на отсутствие знака доллара перед name)
Обращение внутри метода к другому методу тоже через $this: $this->foo(); . Объект создается с помощью оператора new на основании шаблона, называемого классом . Класс определяется ключевым словом class .

Пример 1

Класс со свойством и методом ".$this->имя."! Привет!"; } function Пока($a) { $this->имя = $a; echo "

".$this->имя."! Пока!

"; } } $obj = new классN1(); $obj->Привет(); $obj->имя = "Миша"; $obj->Привет(); $obj->Пока("Яша"); $obj->Привет(); ?>

Модификаторы доступа в ООП :

  • public - позволяет иметь доступ к свойствам и методам из любого места (глобальная область)
  • protected - доступ к родительскому и наследуемому классу (область класса наследника)
  • private - доступ только из класса, в котором объявлен сам элемент (область самого класса)
Метод по умолчанию - public. У свойств значения модификатора по умолчанию нет.

Константы класса в ООП

const NAME = 2; Таким образом можно создавать константы и вне класса. Это именно константы класса, они не принадлежат ни одному объекту, они общие на все объекты, поэтому использование внутри метода: function printname(){ echo self::NAME; } self - это сам класс! Обращение вне класса (можно вызывать из глобальной области видимости без инициализации экземпляра класса): echo OurClass::NAME;

this и self

Внутри класса использована специальная переменная this . Это указатель, с помощью которого объект может ссылаться на самого себя.

Для обращения к статическим методам используется self::

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

РЕЗУЛЬТАТ ПРИМЕРА 1:

Маша! Привет!

Миша! Привет!

Яша! Пока!

Яша! Привет!

Конструктор - это метод, который автоматически вызывается при создании нового объекта: public function __construct(){} . При инициализации6 объекта через служебную конструкцию new, PHP ищет __construct и если он есть, то вызывается.

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

Пример 2

Класс с конструктором имя = $a; } function Привет() { echo "

".$this->имя."! Привет!

"; } } $obj0 = new классN2(); $obj1 = new классN2("Миша"); $obj2 = new классN2("Маша"); $obj0->Привет(); $obj1->Привет(); $obj2->Привет(); ?>

РЕЗУЛЬТАТ ПРИМЕРА 2:

Кто-то там! Привет!

Миша! Привет!

Маша! Привет!

Сложив все, изложенное выше, можно создать более осмысленный класс. Например, класс, который будет располагать данные в виде таблицы с поименнованными столбцами.

Пример 3

Класс Table headers = $headers; } function addRow ($row) { $tmp = ; foreach ($this->headers as $header) { if (! isset($row[$header])) $row[$header] = ""; $tmp = $row[$header]; } array_push ($this->
";
 foreach ($this->
"; foreach ($this->
"; } echo "
"; } } $test = new Table (array("a","b","c")); $test->addRow(array("a"=>1,"b"=>3,"c"=>2)); $test->addRow(array("b"=>1,"a"=>3)); $test->addRow(array("c"=>1,"b"=>3,"a"=>4)); $test->output(); ?>

Свойства класса Table - массив имен столбцов таблицы и двумерный массив строк данных. Конструктор класса Table получает массив имен столбцов таблицы. Метод addRow добавляет в таблицу новую строку данных. Метод output выводит таблицу на экран.

РЕЗУЛЬТАТ ПРИМЕРА 3:

a b c 1 3 2 3 1 4 3 1

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

Свойства и методы класса могут быть как открытыми (public), так и скрытыми (private). Скрытые свойства и методы недоступны извне класса, т.е. из сценария, в котором используется данный класс, или из другого класса.

Наследование

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

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

Class классN2 extends классN1 { ....... }

Здесь классN1 - родительский класс, классN2 - производный.

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

КлассN1::классN1();

Производный класс будет иметь все свойства и методы родительского класса. Но их можно и переопределить в производном классе.

Пример 4

Переопределение метода родительского класса ".$this->имя."! Привет!"; } } class классN4 extends классN3 { function Привет() { echo "

".$this->имя."! Какая встреча!

"; } } $obj = new классN4(); $obj->Привет(); ?>

Метод Привет переопределен для производного класса. Свойство имя наследуется от родительского.

РЕЗУЛЬТАТ ПРИМЕРА 4:

Маша! Какая встреча!

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

Пример 5

Вызов метода родительского класса ".$this->имя."! Привет!"; } function Пока() { echo "

".$this->имя.", пока!

"; } } /** * Class классN6 */ class классN6 extends классN5 { /** * */ function Привет() { echo "

".$this->имя."! Какая встреча!

"; классN5::Привет(); } } $obj = new классN6(); $obj->Привет(); $obj->Пока(); ?>

РЕЗУЛЬТАТ ПРИМЕРА 5:

Маша! Какая встреча!

Маша! Привет!

Маша, пока!

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

В следующем примере создан класс HTMLTable , основанный на классе Table из примера 3. Новый класс формирует данные, сохраненные методом addRow родительского класса, и выводит их в HTML-таблицу. Свойства $cellpadding и $bgcolor дают возможность изменять соответствующие аргументы, при этом переменной $cellpadding присваивается значение по умолчанию, равное 2.

Пример 6

Классы Table и HTMLTable headers = $headers; } function addRow ($row) { $tmp = ; foreach ($this->headers as $header) { if (! isset($row[$header])) $row[$header] = ""; $tmp = $row[$header]; } array_push ($this->data, $tmp); } function output () { echo "
";
 foreach ($this->headers as $header) echo "$header ";
 echo "
"; foreach ($this->data as $y) { foreach ($y as $x) echo "$x "; echo "
"; } echo "
"; } } class HTMLTable extends Tables { public $cellpadding = "2"; public $bgcolor; function HTMLTable ($headers, $bg="FFFFFF") { Tables::Tables($headers); $this->bgcolor = $bg; } function setCellpadding ($padding) { $this->cellpadding = $padding; } function output () { echo "cellpadding."">"; foreach ($this->headers as $header) echo ""; foreach ($y as $x) echo "
bgcolor."">".$header; foreach ($this->data as $y) { echo "
bgcolor."">$x"; } echo "
"; } } $test = new HTMLTable (array("a","b","c"), "#00FFFF"); $test->setCellpadding (7); $test->addRow(array("a"=>1,"b"=>3,"c"=>2)); $test->addRow(array("b"=>1,"a"=>3)); $test->addRow(array("c"=>1,"b"=>3,"a"=>4)); $test->output(); ?>

Обратите внимание на то, что значение свойства сellpadding меняется с помощью отдельного метода setCellpadding . Конечно, значения свойств можно менять непосредственно, вне объекта:

$test->сellpadding = 7 ;

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

РЕЗУЛЬТАТ ПРИМЕРА 6:

a b c
1 3 2
3 1
4 3 1

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

Удаление объектов

Удалить ранее созданный объект можно следующим образом:

Unset($objName);

Ниже приведен пример, в котором объект класса Саг создается, а затем удаляется.

$myCar = new Car; unset($myCar);

После вызова функции unset() объект больше не существует. В РНР имеется специальный метод __destruct(), который автоматически вызывается при удалении объекта. Ниже приведен класс, содержащий этот метод.

Class Bridge { function __destruct() { echo "Мост разрушен"; } } $bigBridge = new Bridge; unset($bigBridge);

При создании объекта класса Bridge, а затем его удалении отобразится следующее сообщение:

Мост разрушен

Оно отображается вследствие вызова метода __destruct() при вызове функции unset(). При удалении объекта может потребоваться акрыть некоторые файлы или записать информацию в базу данных.

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

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

$a = clone $b;

Конструктор не вызывается при клонировании, вызывается магический метод __clone() {} . Он НЕ принимает аргументов и к нему нельзя обратиться как к методу.

Преобразование объекта в строку

Для конвертации объекта в строку, и обратно, используются следующие функции:
serialize() - принимает объект и возвращает строковое представление его класса и свойств;
unserialize() - принимает строку, созданную при помощи serialize(), и возвращает объект.

serialize() и unserialize() работают со всеми типами данных, но они не работают с ресурсами.


Специальные методы для обслуживания функций serialize() и unserialize():
__sleep() - вызывается строго перед тем, как объект сериализуется с помощью функции serialize(). Функция __sleep() должна будет вернуть список полей класса, которые функция serialize() включит в возвращаемую строку. Вы можете использовать это для того, чтобы исключить ненужные поля из строкового представления объекта. Например:

Public function __sleep() { // почистить return array_keys(get_object_vars($this)); } __wakeup() - вызывается сразу после того, как объект десериализуется с помощью unserialize().

Абстрактный класс

Абстрактный класс - это класс, который не может быть реализован, то есть, вы не сможете создать объект класса, если он абстрактный. Вместо этого вы создаете дочерние классы от него и спокойно создаете объекты от этих дочерних классов. Абстрактные классы представляют собой шаблоны для создания классов. abstract class Person { private $firstName = ""; private $lastName = ""; public function setName($firstName, $lastName) { $this->firstName = $firstName; $this->lastName = $lastName; } public function getName() { return "$this->firstName $this->lastName"; } abstract public function showWelcomeMessage(); /* абстрактный метод showWelcomeMessage(). Так как он абстрактный, в нем нет ни строчки кода, это просто его объявление. Любой дочерний класс обязан добавить и описать метод showWelcomeMessage() */ }

Интерфейс

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

  • Ни один метод не может быть описан в интерфейсе. Они все абстрактны. В абстрактном классе могут быть и не абстрактные методы.
  • Интерфейс не может содержать полей - только методы.
  • Класс имплементирует интерфейс, и класс наследует или расширяет другой класс.
  • Класс может имплементировать несколько интерфейсов одновременно. Этот же класс может наследовать другой класс. Но у дочернего класса может быть только один супер-класс (абстрактный или нет).
interface MyInterface { public function aMethod(); public function anotherMethod(); } class MyClass implements MyInterface { public function aMethod() { // (имплементация метода) } public function anotherMethod() { // (имплементация метода) } }

Методы-перехватчики (магические методы)

Пример использования необъявленных свойств класса

Где и зачем могут быть использованны методы-перехватчики?

Например есть у вас таблица в базе данных, называется user и есть в ней некие поля, например id, name, email, phone, password, avatar И Вы создали класс на для работы с юзерами, так его и назвали - User

Какие свойства будут у данного класса? Если вы сделаете такие же как в БД - id, name, email и так далее, то получается что при каждом изменении базы данных - вам нужно менять код в классе User, как то не очень удобно. Добавили вы например поле site - значит нужно его добавлять и в класс User, ну и так далее.
Используя же методы __get() и __set() Вы можете это всё автоматизировать. У вас в классе User вообще не будет ни одного свойства из БД, у нас есть допустим только одно $data - мы туда взяли, да и загрузили всё что есть в базе данных на данного пользователя. А потом, когда программист что то запрашивает, например $user->email мы просто в __get() методе можете посмотреть - если мы такую информацию загрузили из БД, и она лежит в $data["email"] - то вот мы её вам и возвращаем. А в __set() наоборот. Есть такое поле в БД? Значит присвоим ему новое значение.

/** * Class User * @property-read integer id текущего пользователя * @property-write String site возвращает ссылку на сайт пользователя */ class User { private $data; private $f_write=false; public function __set($name, $value) { $this->data[$name] = $value; $this->f_write=true; // признак, что нужно сохранить данные } public function __get($name) { if(empty($data)){ // читаем запись из БД в data } return $this->data[$name]; } function __destruct() { if(!empty($data)&&$this->f_write){ // сохраняем изменения в БД } } } $user=new User(); $user->site="http://kdg.сайт/"; //присваеваем переменной echo $user->site; //выводим значение переменной // записываем в БД. Можно это явно не делать, т.к. при окончании работы скрипта это поизойдет автоматически unset($user);

Пример использование необъявленного свойства класса как элемент массива

Обратите внимание на то, что из __get возвращается ссылка:

Class Foo { private $data = ; public function __set($name, $value) { $this->data[$name] = $value; } public function & __get($name) { return $this->data[$name]; } } $foo = new Foo(); $foo->bar = "lol"; var_dump($foo->bar);

Использоватние перехватчиков обращения к необъявленным методам класса

class OurClass { public function __call($name,array $params) { echo "Вы хотели вызвать $Object->".$name.", но его не существует, и сейчас выполняется ".__METHOD__."()"; return; } public static function __callStatic($name,array $params) { echo "Вы хотели вызвать ".__CLASS__."::".$name.", но его не существует, и сейчас выполняется ".__METHOD__."()"; return; } } $Object=new OurClass; $Object->DynamicMethod(); OurClass::StaticMethod();

Пример обхода закрытых метов класса:

Class _byCallStatic{ // Пример обхода "закрытых" методов класса, // при использовании метода "__callStatic()" для вызова статического метода. public static function __callStatic($_name, $_param) { return call_user_func_array("static::". $_name, $_param); } private static function _newCall(){ echo "Method: ". __METHOD__; } } echo _byCallStatic::_newCall(114, "Integer", 157); # Результат: Method: _byCallStatic::_newCall

Как вызвать через статический метод любой динамический:

/** * Class o * @method static void __f(int $a1 = 1) */ class o { public static function __callStatic($method, $args) { $class = get_called_class(); $obj = new $class($args); $method = substr($method, 2); $pass = array_slice($args,1); $reflection = new ReflectionMethod($obj, $method); return $reflection->invokeArgs($obj, $pass); } public function f($a1 = 1) { var_dump("oo", func_get_args()); } } class a extends o { public function f($a1 = 1, $a2 = 2) { var_dump("aa", $a1); } } class b extends o { public function f($b1 = 1) { var_dump("bb", $b1); } } a::__f(1,2,3); b::__f(4,5,6);

Полезное описание работы с ReflectionClass, когда вы можете проанализировать свойства и методы класса, проверить параметры по шаблонам и т.д.: http://habrahabr.ru/post/139649/

Как использовать объект как функцию?

class Dog { private $name; public function __construct($dogName = "Тузик") { $this->name = $dogName; } public static function __invoke() { $args = func_get_args(); echo "Собака получила: " . implode(" и ", $args); } } $dog = new Dog("Мухтар"); $dog("кость", "поводок");

Собака получила: кость и поводок

Как обращаться к объекту как к массиву?

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

Class MyArray implements ArrayAccess { protected $arr = array(); public function offsetSet($key, $value) { $this->arr[$key] = $value; } public function offsetUnset($key) { unset($this->arr[$key]); } public function offsetGet($key) { return $this->arr[$key]; } public function offsetExists($key) { return isset($this->arr[$key]); } public function __get($key) { return $this->offsetGet($key); } public function __set($key, $val) { $this->offsetSet($key, $val); } } $a = new MyArray(); $a["whoam"] = "Я значение массива, или объекта?
"; echo $a["whoam"]; echo $a->whoam;

Я значение массива, или объекта? Я значение массива, или объекта?

Автозагрузка классов

Файлы автозагружаемых классов обычно располагаются в общем месте, например в /include/class/. Имя файла формируется в формате ИМЯ_КЛАССА.php. Данный код необходимо подключить во все PHP-скрипты: spl_autoload_register(function ($class_name) { //echo "Autoload ".$class_name; $file = $_SERVER["DOCUMENT_ROOT"] . "/include/class/" . strtolower($class_name) . ".php"; if (file_exists($file) == false) { if($GLOBALS["DEBUG"]) echo "Нет файла ".$file; return false; } include_once($file); return true; });

Для автоподгрузки классов можно также использовать определение функции __autoload();

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

Для обработки некритических ошибок используются исключения(Exception).

Try { $a = 1; $b = 0; if($b == 0) throw new Exception ("деление на ноль!"); $c = $a/$b; } catch (Exception $e) { echo $e->getMessage(); echo $e->getLine(); }

Exception - встроенный класс. Если попали в throw, то код ниже не выполняется и осуществляется переход к блоку catch.

Блок try-catch используется как в процедурном, так и в ООП программировании. Он используется для отлова ошибок - большой блок try с множеством throw и все отлавливаются в одном месте - блоке catch.

Exception можно наследовать, желательно при этом перезагрузить конструктор: class MyException extends Exception { function __construct($msg){ parent::__construct($msg); } }

Блоков catch может быть несколько - для каждого класса наследника Exception.

Объект класса - представитель класса, который имеет свое уникальное состояние и поведение.
Для объявления объекта необходимо использовать оператор 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;

Переменные, которые являются членами класса, называются "свойства". Также их называют, используя другие термины, такие как "атрибуты" или "поля", но в рамках этой документации, мы будем называть их свойствами. Они определяются с помощью ключевых слов 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;
}
}

В этом уроке вы ознакомитесь с основами объектно-ориентированного программирования в PHP. Вы узнаете о принципах ООП вообще и научитесь писать простенькие скрипты на PHP.

Добро пожаловать в первый из серии уроков по ООП на PHP! Ознакомившись со всеми уроками данной серии, вы узнаете об основных принципах и концепциях ООП и научитесь быстро и легко создавать полезные приложения на PHP.

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

  • что такое ООП
  • как ООП поможет вам создавать лучшие PHP скрипты
  • некоторые основные понятия, такие как классы, объекты, методы, переменные класса
  • с чего начать написание PHP скрипта

Вы готовы погрузиться в мир объектов PHP? Тогда вперед!

Что такое объектно-ориентированное программирование?

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

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

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

Зачем использовать ООП?

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

Однако, вот некоторые преимущества ООП для разработчиков:

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

Некоторые основные понятия

Перед тем, как начать писать скрипты, необходимо хорошо разобраться с такими понятиями, как класс, объект, переменная класса и метод.

Классы

Класс - это каркас для объекта. Это кусок кода, который определяет:

  • Типы данных, которые будут содержать созданные объекты класса
  • Функции, которые будут содержать эти объекты.

Когда вы создаете приложение на ООП, вы обычно будете создавать несколько классов, которые будут представлять различные типы сущностей вашего приложения. Например, для создания форума вы можете создать классы Forum, Topic, Post и Member.

Объекты

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

Для сравнения с реальными сущностями:

  • Класс - это каркас для автомобиля: он определяет, как автомобиль будет выглядеть и действовать, но это все же абстрактная сущность
  • Объект - это настоящий автомобиль, созданный из каркаса: у него есть настоящие свойства (например, скорость) и поведение (например, ускорение или торможение).

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

Переменные класса

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

Методы

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

Как создать класс в PHP?

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

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

Class ClassName { // (определение класса) }

К примеру, если вы создаете класс Member для вашего форума, вы напишите так:

Class Member { // (определение класса) }

Это достаточно просто. Естественно, класс этот ничего не сделает, пока вы не добавите в него переменные и методы. Тем не менее, приведенный выше код создает валидный класс на PHP, который можно использовать.

Правило хорошего тона: каждый класс помещайте в отдельный файл с названием, совпадающим с именем класса. Например, поместите класс Member в файл Member.php и храните его в папке, допустим, classes.

Как создавать объекты в PHP?

Создать объект можно с помощью ключевого слова new:

New ClassName()

Этот код создаст объект класса ClassName. Вам впоследствии понадобится использовать этот объект, поэтому его нужно хранить в переменной. Например, создадим объект класса Member и сохраним его в переменной $member:

$member = new Member();

Мы также можем создать еще один объект того же класса:

$member2 = new Member();

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

Создаем переменные класса

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

  • Открытые переменные класса (public): доступны - т.е. их можно прочитать и/или изменять - в любом месте скрипта, независимо от того, где находится этот код - внутри класса или за его пределами
  • Частные переменные класса (private): доступны только методам класса. Лучше всего делать переменные класса именно частными, чтобы отделить объекты от остальной части кода.
  • Защищенные переменные класса (protected): доступны методам собственного класса, а также методам наследуемых классов (мы поговорим о наследовании позже).

Чтобы создать переменную класса, напишите ключевое слово public, private или protected, а затем введите имя переменной:

Class ClassName { public $propertyName; private $propertyName; protected $propertyName; }

Давайте добавим переменную класса public нашему классу Member для хранения имени пользователя:

Class Member { public $username = ""; }

Обратите внимание на то, что мы инициализировали нашу переменную класса, его значение - пустая строка, “”. Это значит, что при создании нового пользователя значение его имени по умолчанию будет равняться пустой строке. Так же, как и в случае с обычными переменными в PHP, переменные класса не обязательно инициализировать, но лучше все-таки не лениться. Если вы не инициализируете переменную класса, то по умолчанию ее значение равно null.

Доступ к переменным класса

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

$object->propertyName

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

username = "Fred"; echo $member->username; // Выведет "Fred" ?>

Запустите данный код, он выведет на экран строку “Fred”, значение переменной класса $member->username. Как видите, вы оперируете переменной объекта так же, как обычной переменной - вы можете задать ей значение и прочитать его.

Добавление методов в класс

Что скажете насчет создания методов? Как я ранее упоминал, методы - это обычные функции, являющиеся частью класса. Так что вы, возможно, не удивитесь тому, что и создаются они с помощью того же ключевого слова function. Единственное отличие от создания обычных функций заключается в том, что вы также можете добавить один из идентификаторов доступа (public, private, protected) в ее объявлении. В этом методы схожи с переменными класса:

Class ClassName { public function methodName() { // (код) } private function methodName() { // (код) } protected function methodName() { // (код) } }

На заметку: так же, как и в случае с переменными класса, методы public могут быть вызваны откуда угодно, методы private могут вызываться только в пределах класса, а методы protected - из самого класса и его наследника.

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

  • переменная класса private $loggedIn для идентификации пользователя, т.е. зашел он или нет,
  • метод login(), который будет осуществлять вход на форум, устанавливая значение переменной класса $loggedIn в true,
  • метод logout(), который будет осуществлять выход из форума, устанавливая значение переменной класса $loggedIn в false,
  • метод isLoggedIn(), который будет возвращать значение переменной класса $loggedIn.

Вот наш код:

loggedIn = true; } public function logout() { $this->loggedIn = false; } public function isLoggedIn() { return $this->loggedIn; } } ?>

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

Например, метод login() может получить доступ к переменной класса $loggedIn объекта через $this->loggedIn.

Кстати, наша переменная класса - частная (private), поэтому ее нельзя вызывать из любой части скрипта, а только из методов login(), logout() и isLoggedIn(). Это хороший подход, так как внутренняя часть объекта (например, то, как именно записывается, авторизовался ли пользователь или нет) находится отдельно от остального кода. По возможности старайтесь использовать именно переменные класса private, чтобы ваши объекты были автономными, мобильными и защищенными.

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

Использование методов

Чтобы вызвать метод объекта, воспользуйтесь оператором ->, с которым вы уже успели подружиться.

$object->methodName()

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

loggedIn = true; } public function logout() { $this->loggedIn = false; } public function isLoggedIn() { return $this->loggedIn; } } $member = new Member(); $member->username = "Fred"; echo $member->username . " is " . ($member->
"; $member->login(); echo $member->username . " is " . ($member->isLoggedIn() ? "logged in" : "logged out") . "
"; $member->logout(); echo $member->username . " is " . ($member->isLoggedIn() ? "logged in" : "logged out") . "
"; ?>

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

Fred is logged out Fred is logged in Fred is logged out

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

  1. После описания класса Member мы создали его объект и сохранили в переменной $member. Также мы дали переменной класса $username данного объекта значение “Fred”.
  2. Затем мы вызвали метод $member->isLoggedIn() для того, чтобы определить, залогинился ли пользователь или нет. Данный метод просто-напросто возвращает значение переменной класса $loggedIn. Так как значение по умолчанию этой переменной класса - false, значит результатом вызова $member->isLoggedIn() будет ложь, поэтому отобразится сообщение "Fred is logged out".
  3. Затем вызовем метод login(). Он установит в true значение переменной класса $loggedIn.
  4. Теперь, при вызове метода $member->isLoggedIn() вернется истина, и выведется сообщение "Fred is logged in".
  5. Вызовем метод logout(), который устанавливает в false значение свойства $loggedIn.
  6. В третий раз вызовем метод $member->isLoggedIn(). Сейчас он вернет false, потому что значение свойства $loggedIn опять установлено в ложь. Так, снова выведется сообщение "Fred is logged out".

На заметку: на случай, если вы в первые увидели такое: ?:, - это тернарный оператор. Это упрощенная версия блоков if … else. Узнать о такого рода операторах можно .

Выводы

В этом уроке вы познакомились с основами ООП в PHP. Вы узнали о таких вещах, как:

  • что такое ООП и почему его полезно применять
  • понятия классов, объектов, переменных класса и методов
  • как создавать классы и объекты
  • как создавать и использовать переменные классов
  • понятия идентификаторов доступа public, private, protected
  • как создавать и применять методы классов

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



В продолжение темы:
Android

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