GeniXCMS

Container Class

categoryAPI edit_calendar31 Mar 2026

Dependency Injection Container


The Container class is a lightweight Dependency Injection (DI) Container in v2.0.0. It provides a central registry for core GeniXCMS services, decouping them from global states and hardcoded static calls.

This architecture transition enables easier unit testing, service mocking, and improved maintainability of the codebase.


โšก Core Principles

GeniXCMS uses a Service Registry pattern:

  1. Centralization: All major services (Database, Session, User, etc.) are registered during system initialization.
  2. Decoupling: Classes do not need to know how to instantiate their dependencies; they just request them from the Container.
  3. Singleton Nature: Each service key typically points to a persistent instance for the duration of the request.

๐Ÿ—๏ธ Initialization & Lifecycle

Core services are registered by the System class constructor at the very beginning of the application lifecycle:

// inc/lib/System.class.php
Container::set('db', new Db());
Container::set('hooks', new Hooks());
Container::set('user', new User());
// ... and more

Registered Core Services

Key Class Description
db Db PDO-based database connectivity.
hooks Hooks System-wide action and filter registry.
user User Authentication and role-based access engine.
session Session Encapsulated session management.
options Options Site configuration manager.
http Http Request and response abstraction.
router Router URL scraping and routing logic.
language Language Localization and i18n support.

โš™๏ธ How to Use

1. Basic Retrieval

You can fetch any service instance manually if you are working outside the standard controller flow:

// Manual retrieval
$db = Container::get('db');
$rows = $db->query("SELECT * FROM `posts`")->result();

2. Static Shortcut Methods

For cleaner code, the Container provides static helpers for the most frequently used services:

$db    = Container::db();
$user  = Container::user();
$hooks = Container::hooks();

3. Usage in Controllers (Preferred)

All controllers extending BaseControl are automatically injected with these services via the constructor. Avoid using static class calls inside controllers and instead use internal properties:

class MyControl extends BaseControl
{
    public function run($param)
    {
        // โŒ BAD: Static call (hard to test)
        $posts = Posts::fetch(); 

        // โœ… GOOD: Using injected service property
        if ($this->user->isLoggedin()) {
            $data = $this->db->query("...")->fetch();
        }
    }
}

๐Ÿ”Œ Managing Services

Container::set(string $key, object $instance)

Maps a service key to an object instance. If the key already exists, it will be overridden.

Container::set('mailer', new MyCustomMailer());

Container::get(string $key)

Retrieves the object associated with the key. Returns null if not found.


๐Ÿงช Benefits for Testing

The primary advantage of the Container is the ability to swap real services with Mocks during unit tests:

// In a test environment
$mockDb = $this->createMock(Db::class);
$mockDb->method('query')->willReturn(...);

// Inject the mock into the container
Container::set('db', $mockDb);

// Now, any code calling Container::db() will receive the mock!

See Also

  • BaseControl Class โ€” How core services are injected into controllers.
  • System Class โ€” The location where services are initialized.
  • Db Class โ€” Reference for the core database service.