Kort sagt: For at udvikle PHP lokalt er der tre gængse veje: den indbyggede webserver (php -S) til hurtige forsøg, de officielle PHP-Docker-images til reproducerbare miljøer og værktøjer som DDEV, der frembringer færdige projektmiljøer til WordPress, TYPO3, Shopware eller Laravel. Afgørende er mindre værktøjet end overensstemmelsen: Lokalt bør samme PHP-version med samme udvidelser køre som live. For sikkerheden tæller til sidst dog altid runtime på serveren.
Hvorfor et eget udviklingsmiljø?
At lave ændringer direkte på live-serveren er risikabelt: Hver tastefejl er straks synlig for kunderne, og testfiler bliver gerne liggende. Et lokalt miljø adskiller afprøvning fra drift. Det er samtidig stedet, hvor nye PHP-versioner og sikkerhedsopdateringer testes først.
For ledelsen og it-chefen er spørgsmålet derfor ikke, om der findes et udviklingsmiljø, men om det svarer til live-systemet. Et lokalt miljø med PHP 8.4, mens live stadig kører 8.1, tilslører problemer i stedet for at vise dem. Det samme gælder databaseversion, webserver og udvidelser som intl, gd eller pdo_mysql: Allerede en manglende udvidelse kan medføre, at en fejl først opdages live.
Mulighederne i overblik
| Mulighed | Egnet til | Styrker | Grænser |
|---|---|---|---|
Indbygget server php -S |
korte forsøg, små scripts | uden installation af yderligere software | ingen erstatning for Nginx eller Apache, ikke til offentlige netværk |
| Officielt Docker-image | teams, reproducerbare miljøer | version kan fastlægges via tag, tæt på containerdrift | konfiguration og samspil mellem flere containere skal bygges selv |
| DDEV | CMS- og framework-projekter | færdige projekttyper, database og webserver inklusive | forudsætter Docker, egne konventioner |
| Lokalt installeret PHP | enkeltudviklere | hurtigt, direkte | versioner til flere projekter er svære at holde parallelt |
Den indbyggede webserver
Siden PHP 5.4 indeholder kommandolinjen en lille webserver. Den starter i den aktuelle mappe eller med -t i en anden dokumentmappe:
php -S localhost:8000 -t public/
Valgfrit giver I et router-script, som kører først ved hver forespørgsel. Manualen er i sin vurdering entydig: Serveren skal støtte udviklingen, er ikke en fuldgyldig webserver og skal ikke bruges i et offentligt netværk. Bind den derfor til localhost, ikke til 0.0.0.0, ellers kan den under omstændigheder nås i firmaets eller hotellets wifi. Mere om kommandolinjen under PHP på kommandolinjen.
Docker: officielle PHP-images
De officielle images findes i flere varianter: cli til kommandolinjen, apache med Apache og mod_php, fpm til drift bag Nginx eller en anden proxy, dertil Alpine-varianter til små images. En hurtig start med Apache:
docker run --rm -p 8080:80 -v "$PWD":/var/www/html php:8.4-apache
Images indeholder skabelonerne php.ini-development og php.ini-production i mappen $PHP_INI_DIR. Lokalt er udviklingsskabelonen fornuftig, fordi den viser fejl. Til produktion anbefaler image-dokumentationen udtrykkeligt produktionsskabelonen. Udvidelser installerer I med de medfølgende hjælpescripts docker-php-ext-configure, docker-php-ext-install og docker-php-ext-enable. Hvordan tags og digests fungerer, forklarer Officielle PHP-Docker-images.
DDEV: færdige miljøer til CMS og frameworks
DDEV bygger på Docker og opsætter til et projekt webserver, PHP, database og hjælpetjenester. Hurtigstartvejledningerne følger næsten altid det samme mønster:
ddev config --project-type=wordpress --docroot=web
ddev start
ddev composer install
ddev launch
Som projekttyper kender DDEV blandt andet wordpress, typo3, shopware6, laravel, symfony, drupal11, magento2 og den generelle type php. PHP-versionen fastlægger I i .ddev/config.yaml; ifølge dokumentationen er versioner fra 5.6 til 8.5 mulige, standarden er 8.4:
# .ddev/config.yaml (uddrag)
php_version: "8.3"
webserver_type: nginx-fpm # alternativt apache-fpm
Sådan svarer det lokale miljø til live-versionen, også selv om denne endnu ikke er den nyeste.
Lokal udvikling, patch-status og PHP2Shell
Efter PHP2Shell har flere platformudbydere peget på en typisk tankefejl. Vercel understreger ifølge bulletinen, at en opdatering af det lokale udviklingsmiljø, applikationskoden eller pluginsene ikke er nok; afgørende er den PHP-runtime, der faktisk leverer. At have PHP 8.4.27 lokalt beskytter ikke serveren med 8.4.26.
Omvendt bringer udviklingsmiljøet egne risici med, som kan vandre ind i produktionen:
- Udviklings-ini i produktion:
display_errorser slået til iphp.ini-development. Havner denne fil på serveren, ser besøgende stier og fejlmeddelelser. Se Slå fejlvisning fra i produktion. - Glemte testfiler:
phpinfo()-filer, database-dumps eller.env-filer med adgangsdata hører ikke til i udrulningen. - Åbne udviklingsservere:
php -Seller containere med udgivne porte på maskiner i netværket. - Forældede images: Lokale images opdateres ikke af sig selv; efter en PHP-sikkerhedsudgivelse bør også udviklingsmiljøet bygges om, så tests kører med den rettede version.
Fastlæg PHP-versionen ét sted, f.eks. i Dockerfile eller i .ddev/config.yaml, og ændr den ved opdateringer sammen med serverkonfigurationen.
Hvordan hjælper PHP SOS konkret?
I sikkerhedsvedligeholdelsesaftalen sørger vi for, at udvikling og drift passer sammen:
- Afstemning: Vi sammenligner PHP-version og udvidelser i udviklings-, test- og live-miljø.
- Opdateringsforløb: Nye PHP-udgivelser indspilles først i testmiljøet, derefter live, hver gang med genstart.
- Kontrollere udrulningen: Vi sørger for, at ingen udviklings-ini, testfiler eller adgangsdata havner på serveren.
- Dokumentation: I ved til enhver tid, hvilken version der kører hvor.
Ofte stillede spørgsmål
Må jeg bruge den indbyggede PHP-webserver offentligt?
Nej. PHP-manualen siger udtrykkeligt, at serveren startet med php -S tjener udvikling og ikke skal bruges i et offentligt netværk. Til drift hører PHP-FPM med Nginx eller Apache.
Hvad er DDEV?
DDEV er et værktøj, der bygger på Docker og frembringer færdige udviklingsmiljøer til PHP-projekter. Det kender projekttyper til WordPress, TYPO3, Shopware 6, Laravel, Drupal og flere systemer.
Er det nok at opdatere den lokale PHP-version?
Nej. Mod sårbarheder som PHP2Shell tæller den PHP-runtime, der faktisk leverer, altså den på serveren. Det lokale miljø bør dog have samme version, så tests er meningsfulde.
Hvilken php.ini bruger jeg lokalt?
Lokalt er php.ini-development fornuftig, fordi den viser fejl. I produktion bør php.ini-production bruges. De officielle Docker-images har begge skabeloner med.