Основы

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

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

Класс может содержать собственные константыпеременные (называемые свойствами) и функции (называемые методами).

Пример #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

 

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

 

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

Пример #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();
?>

 

Результат выполнения данного примера:

Расширенный класс
значение по умолчанию