Skip to content

Refactor service initialization and request lifecycle - #956

Merged
giuscris merged 5 commits into
2.xfrom
refactor/service-initializaition-and-request-lifecycle
Sep 26, 2026
Merged

giuscris merged 5 commits into
2.xfrom
refactor/service-initializaition-and-request-lifecycle

Conversation

@giuscris

Copy link
Copy Markdown
Member

Summary

This pull request refactors Formwork's service initialization lifecycle to reduce unnecessary transitive dependencies and make lazy service resolution follow the actual application lifecycle.

It also introduces a new Cms\UriGenerator service to centralize application URI and route generation without requiring higher-level services such as Site.

Changes

Service lifecycle

  • Add explicit lazy/eager control to service definitions.
  • Keep core infrastructure services such as Container, App and Config eagerly initialized.
  • Keep application and CMS services lazy and resolve them only when they are actually required.
  • Introduce dedicated service loaders where initialization requires configuration, runtime resources or additional setup.
  • Keep plugin initialization separate from the router and defer other plugin-related services until needed.
  • Add resolution-time initialization support for services that require post-resolution setup.

Dependency decoupling

  • Reduce Site to its actual page-related dependencies instead of using it as an entry point for unrelated CMS services.
  • Decouple language resolution from Site, allowing the language filter to initialize Languages and Translations independently.
  • Decouple FileFactory from Schemes.
  • Keep Schemes, Templates, Users, Files, Cache and other services independently resolvable.
  • Reduce transitive service initialization so resolving one service does not implicitly initialize unrelated parts of the CMS.

URI generation

  • Add Formwork\Cms\UriGenerator for generating application paths and named routes.
  • Expose the service through App::uri().
  • Use UriGenerator for controller redirects, asset URI generation and file URI generation.
  • Keep low-level Uri and Path utilities for actual URI/path manipulation rather than using them directly to implement application-level URI generation.

This allows services that need an application URI to depend directly on UriGenerator instead of depending on Site or duplicating URI construction logic.

Result

The refactoring makes the service dependency graph substantially flatter and better aligned with the request lifecycle.

Previously, resolving Site could implicitly initialize a large portion of the CMS, including languages, translations, schemes, templates, users and files.

The resulting lifecycle is now closer to:

    Application load
    ├── Container
    ├── App
    ├── Config
    ├── Request
    ├── Plugins
    └── Router
          ↓
    Router dispatch
    ├── Language filter
    │     └── Languages
    │           └── Translations
    ├── Route matching
    └── Route action
          ├── Site
          ├── Cache
          ├── Files
          ├── Schemes
          ├── Fields
          └── Templates
                ↓
              View
                ├── Assets
                ├── UriGenerator
                └── File URI generation
                ↓
             Response

As a result, Site is no longer a central dependency for unrelated services and the cost of its initialization is greatly reduced.

In profiling, the initial request was around 37.5 ms, with Site accounting for roughly 17 ms of initialization. After the refactoring, Site is around 0.3 ms, while total request times are generally in the ~25–32 ms range depending on filesystem/cache state.

The remaining cost is now concentrated in the actual page loading and rendering work rather than service bootstrap and transitive dependency resolution.

Dependency Injection and Service Loading:

  • Updated the service container definitions to control lazy loading for core services and to register the new UriGenerator and Languages services (formwork/src/Cms/App.php). [1] [2] [3]
  • Refactored constructors and method dependencies in several classes to remove unused or redundant dependencies, such as FileUploader, ViewFactory, and LanguagesFactory (formwork/src/Controllers/AbstractController.php, formwork/src/Cms/Site.php, formwork/src/Files/FileFactory.php). [1] [2] [3]

Code Cleanup:

  • Removed unused imports and cleaned up constructor parameters to match the new service injection approach across several files (formwork/config/views/methods.php, formwork/src/Files/FileUriGenerator.php, formwork/src/Controllers/AbstractController.php). [1] [2] [3]

Languages Service Refactoring:

  • Refactored how the Languages service is injected and accessed, moving from direct instantiation in Site to service container retrieval, and updating route and service definitions accordingly (formwork/config/routes/routes.php, formwork/src/Cms/Site.php, formwork/src/Cms/App.php). [1] [2] [3]

Site and File Model Simplification:

  • Changed how Site and File objects retrieve their associated services and schemes, using lazy loading via the application container and removing explicit scheme assignment (formwork/src/Cms/Site.php, formwork/src/Files/File.php, formwork/src/Files/FileFactory.php). [1] [2] [3]

Routing and URI Generation Improvements:

  • Added a new UriGenerator class to encapsulate URI and route generation logic, and registered it as a service in the application container (formwork/src/Cms/UriGenerator.php, formwork/src/Cms/App.php). [1] [2] [3]
  • Refactored usages of direct Uri and Path calls to use the new UriGenerator service in views, controllers, and route definitions (formwork/config/views/methods.php, formwork/src/Controllers/AbstractController.php, formwork/config/routes/routes.php). [1] [2] [3]

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

It introduces model accessor regressions, duplicate controller construction, and broken panel compatibility and redirect behavior.

Review effort: Balanced
Findings: 1 High severity · 5 Medium severity

Open (6)
What changed in this PR

Refactors service initialization for lazier dependency resolution and centralizes application URI generation.

Changes:

  • Adds lazy service loaders and route-action lifecycle events.
  • Introduces Cms\UriGenerator and migrates URI generation.
  • Lazily initializes model schemes and fields.
File Description
panel/​config/​routes/​routes.php Uses named routes and removes authentication filters.
formwork/​src/​Users/​User.php Lazily resolves user schemes.
formwork/​src/​Services/​Loaders/​PanelServiceLoader.php Moves panel access checks into route events.
formwork/​src/​Services/​Loaders/​LanguagesServiceLoader.php Adds independent language initialization.
formwork/​src/​Services/​Loaders/​AssetsServiceLoader.php Decouples assets from Site.
formwork/​src/​Schemes/​Scheme.php Clarifies field collection behavior.
formwork/​src/​Router/​Router.php Dispatches resolved-action events.
formwork/​src/​Router/​Events/​RouteActionResolvedEvent.php Adds mutable route-action event.
formwork/​src/​Plugins/​Plugin.php Lazily retrieves view and URI services.
formwork/​src/​Panel/​Controllers/​UsersController.php Injects upload service per action.
formwork/​src/​Panel/​Controllers/​PagesController.php Uses centralized named-route generation.
formwork/​src/​Panel/​Controllers/​FilesController.php Lazily injects uploader and generates routes.
formwork/​src/​Panel/​Controllers/​ErrorsController.php Uses named dashboard routes.
formwork/​src/​Panel/​Controllers/​BackupController.php Uses named backup routes.
formwork/​src/​Panel/​Controllers/​AbstractController.php Delegates view creation to the base controller.
formwork/​src/​Pages/​Page.php Defers page field initialization.
formwork/​src/​Model/​Model.php Lazily creates and caches model fields.
formwork/​src/​Files/​FileUriGenerator.php Uses the centralized URI generator.
formwork/​src/​Files/​FileFactory.php Removes eager scheme initialization.
formwork/​src/​Files/​File.php Resolves file schemes lazily.
formwork/​src/​Controllers/​AbstractController.php Lazily resolves views, forms, and upload dependencies.
formwork/​src/​Cms/​UriGenerator.php Adds application path and route generation.
formwork/​src/​Cms/​Site.php Removes unrelated eager dependencies.
formwork/​src/​Cms/​App.php Registers lifecycle-aware services.
formwork/​config/​views/​methods.php Delegates view URI generation.
formwork/​config/​routes/​routes.php Resolves languages independently of Site.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread formwork/src/Files/File.php Outdated
Comment thread formwork/src/Cms/Site.php
Comment thread formwork/src/Router/Router.php Outdated
Comment thread formwork/src/Services/Loaders/PanelServiceLoader.php
Comment thread formwork/src/Services/Loaders/PanelServiceLoader.php
Comment thread formwork/src/Users/User.php
@giuscris
giuscris marked this pull request as ready for review September 26, 2026 07:50
@giuscris
giuscris merged commit f9e67f8 into 2.x Sep 26, 2026
1 check passed
@giuscris
giuscris deleted the refactor/service-initializaition-and-request-lifecycle branch September 26, 2026 07:50
@giuscris giuscris added the core label Sep 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants