Конструктор класса с параметрами php

Обновлено: 28.04.2024

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

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

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

Самой трудной для понимания концепцией являются основы ООП , так как они отличаются от обычного программирования на PHP. Но как только вы поймете основные принципы, сама модель станет для вас простой и понятной.

Что такое ООП в PHP?

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

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

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

Простое определение объектно-ориентированного программирования

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

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

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

Важные термины руководства по ООП в PHP

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

Класс

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

Объект

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

Переменная-член

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

Функция-член

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

Конструктор

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

Деструктор

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

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

В PHP 5 ООП наследование – это процесс, при котором класс ( подкласс ) получает все атрибуты и функции другого класса (суперкласса).

Суперкласс

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

Подкласс

Дочерний или производный класс, подкласс наследуется от суперкласса.

Полиморфизм

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

Инкапсуляция

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

Абстракция

Абстракция означает, что детали реализации функций или классов не видны.

Перезагрузка

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

Классы и объекты

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

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

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

Классы и объекты

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

Преимущества ООП в PHP

Улучшение архитектуры и более чистый код

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

Повторное использование

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

Простота в обслуживании и обновлении

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

Инкапсуляция

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

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

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

Меньше ошибок

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

Это руководством по ООП в PHP является свободным и полным источником, с помощью которого вы сможете изучить все необходимые приемы.

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

Именем класса может быть любое слово, при условии, что оно не входит в список зарезервированных слов PHP, начинается с буквы или символа подчёркивания и за которым следует любое количество букв, цифр или символов подчёркивания. Если задать эти правила в виде регулярного выражения, то получится следующее выражение: ^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$ .

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

class SimpleClass
// объявление свойства
public $var = 'значение по умолчанию' ;

// объявление метода
public function displayVar () echo $this -> var ;
>
>
?>

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

Вызов нестатического метода статически вызывает ошибку Error . До PHP 8.0.0 это привело бы к уведомлению об устаревании, и $this не была бы определена.

class A
function foo ()
if (isset( $this )) echo '$this определена (' ;
echo get_class ( $this );
echo ")\n" ;
> else echo "\$this не определена.\n" ;
>
>
>

$a = new A ();
$a -> foo ();

$b = new B ();
$b -> bar ();

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

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

Для создания экземпляра класса используется директива new . Новый объект всегда будет создан, за исключением случаев, когда он содержит конструктор, в котором определён вызов исключения в случае возникновения ошибки. Рекомендуется определять классы до создания их экземпляров (в некоторых случаях это обязательно).

Если с директивой new используется строка ( string ), содержащая имя класса, то будет создан новый экземпляр этого класса. Если имя находится в пространстве имён, то оно должно быть задано полностью.

Замечание:

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

// Это же можно сделать с помощью переменной:
$className = 'SimpleClass' ;
$instance = new $className (); // new SimpleClass()
?>

Начиная с PHP 8.0.0, поддерживается использование оператора new с произвольными выражениями. Это позволяет создавать более сложные экземпляры, если выражение представлено в виде строки ( string ). Выражения должны быть заключены в круглые скобки.

В данном примере мы показываем несколько вариантов допустимых произвольных выражений, которые представляют имя класса. Пример вызова функции, конкатенации строк и константы ::class .

class ClassA extends \ stdClass <>
class ClassB extends \ stdClass <>
class ClassC extends ClassB <>
class ClassD extends ClassA <>

function getSomeClass (): string
return 'ClassA' ;
>

var_dump (new ( getSomeClass ()));
var_dump (new ( 'Class' . 'B' ));
var_dump (new ( 'Class' . 'C' ));
var_dump (new ( ClassD ::class));
?>

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

В контексте класса можно создать новый объект через new self и new parent .

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

$instance = new SimpleClass ();

$assigned = $instance ;
$reference =& $instance ;

$instance -> var = '$assigned будет иметь это значение' ;

$instance = null ; // $instance и $reference становятся null

var_dump ( $instance );
var_dump ( $reference );
var_dump ( $assigned );
?>

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

Создавать экземпляры объекта можно двумя способами:

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 );
?>

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

Обратиться к свойству или методу только что созданного объекта можно с помощью одного выражения:

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

Замечание: До PHP 7.1 аргументы не имели значения, если не определена функция конструктора.

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

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

public function bar () return 'метод' ;
>
>

$obj = new Foo ();
echo $obj -> bar , PHP_EOL , $obj -> bar (), PHP_EOL ;

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

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

public function __construct () $this -> bar = function() return 42 ;
>;
>
>

echo ( $obj -> bar )(), PHP_EOL ;

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

extends

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

Наследуемые константы, методы и свойства могут быть переопределены (за исключением случаев, когда метод или константа класса объявлены как final) путём объявления их с теми же именами, как и в родительском классе. Существует возможность доступа к переопределённым методам или статическим свойствам путём обращения к ним через parent::

Замечание: Начиная с PHP 8.1.0, константы можно объявлять окончательными (final).

class ExtendClass extends SimpleClass
// Переопределение метода родителя
function displayVar ()
echo "Расширенный класс\n" ;
parent :: displayVar ();
>
>

$extended = new ExtendClass ();
$extended -> displayVar ();
?>

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

Правила совместимости сигнатуры

При переопределении метода его сигнатура должна быть совместима с родительским методом. В противном случае выдаётся фатальная ошибка или, до PHP 8.0.0, генерируется ошибка уровня E_WARNING . Сигнатура является совместимой, если она соответствует правилам контравариантности, делает обязательный параметр необязательным и если какие-либо новые параметры являются необязательными. Это известно как принцип подстановки Барбары Лисков или сокращённо LSP. Правила совместимости не распространяются на конструктор и сигнатуру private методов, они не будут выдавать фатальную ошибку в случае несоответствия сигнатуры.

class Base
public function foo ( int $a ) echo "Допустимо\n" ;
>
>

class Extend1 extends Base
function foo ( int $a = 5 )
parent :: foo ( $a );
>
>

class Extend2 extends Base
function foo ( int $a , $b = 5 )
parent :: foo ( $a );
>
>

$extended1 = new Extend1 ();
$extended1 -> foo ();
$extended2 = new Extend2 ();
$extended2 -> foo ( 1 );

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

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

class Base
public function foo ( int $a = 5 ) echo "Допустимо\n" ;
>
>

class Extend extends Base
function foo ()
parent :: foo ( 1 );
>
>

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

class Base
public function foo ( int $a = 5 ) echo "Допустимо\n" ;
>
>

class Extend extends Base
function foo ( int $a )
parent :: foo ( $a );
>
>

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

Переименование параметра метода в дочернем классе не является несовместимостью сигнатуры. Однако это не рекомендуется, так как приведёт к Error во время выполнения, если используются именованные аргументы.

class A public function test ( $foo , $bar ) <>
>

class B extends A public function test ( $a , $b ) <>
>

// Передача параметров согласно контракту A::test()
$obj -> test ( foo : "foo" , bar : "bar" ); // ОШИБКА!

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

::class

Ключевое слово class используется для разрешения имени класса. Чтобы получить полное имя класса ClassName , используйте ClassName::class . Обычно это довольно полезно при работе с классами, использующими пространства имён.

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

Замечание:

Разрешение имён класса с использованием ::class происходит на этапе компиляции. Это означает, что на момент создания строки с именем класса автозагрузки класса не происходит. Как следствие, имена классов раскрываются, даже если класс не существует. Ошибка в этом случае не выдаётся.

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

Начиная с PHP 8.0.0, константа ::class также может использоваться для объектов. Это разрешение происходит во время выполнения, а не во время компиляции. То же самое, что и при вызове get_class() для объекта.

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

Методы и свойства Nullsafe

Начиная с PHP 8.0.0, к свойствам и методам можно также обращаться с помощью оператора "nullsafe": ?-> . Оператор nullsafe работает так же, как доступ к свойству или методу, как указано выше, за исключением того, что если разыменование объекта выдаёт null , то будет возвращён null , а не выброшено исключение. Если разыменование является частью цепочки, остальная часть цепочки пропускается.

Аналогично заключению каждого обращения в is_null() , но более компактный.

// Начиная с 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 считается допустимым и ожидаемым значением для возвращаемого свойства или метода. Для индикации ошибки предпочтительнее выбрасывать исключение.

User Contributed Notes 13 notes

I was confused at first about object assignment, because it's not quite the same as normal assignment or assignment by reference. But I think I've figured out what's going on.

First, think of variables in PHP as data slots. Each one is a name that points to a data slot that can hold a value that is one of the basic data types: a number, a string, a boolean, etc. When you create a reference, you are making a second name that points at the same data slot. When you assign one variable to another, you are copying the contents of one data slot to another data slot.

Now, the trick is that object instances are not like the basic data types. They cannot be held in the data slots directly. Instead, an object's "handle" goes in the data slot. This is an identifier that points at one particular instance of an obect. So, the object handle, although not directly visible to the programmer, is one of the basic datatypes.

What makes this tricky is that when you take a variable which holds an object handle, and you assign it to another variable, that other variable gets a copy of the same object handle. This means that both variables can change the state of the same object instance. But they are not references, so if one of the variables is assigned a new value, it does not affect the other variable.

// Assignment of an object
Class Object public $foo = "bar" ;
>;

$objectVar = new Object ();
$reference =& $objectVar ;
$assignment = $objectVar

//
// $objectVar --->+---------+
// |(handle1)----+
// $reference --->+---------+ |
// |
// +---------+ |
// $assignment -->|(handle1)----+
// +---------+ |
// |
// v
// Object(1):foo="bar"
//
?>

$assignment has a different data slot from $objectVar, but its data slot holds a handle to the same object. This makes it behave in some ways like a reference. If you use the variable $objectVar to change the state of the Object instance, those changes also show up under $assignment, because it is pointing at that same Object instance.

$objectVar -> foo = "qux" ;
print_r ( $objectVar );
print_r ( $reference );
print_r ( $assignment );

//
// $objectVar --->+---------+
// |(handle1)----+
// $reference --->+---------+ |
// |
// +---------+ |
// $assignment -->|(handle1)----+
// +---------+ |
// |
// v
// Object(1):foo="qux"
//
?>

But it is not exactly the same as a reference. If you null out $objectVar, you replace the handle in its data slot with NULL. This means that $reference, which points at the same data slot, will also be NULL. But $assignment, which is a different data slot, will still hold its copy of the handle to the Object instance, so it will not be NULL.

$objectVar = null ;
print_r ( $objectVar );
print_r ( $reference );
print_r ( $assignment );

Basic class definitions begin with the keyword class , followed by a class name, followed by a pair of curly braces which enclose the definitions of the properties and methods belonging to the class.

The class name can be any valid label, provided it is not a PHP reserved word. A valid class name starts with a letter or underscore, followed by any number of letters, numbers, or underscores. As a regular expression, it would be expressed thus: ^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$ .

A class may contain its own constants, variables (called "properties"), and functions (called "methods").

class SimpleClass
// property declaration
public $var = 'a default value' ;

// method declaration
public function displayVar () echo $this -> var ;
>
>
?>

The pseudo-variable $this is available when a method is called from within an object context. $this is the value of the calling object.

Calling a non-static method statically throws an Error . Prior to PHP 8.0.0, this would generate a deprecation notice, and $this would be undefined.

class A
function foo ()
if (isset( $this )) echo '$this is defined (' ;
echo get_class ( $this );
echo ")\n" ;
> else echo "\$this is not defined.\n" ;
>
>
>

$a = new A ();
$a -> foo ();

$b = new B ();
$b -> bar ();

Output of the above example in PHP 7:

Output of the above example in PHP 8:

To create an instance of a class, the new keyword must be used. An object will always be created unless the object has a constructor defined that throws an exception on error. Classes should be defined before instantiation (and in some cases this is a requirement).

If a string containing the name of a class is used with new , a new instance of that class will be created. If the class is in a namespace, its fully qualified name must be used when doing this.

Note:

If there are no arguments to be passed to the class's constructor, parentheses after the class name may be omitted.

// This can also be done with a variable:
$className = 'SimpleClass' ;
$instance = new $className (); // new SimpleClass()
?>

As of PHP 8.0.0, using new with arbitrary expressions is supported. This allows more complex instantiation if the expression produces a string . The expressions must be wrapped in parentheses.

In the given example we show multiple examples of valid arbitrary expressions that produce a class name. This shows a call to a function, string concatenation, and the ::class constant.

class ClassA extends \ stdClass <>
class ClassB extends \ stdClass <>
class ClassC extends ClassB <>
class ClassD extends ClassA <>

function getSomeClass (): string
return 'ClassA' ;
>

var_dump (new ( getSomeClass ()));
var_dump (new ( 'Class' . 'B' ));
var_dump (new ( 'Class' . 'C' ));
var_dump (new ( ClassD ::class));
?>

Output of the above example in PHP 8:

In the class context, it is possible to create a new object by new self and new parent .

When assigning an already created instance of a class to a new variable, the new variable will access the same instance as the object that was assigned. This behaviour is the same when passing instances to a function. A copy of an already created object can be made by cloning it.

$instance = new SimpleClass ();

$assigned = $instance ;
$reference =& $instance ;

$instance -> var = '$assigned will have this value' ;

$instance = null ; // $instance and $reference become null

var_dump ( $instance );
var_dump ( $reference );
var_dump ( $assigned );
?>

The above example will output:

It's possible to create instances of an object in a couple of ways:

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 );
?>

The above example will output:

It is possible to access a member of a newly created object in a single expression:

The above example will output something similar to:

Note: Prior to PHP 7.1, the arguments are not evaluated if there is no constructor function defined.

Properties and methods

Class properties and methods live in separate "namespaces", so it is possible to have a property and a method with the same name. Referring to both a property and a method has the same notation, and whether a property will be accessed or a method will be called, solely depends on the context, i.e. whether the usage is a variable access or a function call.

public function bar () return 'method' ;
>
>

$obj = new Foo ();
echo $obj -> bar , PHP_EOL , $obj -> bar (), PHP_EOL ;

The above example will output:

That means that calling an anonymous function which has been assigned to a property is not directly possible. Instead the property has to be assigned to a variable first, for instance. It is possible to call such a property directly by enclosing it in parentheses.

public function __construct () $this -> bar = function() return 42 ;
>;
>
>

echo ( $obj -> bar )(), PHP_EOL ;

The above example will output:

extends

A class can inherit the constants, methods, and properties of another class by using the keyword extends in the class declaration. It is not possible to extend multiple classes; a class can only inherit from one base class.

The inherited constants, methods, and properties can be overridden by redeclaring them with the same name defined in the parent class. However, if the parent class has defined a method or constant as final, they may not be overridden. It is possible to access the overridden methods or static properties by referencing them with parent::.

Note: As of PHP 8.1.0, constants may be declared as final.

class ExtendClass extends SimpleClass
// Redefine the parent method
function displayVar ()
echo "Extending class\n" ;
parent :: displayVar ();
>
>

$extended = new ExtendClass ();
$extended -> displayVar ();
?>

The above example will output:

Signature compatibility rules

When overriding a method, its signature must be compatible with the parent method. Otherwise, a fatal error is emitted, or, prior to PHP 8.0.0, an E_WARNING level error is generated. A signature is compatible if it respects the variance rules, makes a mandatory parameter optional, and if any new parameters are optional. This is known as the Liskov Substitution Principle, or LSP for short. The constructor, and private methods are exempt from these signature compatibility rules, and thus won't emit a fatal error in case of a signature mismatch.

class Base
public function foo ( int $a ) echo "Valid\n" ;
>
>

class Extend1 extends Base
function foo ( int $a = 5 )
parent :: foo ( $a );
>
>

class Extend2 extends Base
function foo ( int $a , $b = 5 )
parent :: foo ( $a );
>
>

$extended1 = new Extend1 ();
$extended1 -> foo ();
$extended2 = new Extend2 ();
$extended2 -> foo ( 1 );

The above example will output:

The following examples demonstrate that a child method which removes a parameter, or makes an optional parameter mandatory, is not compatible with the parent method.

class Base
public function foo ( int $a = 5 ) echo "Valid\n" ;
>
>

class Extend extends Base
function foo ()
parent :: foo ( 1 );
>
>

Output of the above example in PHP 8 is similar to:

class Base
public function foo ( int $a = 5 ) echo "Valid\n" ;
>
>

class Extend extends Base
function foo ( int $a )
parent :: foo ( $a );
>
>

Output of the above example in PHP 8 is similar to:

Renaming a method's parameter in a child class is not a signature incompatibility. However, this is discouraged as it will result in a runtime Error if named arguments are used.

class A public function test ( $foo , $bar ) <>
>

class B extends A public function test ( $a , $b ) <>
>

// Pass parameters according to A::test() contract
$obj -> test ( foo : "foo" , bar : "bar" ); // ERROR!

The above example will output something similar to:

::class

The class keyword is also used for class name resolution. To obtain the fully qualified name of a class ClassName use ClassName::class . This is particularly useful with namespaced classes.

The above example will output:

Note:

The class name resolution using ::class is a compile time transformation. That means at the time the class name string is created no autoloading has happened yet. As a consequence, class names are expanded even if the class does not exist. No error is issued in that case.

The above example will output:

As of PHP 8.0.0, the ::class constant may also be used on objects. This resolution happens at runtime, not compile time. Its effect is the same as calling get_class() on the object.

The above example will output:

Nullsafe methods and properties

As of PHP 8.0.0, properties and methods may also be accessed with the "nullsafe" operator instead: ?-> . The nullsafe operator works the same as property or method access as above, except that if the object being dereferenced is null then null will be returned rather than an exception thrown. If the dereference is part of a chain, the rest of the chain is skipped.

The effect is similar to wrapping each access in an is_null() check first, but more compact.

// As of PHP 8.0.0, this line:
$result = $repository ?-> getUser ( 5 )?-> name ;

// Is equivalent to the following code block:
if ( is_null ( $repository )) $result = null ;
> else $user = $repository -> getUser ( 5 );
if ( is_null ( $user )) $result = null ;
> else $result = $user -> name ;
>
>
?>

Note:

The nullsafe operator is best used when null is considered a valid and expected possible value for a property or method return. For indicating an error, a thrown exception is preferable.

User Contributed Notes 13 notes

I was confused at first about object assignment, because it's not quite the same as normal assignment or assignment by reference. But I think I've figured out what's going on.

First, think of variables in PHP as data slots. Each one is a name that points to a data slot that can hold a value that is one of the basic data types: a number, a string, a boolean, etc. When you create a reference, you are making a second name that points at the same data slot. When you assign one variable to another, you are copying the contents of one data slot to another data slot.

Now, the trick is that object instances are not like the basic data types. They cannot be held in the data slots directly. Instead, an object's "handle" goes in the data slot. This is an identifier that points at one particular instance of an obect. So, the object handle, although not directly visible to the programmer, is one of the basic datatypes.

What makes this tricky is that when you take a variable which holds an object handle, and you assign it to another variable, that other variable gets a copy of the same object handle. This means that both variables can change the state of the same object instance. But they are not references, so if one of the variables is assigned a new value, it does not affect the other variable.

// Assignment of an object
Class Object public $foo = "bar" ;
>;

$objectVar = new Object ();
$reference =& $objectVar ;
$assignment = $objectVar

//
// $objectVar --->+---------+
// |(handle1)----+
// $reference --->+---------+ |
// |
// +---------+ |
// $assignment -->|(handle1)----+
// +---------+ |
// |
// v
// Object(1):foo="bar"
//
?>

$assignment has a different data slot from $objectVar, but its data slot holds a handle to the same object. This makes it behave in some ways like a reference. If you use the variable $objectVar to change the state of the Object instance, those changes also show up under $assignment, because it is pointing at that same Object instance.

$objectVar -> foo = "qux" ;
print_r ( $objectVar );
print_r ( $reference );
print_r ( $assignment );

//
// $objectVar --->+---------+
// |(handle1)----+
// $reference --->+---------+ |
// |
// +---------+ |
// $assignment -->|(handle1)----+
// +---------+ |
// |
// v
// Object(1):foo="qux"
//
?>

But it is not exactly the same as a reference. If you null out $objectVar, you replace the handle in its data slot with NULL. This means that $reference, which points at the same data slot, will also be NULL. But $assignment, which is a different data slot, will still hold its copy of the handle to the Object instance, so it will not be NULL.

$objectVar = null ;
print_r ( $objectVar );
print_r ( $reference );
print_r ( $assignment );

Конструктор класса вызывается автоматически всякий раз, когда создаются экземпляры класса и объекты из класса. В PHP ООП конструктор используется для инициализации свойств во время создания объекта. Конструктор выглядит как обычный метод PHP , разница заключается только в том, что он начинается с __ ( двух символов подчеркивания ).

Конструктор класса PHP может содержать столько аргументов или параметров, сколько необходимо. Также можно определить конструктор вообще без параметров.

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

Чтобы создать экземпляр класса, мы используем ключевое слово new, и в этот момент вызывается конструктор. В PHP родительский конструктор вызывается явно, если определен конструктор производного класса. Если требуется конструктор суперкласса, в производном классе нужен вызов parent::__construct() . Конструктор суперкласса может наследоваться, если производный класс не определяет конструктор сам. Наследуется конструктор так же, как и любой другой метод класса, если в суперклассе он не был объявлен как privat .

В PHP4 и ниже при определении конструктора использовался метод с таким же именем, что и класс ( как в C++ и Java ). PHP5 ООП для определения конструктора любого класса содержит специальную функцию __construct() . Конструктор может содержать аргументы в соответствии с конкретными требованиями. Все объекты могут иметь встроенную функцию-конструктор, которая инициализирует при создании объекта его свойства. PHP позволяет создать только один конструктор для каждого класса, и мы не можем перегрузить конструктор.

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

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

Пример PHP-конструктора

Давайте предположим, что у нас есть класс PHP Human , и он содержит переменную name . Исходный код будет выглядеть следующим образом:

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

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

В этом ООП PHP примере мы создали объекты и инициализировали переменную $name . Первый объект будет хранить в переменной $name значение " Joseph ", а второй - " Taylor ". Мы присвоили объектам значения во время создания, чтобы избежать путаницы. Если бы для класса Human конструктор не был определен, то объекты создавались бы следующим образом:

PHP-конструктор с несколькими аргументами

Мы добавим новую переменную age в класс Human :

Сейчас наш класс содержит две переменные для хранения данных каждого объекта. Name и age представлены переменными $name и $age . Определяем конструктор еще раз, но на этот раз с двумя аргументами, один - чтобы установить экземпляр Name , а второй - age :

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

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

Тот же класс с двумя дополнительными методами:

Мы можем вызывать два новых метода, чтобы изменить имя или возраст. Добавим в пример еще два метода, чтобы вывести имя и возраст:

Полный пример использования конструктора класса PHP ООП с четырьмя функциями:

Еще один пример PHP-конструктора

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

Давайте посмотрим, как используется конструктор. Сначала создаем простой класс с одним свойством и одной функцией:

Это простой класс, который содержит одну переменную данных, название машины, и метод вывода этого названия.

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

Теперь создаем из класса объект:

Выводим значение данных переменной через вызов метода get_carname() :

Результат будет следующим:

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

Используем конструктор в примере объекта PHP ООП , который мы рассматривали ранее. В классе bookinfo мы добавляем следующий код:

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

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

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

Этот PHP-код дает следующий результат:

Up to date astrology
Up to date PHP
Up to date DB
25
36
17

Мы видим, что полученный результат тот же самый, но он достигнут с помощью конструктора.

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

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

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

Классы в PHP - определение и использование

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

Определение класса в PHP выглядит так же, как объявление функции, но вместо function , используется ключевое слово class . Давайте начнем с наброска нашего PHP class User :

На данный момент этот класс PHP ничего не может сделать. Мы можем создать экземпляр, это делается с помощью ключевого слова new :

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

В примере класса в php мы объявляем две переменные класса - name и age . Переменная name снабжена спецификатором доступа " public ", который означает, что к переменной можно получить доступ за пределами класса.

Далее мы объявляем функцию Describe() . Это выглядит точно так же, как объявление обычной функции, но с несколькими отличиями. Перед объявлением ставится ключевое слово public , чтобы указать спецификатор доступа. Внутри функции мы используем переменную " $this ", чтобы получить доступ к переменным самого класса. $this - специальная переменная в PHP , которая доступна в функциях класса и всегда ссылается на объект, из которого она используется.

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

Первое, на что вы должны обратить внимание, это использование оператора - > . Мы также использовали его в методе Describe() . Это означает, что мы хотим получить доступ к чему-то из объекта, указанного перед оператором. $user->name означает: " Дайте мне переменную name из объекта $user ". После этого идет то же самое, что и присвоение значения обычной переменной, к которой мы дважды обращались для получения имени и возраста объекта пользователя. В последней строке мы вызываем метод Describe() объекта пользователя, который будет возвращать строку, которую мы затем выводим.

Результат должен выглядеть следующим образом:

John Doe 42 лет

Поздравляем, вы только что определили и использовали свой первый класс в php .

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

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

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

С помощью этой строки кода будет создан объект, вызван конструктор и в нем выполнится код, что приведет к выводу строки “ I'm alive! ”. Но как уже упоминалось ранее, основным преимуществом конструктора является возможность передавать параметры, которые могут быть использованы для инициализации переменных – членов класса.

Давайте попробуем сделать это:

Объявление конструктора с параметрами такое же, как объявление функции, и передача параметров очень похожа на вызов обычной функции, но с ключевым словом “ new ”. Конструктор может иметь столько параметров, сколько вам хочется.

Деструкторы

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

Читайте также: