<? phpukraine ДОКУМЕНТАЦІЯ
⌕Пошук по платформі
Документація українською

Переклад офіційної документації українською. Кожен розділ показує стан готовності: недоперекладене позначене відкрито, а не приховане.

МОВА · ПЕРЕКЛАДЕНО оновлено 18 вересня 2026

Трейти · PHP Manual

PHP реалізує спосіб повторного використання коду, який називається трейтами (Traits).

Трейти - це механізм повторного використання коду в мовах з одиничним успадкуванням, таких як PHP. Трейт покликаний зменшити деякі обмеження одиничного успадкування, даючи розробнику змогу вільно повторно використовувати набори методів у кількох незалежних класах, що належать до різних ієрархій. Семантика поєднання трейтів і класів визначена так, щоб знизити складність і уникнути типових проблем, повʼязаних із множинним успадкуванням та міксинами (Mixins).

Трейт схожий на клас, але призначений лише для того, щоб згрупувати функціональність дрібними узгодженими частинами. Створити екземпляр самого трейта неможливо. Це доповнення до традиційного успадкування, яке вмикає горизонтальну композицію поведінки, тобто застосування членів класу без потреби успадковувати.

Приклад трейта

<?php

trait TraitA {
    public function sayHello() {
        echo 'Hello';
    }
}

trait TraitB {
    public function sayWorld() {
        echo 'World';
    }
}

class MyHelloWorld
{
    use TraitA, TraitB; // Клас може використовувати кілька трейтів

    public function sayHelloWorld() {
        $this->sayHello();
        echo ' ';
        $this->sayWorld();
        echo "!\n";
    }
}

$myHelloWorld = new MyHelloWorld();
$myHelloWorld->sayHelloWorld();

?>

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

Hello World!

Пріоритет

Успадкований від базового класу член перевизначається членом, який вставляє трейт. Порядок пріоритету такий: члени поточного класу перевизначають методи трейта, а ті, своєю чергою, перевизначають успадковані методи.

Починаючи з PHP 8.5.0, трейти привʼязуються до класу перед його батьківським класом; раніше вони привʼязувалися після. Це точніше відображає семантику копіювання та вставки, властиву трейтам. Зокрема, коли трейт і батьківський клас обидва оголошують властивість чи константу з однаковим імʼям, визначення з трейта тепер має вищий пріоритет за успадковане, тоді як попередні версії видавали фатальну помилку про несумісну композицію. На розвʼязання методів це не впливає. Подробиці дивіться в посібнику з міграції.

Приклад порядку пріоритету

Успадкований від базового класу метод перевизначається методом, який вставляється в MyHelloWorld із трейта SayWorld. Поведінка така сама для методів, визначених у класі MyHelloWorld. Порядок пріоритету такий: методи поточного класу перевизначають методи трейта, а ті, своєю чергою, перевизначають методи базового класу.

<?php
class Base {
    public function sayHello() {
        echo 'Hello ';
    }
}

trait SayWorld {
    public function sayHello() {
        parent::sayHello();
        echo 'World!';
    }
}

class MyHelloWorld extends Base {
    use SayWorld;
}

$o = new MyHelloWorld();
$o->sayHello();
?>

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

Hello World!

Інший приклад порядку пріоритету

<?php
trait HelloWorld {
    public function sayHello() {
        echo 'Hello World!';
    }
}

class TheWorldIsNotEnough {
    use HelloWorld;
    public function sayHello() {
        echo 'Hello Universe!';
    }
}

$o = new TheWorldIsNotEnough();
$o->sayHello();
?>

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

Hello Universe!

Кілька трейтів

Кілька трейтів можна вставити в клас, перелічивши їх через кому в інструкції use.

Використання кількох трейтів

<?php
trait Hello {
    public function sayHello() {
        echo 'Hello ';
    }
}

trait World {
    public function sayWorld() {
        echo 'World';
    }
}

class MyHelloWorld {
    use Hello, World;
    public function sayExclamationMark() {
        echo '!';
    }
}

$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();
$o->sayExclamationMark();
?>

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

Hello World!

Розвʼязання конфліктів

Якщо два трейти вставляють метод з однаковим імʼям, виникає фатальна помилка, доки конфлікт не розвʼязано явно.

Щоб розвʼязати конфлікт імен між трейтами, використаними в одному класі, потрібен оператор insteadof: він обирає рівно один із конфліктних методів.

Оскільки так можна лише виключити методи, оператор as дає змогу додати псевдонім одному з методів. Зверніть увагу: оператор as не перейменовує метод і не впливає на жоден інший метод.

Розвʼязання конфліктів

У цьому прикладі Talker використовує трейти A і B. Оскільки A і B мають конфліктні методи, він вказує, що використовує варіант smallTalk із трейта B, а варіант bigTalk - із трейта A.

Aliased_Talker використовує оператор as, щоб мати змогу звертатися до реалізації bigTalk із B під додатковим псевдонімом talk.

<?php
trait A {
    public function smallTalk() {
        echo 'a';
    }
    public function bigTalk() {
        echo 'A';
    }
}

trait B {
    public function smallTalk() {
        echo 'b';
    }
    public function bigTalk() {
        echo 'B';
    }
}

class Talker {
    use A, B {
        B::smallTalk insteadof A;
        A::bigTalk insteadof B;
    }
}

class Aliased_Talker {
    use A, B {
        B::smallTalk insteadof A;
        A::bigTalk insteadof B;
        B::bigTalk as talk;
    }
}
?>

Зміна видимості методу

За допомогою синтаксису as можна також скоригувати видимість методу в класі, який його використовує.

Зміна видимості методу

<?php
trait HelloWorld {
    public function sayHello() {
        echo 'Hello World!';
    }
}

// Змінюємо видимість sayHello
class MyClass1 {
    use HelloWorld { sayHello as protected; }
}

// Псевдонім методу зі зміненою видимістю
// Видимість sayHello не змінена
class MyClass2 {
    use HelloWorld { sayHello as private myPrivateHello; }
}
?>

Трейти, складені з трейтів

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

Трейти, складені з трейтів

<?php
trait Hello {
    public function sayHello() {
        echo 'Hello ';
    }
}

trait World {
    public function sayWorld() {
        echo 'World!';
    }
}

trait HelloWorld {
    use Hello, World;
}

class MyHelloWorld {
    use HelloWorld;
}

$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();
?>

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

Hello World!

Абстрактні члени трейта

Трейти підтримують абстрактні методи, щоб накласти вимоги на клас, який їх використовує. Підтримуються public-, protected- і private-методи. До PHP 8.0.0 підтримувалися лише public- і protected-абстрактні методи.

Починаючи з PHP 8.0.0, сигнатура конкретного методу має відповідати правилам сумісності сигнатур. Раніше його сигнатура могла бути іншою.

Вираження вимог через абстрактні методи

<?php
trait Hello {
    public function sayHelloWorld() {
        echo 'Hello'.$this->getWorld();
    }
    abstract public function getWorld();
}

class MyHelloWorld {
    private $world;
    use Hello;
    public function getWorld() {
        return $this->world;
    }
    public function setWorld($val) {
        $this->world = $val;
    }
}
?>

Статичні члени трейта

Трейти можуть визначати статичні змінні, статичні методи та статичні властивості.

Починаючи з PHP 8.1.0, виклик статичного методу або звернення до статичної властивості безпосередньо на трейті є застарілим. До статичних методів і властивостей слід звертатися через клас, який використовує трейт.

Статичні змінні

<?php

trait Counter
{
    public function inc()
    {
        static $c = 0;
        $c = $c + 1;
        echo "$c\n";
    }
}

class C1
{
    use Counter;
}

class C2
{
    use Counter;
}

$o = new C1();
$o->inc();
$p = new C2();
$p->inc();

?>

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

1
1

Статичні методи

<?php

trait StaticExample
{
    public static function doSomething()
    {
        return 'Doing something';
    }
}

class Example
{
    use StaticExample;
}

echo Example::doSomething();

?>

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

Doing something

Статичні властивості

До PHP 8.3.0 статичні властивості, визначені в трейті, були спільними для всіх класів однієї ієрархії успадкування, які використовували цей трейт. Починаючи з PHP 8.3.0, якщо дочірній клас використовує трейт зі статичною властивістю, вона вважається окремою від тієї, що визначена в батьківському класі.

<?php

trait T
{
    public static $counter = 1;
}

class A
{
    use T;

    public static function incrementCounter()
    {
        static::$counter++;
    }
}

class B extends A
{
    use T;
}

A::incrementCounter();

echo A::$counter, "\n";
echo B::$counter, "\n";

?>

Результат виконання цього прикладу в PHP 8.3:

2
1

Властивості

Трейти можуть також визначати властивості.

Визначення властивостей

<?php

trait PropertiesTrait
{
    public $x = 1;
}

class PropertiesExample
{
    use PropertiesTrait;
}

$example = new PropertiesExample();
$example->x;

?>

Якщо трейт визначає властивість, то клас не може визначити властивість з таким самим імʼям, якщо вона не сумісна (та сама видимість і тип, модифікатор readonly та початкове значення), інакше видається фатальна помилка.

Розвʼязання конфліктів

<?php
trait PropertiesTrait {
    public $same = true;
    public $different1 = false;
    public bool $different2;
    public bool $different3;
}

class PropertiesExample {
    use PropertiesTrait;
    public $same = true;
    public $different1 = true; // Фатальна помилка
    public string $different2; // Фатальна помилка
    readonly protected bool $different3; // Фатальна помилка
}
?>

Константи

Починаючи з PHP 8.2.0, трейти можуть також визначати константи.

Визначення констант

<?php
trait ConstantsTrait {
    public const FLAG_MUTABLE = 1;
    final public const FLAG_IMMUTABLE = 5;
}

class ConstantsExample {
    use ConstantsTrait;
}

$example = new ConstantsExample;
echo $example::FLAG_MUTABLE;
?>

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

1

Якщо трейт визначає константу, то клас не може визначити константу з таким самим імʼям, якщо вона не сумісна (та сама видимість, початкове значення та фінальність), інакше видається фатальна помилка.

Розвʼязання конфліктів

<?php
trait ConstantsTrait {
    public const FLAG_MUTABLE = 1;
    final public const FLAG_IMMUTABLE = 5;
}

class ConstantsExample {
    use ConstantsTrait;
    public const FLAG_IMMUTABLE = 5; // Фатальна помилка
}
?>

Фінальні методи

Починаючи з PHP 8.3.0, модифікатор final можна застосувати через оператор as до методів, імпортованих із трейтів. Так можна заборонити дочірнім класам перевизначати метод. Проте клас, який використовує трейт, усе ще може його перевизначити.

Визначення методу з трейта як final

<?php

trait CommonTrait
{
    public function method()
    {
        echo 'Hello';
    }
}

class FinalExampleA
{
    use CommonTrait {
        CommonTrait::method as final; // 'final' забороняє дочірнім класам перевизначати метод
    }
}

class FinalExampleB extends FinalExampleA
{
    public function method() {}
}

?>

Результат виконання цього прикладу буде подібний до:

Fatal error: Cannot override final method FinalExampleA::method() in ...
Стан перекладу

Перекладаємо з офіційної документації, розділ за розділом, і не ховаємо недоперекладене. Помітили неточність у терміні чи реченні: напишіть, виправимо.

48%
Готовності
1
У роботі
15
Ще не перекладено
Глосарій термінів