Stručne: Objektovo orientované programovanie (OOP) zoskupuje údaje a príslušné funkcie do tried. PHP na to ponúka triedy, abstraktné triedy, rozhrania, traity a od PHP 8.1 enumy. S PHP 8.0 až 8.4 pribudlo veľa jazykových prostriedkov, napríklad promócia konštruktora, readonly, property hooks a asymetrická viditeľnosť. Pre bezpečnosť je dôležité: dobre zapuzdrený kód sa ľahšie kontroluje a magické metódy robia nebezpečnou nebezpečnú deserializáciu. Proti zraniteľnostiam v interpreteri, ako PHP2Shell, OOP nepomáha.
Čo znamená objektovo orientované programovanie v PHP
Namiesto voľných funkcií a globálnych premenných opisuje trieda vec z reálneho sveta: objednávku, zákazníka, faktúru. Určuje, aké údaje k nej patria (vlastnosti) a čo sa s nimi dá robiť (metódy). Objekt je konkrétny exemplár tejto triedy.
Pre rozhodovateľov to má praktickú hodnotu: objektovo orientovaný kód s jasnými triedami sa lepšie testuje, kontroluje a odovzdáva dodávateľom. Staré aplikácie PHP zložené z mnohých jednotlivých skriptov s globálnymi premennými sa naopak ťažko udržiavajú a pri upgradoch sú náchylné na chyby.
Ústrednou myšlienkou je zapuzdrenie: trieda navonok sprístupní iba tie metódy, ktoré ostatní skutočne potrebujú, a chráni svoj vnútorný stav. Objednávku potom možno označiť ako zaplatenú napríklad iba metódou, ktorá najprv skontroluje, či je to vôbec prípustné. Zhromaždiť takéto pravidlá na jednom mieste je prínosom aj pre bezpečnosť.
Stavebné prvky v prehľade
| Stavebný prvok | Účel | Krátky príklad |
|---|---|---|
| Trieda | plán pre objekty s vlastnosťami a metódami | class Rechnung { ... } |
| abstraktná trieda | spoločný základ, nedá sa priamo inštanciovať | abstract class Zahlart { ... } |
| Rozhranie | zmluva: aké metódy musí trieda ponúkať | interface Versandfaehig { ... } |
| Trait | opakovane použiteľné metódy pre triedy bez spoločnej rodičovskej triedy | trait MitZeitstempel { ... } |
| Enum | pevná množina povolených hodnôt ako vlastný typ, od PHP 8.1 | enum Status { case Offen; ... } |
Viditeľnosti (public, protected, private) určujú, kto smie pristupovať k vlastnostiam a metódam. Triedy sa organizujú do menných priestorov a načítavajú cez autoloader; ako to funguje, ukazuje stránka Menné priestory a autoloading.
Moderné PHP: novinky od 8.0 po 8.4
Nasledujúce jazykové prostriedky sú zdokumentované v príručke PHP, resp. v oznámeniach o vydaní:
| Verzia | Novinka |
|---|---|
| 8.0 | promócia konštruktora, nullsafe operátor ?->, ::class na objektoch |
| 8.1 | vlastnosti readonly, enumy, new v inicializátoroch, final pre konštanty tried |
| 8.2 | triedy readonly; dynamické vlastnosti sú považované za zastarané |
| 8.3 | atribút #[\Override], typované konštanty tried |
| 8.4 | property hooks, asymetrická viditeľnosť, new bez obklopujúcich zátvoriek |
Príklad, ktorý kombinuje viaceré z týchto prostriedkov:
<?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, // od 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 namiesto chyby
readonly bráni tomu, aby sa ID po vytvorení zmenilo. private(set) povoľuje čítanie zvonku, ale zápis iba vnútri triedy. Takéto záruky v kóde robia menej pravdepodobnými chyby, ktoré by sa inak prejavili až v prevádzke. Typy, ktoré za tým stoja, vysvetľuje stránka Typový systém PHP.
Pasce upgradu v objektovo orientovanom kóde
Pre staršie aplikácie sú osobitne relevantné dve zmeny. Od PHP 8.2.0 je vytváranie dynamických vlastností zastarané, teda vlastností, ktoré nie sú v triede deklarované, pokiaľ trieda nemá atribút #[\AllowDynamicProperties]. Starší kód to často používa neúmyselne a potom zaplní logy upozorneniami. Okrem toho musia byť typované vlastnosti podľa príručky inicializované pred prvým čítaním, inak PHP vyhodí Error.
Užitočný je atribút #[\Override] z PHP 8.3: označí metódu ako prepísanie metódy rodiča. Ak takáto metóda už neexistuje, napríklad po premenovaní v knižnici, PHP ohlási chybu namiesto toho, aby metóda potichu bežala naprázdno. Takéto kontroly robia upgrady plánovateľnejšími; pri uviaznutých starých projektoch pomáha naša migrácia na podporovanú verziu PHP.
Objekty a pamäť
Objekty sa v PHP odovzdávajú pomocou identifikátorov (handles). Ak sa objekt odovzdá funkcii, táto pracuje s tým istým objektom, nie s kópiou. Je to efektívne, no ľahko to vedie ku kruhovým odkazom, napríklad keď objednávka pozná svoje položky a každá položka zasa svoju objednávku. Takéto cykly samotné počítanie referencií neupratuje; na to má PHP vlastný garbage collector. Podrobnosti sú na stránke Správa pamäte v PHP.
OOP a bezpečnosť: magické metódy a deserializácia
PHP pozná magické metódy, ktoré sa volajú automaticky, napríklad __construct, __destruct, __toString, __get alebo __wakeup. Je to praktické, ale má to tienistú stránku: ak aplikácia premieňa cudzie údaje pomocou unserialize() späť na objekty, útočník môže určiť, ktoré triedy vzniknú, a tým spustiť existujúci kód v magických metódach. Ako tomu zabrániť, opisuje sprievodca Nebezpečná deserializácia v PHP. Stručne: na výmenu údajov používajte json_encode() a json_decode() a unserialize() používajte iba pre vlastné, dôveryhodné údaje, ideálne s voľbou allowed_classes.
Pri PHP2Shell však dobrý objektovo orientovaný kód nepomáha. CVE-2026-109618 a CVE-2026-109619 sú v interpreteri a pri mod_php bol podľa tímu PHP predvedený exploit skôr, než sa spustí aplikačný kód. Povinná je aktualizácia na PHP 8.5.12, 8.4.27, 8.3.36 alebo 8.2.35 a reštart všetkých procesov PHP.
Ako PHP SOS konkrétne pomáha?
- Hodnotíme štruktúru vašej aplikácie a ukazujeme, ktoré časti sťažujú upgrade na podporovanú verziu PHP.
- Cielene hľadáme rizikové vzory, ako
unserialize()nad cudzími údajmi a nebezpečné magické metódy. - Vlastné vývojové diela kontrolujeme v rámci bezpečnostného auditu a penetračného testu.
- Nasadzujeme aktualizáciu PHP, reštartujeme všetky workery a potom aplikáciu testujeme.
Časté otázky
Je PHP objektovo orientovaný jazyk?
PHP podporuje procedurálny aj objektovo orientovaný kód. Frameworky, jadrá CMS a obchodné systémy sú dnes však prevažne objektovo orientované, s triedami, rozhraniami a menými priestormi.
Aký je rozdiel medzi rozhraním a abstraktnou triedou?
Rozhranie opisuje iba to, aké metódy musí trieda ponúkať. Abstraktná trieda môže navyše obsahovať už aj kód a vlastnosti, ale nedá sa priamo inštanciovať. Trieda môže mať viac rozhraní, ale iba jednu rodičovskú triedu.
Odkedy existujú enumy v PHP?
Enumerácie prišli s PHP 8.1. Nahrádzajú zbierky konštánt vlastným typom, ktorý pripúšťa iba definované prípady. Backed enumy majú navyše hodnotu typu int alebo string.
Prečo sú magické metódy relevantné z hľadiska bezpečnosti?
Metódy ako __destruct alebo __wakeup volá PHP automaticky, napríklad pri deserializácii údajov. Ak sa cudzie údaje dostanú bez kontroly do unserialize(), môže to vyvolať neočakávané priebehy vo existujúcich triedach.