Lühidalt: Objektorienteeritud programmeerimine (OOP) koondab andmed ja nendega seotud funktsioonid klassidesse. PHP pakub selleks klasse, abstraktseid klasse, liideseid, trait'e ja alates PHP 8.1-st enume. PHP 8.0–8.4-ga lisandus palju keelevahendeid, näiteks konstruktori promotsioon, readonly, Property Hooks ja asümmeetriline nähtavus. Turvalisuse jaoks on oluline: hästi kapseldatud koodi on lihtsam kontrollida ning maagilised meetodid muudavad ebaturvalise deserialiseerimise ohtlikuks. Interpretaatori turvaaukude nagu PHP2Shell vastu OOP ei aita.
Mida objektorienteeritud programmeerimine PHP-s tähendab
Lahtiste funktsioonide ja globaalsete muutujate asemel kirjeldab klass asja erialamaailmast: tellimust, klienti, arvet. See määrab, millised andmed sinna kuuluvad (omadused) ja mida nendega teha saab (meetodid). Objekt on selle klassi konkreetne eksemplar.
Otsustajale on sellel praktiline väärtus: selgete klassidega objektorienteeritud koodi on parem testida, kontrollida ja teenusepakkujale üle anda. Vanad PHP rakendused, mis koosnevad paljudest üksikutest skriptidest ja globaalsetest muutujatest, on seevastu raskesti hooldatavad ja uuenduste puhul veaaldised.
Kesksel kohal on kapseldus: klass avab väljapoole ainult need meetodid, mida teised tõesti vajavad, ja kaitseb oma sisemist seisundit. Tellimuse saab siis näiteks tasutuks märkida ainult meetodiga, mis kontrollib enne, kas see on üldse lubatud. Sellised reeglid ühte kohta koondada on kasu ka turvalisusele.
Ehituskivid ülevaatlikult
| Ehituskivi | Otstarve | Lühinäide |
|---|---|---|
| Klass | objektide ehitusplaan omaduste ja meetoditega | class Rechnung { ... } |
| abstraktne klass | ühine alus, otse instantseerimatu | abstract class Zahlart { ... } |
| liides (interface) | leping: milliseid meetodeid klass pakkuma peab | interface Versandfaehig { ... } |
| trait | taaskasutatavad meetodid klassidele, millel pole ühist vanemklassi | trait MitZeitstempel { ... } |
| enum | kindel lubatud väärtuste kogum oma tüübina, alates PHP 8.1-st | enum Status { case Offen; ... } |
Nähtavused (public, protected, private) reguleerivad, kes omadustele ja meetoditele ligi pääseb. Klassid organiseeritakse nimeruumidesse ja laaditakse automaatlaaduri kaudu; kuidas see töötab, näitab leht Nimeruumid ja automaatlaadimine.
Kaasaegne PHP: uuendused versioonides 8.0–8.4
Järgmised keelevahendid on dokumenteeritud PHP käsiraamatus või väljalaskekuulutustes:
| Versioon | Uuendus |
|---|---|
| 8.0 | konstruktori promotsioon, nullsafe-operaator ?->, ::class objektidel |
| 8.1 | readonly-omadused, enumid, new initsialiseerijates, final klassikonstantidele |
| 8.2 | readonly-klassid; dünaamilised omadused loetakse iganenuks |
| 8.3 | atribuut #[\Override], tüpiseeritud klassikonstandid |
| 8.4 | Property Hooks, asümmeetriline nähtavus, new ilma ümbritsevate sulgudeta |
Näide, mis ühendab mitu neist vahenditest:
<?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, // alates PHP 8.4-st
) {}
public function alsBezahltMarkieren(): void
{
$this->status = Status::Bezahlt;
}
}
$b = new Bestellung(42);
$b->alsBezahltMarkieren();
echo $b->status->value; // bezahlt
$s = Status::tryFrom('storniert'); // null vea asemel
readonly takistab ID muutmist pärast loomist. private(set) lubab lugemist väljastpoolt, kirjutamist aga ainult klassi sees. Sellised tagatised koodis muudavad ebatõenäolisemaks vead, mis muidu tulevad välja alles töö käigus. Nende taga olevaid tüüpe selgitab leht PHP tüübisüsteem.
Uuenduse lõksud objektorienteeritud koodis
Vanemate rakenduste jaoks on eriti olulised kaks muudatust. Alates PHP 8.2.0-st on dünaamiliste omaduste loomine iganenud, see tähendab omaduste, mida klassis ei ole deklareeritud, välja arvatud juhul, kui klassil on atribuut #[\AllowDynamicProperties]. Vanem kood teeb seda sageli tahtmatult ja täidab seejärel logid märkustega. Lisaks peavad tüpiseeritud omadused käsiraamatu järgi olema enne esimest lugemist initsialiseeritud, vastasel juhul viskab PHP vea Error.
Abiks on PHP 8.3 atribuut #[\Override]: see märgib meetodi vanemmeetodi ülekirjutusena. Kui seda meetodit enam ei ole, näiteks teegis ümbernimetamise järel, teatab PHP veast, selle asemel et lasta meetodil vaikselt tühja jooksma. Sellised kontrollid teevad uuendused planeeritavamaks; kinni kiilunud vanade projektide puhul aitab meie üleminek toetatud PHP versioonile.
Objektid ja mälu
Objekte antakse PHP-s edasi tunnuste (handle'ite) kaudu. Kui objekt funktsioonile üle anda, töötab see sama objektiga, mitte koopiaga. See on tõhus, kuid viib kergesti tsükliliste viideteni, näiteks kui tellimus teab oma positsioone ja iga positsioon omakorda oma tellimust. Selliseid tsükleid viidete loendur üksi ei koristata; selleks on PHP-l oma prügikoristaja (Garbage Collector). Üksikasjad on lehel Mäluhaldus PHP-s.
OOP ja turvalisus: maagilised meetodid ja deserialiseerimine
PHP tunneb maagilisi meetodeid, mida kutsutakse välja automaatselt, näiteks __construct, __destruct, __toString, __get või __wakeup. See on praktiline, kuid sel on varjukülg: kui rakendus muudab võõrad andmed funktsiooniga unserialize() tagasi objektideks, saab ründaja määrata, millised klassid tekivad, ja käivitada nii olemasolevat koodi maagilistes meetodites. Kuidas seda vältida, kirjeldab juhend Ebaturvaline deserialiseerimine PHP-s. Lühidalt: andmevahetuseks kasutage json_encode() ja json_decode() ning unserialize() ainult oma usaldusväärsete andmete jaoks, ideaalis suvandiga allowed_classes.
PHP2Shelli vastu hea objektorienteeritud kood seevastu ei aita. CVE-2026-109618 ja CVE-2026-109619 asuvad interpretaatoris ning mod_php puhul näidati PHP meeskonna andmetel ekspluateerimist enne, kui rakenduse kood käivitub. Kohustuslik on uuendus versioonile PHP 8.5.12, 8.4.27, 8.3.36 või 8.2.35 ja kõigi PHP protsesside taaskäivitus.
Kuidas PHP SOS konkreetselt aitab?
- Hindame teie rakenduse ülesehitust ja näitame, millised osad raskendavad üleminekut toetatud PHP versioonile.
- Otsime sihipäraselt riskantseid mustreid, nagu
unserialize()võõraste andmete peal ja ohtlikud maagilised meetodid. - Kontrollime omaarendusi turvaauditi ja penetratsioonitesti raames.
- Paigaldame PHP uuenduse, käivitame kõik workerid uuesti ja testime rakendust seejärel.
Korduma kippuvad küsimused
Kas PHP on objektorienteeritud keel?
PHP toetab nii protseduurset kui ka objektorienteeritud koodi. Raamistikud, CMS-ide tuumad ja poesüsteemid on tänapäeval siiski valdavalt objektorienteeritud, klasside, liideste ja nimeruumidega.
Mis vahe on liidesel ja abstraktsel klassil?
Liides kirjeldab ainult seda, milliseid meetodeid klass pakkuma peab. Abstraktne klass võib lisaks sisaldada juba koodi ja omadusi, kuid seda ei saa otse instantseerida. Klassil võib olla mitu liidest, aga ainult üks vanemklass.
Millest alates on PHP-s enumid?
Enumeratsioonid tulid PHP 8.1-ga. Need asendavad konstantide kogumeid oma tüübiga, mis lubab ainult defineeritud juhtumeid. Backed Enumidel on lisaks int- või string-väärtus.
Miks on maagilised meetodid turvalisuse seisukohast olulised?
Meetodeid nagu __destruct või __wakeup kutsub PHP välja automaatselt, näiteks andmete deserialiseerimisel. Kui võõrad andmed jõuavad kontrollimata funktsiooni unserialize(), võib see käivitada olemasolevates klassides ootamatuid protsesse.