# Objektno programiranje v PHP

> Objektno programiranje v PHP: razredi, vmesniki, trait in enumi, jezikovne novosti od PHP 8.0 do 8.4 ter povezava z deserializacijo in varnostjo.

Vir: https://phpsos.de/sl/php/objektorientierung/  
Stanje: 25.10.2026  
Ponudnik: PHP SOS, Nujna pomoč za PHP in varnost strežnikov. Takojšnja pomoč po WhatsAppu: https://wa.me/491736494914?text=Pozdravljeni%2C%20PHP%20SOS%2C%20potrebujemo%20pomo%C4%8D%20z%20na%C5%A1im%20stre%C5%BEnikom%20PHP.%20Podjetje%3A%20%E2%80%A6%20Spletna%20stran%3A%20%E2%80%A6

**Na kratko:** Objektno usmerjeno programiranje (OOP) podatke in pripadajoče funkcije združuje v razrede. PHP za to ponuja razrede, abstraktne razrede, vmesnike, trait in od PHP 8.1 enume. S PHP 8.0 do 8.4 je prišlo veliko jezikovnih sredstev, na primer promocija konstruktorja, `readonly`, property hooks in asimetrična vidnost. Pomembno za varnost: dobro zaprto kodo je lažje preverjati, magične metode pa naredijo nevarno deserializacijo nevarno. Proti vrzelim v interpreterju, kot je PHP2Shell, OOP ne pomaga.

## Kaj pomeni objektno usmerjeno programiranje v PHP

Namesto ohlapnih funkcij in globalnih spremenljivk razred opisuje stvar iz stroke: naročilo, stranko, račun. Določa, kateri podatki sodijo zraven (lastnosti) in kaj je z njimi mogoče početi (metode). Objekt je konkreten primerek tega razreda.

Za odločevalce ima to praktično vrednost: objektno usmerjeno kodo z jasnimi razredi je mogoče bolje testirati, preverjati in predati izvajalcem. Stare aplikacije PHP iz številnih posameznih skript z globalnimi spremenljivkami pa je težko vzdrževati in so pri nadgradnjah nagnjene k napakam.

Osrednja zamisel je enkapsulacija: razred navzven sprosti samo metode, ki jih drugi resnično potrebujejo, in ščiti svoje notranje stanje. Naročilo je tako mogoče označiti kot plačano na primer samo z metodo, ki prej preveri, ali je to sploh dovoljeno. Združevanje takih pravil na enem mestu je dobiček tudi za varnost.

## Gradniki na hitro

| Gradnik | Namen | Kratek primer |
|---|---|---|
| Razred | načrt za objekte z lastnostmi in metodami | `class Rechnung { ... }` |
| abstraktni razred | skupna osnova, ni neposredno instanciran | `abstract class Zahlart { ... }` |
| Vmesnik | pogodba: katere metode mora razred ponujati | `interface Versandfaehig { ... }` |
| Trait | ponovno uporabne metode za razrede brez skupnega nadrejenega | `trait MitZeitstempel { ... }` |
| Enum | fiksen nabor dovoljenih vrednosti kot lasten tip, od PHP 8.1 | `enum Status { case Offen; ... }` |

Vidnosti (`public`, `protected`, `private`) urejajo, kdo sme dostopati do lastnosti in metod. Razredi so organizirani v imenskih prostorih in naloženi prek samodejnega nalagalnika; kako to deluje, kaže stran [Imenski prostori in samodejno nalaganje](https://phpsos.de/sl/php/namespaces-autoloading/).

## Sodobni PHP: novosti od 8.0 do 8.4

Naslednja jezikovna sredstva so dokumentirana v priročniku PHP oziroma v objavah izdaj:

| Različica | Novost |
|---|---|
| 8.0 | promocija konstruktorja, operator nullsafe `?->`, `::class` na objektih |
| 8.1 | lastnosti `readonly`, enumi, `new` v inicializatorjih, `final` za konstante razredov |
| 8.2 | razredi `readonly`; dinamične lastnosti veljajo za zastarele |
| 8.3 | atribut `#[\Override]`, tipizirane konstante razredov |
| 8.4 | property hooks, asimetrična vidnost, `new` brez obdajajočih oklepajev |

Primer, ki združuje več teh sredstev:

```php
<?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 namesto napake
```

`readonly` preprečuje, da bi se ID po ustvarjanju spremenil. `private(set)` dovoljuje branje od zunaj, pisanje pa samo znotraj razreda. Takšna zagotovila v kodi zmanjšajo verjetnost napak, ki bi sicer opazile šele v obratovanju. Tipe za tem razlaga stran [Tipski sistem PHP](https://phpsos.de/sl/php/typsystem/).

### Pasti nadgradnje v objektno usmerjeni kodi

Za starejše aplikacije sta posebej pomembni dve spremembi. Od PHP 8.2.0 je ustvarjanje dinamičnih lastnosti zastarelo, torej lastnosti, ki v razredu niso deklarirane, razen če ima razred atribut `#[\AllowDynamicProperties]`. Starejša koda to pogosto uporablja nezavedno in nato dnevnike polni z namigi. Poleg tega morajo biti tipizirane lastnosti po priročniku inicializirane pred prvim branjem, sicer PHP sproži `Error`.

Koristen je atribut `#[\Override]` iz PHP 8.3: metodo označi kot prepis metode nadrejenega razreda. Če te metode ni več, na primer po preimenovanju v knjižnici, PHP javi napako, namesto da bi metoda tiho tekla v prazno. Takšna preverjanja nadgradnje naredijo bolj predvidljive; pri zataknjenih starih projektih pomaga naša [selitev na podprto različico PHP](https://phpsos.de/sl/leistungen/php-migration-legacy/).

## Objekti in pomnilnik

Objekti se v PHP posredujejo prek oznak (handle). Če objekt predate funkciji, ta dela z istim objektom, ne s kopijo. To je učinkovito, a hitro vodi do krožnih sklicevanj, na primer ko naročilo pozna svoje postavke in vsaka postavka spet svoje naročilo. Takih ciklov samo štetje sklicev ne pospravi; za to ima PHP lasten Garbage Collector. Podrobnosti so na strani [Upravljanje pomnilnika v PHP](https://phpsos.de/sl/php/speicherverwaltung/).

## OOP in varnost: magične metode in deserializacija

PHP pozna magične metode, ki se kličejo samodejno, na primer `__construct`, `__destruct`, `__toString`, `__get` ali `__wakeup`. To je priročno, a ima senčno stran: če aplikacija tuje podatke z `unserialize()` pretvori nazaj v objekte, lahko napadalec določi, kateri razredi nastanejo, in tako sproži obstoječo kodo v magičnih metodah. Kako to preprečiti, opisuje vodnik [Nevarna deserializacija v PHP](https://phpsos.de/sl/ratgeber/deserialisierung-php/). Na kratko: za izmenjavo podatkov uporabljajte `json_encode()` in `json_decode()`, `unserialize()` pa samo za lastne, zaupanja vredne podatke, idealno z možnostjo `allowed_classes`.

Pri PHP2Shell dobra objektno usmerjena koda ne pomaga. CVE-2026-109618 in CVE-2026-109619 ležita v interpreterju, pri mod_php pa je bil po navedbah ekipe PHP exploit prikazan, še preden se izvede koda aplikacije. Obvezna sta posodobitev na PHP 8.5.12, 8.4.27, 8.3.36 ali 8.2.35 in ponovni zagon vseh procesov PHP.

## Kako PHP SOS pomaga konkretno?

- Ocenimo zgradbo vaše aplikacije in pokažemo, kateri deli otežujejo nadgradnjo na podprto različico PHP.
- Ciljno iščemo tvegane vzorce, kot sta `unserialize()` na tujih podatkih in nevarne magične metode.
- Lastne razvoje preverimo v okviru [varnostnega pregleda in penetracijskega testa](https://phpsos.de/sl/leistungen/sicherheitsaudit-penetrationstest/).
- Namestimo posodobitev PHP, znova zaženemo vse workerje in nato preizkusimo aplikacijo.


## Pogosta vprašanja

**Ali je PHP objektno usmerjen jezik?**  
PHP podpira proceduralno in objektno usmerjeno kodo. Ogrodja, jedra sistemov CMS in sistemi za spletne trgovine pa so danes večinoma objektno zgrajeni, z razredi, vmesniki in imenskimi prostori.

**Kakšna je razlika med vmesnikom in abstraktnim razredom?**  
Vmesnik samo opisuje, katere metode mora razred ponujati. Abstraktni razred lahko dodatno že vsebuje kodo in lastnosti, vendar ga ni mogoče neposredno instancirati. Razred ima lahko več vmesnikov, a samo enega nadrejenega.

**Od kdaj obstajajo enumi v PHP?**  
Naštevni tipi (enum) so prišli s PHP 8.1. Zbirke konstant nadomestijo z lastnim tipom, ki dovoljuje samo definirane primere. Backed enumi imajo dodatno vrednost tipa int ali string.

**Zakaj so magične metode pomembne za varnost?**  
Metode, kot sta __destruct ali __wakeup, PHP kliče samodejno, na primer pri deserializaciji podatkov. Če tuji podatki neprevereni pridejo v unserialize(), lahko to sproži nepričakovane poteke v obstoječih razredih.

## Viri

- [Priročnik PHP: razredi in objekti, osnove](https://www.php.net/manual/de/language.oop5.basic.php)
- [Priročnik PHP: lastnosti](https://www.php.net/manual/en/language.oop5.properties.php)
- [Priročnik PHP: vidnost](https://www.php.net/manual/en/language.oop5.visibility.php)
- [PHP 8.1 Release](https://www.php.net/releases/8.1/en.php)
