feat(laravel): boot without a database via dumped metadata#8290
Open
soyuka wants to merge 1 commit into
Open
Conversation
d3dee6c to
602b7eb
Compare
API Platform reads Eloquent model metadata from the live database schema while building resource metadata. That build runs at boot (route registration iterates every resource), so the app cannot boot when no migrated database is reachable — breaking Docker image builds, `composer install` (package:discover) and static analysis in CI. Add `api-platform:metadata:dump`, which computes every resource's ResourceMetadataCollection with the database up and serializes the map to a file. A new DumpedResourceCollectionMetadataFactory is wired as the outermost resource metadata factory: when a dump file is configured it serves metadata from the file and short-circuits the database-reading factories. The decorator is skipped when APP_DEBUG is true so local development always recomputes fresh metadata. The dump file can be committed to the repository or baked into a Docker image, letting the app boot with no database connection. Refs api-platform#8131
602b7eb to
62b74ce
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
To expose an Eloquent model, API Platform reads its metadata (columns, types, relations, identifiers) from the live database schema (
ModelMetadata::getColumns()). That introspection runs while theResourceMetadataCollectionis built, and that build happens at boot:src/Laravel/routes/api.phpiterates every resource to register routes.So the app cannot boot when no migrated database is reachable. This breaks common cacheless boots:
docker build(DB service not running);composer install→@php artisan package:discover;The existing metadata cache only short-circuits the DB read if it was already warmed — and warming needs a boot with the DB up; the configured store may also be redis/memcached (unavailable at build, not committable).
Refs #8131.
Solution
Let users pre-compute the resource metadata once, with the DB up, dump it to a single file that can be committed to git or baked into a Docker image, and serve metadata from that file at boot — bypassing the DB.
api-platform:metadata:dump {--path=}— resolves the path from--pathor theapi-platform.metadata_dumpconfig, iteratesResourceNameCollectionFactoryInterface, builds eachResourceMetadataCollection(this is the step that hits the DB — run it with the DB up), and serializes thearray<class-string, ResourceMetadataCollection>map to the file. It unwraps any activeDumpedResourceCollectionMetadataFactoryso it always rebuilds from the live source, never from a stale dump.DumpedResourceCollectionMetadataFactory— decorator that loads the dumped map once and returns the dumped collection for known classes, delegating otherwise. Wired as the outermost resource metadata factory, so a dump hit short-circuits before the cache/Eloquent/DB factories are touched. Skipped whenAPP_DEBUGis true so local dev always recomputes fresh metadata (mirrors the existingarraycache choice).api-platform.metadata_dumpdefaults tonull(feature disabled); the user explicitly chooses a VCS/image-committable path.Only the
ResourceMetadataCollectionis dumped: the boot-time DB hit happens entirely inside its build, so serving it from the file means the nested factories are never invoked at boot. Per-request paths still use the normal factories (DB available at request time).Design notes
->extend()inApiPlatformProvider::register()(after the Parameter/ObjectMapper extends) so it sits above the always-appliedParameterResourceMetadataCollectionFactory— genuinely outermost.ResourceMetadataCollectionis already serialized into the cache store byCacheResourceCollectionMetadataFactorytoday, so the object graph is serializable; the dump reuses that.Tests
New tests (run without a database):
Tests/Unit/Metadata/DumpedResourceCollectionMetadataFactoryTest.phpTests/Console/DumpMetadataCommandTest.php(includes re-dump-over-stale)Tests/Metadata/DumpedMetadataBootTest.php(boots with a dump file +app.debug=false, asserts the dumped decorator serves metadata without DB introspection; asserts it is skipped whenapp.debug=true)php-cs-fixer dry-run on changed files: 0 issues.
Follow-up
Docs for the workaround/command: api-platform/docs#2294.