Основы
class
Каждое определение класса начинается с ключевого слова class
, затем
следует имя класса, и далее пара фигурных скобок, которые заключают в себе определение
свойств и методов этого класса.
Именем класса может быть любое слово, при условии, что оно не входит в список
зарезервированных слов PHP, начинается с буквы или
символа подчеркивания и за которым следует любое количество букв, цифр или символов
подчеркивания. Если задать эти правила в виде регулярного выражения, то получится
следующее выражение: ^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$
.
Класс может содержать собственные константы, переменные (называемые свойствами) и функции (называемые методами).
Пример #1 Простое определение класса
<?php
class SimpleClass
{
// объявление свойства
public $var = 'значение по умолчанию';
// объявление метода
public function displayVar() {
echo $this->var;
}
}
?>
Псевдопеременная $this доступна в том случае, если метод был вызван в контексте объекта. $this является ссылкой на вызываемый объект. Обычно это тот объект, которому принадлежит вызванный метод, но может быть и другой объект, если метод был вызван статически из контекста другого объекта. Начиная с PHP 7.0.0, вызов нестатического метода статическим способом из неподходящего контекста приведет к тому, что $this будет неопределен внутри метода. Вызов нестатического метода статическим способом из неподходящего контекста было объявлено устаревшим в PHP 5.6.0. Начиная с PHP 7.0.0, подобный вызов объявлен совсем устаревшим (если только вызов не произошел из подходящего контекста). До PHP 5.6.0, подобные вызовы уже сопровождались строгим уведомлением.
Пример #2 Несколько примеров с псевдопеременной $this
Мы предполагаем, что error_reporting отключен для этого примера; в противном случае следующий код, в зависимости от версии PHP, вызовет предупреждения уровней "устаревшее" или "строгое".
<?php
class A
{
function foo()
{
if (isset($this)) {
echo '$this определена (';
echo get_class($this);
echo ")\n";
} else {
echo "\$this не определена.\n";
}
}
}
class B
{
function bar()
{
A::foo();
}
}
$a = new A();
$a->foo();
A::foo();
$b = new B();
$b->bar();
B::bar();
?>
Результат выполнения данного примера в PHP 5:
$this определена (A) $this не определена. $this определена (B) $this не определена.
Результат выполнения данного примера в PHP 7:
$this определена (A) $this не определена. $this не определена. $this не определена.
new
Для создания экземпляра класса используется директива new
.
Новый объект всегда будет создан, за исключением случаев, когда он содержит
конструктор, в котором определен вызов
исключения в случае ошибки.
Рекомендуется определять классы до создания их экземпляров
(в некоторых случаях это обязательно).
Если с директивой new
используется строка (string),
содержащая имя класса, то будет создан новый экземпляр этого класса. Если
имя находится в пространстве имен, то оно должно быть задано полностью.
Замечание:
В случае отсутствия аргументов в конструктор класса, круглые скобки после названия класса можно опустить.
Пример #3 Создание экземпляра класса
<?php
$instance = new SimpleClass();
// Это же можно сделать с помощью переменной:
$className = 'SimpleClass';
$instance = new $className(); // new SimpleClass()
?>
В контексте класса можно создать новый объект через
new self
и new parent
.
Когда происходит присвоение уже существующего экземпляра класса новой переменной, то эта переменная будет указывать на этот же экземпляр класса. То же самое происходит и при передаче экземпляра класса в функцию. Копию уже созданного объекта можно создать через ее клонирование.
Пример #4 Присваивание объекта
<?php
$instance = new SimpleClass();
$assigned = $instance;
$reference =& $instance;
$instance->var = '$assigned будет иметь это значение';
$instance = null; // $instance и $reference становятся null
var_dump($instance);
var_dump($reference);
var_dump($assigned);
?>
Результат выполнения данного примера:
NULL NULL object(SimpleClass)#1 (1) { ["var"]=> string(30) "$assigned будет иметь это значение" }
В PHP 5.3.0 введены несколько новых методов создания экземпляров объекта:
Пример #5 Создание новых объектов
<?php
class Test
{
static public function getNew()
{
return new static;
}
}
class Child extends Test
{}
$obj1 = new Test();
$obj2 = new $obj1;
var_dump($obj1 !== $obj2);
$obj3 = Test::getNew();
var_dump($obj3 instanceof Test);
$obj4 = Child::getNew();
var_dump($obj4 instanceof Child);
?>
Результат выполнения данного примера:
bool(true) bool(true) bool(true)
В PHP 5.4.0 введена возможность обратиться к свойству или методу только что созданного объекта в одном выражении:
Пример #6 Доступ к свойствам/методам только что созданного объекта
<?php
echo (new DateTime())->format('Y');
?>
Результатом выполнения данного примера будет что-то подобное:
2016
Замечание: До PHP 7.1 аргументы не имели значения, если не определена функция конструктора.
Свойства и методы
Свойства и методы класса живут в разделенных "пространствах имен", так что возможно иметь свойство и метод с одним и тем же именем. Ссылки как на свойства, так и на методы имеют одинаковую нотацию, и получается, что получите вы доступ к свойству или же вызовете метод - определяется контекстом использования.
Пример #7 Доступ к свойству vs. вызов метода
<?php
class Foo
{
public $bar = 'свойство';
public function bar() {
return 'метод';
}
}
$obj = new Foo();
echo $obj->bar, PHP_EOL, $obj->bar(), PHP_EOL;
Результат выполнения данного примера:
свойство метод
Это означает, что вызвать анонимную функцию, присвоенную переменной, напрямую не получится. Вместо этого свойство должно быть назначено, например, переменной. Начиная с PHP 7.0.0, можно вызвать такое свойство напрямую, заключив его в скобки.
Пример #8 Вызов анонимной функции, содержащейся в свойстве
<?php
class Foo
{
public $bar;
public function __construct() {
$this->bar = function() {
return 42;
};
}
}
$obj = new Foo();
// Начиная с PHP 5.3.0:
$func = $obj->bar;
echo $func(), PHP_EOL;
// Или так, начиная с PHP 7.0.0:
echo ($obj->bar)(), PHP_EOL;
Результат выполнения данного примера:
42
extends
Класс может наследовать методы и свойства другого класса используя
ключевое слово extends
в его объявлении. Невозможно наследовать несколько
классов, один класс может наследовать только один базовый класс.
Наследуемые методы и свойства могут быть переопределены (за исключением случаев, когда метод класса объявлен как final) путем объявления их с теми же именами, как и в родительском классе. Существует возможность доступа к переопределенным методам или статическим свойствам путем обращения к ним через parent::
При переопределении методов количество и типы аргументов должны оставаться
такими же, как и были, иначе PHP вызовет ошибку уровня E_STRICT
.
Это не относится к конструктору, который можно
переопределить с другими параметрами.
Пример #9 Простое наследование классов
<?php
class ExtendClass extends SimpleClass
{
// Переопределение метода родителя
function displayVar()
{
echo "Расширенный класс\n";
parent::displayVar();
}
}
$extended = new ExtendClass();
$extended->displayVar();
?>
Результат выполнения данного примера:
Расширенный класс значение по умолчанию
::class
Ключевое слово class
используется
для разрешения имени класса. С помощью конструкции ClassName::class
можно получить строку с абсолютным именем класса ClassName
.
Обычно это довольно полезно при работе с классами, использующими
пространства имен.
Пример #10 Разрешение имени класса
<?php
namespace NS {
class ClassName {
}
echo ClassName::class;
}
?>
Результат выполнения данного примера:
NS\ClassName
Замечание:
Разрешение имен класса с использованием
::class
происходит на этапе компиляции. Это означает, что на момент создания строки с именем класса автозагрузки класса не происходит. Как следствие, имена классов раскрываются, даже если класс не существует. Ошибка в этом случае не выдается.Пример #11 Отсутствует разрешение имени класса
<?php
print Does\Not\Exist::class;
?>Результат выполнения данного примера:
Does\Not\Exist
Начиная с PHP 8.0.0, константа ::class
также может использоваться
для объектов. Это разрешение происходит во время выполнения, а не во время компиляции.
Тоже самое, что и при вызове get_class() для объекта.
Пример #12 Разрешение имени объекта
<?php
namespace NS {
class ClassName {
}
}
$c = new ClassName();
print $c::class;
?>
Результат выполнения данного примера:
NS\ClassName
Методы и свойства Nullsafe
Начиная с PHP 8.0.0, к свойствам и методам можно также
обращаться с помощью оператора "nullsafe": ?->
.
Оператор nullsafe работает так же, как доступ к свойству или методу, как указано выше,
за исключением того, что если разыменование объекта выдает null
, то
будет возвращен null
, а не выброшено исключение. Если разыменование является частью цепочки,
остальная часть цепочки пропускается.
Аналогично заключению каждого обращения в is_null(), но более компактный.
Пример #13 Оператор Nullsafe
<?php
// Начиная с PHP 8.0.0, эта строка:
$result = $repository?->getUser(5)?->name;
// Эквивалентна следующему блоку кода:
if (is_null($repository)) {
$result = null;
} else {
$user = $repository->getUser(5);
if (is_null($user)) {
$result = null;
} else {
$result = $user->name;
}
}
?>
Замечание:
Оператор nullsafe лучше всего использовать, когда null считается допустимым и ожидаемым значением для возвращаемого свойства или метода. Для индикации ошибки предпочтительнее выбрасывать исключение.