# PHP:s typsystem

> PHP:s typsystem förklarat: datatyper, typdeklarationer från PHP 7.1 till 8.3, strict_types och lösa jämförelser, med exempel och koppling till säkerhet.

Källa: https://phpsos.de/sv/php/typsystem/  
Aktualitet: 2026-10-25  
Leverantör: PHP SOS, PHP-nödhjälp och serversäkerhet. Omedelbar hjälp via WhatsApp: https://wa.me/491736494914?text=Hej%20PHP%20SOS%2C%20vi%20beh%C3%B6ver%20hj%C3%A4lp%20med%20v%C3%A5r%20PHP-server.%20F%C3%B6retag%3A%20%E2%80%A6%20Webbplats%3A%20%E2%80%A6

**Kort sagt:** PHP är dynamiskt typat: Ett värdes typ fastställs först vid körning, och utan ytterligare föreskrifter omvandlar PHP värden automatiskt vid behov. Sedan PHP 7 kan dock parametrar, returvärden och egenskaper förses med typer, och `declare(strict_types=1)` gör kontrollen sträng. Den som kan reglerna och använder strikta jämförelser med `===` undviker en hel klass av logik- och säkerhetsfel.

## Dynamiskt typat, men inte utan typer

I PHP behöver man inte ange någon typ vid `$preis = 19.90;`. PHP ser att det är ett flyttal. Om värdet senare kopplas ihop med en sträng omvandlar PHP det. Det beteendet kallas type juggling, alltså automatisk typomvandling. Det gör starten enkel men kan ge överraskande resultat.

För beslutsfattare är det relevant eftersom många äldre PHP-applikationer skrevs utan typangivelser. Sådan kod är svårare att granska och modernisera. Nyare projekt använder typer konsekvent, vilket gör fel synliga tidigare och först gör den [statiska analysen](https://phpsos.de/sv/php/statische-analyse/) med verktyg som PHPStan eller Psalm riktigt effektiv.

## PHP:s typer i överblick

PHP-manualen nämner nio interna typer som varje uttryck kan ha. Vanligtvis delas de in i tre grupper:

| Grupp | Typer | Exempel |
|---|---|---|
| Skalära typer | `bool`, `int`, `float`, `string` | `true`, `42`, `3.5`, `"Text"` |
| Sammansatta typer | `array`, `object`, `callable` | `[1, 2]`, `new DateTime()` |
| Särskilda typer | `null`, `resource` | `null`, en öppnad fil |

För typkontroller rekommenderar manualen `is_*()`-funktionerna som `is_int()`. För att undersöka ett värde passar `get_debug_type()`, som sedan PHP 8.0.0 ger de gängse typnamnen, medan det äldre `gettype()` till exempel returnerar `"integer"` och `"double"`.

Vid sidan av den automatiska omvandlingen finns den uttryckliga: Med en cast som `(int) $wert` eller med `settype()` bestämmer koden själv vilken typ ett värde ska ha. Det är vanligt för inmatning från formulär, eftersom allt som kommer in via `$_GET` eller `$_POST` först är en sträng eller en array. En cast kontrollerar dock inte om värdet var vettigt: Av `"abc"` blir tyst `0`. För inmatning är en riktig kontroll med `filter_var()` därför oftast det bättre valet.

Klasser och gränssnitt är också typer i PHP. En funktion kan alltså kräva att en parameter är ett objekt av en viss klass eller uppfyller ett visst gränssnitt. Hur klasser, gränssnitt och enums samverkar förklarar sidan [Objektorientering i PHP](https://phpsos.de/sv/php/objektorientierung/).

## Typdeklarationer: från PHP 7.1 till 8.3

Typdeklarationer anger vilka värden en funktion tar emot och returnerar. Typsystemet har vuxit över många versioner. Enligt manualens ändringslogg tillkom bland annat följande möjligheter:

| Version | Nytt |
|---|---|
| 7.1.0 | nullbara typer (`?int`), `void`, `iterable` |
| 7.2.0 | `object` |
| 7.4.0 | typade klassegenskaper |
| 8.0.0 | unionstyper (flera tillåtna typer i en angivelse), `mixed`, returtypen `static` |
| 8.1.0 | intersektionstyper (`A&B`), returtypen `never` |
| 8.2.0 | DNF-typer, literaltypen `true`, `null` och `false` som självständiga typer |
| 8.3.0 | typade konstanter i klasser, gränssnitt, traits och enums |

DNF står för disjunktiv normalform och tillåter kombinationer som `(A&B)|null`. Den som planerar PHP-versioner ser av den här tabellen också vilka språkmedel en applikation förutsätter.

## strict_types: omvandling eller TypeError

Utan ytterligare angivelse arbetar PHP i omvandlande läge. En funktion med `int`-parametrar tar då även emot `1.5` och gör om det till `1`; sedan PHP 8.1 är den förlustbehäftade omvandlingen markerad som föråldrad. Med `declare(strict_types=1)` i filens början kastar PHP i stället ett `TypeError`.

```php
<?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, i stället för tyst 3
```

Två finesser är viktiga. För det första gäller `strict_types` för anrop från filen där det står, inte för de funktioner som definieras där. Anropar en fil utan `strict_types` samma funktion sker omvandling. För det andra är ett heltal där ett flyttal förväntas tillåtet även i strikt läge.

## Lösa och strikta jämförelser

Operatorn `==` jämför efter typomvandling, `===` jämför värde och typ utan omvandling. Manualen rekommenderar i de flesta fall `===` och `!==`, eftersom omvandlingsreglerna inte alltid är uppenbara.

```php
<?php
var_dump(0 == "a");    // PHP 7: true,  PHP 8: false
var_dump("1" == "01"); // true, båda är numeriska strängar
var_dump("1" === "01");// false, samma typ men olika sträng
var_dump(1 == true);   // true
var_dump(1 === true);  // false
```

Med PHP 8.0 blev jämförelser mellan tal och icke-numeriska strängar mer rimliga. Äldre applikationer kan bete sig annorlunda efter uppgraderingen, till exempel i `switch`-block. Uttrycket `match`, som också infördes med PHP 8.0, jämför alltid strikt. Hur lösa jämförelser leder till säkerhetsluckor, till exempel vid kontroll av token eller lösenord, beskriver inlägget [Type juggling: lösa jämförelser som säkerhetsrisk](https://phpsos.de/sv/blog/type-juggling-php/).

## Typer, uppgraderingar och PHP2Shell

Ett strikt typsystem gör applikationskod mer robust, men det skyddar inte mot fel i själva tolken. PHP2Shell-sårbarheterna CVE-2026-109618 och CVE-2026-109619 ligger i PHP:s minnes- och förfrågningshantering. De är åtgärdade i PHP 8.5.12, 8.4.27, 8.3.36 och 8.2.35; därefter måste alla PHP-processer startas om.

Typsystemet spelar ändå en roll, nämligen vid uppgraderingen. Applikationer som fortfarande sitter fast på PHP 8.1 eller äldre får inga officiella uppdateringar längre från PHP-projektet. Väl typad kod går betydligt lättare att lyfta till en version som stöds, eftersom verktyg hittar inkompatibiliteter tidigt. För äldre projekt hjälper vår [migrering till en PHP-version som stöds](https://phpsos.de/sv/leistungen/php-migration-legacy/).

> **Tips:**
> Aktivera `strict_types` stegvis i nya och omarbetade filer. Då växer typsäkerheten utan att gammal kod går sönder på en gång.

## Hur hjälper PHP SOS konkret?

- Vi kontrollerar vilken PHP-version er applikation minst behöver och jämför med de åtgärdade versionerna.
- Vi kör statisk analys över koden och markerar ställen med lösa jämförelser i säkerhetsrelevanta kontroller.
- Vi planerar uppgraderingar så att ändrade jämförelseregler testas i förväg.
- Vi installerar PHP-uppdateringen, startar om alla workers och dokumenterar läget.


## Vanliga frågor

**Är PHP starkt eller svagt typat?**  
PHP är dynamiskt typat: En variabels typ fastställs först vid körning. Utan strict_types omvandlar PHP värden vid behov. Med typdeklarationer och strict_types kan koden ändå göras mycket sträng.

**Vad gör declare(strict_types=1)?**  
Det stänger av den automatiska omvandlingen av skalära värden för anrop från just den filen. Passar ett värde inte den deklarerade typen kastar PHP ett TypeError. Det enda undantaget är ett heltal där ett flyttal förväntas.

**Varför är 0 == "a" falskt i PHP 8 men sant i PHP 7?**  
Till och med PHP 7 omvandlades en icke-numerisk sträng vid jämförelse med ett tal till ett tal, och "a" blev 0. Sedan PHP 8.0 jämför PHP i det fallet inte längre numeriskt, och resultatet är false.

**Skyddar typer mot säkerhetsluckor i själva PHP?**  
Nej. Typer förhindrar fel i er applikationskod. Luckor i tolken som PHP2Shell stängs bara av en PHP-uppdatering. Moderna typfunktioner kräver dock aktuella PHP-versioner och är därmed ett bra tillfälle att uppgradera.

## Källor

- [PHP-manualen: Typdeklarationer](https://www.php.net/manual/de/language.types.declarations.php)
- [PHP-manualen: Introduktion till typer](https://www.php.net/manual/de/language.types.intro.php)
- [PHP-manualen: Jämförelseoperatorer](https://www.php.net/manual/de/language.operators.comparison.php)
- [PHP 8.0 Release](https://www.php.net/releases/8.0/en.php)
