Clean Framework · DOCUMENTATION
PHP 8.5 migration and compatibility acceptance
PHP 8.5 migration and compatibility acceptance
Bounded candidate reference — 2026-10-20: 0.2.0-rc.1 is committed locally through 84f415b3098af5653577b2c65eea31fca21df79c, unpublished and not production-approved; stable PHP >=8.5.11 <8.6.0 is required. This is documentation, not adoption: this knowledge base retains its installed 0.1.0-rc.1 dependency and PHP 8.2.11 local profile. Dated PHP 8.2 evidence is historical; earlier dirty-source reports retain their original test provenance, not retroactive clean-commit proof. Candidate examples are illustrative: API signatures were reviewed, but candidate code was not executed by this editorial update. See current checkpoint, open criteria and adoption boundary.
Updated 2026-10-16. Unpublished candidate 0.2.0-rc.1; scoped local PHP 8.5 verification and Apache/FPM acceptance pass. Full program/host release is open. PHP >=8.5.11 <8.6.0 is the new installation/boot requirement.
Current stabilization update2026-10-17: saved source5af3471 retains actual PHP8.5.11/Apache2.4.68-FPM/MySQL8.4.11 local evidence. The owner approved six legacy exceptions with exact archived originals; three selected-model tests plus24 constructor checks pass. See current BC/adoption/rollback checklist. No consuming application upgraded. Older baseline/provisioning discussion below is historical, not permission to reinstall a runtime or choose a rollback target.
What changed
- Four package manifests and dependency-free root lock use the same constraint.
- RuntimeRequirements enforces stable releases with IDs 80511 through 80599; config/runtime.php remains a pure check, with no application composition.
- cURL and GD cleanup now releases object references rather than calling the resource-era close functions deprecated by PHP 8.5. The Apache fixture also drops closures capturing handles. No request/TLS/size policy was relaxed.
- Tests treat runtime deprecations as failures. A separate offline token check rejects the targeted deprecated function calls and noncanonical casts.
- Apache defaults to an isolated FPM profile, explicitly checks actual handler binary and SAPI, and retains method/private-file/TLS/session/error probes.
- Six bridge constructors needed explicit
?callableinstead of implicit nullablecallable. The deliberate fix retains default/null/callable/rejected invalid-value behavior and lazy injection. Original hashes are recorded in the manifest alongside current hashes; 24 focused checks pass. No bridge business logic, queries or provider behavior was changed or certified.
Migration review and remaining proof
| Migration concern | Source inspection / disposition | Still required |
|---|---|---|
| 8.3 process/exit and date failures | Owned process helpers use explicit status/exit integers; no broad process rewrite | Actual 8.5 process/failure runs; inspect every observed warning |
| 8.4 implicit nullable parameters | Neutral APIs normally use explicit nullable types; token gate is NOT a full signature analyzer | Compile all sources and legacy bridge on actual 8.5; review any deprecation |
| mysqli reconnect/ping and constructor changes | Neutral health uses SELECT 1; fresh mysqli allocation; no neutral ping/kill/refresh alias found | Real supported DB/connection-loss/type/transaction proof |
| 8.5 close APIs/casts | Neutral cURL/GD calls repaired; targeted token scan covers neutral executable surfaces | Real extension execution and negative source-gate cases |
| fileinfo and extension failure categories | Input paths/types stay bounded; no blanket change to exception semantics | Actual 8.5 invalid/hostile-input and extension cases |
| native typed constants, serialization, numeric conversions | No new language syntax or automatic legacy modernization | Full target-runtime compile/runtime review; scanner is not proof of absence |
| output buffering / OPcache | Native views and existing cleanup boundaries preserved | Target-runtime buffers, OPcache/INI and safe HTTP error checks |
Official migration references: 8.3 incompatibilities, 8.4 incompatibilities, 8.4 deprecations, 8.5 incompatibilities, 8.5 deprecations. This focused review is supplemented by actual 8.5.11 E_ALL compilation, deterministic/portability and Apache/FPM tests. It is not certification of all legacy business behavior or every PHP incompatibility. See the current runtime/integration checkpoint.
Reproduce on the current old host
# Pure checks, no Composer/application boot, no DB connection.
php tests/runtime_policy.php
php tests/php85_source_review.php
php tests/disposable_database_policy.php
php bin/platform-inventory
# Expected nonzero on unsupported PHP 8.2: do not suppress it.
php bin/platform-check
composer test
composer verifyNo guard override is supplied. A green policy/source scan does not establish L1 development readiness. The platform failure is a missing required runtime, not a reason to run application tests with a home-made autoloader bypass.
Exact isolated-runtime prerequisites and commands
An operator must supply approved local absolute paths to PHP CLI 8.5.11+, matching FPM, Apache/modules and OpenSSL, plus the required json/fileinfo extensions and optional mysqli/curl/sodium/gd/pcntl for enabled checks. A current-patch supported OS/Apache profile remains separately qualified. Do not replace /usr/local/bin/php, start installed services, download an image or repoint a consuming application as part of this runbook.
After those paths and resource scope are approved, prepend the isolated PHP bin directory to PATH (without changing a system symlink) so Composer scripts and subprocesses use the same approved CLI. Run from the framework root:
php -v
php bin/platform-inventory
composer validate --strict --no-check-publish
composer test
composer verify
php tests/apache_compatibility.php --handler=fpm
# Only if independently supplied/approved, not inferred from FPM:
php tests/apache_compatibility.php --handler=moduleThe Apache harness accepts CLEAN_PHP_FPM_BIN, CLEAN_APACHE_BIN, CLEAN_APACHE_MODULES, CLEAN_OPENSSL_BIN and optional CLEAN_PHP_MODULE as explicit local paths. Record the actual handler/pool binary, extensions, OS, stderr, counts and cleanup. Do not reuse the old 200-assertion result as 8.5 evidence; new binary-identity assertions change counts. Do not run the DB test until the disposable target prerequisites are independently met.
Lock maintenance and recovery
Approved isolated provisioning boundary
The owner subsequently approved this reviewed setup and downloads. Official PHP 8.5.11 FPM, Composer 2.10.3 and MySQL 8.4.11 images were pinned by digest; a source-free tooling image adds Apache 2.4.68 and required extensions. Actual tests now run without changing host services, consumer dependencies or apps. See tooling and the current checkpoint for exact image identities, reproducible commands and cleanup. The proposal below records its original limits; it is not continuing permission for arbitrary new infrastructure, providers or deployments.
Read-only inventory confirmed Docker daemon 24.0.5 through its explicit local Unix socket after an initial sandbox denial. No cached named PHP 8.5 image or known Homebrew/MAMP/Herd/MacPorts PHP 8.5 executable was found. Do not pull/build an image merely because Docker is reachable.
Proposed next resource scope: a disposable non-root PHP 8.5.11+ CLI/FPM plus Apache test image and a separately owned supported SQL fixture with synthetic TEST-only account/schemas. Review exact official image/build sources, pinned digests, dependencies, licenses and resource limits before any download. Do not switch installed host PHP, Apache or existing application runtimes. Use only an explicit sanitized framework source snapshot, no populated .env, existing vendor/runtime/backup data, user home, Docker socket inside a workload, other application mounts or host-service configuration. Limit test networking to loopback/owned internal fixtures, providers off; track owned IDs and bounded cleanup. No database volume or real credential may be borrowed. The owner must approve downloads/builds, disposable runtime and TEST identity provisioning before implementation. This proposal is not an install/deploy command.
Metadata maintenance and recovery reference
The root lock has no packages/dependencies. It was regenerated locally using COMPOSER_DISABLE_NETWORK=1 and composer update --lock --no-install --no-scripts --no-plugins --ignore-platform-req=php. The ignore flag was used ONLY for metadata generation under the old CLI, never to install, boot or qualify the candidate. No vendor tree or consumer lock was regenerated. A first attempt to load Composer's internal PHAR API was unavailable and made no source change; the supported offline lock command above succeeded instead.
Baseline commit 0d50335 is the committed recovery reference, but it does not contain all later owner changes. The dirty-tree evidence records those hashes. Do not git reset or overwrite them. Before a real consumer upgrade, preserve its complete approved artifact/configuration and an operator-verified matched backup. Restore an approved prior artifact under its matching runtime only; code rollback is not a database down migration. No actual restore, new supported release or consumer upgrade is claimed here.
Editorial provenance
Source: docs/PHP_85_MIGRATION.md. Source SHA-256: fe323fca836b4b5dc6e5b86a423adfaf8295e60dfc78694baf554fa3bc2a6032.
Framework candidate reference; editorial checkpoint 2026-10-20. See candidate status and adoption boundary.