Röviden: A PHP dinamikusan típusos: egy érték típusa csak futásidőben dől el, és további előírás nélkül a PHP szükség esetén automatikusan átalakítja az értékeket. A PHP 7 óta azonban a paraméterek, a visszatérési értékek és a tulajdonságok típussal láthatók el, a declare(strict_types=1) pedig szigorúvá teszi az ellenőrzést. Aki ismeri a szabályokat, és a === szigorú összehasonlítást használja, a logikai és biztonsági hibák egész osztályát elkerüli.
Dinamikusan típusos, de nem típus nélküli
A PHP-ban a $preis = 19.90; esetén nem kell típust megadni. A PHP felismeri, hogy lebegőpontos számról van szó. Ha az értéket később karakterlánccal kapcsolják össze, a PHP átalakítja. Ezt a viselkedést nevezik type jugglingnak, vagyis automatikus típusátalakításnak. Megkönnyíti a belépést, de meglepő eredményekhez vezethet.
A döntéshozók számára ez azért fontos, mert sok régebbi PHP-alkalmazás típusmegadások nélkül készült. Az ilyen kódot nehezebb ellenőrizni és korszerűsíteni. Az újabb projektek következetesen használnak típusokat, ami korábban láthatóvá teszi a hibákat, és a statikus elemzést olyan eszközökkel, mint a PHPStan vagy a Psalm, csak így teszi igazán hatékonnyá.
A PHP típusainak áttekintése
A PHP-kézikönyv kilenc belső típust nevez meg, amelyekkel bármely kifejezés rendelkezhet. Általában három csoportba sorolják őket:
| Csoport | Típusok | Példa |
|---|---|---|
| Skaláris típusok | bool, int, float, string |
true, 42, 3.5, "Text" |
| Összetett típusok | array, object, callable |
[1, 2], new DateTime() |
| Különleges típusok | null, resource |
null, egy megnyitott fájl |
A típusellenőrzésekhez a kézikönyv az is_*() függvényeket ajánlja, például az is_int()-et. Vizsgálatra a get_debug_type() alkalmas, amely a PHP 8.0.0 óta a megszokott típusneveket adja vissza, míg a régebbi gettype() például "integer" és "double" értéket ad.
Az automatikus átalakítás mellett létezik a kifejezett is: egy castal, például (int) $wert, vagy a settype() függvénnyel maga a kód határozza meg, milyen típusú legyen egy érték. Ez az űrlapokból érkező adatoknál megszokott, mert minden, ami a $_GET-en vagy a $_POST-on át beérkezik, először karakterlánc vagy tömb. A cast azonban nem ellenőrzi, hogy az érték értelmes volt-e: az "abc" csendben 0 lesz. A bemenetekhez ezért többnyire a filter_var() szerinti valódi ellenőrzés a jobb választás.
Az osztályok és az interfészek a PHP-ban szintén típusok. Egy függvény tehát megkövetelheti, hogy egy paraméter egy adott osztály objektuma legyen, vagy teljesítsen egy adott interfészt. Az osztályok, interfészek és enumok együttműködését az Objektumorientáltság a PHP-ban oldal magyarázza.
Típusdeklarációk: a PHP 7.1-től a 8.3-ig
A típusdeklarációk meghatározzák, milyen értékeket fogad el és ad vissza egy függvény. A típusrendszer sok verzión át bővült. A kézikönyv változásnaplója szerint többek között ezek a lehetőségek kerültek bele:
| Verzió | Újdonság |
|---|---|
| 7.1.0 | nullázható típusok (?int), void, iterable |
| 7.2.0 | object |
| 7.4.0 | típusos osztálytulajdonságok |
| 8.0.0 | union típusok (több megengedett típus egy megadásban), mixed, static visszatérési típus |
| 8.1.0 | intersection típusok (A&B), never visszatérési típus |
| 8.2.0 | DNF típusok, true literáltípus, null és false önálló típusként |
| 8.3.0 | típusos osztály-, interfész-, trait- és enumkonstansok |
A DNF a diszjunktív normálforma rövidítése, és olyan kombinációkat tesz lehetővé, mint a (A&B)|null. Aki PHP-verziókat tervez, ebből a táblázatból azt is látja, milyen nyelvi eszközöket tételez fel egy alkalmazás.
strict_types: átalakítás vagy TypeError
További megadás nélkül a PHP az átalakító módban dolgozik. Egy int paraméterű függvény ilyenkor az 1.5-öt is elfogadja, és 1-et csinál belőle; a PHP 8.1 óta ez a veszteséges átalakítás elavultnak minősül. A fájl elején álló declare(strict_types=1) esetén a PHP ehelyett TypeErrort dob.
<?php
declare(strict_types=1);
function summe(int $a, int $b): int
{
return $a + $b;
}
echo summe(1, 2); // 3
echo summe(1.5, 2.5); // TypeError, a csendes 3 helyett
Két finomság fontos. Először, a strict_types azokra a hívásokra vonatkozik, amelyek abban a fájlban állnak, ahol megadták, nem pedig az ott definiált függvényekre. Ha egy strict_types nélküli fájl hívja ugyanezt a függvényt, akkor átalakítás történik. Másodszor, ott, ahol lebegőpontos szám várt, az egész szám szigorú módban is megengedett.
Laza és szigorú összehasonlítások
A == operátor típusátalakítás után hasonlít össze, a === átalakítás nélkül az értéket és a típust is. A kézikönyv a legtöbb esetben a === és a !== használatát ajánlja, mert az átalakítási szabályok nem mindig nyilvánvalók.
<?php
var_dump(0 == "a"); // PHP 7: true, PHP 8: false
var_dump("1" == "01"); // true, mindkettő numerikus karakterlánc
var_dump("1" === "01");// false, azonos típus, de más karakterlánc
var_dump(1 == true); // true
var_dump(1 === true); // false
A PHP 8.0-val a számok és a nem numerikus karakterláncok összehasonlítása észszerűbb lett. A régebbi alkalmazások a frissítés után másként viselkedhetnek, például a switch blokkokban. A szintén a PHP 8.0-val bevezetett match kifejezés mindig szigorúan hasonlít össze. Hogy a laza összehasonlítások hogyan vezetnek biztonsági résekhez, például token- vagy jelszóellenőrzéseknél, azt a Type juggling: a laza összehasonlítások mint biztonsági kockázat cikk írja le.
Típusok, frissítések és PHP2Shell
A szigorú típusrendszer robusztusabbá teszi az alkalmazáskódot, de nem véd magának az értelmezőnek a hibái ellen. A CVE-2026-109618 és CVE-2026-109619 számú PHP2Shell-rések a PHP memória- és kéréskezelésében vannak. A PHP 8.5.12, 8.4.27, 8.3.36 és 8.2.35 verzióban javították őket; ezután minden PHP-folyamatot újra kell indítani.
A típusrendszernek ennek ellenére szerepe van, mégpedig a frissítésnél. Azok az alkalmazások, amelyek még a PHP 8.1-en vagy régebbin ragadtak, a PHP-projekttől már nem kapnak hivatalos frissítéseket. A jól típusozott kód sokkal könnyebben emelhető támogatott verzióra, mert az eszközök korán megtalálják az összeférhetetlenségeket. Régebbi projekteknél a Migráció támogatott PHP-verzióra szolgáltatásunk segít.
A strict_types-t fokozatosan kapcsolja be az új és az átdolgozott fájlokban. Így a típusbiztonság növekszik, anélkül hogy a régi kód egy csapásra összeomlana.
Hogyan segít konkrétan a PHP SOS?
- Megvizsgáljuk, legalább milyen PHP-verzióra van szüksége az alkalmazásának, és összevetjük a javított verziókkal.
- Statikus elemzést futtatunk a kódon, és megjelöljük a biztonsági szempontból releváns ellenőrzések laza összehasonlításait.
- A frissítéseket úgy tervezzük, hogy a megváltozott összehasonlítási szabályokat előtte teszteljük.
- Telepítjük a PHP-frissítést, újraindítjuk az összes workert, és dokumentáljuk az állapotot.
Gyakori kérdések
Erősen vagy gyengén típusos a PHP?
A PHP dinamikusan típusos: egy változó típusa csak futásidőben dől el. strict_types nélkül a PHP szükség esetén átalakítja az értékeket. Típusdeklarációkkal és strict_types-szal a kód mégis nagyon szigorúvá tehető.
Mit okoz a declare(strict_types=1)?
Az adott fájlból induló hívásoknál kikapcsolja a skaláris értékek automatikus átalakítását. Ha egy érték nem illik a deklarált típushoz, a PHP TypeErrort dob. Az egyetlen kivétel az egész szám ott, ahol lebegőpontos szám várt.
Miért hamis a 0 == „a” a PHP 8-ban, a PHP 7-ben viszont igaz?
A PHP 7-ig a nem numerikus karakterláncot számmal való összehasonlításkor számmá alakították, így az „a” 0 lett. A PHP 8.0 óta a PHP ilyenkor már nem numerikusan hasonlít össze, az eredmény false.
Védenek a típusok a PHP-ban magában lévő biztonsági rések ellen?
Nem. A típusok az Ön alkalmazáskódjának hibáit előzik meg. Az értelmezőben lévő réseket, mint a PHP2Shell, csak PHP-frissítés zárja be. A modern típusfunkciók viszont naprakész PHP-verziókat igényelnek, így jó alkalmat adnak a frissítésre.