Текуща ситуация: PHP2Shell. Две критични уязвимости в PHP (CVSS 9,2) позволяват злонамерен код без вход. Корекции от 21.10.2026 г.Какво да направите сега →

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

Съвременните PHP приложения са почти винаги обектно-ориентирани. Страницата обяснява градивните елементи, новостите от PHP 8.0 до 8.4 и защо магическите методи играят роля за сигурността.

Актуалност 5 мин. четенеЗнания за PHP

Накратко: Обектно-ориентираното програмиране (ООП) обединява данните и принадлежащите им функции в класове. За целта PHP предлага класове, абстрактни класове, интерфейси, trait и от PHP 8.1 enum. С PHP 8.0 до 8.4 бяха добавени много езикови средства, например constructor promotion, readonly, property hooks и асиметрична видимост. Важно за сигурността: добре капсулираният код се проверява по-лесно, а магическите методи правят несигурната десериализация опасна. Срещу уязвимости в интерпретатора като PHP2Shell ООП не помага.

Какво означава обектно-ориентирано програмиране в PHP

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

За вземащите решения това има практическа стойност: обектно-ориентираният код с ясни класове се тества, проверява и предава на изпълнители по-добре. Старите PHP приложения от много отделни скриптове с глобални променливи, напротив, се поддържат трудно и са податливи на грешки при надграждане.

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

Градивните елементи накратко

Елемент Предназначение Кратък пример
Клас чертеж за обекти със свойства и методи class Rechnung { ... }
абстрактен клас обща основа, не може да се инстанцира директно abstract class Zahlart { ... }
Интерфейс договор: кои методи трябва да предоставя един клас interface Versandfaehig { ... }
Trait методи за повторна употреба в класове без общ родителски клас trait MitZeitstempel { ... }
Enum фиксиран набор от допустими стойности като самостоятелен тип, от PHP 8.1 enum Status { case Offen; ... }

Видимостите (public, protected, private) определят кой може да достъпва свойствата и методите. Класовете се организират в пространства от имена (namespaces) и се зареждат чрез autoloader; как работи това, показва страницата Пространства от имена и autoloading.

Съвременният PHP: новостите от 8.0 до 8.4

Следните езикови средства са документирани в ръководството на PHP, респективно в съобщенията за изданията:

Версия Новост
8.0 Constructor promotion, nullsafe оператор ?->, ::class върху обекти
8.1 readonly свойства, enum, new в инициализатори, final за константи на клас
8.2 readonly класове; динамичните свойства се считат за остарели
8.3 Атрибут #[\Override], типизирани константи на клас
8.4 Property hooks, асиметрична видимост, new без заобикалящи скоби

Пример, който комбинира няколко от тези средства:

<?php
declare(strict_types=1);

enum Status: string
{
    case Offen = 'offen';
    case Bezahlt = 'bezahlt';
}

final class Bestellung
{
    public function __construct(
        public readonly int $id,
        public private(set) Status $status = Status::Offen,  // от PHP 8.4
    ) {}

    public function alsBezahltMarkieren(): void
    {
        $this->status = Status::Bezahlt;
    }
}

$b = new Bestellung(42);
$b->alsBezahltMarkieren();
echo $b->status->value;              // bezahlt
$s = Status::tryFrom('storniert');   // null вместо грешка

readonly пречи идентификаторът да бъде променян след създаването. private(set) позволява четене отвън, но запис само в рамките на класа. Такива гаранции в кода правят по-малко вероятни грешките, които иначе проличават едва в експлоатация. Типовете зад това обяснява страницата Типовата система на PHP.

Клопки при надграждане в обектно-ориентирания код

За по-старите приложения две промени са особено важни. От PHP 8.2.0 създаването на динамични свойства е остаряло, т.е. на свойства, които не са декларирани в класа, освен ако класът не носи атрибута #[\AllowDynamicProperties]. По-старият код често ги използва неосъзнато и тогава логовете се пълнят със забележки. Освен това типизираните свойства според ръководството трябва да са инициализирани преди първото четене, иначе PHP хвърля Error.

Полезен е атрибутът #[\Override] от PHP 8.3: той отбелязва метод като презаписване на метод на родителя. Ако този метод вече не съществува, например след преименуване в библиотека, PHP съобщава грешка, вместо методът тихо да остане без ефект. Такива проверки правят надграждането по-предвидимо; при закъсали стари проекти ни подпомага нашата миграция към поддържана версия на PHP.

Обекти и памет

Обектите в PHP се предават чрез идентификатори (handles). Ако един обект се подаде на функция, тя работи със същия обект, а не с копие. Това е ефективно, но лесно води до циклични препратки, например когато поръчката познава своите позиции, а всяка позиция – отново своята поръчка. Такива цикли броенето на препратките само не почиства; за това PHP има собствен garbage collector. Подробности има на страницата Управление на паметта в PHP.

ООП и сигурност: магически методи и десериализация

PHP познава магически методи, които се извикват автоматично, например __construct, __destruct, __toString, __get или __wakeup. Това е удобно, но има и обратна страна: когато приложение превръща чужди данни с unserialize() обратно в обекти, атакуващият може да определи кои класове да възникнат и така да задейства наличен код в магически методи. Как това се предотвратява, описва наръчникът Несигурна десериализация в PHP. Накратко: за обмен на данни използвайте json_encode() и json_decode(), а unserialize() само за собствени, достоверни данни, в идеалния случай с опцията allowed_classes.

При PHP2Shell добре написаният обектно-ориентиран код, напротив, не помага. CVE-2026-109618 и CVE-2026-109619 се намират в интерпретатора, а при mod_php според екипа на PHP е показан експлойт, преди да се изпълни кодът на приложението. Задължителни са актуализацията до PHP 8.5.12, 8.4.27, 8.3.36 или 8.2.35 и рестартирането на всички PHP процеси.

Как помага PHP SOS конкретно?

  • Оценяваме структурата на Вашето приложение и показваме кои части затрудняват надграждането до поддържана версия на PHP.
  • Търсим целенасочено рискови шаблони като unserialize() върху чужди данни и опасни магически методи.
  • Проверяваме собствените разработки в рамките на одит на сигурността и тест за проникване.
  • Внедряваме актуализацията на PHP, рестартираме всички worker процеси и след това тестваме приложението.

Често задавани въпроси

PHP обектно-ориентиран език ли е?

PHP поддържа както процедурен, така и обектно-ориентиран код. Фреймуърците, ядрата на CMS и магазинните системи днес обаче са изградени предимно обектно-ориентирано, с класове, интерфейси и пространства от имена.

Каква е разликата между интерфейс и абстрактен клас?

Интерфейсът описва само кои методи трябва да предоставя един клас. Абстрактният клас може допълнително да съдържа вече код и свойства, но не може да се инстанцира директно. Един клас може да има няколко интерфейса, но само един родителски клас.

Откога има enum в PHP?

Изброените типове (enumerations) се появиха с PHP 8.1. Те заменят набори от константи със самостоятелен тип, който допуска само дефинираните случаи. Backed enum имат допълнително стойност от тип int или string.

Защо магическите методи са важни за сигурността?

Методи като __destruct или __wakeup PHP извиква автоматично, например при десериализиране на данни. Ако чужди данни попаднат непроверени в unserialize(), това може да задейства неочаквани процеси в наличните класове.

Източници

Незабавен контакт

Всеки час има значение. Пишете ни сега.

Опишете накратко системата, версията на PHP и какво сте забелязали. Ние се свързваме с Вас, уточняваме ситуацията и работим отдалечено, докато инцидентът бъде приключен и документиран.

Незабавна помощ