[{"data":1,"prerenderedAt":234},["ShallowReactive",2],{"seo-verification":3,"blog-laravel-octane-vps-frankenphp-docker-traefik-en":6},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-laravel-octane-vps-frankenphp-docker-traefik-en",{"id":9,"slug":10,"slugs":11,"title":14,"excerpt":15,"readTime":16,"views":17,"isPinned":18,"publishedAt":19,"updatedAt":20,"category":21,"categories":27,"featuredImage":29,"bgImage":30,"posterImage":31,"relatedSolution":29,"intro":32,"sections":33,"ctaTitle":29,"ctaBody":29,"ctaButton":141,"ctaUrl":142,"relatedPosts":143},436,"laravel-octane-vps-frankenphp-docker-traefik",{"fr":12,"en":10,"ar":13,"es":10},"deployer-laravel-vps-octane","laravel-octane-على-vps-frankenphp-docker-traefik","Laravel Octane on VPS: FrankenPHP, Docker and Traefik","Move from PHP-FPM to Laravel Octane with FrankenPHP in Docker Compose behind Traefik, understand request lifecycle changes and avoid memory leaks in production.",11,0,false,"2026-10-12T00:00:00+00:00","2026-10-13T14:10:28+00:00",{"id":22,"name":23,"slug":24,"color":25,"icon":26},4,"Development","developpement","bg-warning\u002F10 text-warning","dev",[28],{"id":22,"name":23,"slug":24,"color":25,"icon":26},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fdeployer-laravel-vps-octane-poster.svg","PHP-FPM spawns a process per request: efficient for small apps, but expensive as traffic grows. Laravel Octane changes the paradigm — the application is loaded once into memory and handles thousands of requests without reinitializing. The gain is real: official Laravel benchmarks show 4× to 6× more requests\u002Fsecond compared to PHP-FPM 8.3. FrankenPHP, the recommended Octane driver since Laravel 11, embeds the HTTP server directly in the PHP binary — no nginx in front needed. On a VPS with root access, Docker Compose and Traefik, the migration is clean and reproducible.",[34,38,49,52,83,86,97,131,135,138],{"type":35,"title":36,"body":37},"h2","PHP-FPM vs Laravel Octane — what really changes","PHP-FPM follows the \"shared nothing\" model: every request loads the framework from scratch, executes the code, and frees all memory. It is robust by design — a leak in one request dies with it. Octane breaks this contract. The application is bootstrapped once, then requests flow through the same process. The performance gain is massive, but developer responsibility increases.",{"type":39,"title":40,"items":41},"ul","Six structural differences to understand",[42,43,44,45,46,47,48],"**Shared lifecycle** — Laravel's IoC container, providers and singletons are instantiated once and persist across all requests of a worker. A value written to a singleton in request N is still there in request N+1.","**Documented performance gain** — official Laravel Octane documentation benchmarks show 4× to 6× more requests\u002Fsecond versus PHP-FPM 8.3 on typical endpoints, by eliminating PHP bootstrap on every request.","**Static variables = guaranteed leaks** — any `static` property written during a request pollutes subsequent ones. Laravel Facades hide static references; some are cleaned by Octane, others are not.","**Static files served by FrankenPHP** — the binary includes a full HTTP server. On a VPS, no nginx in front of PHP is needed: FrankenPHP handles TLS, HTTP\u002F2 and HTTP\u002F3 natively, but behind Traefik it only receives plain HTTP on the internal Docker network.","**Stable RSS memory ≠ leaked memory** — process memory rises at startup (framework loading) then stabilizes. A real leak shows as continuous growth over thousands of requests, not the initial level.","**Workers and concurrency** — Octane starts `--workers=N` processes (FrankenPHP uses Zend Engine threads). Each worker keeps its own state; no shared memory between workers, but a single worker processes its requests sequentially.","**Laravel 10 and 11 compatibility** — Octane 2.x supports Laravel 10+. FrankenPHP as a driver is available since `laravel\u002Foctane` 2.3. PHP 8.2 minimum, PHP 8.3 recommended.",{"type":35,"title":50,"body":51},"Prerequisites before starting","A VPS with **at least 2 GB RAM** (4 GB recommended for a full stack with Redis and queue workers), root access, Docker 25+ and Docker Compose v2. The application must run on **Laravel 10 or 11**, with `laravel\u002Foctane` 2.x installed (`composer require laravel\u002Foctane`). Traefik 3.x will manage Let's Encrypt certificates and HTTPS routing. No additional nginx is needed: FrankenPHP entirely replaces the HTTP layer.",{"type":53,"title":54,"steps":55},"steps","Deploy Laravel Octane + FrankenPHP + Traefik in Docker Compose",[56,59,62,65,68,71,74,77,80],{"title":57,"body":58},"Install laravel\u002Foctane and publish the configuration","In your Laravel project:\n\n```bash\ncomposer require laravel\u002Foctane\nphp artisan octane:install --server=frankenphp\n```\n\nThis publishes `config\u002Foctane.php` and adds environment variables to `.env.example`. Verify that `OCTANE_SERVER=frankenphp` is set.",{"title":60,"body":61},"Write the FrankenPHP Dockerfile","```dockerfile\nFROM dunglas\u002Ffrankenphp:1-php8.3-alpine\n\nRUN install-php-extensions \\\n    pdo_mysql \\\n    redis \\\n    opcache \\\n    pcntl \\\n    zip \\\n    intl\n\nWORKDIR \u002Fapp\n\nCOPY --chown=www-data:www-data . .\n\nRUN composer install --no-dev --optimize-autoloader --no-interaction \\\n && php artisan config:cache \\\n && php artisan route:cache \\\n && php artisan view:cache\n\nEXPOSE 8000\n\nCMD [\"php\", \"artisan\", \"octane:frankenphp\", \"--host=0.0.0.0\", \"--port=8000\", \"--workers=4\", \"--max-requests=500\"]\n```\n\nThe `--max-requests=500` option restarts a worker after 500 requests: a safety net against residual memory leaks. Reduce to 100 while testing, then increase if memory remains stable.",{"title":63,"body":64},"Write the complete docker-compose.yml","```yaml\nservices:\n  app:\n    build: .\n    restart: unless-stopped\n    environment:\n      APP_ENV: production\n      APP_KEY: ${APP_KEY}\n      DB_CONNECTION: mysql\n      DB_HOST: db\n      DB_DATABASE: ${DB_DATABASE}\n      DB_USERNAME: ${DB_USERNAME}\n      DB_PASSWORD: ${DB_PASSWORD}\n      REDIS_HOST: redis\n      CACHE_DRIVER: redis\n      SESSION_DRIVER: redis\n      QUEUE_CONNECTION: redis\n      OCTANE_SERVER: frankenphp\n    networks:\n      - internal\n      - traefik\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.app.rule=Host(`${DOMAIN}`)\"\n      - \"traefik.http.routers.app.entrypoints=websecure\"\n      - \"traefik.http.routers.app.tls.certresolver=letsencrypt\"\n      - \"traefik.http.services.app.loadbalancer.server.port=8000\"\n    depends_on:\n      db:\n        condition: service_healthy\n      redis:\n        condition: service_healthy\n\n  worker:\n    build: .\n    restart: unless-stopped\n    command: [\"php\", \"artisan\", \"queue:work\", \"redis\", \"--sleep=3\", \"--tries=3\", \"--max-time=3600\"]\n    environment:\n      APP_ENV: production\n      APP_KEY: ${APP_KEY}\n      DB_HOST: db\n      DB_DATABASE: ${DB_DATABASE}\n      DB_USERNAME: ${DB_USERNAME}\n      DB_PASSWORD: ${DB_PASSWORD}\n      REDIS_HOST: redis\n      QUEUE_CONNECTION: redis\n    networks:\n      - internal\n    depends_on:\n      db:\n        condition: service_healthy\n      redis:\n        condition: service_healthy\n\n  scheduler:\n    build: .\n    restart: unless-stopped\n    command: [\"sh\", \"-c\", \"while true; do php artisan schedule:run >> \u002Fdev\u002Fnull 2>&1; sleep 60; done\"]\n    environment:\n      APP_ENV: production\n      APP_KEY: ${APP_KEY}\n      DB_HOST: db\n      DB_DATABASE: ${DB_DATABASE}\n      DB_USERNAME: ${DB_USERNAME}\n      DB_PASSWORD: ${DB_PASSWORD}\n      REDIS_HOST: redis\n    networks:\n      - internal\n    depends_on:\n      db:\n        condition: service_healthy\n\n  db:\n    image: mysql:8.0\n    restart: unless-stopped\n    environment:\n      MYSQL_DATABASE: ${DB_DATABASE}\n      MYSQL_USER: ${DB_USERNAME}\n      MYSQL_PASSWORD: ${DB_PASSWORD}\n      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}\n    volumes:\n      - db_data:\u002Fvar\u002Flib\u002Fmysql\n    networks:\n      - internal\n    healthcheck:\n      test: [\"CMD\", \"mysqladmin\", \"ping\", \"-h\", \"localhost\"]\n      interval: 10s\n      timeout: 5s\n      retries: 5\n\n  redis:\n    image: redis:7-alpine\n    restart: unless-stopped\n    volumes:\n      - redis_data:\u002Fdata\n    networks:\n      - internal\n    healthcheck:\n      test: [\"CMD\", \"redis-cli\", \"ping\"]\n      interval: 10s\n      timeout: 3s\n      retries: 5\n\nvolumes:\n  db_data:\n  redis_data:\n\nnetworks:\n  internal:\n  traefik:\n    external: true\n```",{"title":66,"body":67},"Deploy Traefik with automatic certificates","Create a shared Docker network then start Traefik:\n\n```bash\ndocker network create traefik\n```\n\n`traefik.yml`:\n\n```yaml\nentryPoints:\n  web:\n    address: \":80\"\n    http:\n      redirections:\n        entryPoint:\n          to: websecure\n          scheme: https\n  websecure:\n    address: \":443\"\n\ncertificatesResolvers:\n  letsencrypt:\n    acme:\n      email: admin@example.com\n      storage: \u002Fletsencrypt\u002Facme.json\n      httpChallenge:\n        entryPoint: web\n\nproviders:\n  docker:\n    exposedByDefault: false\n    network: traefik\n\napi:\n  dashboard: false\n```\n\n```bash\nmkdir -p \u002Fopt\u002Ftraefik\u002Fletsencrypt\ntouch \u002Fopt\u002Ftraefik\u002Fletsencrypt\u002Facme.json\nchmod 600 \u002Fopt\u002Ftraefik\u002Fletsencrypt\u002Facme.json\ndocker compose -f \u002Fopt\u002Ftraefik\u002Fdocker-compose.yml up -d\n```",{"title":69,"body":70},"Prepare the production .env file","Critical variables to set on the VPS:\n\n```bash\nAPP_ENV=production\nAPP_DEBUG=false\nAPP_KEY=base64:...  # generated with php artisan key:generate\nDOMAIN=your-domain.com\nDB_DATABASE=laravel\nDB_USERNAME=laravel\nDB_PASSWORD=strong_password\nDB_ROOT_PASSWORD=root_strong_password\nOCTANE_SERVER=frankenphp\nCACHE_DRIVER=redis\nSESSION_DRIVER=redis\nQUEUE_CONNECTION=redis\n```\n\nNever commit `.env` to git. On the VPS, manage it with `scp` or a secret manager.",{"title":72,"body":73},"Run migrations without downtime","Before switching to the new version, run migrations from an ephemeral container sharing the internal network:\n\n```bash\ndocker compose run --rm app php artisan migrate --force\n```\n\nFor zero-downtime deployment, use the `--step` flag on migrations that add NOT NULL columns — first add the column as nullable, deploy the app, then add the constraint in a second migration.",{"title":75,"body":76},"Start the stack and verify the healthcheck","```bash\ndocker compose up -d --build\ndocker compose ps\n```\n\nWait for `db` and `redis` to reach `healthy` status before `app` starts (managed by `depends_on: condition: service_healthy`).\n\nCheck Octane logs:\n\n```bash\ndocker compose logs -f app\n```\n\nNormal output looks like:\n```\nINFO  Server running on http:\u002F\u002F0.0.0.0:8000\nINFO  FrankenPHP workers: 4\n```",{"title":78,"body":79},"Check status with octane:status","```bash\ndocker compose exec app php artisan octane:status\n```\n\nThis command shows the active server (frankenphp), the number of running workers and global status. A `running` response confirms workers are responding. If stuck, `octane:reload` restarts workers without shutting down the server.",{"title":81,"body":82},"Configure hot-reload for deployments","When deploying a new version, rebuild and reload without downtime:\n\n```bash\ndocker compose build app worker scheduler\ndocker compose up -d --no-deps app worker scheduler\n```\n\nWith the Dockerfile in place, this sequence replaces containers one by one. For Octane, the reload signal (SIGUSR1) reloads workers without dropping active connections. Docker Compose handles signal delivery automatically via `restart: unless-stopped`.",{"type":35,"title":84,"body":85},"Compatibility checklist before switching to production","Migrating to Octane does not require rewriting the application, but a few common patterns break silently. Go through this checklist on your code before the first deployment.",{"type":39,"title":87,"items":88},"8 points to check carefully",[89,90,91,92,93,94,95,96],"**Singletons with mutable state** — any service registered with `$this->app->singleton()` that stores request-specific data (current user, locale, tenant ID) must be reset in an `OctaneServiceProvider` via `Octane::tick()` or by implementing a `RequestReceived` listener. Audit: `grep -r 'singleton' app\u002FProviders`.","**Sessions** — with `SESSION_DRIVER=redis`, sessions correctly survive between requests. The `file` driver can create race conditions if multiple workers write simultaneously. Migrate to `redis` or `database` before switching to Octane.","**Database connections** — Octane maintains persistent DB connections per worker. Configure `DB_POOL_MIN` and `DB_POOL_MAX` in `config\u002Fdatabase.php` if using a custom pool. Verify that MySQL accepts `max_connections ≥ workers × replicas`.","**Static variables in models or services** — `static $cache = []` in an Eloquent model or repository persists between requests. Replace with request-scoped dependency injection, or explicitly clear in the `RequestTerminated` listener.","**Non-idempotent event listeners** — a listener registered in a ServiceProvider's `boot()` is only registered once, but fires on every request that triggers the event. No problem by itself, unless the listener accumulates global state (counter, static array).","**Jobs and queues** — Jobs do not run in the main Octane process but in the separate `worker` container. They retain the classic PHP-FPM lifecycle. No adaptations needed for Job code itself.","**Uploaded files and storage** — `Storage::disk('local')` works normally. Watch `storage_path()` in a Docker container: mount a volume for `\u002Fapp\u002Fstorage` so files persist between image rebuilds.","**Third-party packages** — some Laravel packages (Debugbar, Telescope) inject middlewares that accumulate data in memory. Disable them in production with `APP_ENV=production` or via conditions in `config\u002Fdebugbar.php`. Check Octane compatibility on each package's repository.",{"type":98,"title":99,"headers":100,"rows":105},"comparison","FrankenPHP vs Swoole vs RoadRunner: choosing your Octane driver",[101,102,103,104],"Criterion","FrankenPHP","Swoole","RoadRunner",[106,111,116,121,126],[107,108,109,110],"Installation","Official Docker image `dunglas\u002Ffrankenphp` — no PECL extension to compile","PECL extension `swoole` — requires `pecl install swoole` or a custom image","Separate Go binary (`roadrunner`) — downloaded via Composer (`spiral\u002Froadrunner`)",[112,113,114,115],"HTTP\u002F2 and HTTP\u002F3","Native — FrankenPHP is built on Caddy which supports HTTP\u002F3 (QUIC) out of the box","HTTP\u002F2 supported, HTTP\u002F3 not native","HTTP\u002F2 via plugin, HTTP\u002F3 not natively supported",[117,118,119,120],"PHP extension compatibility","Very broad — based on official PHP-FPM, most extensions install normally","Known incompatibilities with some blocking extensions (e.g. ext-curl in certain modes)","Broad, but some complex PECL extensions may need adaptations",[122,123,124,125],"Official Laravel recommendation","Recommended driver since Laravel 11 (2024), listed first in the Octane documentation","First historical driver, still supported but less prominent","Supported, alternative to Swoole, common in Symfony\u002FSpiral ecosystems",[127,128,129,130],"Ops complexity","Low — single container, minimal Dockerfile, no separate daemon","Medium — the swoole extension must be compiled with the right PHP version","Medium — the RoadRunner binary must be synchronized with the Composer package version",{"type":132,"title":133,"body":134},"tip","Monitor Octane in production with octane:status","The `php artisan octane:status` command queries the FrankenPHP server in real time and shows the number of active workers, workers currently handling a request, and global status (`running` \u002F `stopped`). Integrate it in your monitoring:\n\n```bash\n# Simple check in a health-check script\ndocker compose exec -T app php artisan octane:status | grep -q 'running' && echo OK || echo FAIL\n```\n\nTo reload workers without dropping traffic (after a `git pull` without image rebuild):\n\n```bash\ndocker compose exec app php artisan octane:reload\n```\n\nTrack the RSS memory of the main process over time: continuous growth after thousands of requests signals a leak. The `docker stats app` command gives real-time memory; cross with `--max-requests=N` to force preventive recycling.",{"type":35,"title":136,"body":137},"Troubleshooting: common production errors","**Progressive memory leak**: the `app` container memory grows without ever decreasing. Likely cause: a singleton accumulates data per request. Audit with `php artisan octane:status` over several thousand requests. Reduce `--max-requests` to 100 while identifying the source with Laravel Telescope (in staging) or a profiler like Blackfire.\n\n**502 Bad Gateway Traefik**: Traefik can no longer reach the `app` container on port 8000. Check the container is on the `traefik` network (`docker inspect app | jq '.[0].NetworkSettings.Networks'`), that the label `traefik.http.services.app.loadbalancer.server.port=8000` matches the exposed port, and the container is `healthy` (`docker compose ps`). A 502 at startup is often a missing `depends_on` toward the `db` container.\n\n**Worker restarting in a loop**: Octane kills and recreates a worker if it stops responding within the configured timeout. Look for `FATAL` in `docker compose logs app`. Most common cause: an unexecuted migration that raises a `QueryException` during bootstrap. Run `docker compose run --rm app php artisan migrate --force` before starting the stack.\n\n**Sessions lost between requests**: `SESSION_DRIVER=file` with multiple workers can cause reads on a file being written. Switch to `SESSION_DRIVER=redis` — the `redis` container is already in the `docker-compose.yml` above.\n\n**Wrong timezone or locale**: in an Alpine container, the default timezone is UTC. Add `APP_TIMEZONE=Europe\u002FParis` (or your timezone) in `.env` and `RUN apk add --no-cache tzdata` in the Dockerfile if system extensions read `\u002Fetc\u002Flocaltime`.",{"type":35,"title":139,"body":140},"Going further","You now have a working Laravel Octane stack on VPS. The following articles cover the natural next steps: [Deploy Laravel on a VPS](\u002Fblog\u002Fdeployer-laravel-vps) covers the base setup without Octane. [Deploy with Traefik](\u002Fblog\u002Fdeployer-avec-traefik) deepens reverse proxy configuration (middlewares, rate-limiting, secured dashboard). [Docker Compose production checklist](\u002Fblog\u002Fdocker-compose-production-checklist) lists 15 points to check before considering a Compose production-ready. [Host Redis on VPS](\u002Fblog\u002Fheberger-redis-vps) details Redis persistence, authentication and memory limits. [PHP migration checklist](\u002Fblog\u002Fphp-82-fin-de-vie-checklist-migration) is required reading if your application still runs on PHP 8.2.","View ServOrbit VPS plans","\u002Fvps-cloud",[144,161,180,196,220],{"id":145,"slug":146,"slugs":147,"title":151,"excerpt":152,"readTime":22,"views":17,"isPinned":18,"publishedAt":153,"updatedAt":154,"category":155,"categories":156,"featuredImage":29,"bgImage":30,"posterImage":158,"relatedSolution":159},5,"deploying-laravel-on-a-vps-a-production-guide",{"fr":148,"en":146,"ar":149,"es":150},"deployer-laravel-vps","نشر-laravel-على-خادم-vps-دليل-الإنتاج","desplegar-laravel-en-un-vps","Deploying Laravel on a VPS: a production guide","Take Laravel to production on a VPS: PHP, workers, cache, database, reverse proxy and HTTPS configured cleanly.","2026-02-09T00:00:00+00:00","2026-09-07T11:26:10+00:00",{"id":22,"name":23,"slug":24,"color":25,"icon":26},[157],{"id":22,"name":23,"slug":24,"color":25,"icon":26},"\u002Fblog\u002Fcovers\u002Fdeployer-laravel-vps-poster.svg",{"categorySlug":26,"appSlug":160},"laravel-stack",{"id":162,"slug":163,"slugs":164,"title":168,"excerpt":169,"readTime":170,"views":171,"isPinned":18,"publishedAt":172,"updatedAt":154,"category":173,"categories":177,"featuredImage":29,"bgImage":30,"posterImage":179,"relatedSolution":29},38,"deploy-your-applications-with-traefik-on-a-vps",{"fr":165,"en":163,"ar":166,"es":167},"deployer-avec-traefik","انشر-تطبيقاتك-باستخدام-traefik-على-خادم-vps","desplegar-con-traefik","Deploy your applications with Traefik on a VPS","Deploy Traefik as a reverse proxy on your VPS: automatic routing of Docker containers, Let's Encrypt SSL certificates and load balancing.",3,2,"2026-05-13T00:00:00+00:00",{"id":170,"name":174,"slug":175,"color":176,"icon":175},"Deployment","deploiement","bg-success\u002F10 text-success",[178],{"id":170,"name":174,"slug":175,"color":176,"icon":175},"\u002Fblog\u002Fcovers\u002Fdeployer-avec-traefik-poster.svg",{"id":181,"slug":182,"slugs":183,"title":187,"excerpt":188,"readTime":189,"views":17,"isPinned":18,"publishedAt":190,"updatedAt":191,"category":192,"categories":193,"featuredImage":29,"bgImage":30,"posterImage":195,"relatedSolution":29},229,"docker-compose-in-production-10-point-checklist",{"fr":184,"en":182,"ar":185,"es":186},"docker-compose-production-checklist","docker-compose-في-الإنتاج-قائمة-التحقق-من-10-نقاط","checklist-docker-compose-en-produccion","Docker Compose in Production: 10-Point Checklist","Docker Compose production checklist: 10 essential settings, health checks, secrets without downtime, rollback strategy, common error troubleshooting, CVE-2026-17106.",12,"2026-08-06T00:00:00+00:00","2026-09-29T14:40:45+00:00",{"id":170,"name":174,"slug":175,"color":176,"icon":175},[194],{"id":170,"name":174,"slug":175,"color":176,"icon":175},"\u002Fblog\u002Fcovers\u002Fdocker-compose-production-checklist-poster.svg",{"id":197,"slug":198,"slugs":199,"title":203,"excerpt":204,"readTime":205,"views":17,"isPinned":18,"publishedAt":206,"updatedAt":207,"category":208,"categories":214,"featuredImage":29,"bgImage":30,"posterImage":216,"relatedSolution":217},58,"hosting-redis-on-a-vps",{"fr":200,"en":198,"ar":201,"es":202},"heberger-redis-vps","استضافة-redis-على-خادم-vps","alojar-redis-en-un-vps","Hosting Redis on a VPS: the complete guide","Deploy Redis on your Cloud VPS: RAM\u002FCPU requirements, security (ACL, TLS), RDB\u002FAOF persistence, troubleshooting, and high availability.",10,"2026-04-23T00:00:00+00:00","2026-09-08T21:59:59+00:00",{"id":209,"name":210,"slug":211,"color":212,"icon":213},6,"Databases","bases-de-donnees","bg-teal-500\u002F10 text-teal-400","database",[215],{"id":209,"name":210,"slug":211,"color":212,"icon":213},"\u002Fblog\u002Fcovers\u002Fheberger-redis-vps-poster.svg",{"categorySlug":218,"appSlug":219},"databases","redis-stack",{"id":221,"slug":222,"slugs":223,"title":227,"excerpt":228,"readTime":16,"views":171,"isPinned":18,"publishedAt":229,"updatedAt":154,"category":230,"categories":231,"featuredImage":29,"bgImage":30,"posterImage":233,"relatedSolution":29},206,"php-82-end-of-life-planning-your-migration",{"fr":224,"en":222,"ar":225,"es":226},"php-82-fin-de-vie-checklist-migration","نهاية-دعم-php-82-دليل-الترحيل","php-82-fin-de-vida-planificar-la-migracion","PHP 8.2 end of life: your migration checklist","PHP 8.2 reaches EOL on December 31, 2026. Inventory your stack, compare PHP versions, and follow a step-by-step migration checklist to PHP 8.3 or 8.4.","2026-08-01T00:00:00+00:00",{"id":22,"name":23,"slug":24,"color":25,"icon":26},[232],{"id":22,"name":23,"slug":24,"color":25,"icon":26},"\u002Fblog\u002Fcovers\u002Fphp-82-fin-de-vie-checklist-migration-poster.svg",1791901029450]