Plugins and framework services via DI - markstory/cakephp GitHub Wiki

We want to embrace DI further in the framework. One Way I can see that working is via the framework providing the 'collection' registry objects as 'services'. These services would continue to be configured either via the static API's we've had for a long time, or via new configuration objects. These fluent interfaces provide simple set method with public property read API.

use Cake\Core\PluginConfig;

$pluginConfig = new PluginConfig();
// Add configuration data for the framework service
$pluginConfig
    ->add('Tasks', ['routes' => false])
    ->add('DebugKit');

// Application registers its configuration. The framework services rely on these configuration objects.
// The framework will consume the provided configuration, or a default configuration based on either 
$container->set(PluginConfig::class, $config);

Within the framework, we would consume the configuration data like

use Cake\Core\PluginCollection;
use Cake\Core\PluginConfig;

// Framework code would do
$plugins = PluginCollection::fromConfig($container->get(PluginConfig::class));
$container->add(PluginCollection::class, $plugins);

This could be used for several of the registry services. The registries insert their collections into the container. The container can then inject the collection into a controller or command.

With some service provider trickery we could also have ORM tables injected in. Ideally we get to an interface like:

use App\Controller\AppController;
use Cake\Http\ServerRequest;
use Cake\Event\EventManagerInterface;
use Cake\Controller\ComponentRegistry;
use App\Model\Table\ArticlesTable;
use App\Service\CalendarSyncService;

class ArticlesController extends AppController {
    public function __construct(
        // Existing controller constructor parameters.
        ServerRequest $request,
        ?string $name = null,
        ?EventManagerInterface $eventManager = null,
        ?ComponentRegistry $components = null,

        // Get ORM tables injected
        ArticlesTable $articles,
        
        // Get Application Services
        CalendarSyncService $calendarSync,
        
        // Get framework collections
        PluginCollection $plugins,
        CacheCollection $cache
    )
    {
        parent::__construct($request, $name, $eventManager, $components);

        $this->articles = $articles;
        $this->plugins = $plugins;
        $this->cache = $cache;
        $this->calendarSync = $calendarSync;
    }
}

I think this interface would be great for controllers and commands.