Aktuel situation: PHP2Shell. To kritiske PHP-sårbarheder (CVSS 9,2) tillader skadelig kode uden login. Rettelser siden 21.10.2026.Hvad der skal gøres nu →

Objektorientering i PHP

Moderne PHP-applikationer er næsten altid objektorienterede. Siden forklarer byggestenene, nyhederne fra PHP 8.0 til 8.4 og hvorfor magiske metoder spiller en rolle for sikkerheden.

Status 5 min. læsetidPHP-viden

Kort sagt: Objektorienteret programmering (OOP) samler data og de tilhørende funktioner i klasser. PHP tilbyder hertil klasser, abstrakte klasser, interfaces, traits og siden PHP 8.1 enums. Med PHP 8.0 til 8.4 kom mange sprogmidler til, f.eks. constructor promotion, readonly, property hooks og asymmetrisk synlighed. Vigtigt for sikkerheden: Velindkapslet kode er lettere at kontrollere, og magiske metoder gør usikker deserialisering farlig. Mod sårbarheder i fortolkeren som PHP2Shell hjælper OOP ikke.

Hvad objektorienteret programmering betyder i PHP

I stedet for at bruge løse funktioner og globale variabler beskriver en klasse en ting fra fagverdenen: en ordre, en kunde, en faktura. Den fastlægger, hvilke data der hører til (egenskaber), og hvad man kan gøre med dem (metoder). Et objekt er en konkret instans af denne klasse.

For beslutningstagere har det en praktisk værdi: Objektorienteret kode med klare klasser kan testes, kontrolleres og overdrages til tjenesteudbydere bedre. Gamle PHP-applikationer bestående af mange enkelte scripts med globale variabler er derimod svære at vedligeholde og fejlfølsomme ved opgraderinger.

En central tanke er indkapslingen: En klasse frigiver udadtil kun de metoder, som andre virkelig har brug for, og beskytter sin indre tilstand. En ordre kan så for eksempel kun markeres som betalt via en metode, der først kontrollerer, om det overhovedet er tilladt. At samle sådanne regler ét sted er også en gevinst for sikkerheden.

Byggestenene i overblik

Byggesten Formål Kort eksempel
Klasse tegning til objekter med egenskaber og metoder class Rechnung { ... }
abstrakt klasse fælles basis, kan ikke instantieres direkte abstract class Zahlart { ... }
Interface kontrakt: hvilke metoder en klasse skal udbyde interface Versandfaehig { ... }
Trait genbrugelige metoder til klasser uden fælles forældreklasse trait MitZeitstempel { ... }
Enum fast sæt tilladte værdier som egen type, siden PHP 8.1 enum Status { case Offen; ... }

Synligheder (public, protected, private) regulerer, hvem der må tilgå egenskaber og metoder. Klasser organiseres i namespaces og indlæses via en autoloader; hvordan det fungerer, viser siden Namespaces og autoloading.

Moderne PHP: nyhederne fra 8.0 til 8.4

Følgende sprogmidler er dokumenteret i PHP-manualen hhv. i release-meddelelserne:

Version Nyhed
8.0 constructor promotion, nullsafe-operatoren ?->, ::class på objekter
8.1 readonly-egenskaber, enums, new i initialiseringer, final for klassekonstanter
8.2 readonly-klasser; dynamiske egenskaber anses som forældede
8.3 attributten #[\Override], typede klassekonstanter
8.4 property hooks, asymmetrisk synlighed, new uden omsluttende parenteser

Et eksempel, der kombinerer flere af disse midler:

<?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,  // fra 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 i stedet for fejl

readonly forhindrer, at id'et ændres efter oprettelsen. private(set) tillader læsning udefra, men skrivning kun inden for klassen. Sådanne garantier i koden gør fejl mindre sandsynlige, som ellers først opdages i drift. Typerne bagved forklarer siden PHP's typesystem.

Opgraderingsfælder i objektorienteret kode

For ældre applikationer er to ændringer særligt relevante. Siden PHP 8.2.0 er oprettelsen af dynamiske egenskaber forældet, altså af egenskaber, der ikke er deklareret i klassen, medmindre klassen bærer attributten #[\AllowDynamicProperties]. Ældre kode bruger det ofte ubevidst og fylder så logs med notitser. Desuden skal typede egenskaber ifølge manualen være initialiseret før den første læsning, ellers kaster PHP en Error.

Nyttig er attributten #[\Override] fra PHP 8.3: Den markerer en metode som overskrivning af en forældremetode. Findes denne metode ikke mere, f.eks. efter en omdøbning i et bibliotek, melder PHP en fejl i stedet for stiltiende at lade metoden køre ud i ingenting. Sådanne kontroller gør opgraderinger mere planlægbare; ved fastlåste ældre projekter hjælper vores migrering til en understøttet PHP-version.

Objekter og hukommelse

Objekter gives i PHP videre via identifikatorer (handles). Giver man et objekt til en funktion, arbejder den med det samme objekt, ikke med en kopi. Det er effektivt, men fører let til krydsreferencer, f.eks. når en ordre kender sine linjer, og hver linje igen kender sin ordre. Sådanne cyklusser rydder referencetællingen alene ikke op efter; dertil har PHP en egen garbage collector. Detaljer står på siden Hukommelsesstyring i PHP.

OOP og sikkerhed: magiske metoder og deserialisering

PHP kender magiske metoder, der kaldes automatisk, f.eks. __construct, __destruct, __toString, __get eller __wakeup. Det er praktisk, men har en skyggeside: Når en applikation med unserialize() omdanner fremmede data tilbage til objekter, kan en angriber bestemme, hvilke klasser der opstår, og dermed sætte eksisterende kode i magiske metoder i gang. Hvordan det forhindres, beskriver guiden Usikker deserialisering i PHP. Kort sagt: Brug json_encode() og json_decode() til dataudveksling, og brug unserialize() kun til egne, pålidelige data, ideelt med indstillingen allowed_classes.

Ved PHP2Shell hjælper god objektorienteret kode derimod ikke. CVE-2026-109618 og CVE-2026-109619 ligger i fortolkeren, og ved mod_php blev der ifølge PHP-teamet vist en exploit, før applikationskoden kører. Et must er opdateringen til PHP 8.5.12, 8.4.27, 8.3.36 eller 8.2.35 og genstart af alle PHP-processer.

Hvordan hjælper PHP SOS konkret?

  • Vi vurderer opbygningen af jeres applikation og viser, hvilke dele der gør en opgradering til en understøttet PHP-version vanskeligere.
  • Vi søger målrettet efter risikable mønstre som unserialize() på fremmede data og farlige magiske metoder.
  • Vi gennemgår egenudviklinger som led i et sikkerhedsaudit og penetrationstest.
  • Vi indspiller PHP-opdateringen, genstarter alle workers og tester applikationen bagefter.

Ofte stillede spørgsmål

Er PHP et objektorienteret sprog?

PHP understøtter både procedural og objektorienteret kode. Frameworks, CMS-kerner og shopsystemer er dog i dag overvejende bygget objektorienteret op med klasser, interfaces og namespaces.

Hvad er forskellen på et interface og en abstrakt klasse?

Et interface beskriver kun, hvilke metoder en klasse skal udbyde. En abstrakt klasse kan desuden allerede indeholde kode og egenskaber, men kan ikke instantieres direkte. En klasse kan have flere interfaces, men kun én forældreklasse.

Siden hvornår findes der enums i PHP?

Enumerationer kom med PHP 8.1. De erstatter samlinger af konstanter med en egen type, som kun tillader de definerede tilfælde. Backed enums har desuden en int- eller string-værdi.

Hvorfor er magiske metoder sikkerhedsrelevante?

Metoder som __destruct eller __wakeup kalder PHP automatisk, for eksempel når data deserialiseres. Kommer fremmede data ukontrolleret ind i unserialize(), kan det udløse uventede forløb i eksisterende klasser.

Kilder

Akut kontakt

Hver time tæller. Skriv til os nu.

Beskriv kort system, PHP-version og observation. Vi vender tilbage, afklarer situationen og arbejder på afstand, indtil hændelsen er afsluttet og dokumenteret.

Akut hjælp