Trumpai: Objektinis programavimas (OOP) sujungia duomenis ir jiems priklausančias funkcijas klasėse. PHP tam siūlo klases, abstrakčias klases, sąsajas, trait ir nuo PHP 8.1 enum. Su PHP 8.0–8.4 atsirado daug kalbos priemonių, pavyzdžiui, konstruktoriaus promocija, readonly, property hooks ir asimetrinis matomumas. Saugumui svarbu: gerai inkapsuotą kodą lengviau tikrinti, o magiški metodai daro nesaugią deserializaciją pavojingą. Nuo interpretatoriaus spragų, tokių kaip PHP2Shell, OOP nepadeda.
Ką reiškia objektinis programavimas PHP
Užuot naudojusi pavienes funkcijas ir globalius kintamuosius, klasė aprašo dalykinės srities daiktą: užsakymą, klientą, sąskaitą. Ji nustato, kokie duomenys prie jo priklauso (savybės) ir ką su jais galima daryti (metodai). Objektas yra konkretus tos klasės egzempliorius.
Sprendimų priėmėjams tai turi praktinę vertę: objektinį kodą su aiškiomis klasėmis lengviau testuoti, tikrinti ir perduoti paslaugų teikėjams. Senos PHP programos iš daugybės pavienių skriptų su globaliais kintamaisiais, priešingai, sunkiai prižiūrimos, o atnaujinant linkusios klysti.
Pagrindinė mintis yra inkapsuliacija: klasė į išorę atveria tik tuos metodus, kurių kitiems iš tikrųjų reikia, ir saugo savo vidinę būseną. Užsakymą tuomet, pavyzdžiui, galima pažymėti kaip apmokėtą tik per metodą, kuris pirmiausia patikrina, ar tai apskritai leistina. Tokių taisyklių sutelkimas vienoje vietoje yra privalumas ir saugumui.
Elementų apžvalga
| Elementas | Paskirtis | Trumpas pavyzdys |
|---|---|---|
| Klasė | objektų brėžinys su savybėmis ir metodais | class Rechnung { ... } |
| abstrakti klasė | bendras pagrindas, tiesiogiai negalima sukurti objekto | abstract class Zahlart { ... } |
| Sąsaja | sutartis: kokius metodus klasė turi pateikti | interface Versandfaehig { ... } |
| Trait | pakartotinai naudojami metodai klasėms be bendros tėvinės klasės | trait MitZeitstempel { ... } |
| Enum | fiksuotas leistinų reikšmių rinkinys kaip atskiras tipas, nuo PHP 8.1 | enum Status { case Offen; ... } |
Matomumas (public, protected, private) nustato, kas gali pasiekti savybes ir metodus. Klasės organizuojamos vardų erdvėse ir įkeliamos per autoloader; kaip tai veikia, rodo puslapis Vardų erdvės ir autoloading.
Šiuolaikinis PHP: naujovės nuo 8.0 iki 8.4
Šios kalbos priemonės aprašytos PHP vadove ir leidimų pranešimuose:
| Versija | Naujovė |
|---|---|
| 8.0 | konstruktoriaus promocija, nullsafe operatorius ?->, ::class objektams |
| 8.1 | readonly savybės, enum, new inicializatoriuose, final klasės konstantoms |
| 8.2 | readonly klasės; dinaminės savybės laikomos pasenusiomis |
| 8.3 | atributas #[\Override], tipizuotos klasės konstantos |
| 8.4 | property hooks, asimetrinis matomumas, new be apgaubiančių skliaustų |
Pavyzdys, jungiantis kelias iš šių priemonių:
<?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, // nuo 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 vietoj klaidos
readonly neleidžia ID pakeisti sukūrus. private(set) leidžia skaityti iš išorės, bet rašyti tik klasės viduje. Tokie kode įtvirtinti užtikrinimai sumažina tikimybę klaidų, kurios kitaip išryškėtų tik eksploatuojant. Už jų slypinčius tipus paaiškina puslapis PHP tipų sistema.
Atnaujinimo spąstai objektiniame kode
Senesnėms programoms ypač svarbūs du pakeitimai. Nuo PHP 8.2.0 dinaminių savybių, t. y. savybių, kurios klasėje nedeklaruotos, kūrimas laikomas pasenusiu, nebent klasė turi atributą #[\AllowDynamicProperties]. Senesnis kodas tai dažnai naudoja nesąmoningai ir tada užpildo žurnalus pastabomis. Be to, pasak vadovo, tipizuotos savybės prieš pirmą skaitymą turi būti inicializuotos, antraip PHP išmeta Error.
Naudingas PHP 8.3 atributas #[\Override]: jis pažymi metodą kaip tėvinio metodo perrašymą. Jei tokio metodo nebėra, pavyzdžiui, po bibliotekoje atlikto pervadinimo, PHP praneša apie klaidą, užuot tyliai leidusi metodui veikti tuščiai. Tokios patikros daro atnaujinimus nuspėjamesnius; įstrigusiems senų projektų atvejais padeda mūsų perkėlimas į palaikomą PHP versiją.
Objektai ir atmintis
PHP objektai perduodami per identifikatorius (handles). Perdavus objektą funkcijai, ji dirba su tuo pačiu objektu, o ne su kopija. Tai efektyvu, bet lengvai sukelia ciklines nuorodas, pavyzdžiui, kai užsakymas žino savo pozicijas, o kiekviena pozicija vėl žino savo užsakymą. Tokių ciklų vien nuorodų skaičiavimas nesutvarko; tam PHP turi savo šiukšlių surinkėją (garbage collector). Išsamiau puslapyje Atminties valdymas PHP.
OOP ir saugumas: magiški metodai ir deserializacija
PHP turi magiškus metodus, kurie iškviečiami automatiškai, pavyzdžiui, __construct, __destruct, __toString, __get ar __wakeup. Tai patogu, bet turi ir šešėlinę pusę: jei programa svetimus duomenis su unserialize() paverčia atgal objektais, užpuolikas gali nustatyti, kokios klasės bus sukurtos, ir taip paleisti esamą kodą magiškuose metoduose. Kaip to išvengti, aprašo vadovas Nesaugi deserializacija PHP. Trumpai: duomenų mainams naudokite json_encode() ir json_decode(), o unserialize() taikykite tik savo, patikimiems duomenims, geriausia su parinktimi allowed_classes.
Nuo PHP2Shell geras objektinis kodas, priešingai, nepadeda. CVE-2026-109618 ir CVE-2026-109619 slypi interpretatoriuje, o su mod_php, pasak PHP komandos, exploit buvo parodytas dar prieš pradedant vykdyti programos kodą. Privaloma atnaujinti iki PHP 8.5.12, 8.4.27, 8.3.36 ar 8.2.35 ir paleisti iš naujo visus PHP procesus.
Kaip PHP SOS padeda konkrečiai?
- Įvertiname jūsų programos sandarą ir parodome, kurios dalys apsunkina atnaujinimą į palaikomą PHP versiją.
- Tikslingai ieškome rizikingų šablonų, tokių kaip
unserialize()su svetimais duomenimis ir pavojingi magiški metodai. - Nuosavus sprendimus tikriname pagal saugumo audito ir skverbties testo paslaugą.
- Įdiegiame PHP atnaujinimą, paleidžiame iš naujo visus darbinius procesus (worker) ir po to išbandome programą.
Dažni klausimai
Ar PHP yra objektinė kalba?
PHP palaiko tiek procedūrinį, tiek objektinį kodą. Tačiau karkasai, CMS branduoliai ir parduotuvių sistemos šiandien daugiausia sukurti objektiškai, su klasėmis, sąsajomis ir vardų erdvėmis.
Kuo skiriasi sąsaja ir abstrakti klasė?
Sąsaja aprašo tik tai, kokius metodus klasė turi pateikti. Abstrakti klasė papildomai gali turėti kodo ir savybių, bet jos tiesiogiai sukurti objekto negalima. Klasė gali turėti kelias sąsajas, bet tik vieną tėvinę klasę.
Nuo kada PHP yra enum?
Išvardijimai (enum) atsirado su PHP 8.1. Jie pakeičia konstantų rinkinius atskiru tipu, leidžiančiu tik apibrėžtus atvejus. Backed enum papildomai turi int arba string reikšmę.
Kodėl magiški metodai svarbūs saugumui?
Tokius metodus kaip __destruct ar __wakeup PHP iškviečia automatiškai, pavyzdžiui, deserializuojant duomenis. Jei svetimi duomenys nepatikrinti patenka į unserialize(), esamose klasėse gali būti sukeltos netikėtos eigos.