Skip to content

Caching

The library can pre-compile the Edm schema and resolver bindings into PHP classes so that ODataService::schema() skips EdmBuilder, model discovery, and database introspection on warm boot. This is an opcache-friendly optimization for production.

Development-only commands

Both odata:cache and odata:clear are restricted to development environments. They refuse to run in production or staging and exit with an error. The generated Edm/ directory is committed to version control and deployed as-is — no cache commands are run during deployment.

Why?

  • The generated Edm classes depend on the schema at the time of generation. Running odata:cache in production could produce classes inconsistent with the deployed code if the database schema or model code has changed.
  • The cold path requires database access (for Schema::getColumns() during discovery). Production servers should never hit the cold path — the committed cache ensures deterministic startup.
  • Treating the Edm cache like compiled assets (generated locally, committed, deployed) is the safest approach.

Workflow:

  1. Develop and test on local machine (cold path, no cache)
  2. When ready to deploy: php artisan odata:cache
  3. Commit the generated Edm/ directory
  4. Deploy — the warm path loads instantly with no database access

odata:cache

bash
php artisan odata:cache

For each service returned by the registry's services() method:

  1. Builds the EdmxInterface via configure() and model discovery
  2. Builds the ResolverMap via registerBindings() and auto-discovered bindings
  3. Uses EdmxWriter and ResolverMapWriter to generate PHP classes
  4. Writes them to an Edm/ directory next to the service class file

For a service at app/OData/TimesheetService.php, the generated files are placed at:

app/OData/
├── TimesheetService.php
└── Edm/
    ├── Edmx.php            ← cached schema structure
    ├── ResolverMap.php      ← cached resolver bindings
    ├── Types/
    │   ├── User.php
    │   ├── Project.php
    │   └── ...
    └── Entities/
        ├── Users.php
        ├── Projects.php
        └── ...

odata:clear

bash
php artisan odata:clear

Deletes the generated Edm/ directory for each registered service.

Warm boot path

On each request, ODataService::schema() checks for cached classes first:

1. EdmxLoader::forService()        → load cached Edmx
2. ResolverMapLoader::forService()  → load cached ResolverMap
3. If both found → warm path:
   a. resolverMap.applyTo(runtimeBuilder)  → create + bind resolvers
   b. bindFunctions(runtimeBuilder)        → functions + singletons
   c. build() → done
4. If not found → cold path:
   a. configure() + discovery + build Edmx
   b. registerBindings() + discovery → build ResolverMap
   c. resolverMap.applyTo(runtimeBuilder)
   d. bindFunctions(runtimeBuilder)
   e. build() → done

The warm path requires no configure(), no Schema::getColumns(), no reflection, and no database access. Both the Edmx and ResolverMap are plain PHP object graphs, autoloaded via PSR-4 alongside the service class and eligible for opcache preloading.

What is cached and what is not

Cached (Edmx + ResolverMap)Not cached (runs every boot)
Entity types, complex types, enum typesFunction/singleton resolvers (bindFunctions())
Properties, navigation propertiesDatabase connections
Entity sets, singletons, function importsEntitySetSource dependency injection
AnnotationsCustomBinding container resolution
Schema structure
Resolver bindings (Eloquent, Custom, SQL, SqlSource)

Function and singleton resolvers run on every boot via bindFunctions(). Entity set resolver bindings are serialized in the ResolverMap and restored on warm boot without re-running configure() or registerBindings().

For CustomBinding entries, the resolver class is resolved from the Laravel container at runtime, so injected dependencies are always fresh. For SqlSourceBinding entries, the EntitySetSourceInterface class is likewise resolved from the container.

When to cache

  • Development: Do not cache. The schema is rebuilt on each request, reflecting code changes immediately.
  • Before deployment: Run odata:cache on your development machine, commit the Edm/ directory, deploy.
  • After schema changes: Run odata:clear then odata:cache, commit the updated Edm/ directory.
  • Production/staging: Never run odata:cache or odata:clear. The commands refuse to execute in these environments.

OData: MIT | Core: BSL 1.1 | SDK: Commercial License