Composer Dependency Changed PR-6.2-dev Pending

User tests: Successful: Unsuccessful:

avatar HLeithner
HLeithner
4 Aug 2026

This Pull requests allows to use to new interfaces which provide auto-wiring with constructor parameters or auto-wiring by providing an array ob required classes to be injected.

  • I read the Generative AI policy and my contribution is either not created with the help of AI or is compatible with the policy and GNU/GPL 2 or later.

Summary of Changes

We introduce a new service provider factory which uses the newly introduced MVC autowire factory.

The new \Joomla\CMS\MVC\Factory\AutowireFactory does most of the new magic, it's a glue between the existing \DI\Container::buildObject() method and the component service provide. Instead of injecting the needed objects in the server provided we injected the full container into the new AutowireFactory and provide some workarounds for scalar values.

This PR is based on the https://github.com/joomla-framework/di/tree/4.x/autowire branch which allows to support scalar values in the container for autowiring, this is not intended to provide a scalar values or any other fixed values in the container, it's used in the local cloned container in the autowireFactory only.

The MVC base classes got a new method (if needed) to provide all currently injected dependencies, this allows us to use the AbstractAutowireInterface in CMS and 3rd Party.

As example I converted com_contact to use the AbstractAutowireInterface.

Testing Instructions

A bit tricky, for the core you can test com_contact in all variants (already done by the CI).

For own components You need to use the new Autowire Service Provider.

and implement the ConstructorAutowireInterface in your Controller/Model/View

If you extend the FormController it's working out of the box, if you need to extra dependencies you need to create a constructor with all needed parameters from the parent and the dependencies which should be provided to the constructor by the autowire factory.

Actual result BEFORE applying this Pull Request

If works

Expected result AFTER applying this Pull Request

It still works but now cool with autowiring reducing maintainance costs a lot.

Link to documentations

Please select:

  • Documentation link for guide.joomla.org:

  • No documentation changes for guide.joomla.org needed

  • Pull Request link for manual.joomla.org:

  • No documentation changes for manual.joomla.org needed

Additionally

In the code are some todos we should discuss, for example legacy b/c code is included to load "old" objects which will do the same as the MVCFactory.

Known issues

I know that API and frontend tests are failing, I will look at this later, for now it's ready for discussion.

58d7c68 4 Aug 2026 avatar HLeithner CS
avatar HLeithner HLeithner - open - 4 Aug 2026
avatar HLeithner HLeithner - change - 4 Aug 2026
Status New Pending
avatar joomla-cms-bot joomla-cms-bot - change - 4 Aug 2026
Category Administration com_contact Front End External Library Composer Change Libraries
avatar laoneo
laoneo - comment - 5 Aug 2026

Why not letting the base classes implement the interface and use the trait? So we don't have to touch all the MVC classes in each component to support auto wiring. It will be used only when the AutowireMVCFactory is used.

avatar HLeithner
HLeithner - comment - 5 Aug 2026

Why not letting the base classes implement the interface and use the trait? So we don't have to touch all the MVC classes in each component to support auto wiring. It will be used only when the AutowireMVCFactory is used.

I wanted to be safe and didn't thought deep enough about it. But yes the work is really annoying...

One of the issues could be that you can't remove the interface. So if you do it "right" in you extension and use the ConstructorAutowireInterface the buildObject does the work twice.
For example:

You have an CustomController, which extends the BaseController and implements the ConstructorAutowireInterface and have a constructor with __construct(DispatcherAwareInterface $dispatcher, LoggerAwareInterface $logger, CacheControllerFactoryAwareInterface $cacheFactory) everything is fine now.

If the BaseController implements the AbstractAutowireInterface the 3 interfaces will be set again after the construction. Not good performance wise, reflection is already expensive on it's own.

On the other side, it would allow us to add dependencies in the base classes at a later time without bothering extension developers to update the constructor...

I will test what will happen with the interface in the base classes.

avatar voronkovich
voronkovich - comment - 5 Aug 2026

IMHO, this is not a good approach, as it couples classes with the DI container through container-related interfaces. Consequently, service configuration becomes scattered across the codebase.

I would suggest defining autowiring configuration via simple arrays tagged with special "autowire" tags. For example:

// services/provider.php
$container->share('autowire_some_id', fn () => [
    BaseController::class => [
        '__construct'               => true, // enables contructor autowiring
        'setDispatcher'             => DispatcherAwareInterface::class,
        'setLogger'                 => LoggerAwareInterface::class,
        'setCacheControllerFactory' => CacheControllerFactoryAwareInterface::class,
    ],
    BaseDatabaseModel::class => [
        '__construct'               => true,
        'setDispatcher'             => DispatcherAwareInterface::class,
        'setDatabase'               => DatabaseAwareInterface::class,
        'setMVCFactory'             => MVCFactoryInterface::class,
        'setCacheControllerFactory' => CacheControllerFactoryAwareInterface::class,
   ],
]);
$container->tag('autowire_some_id', 'autowire');

On the first call, the AutowireFactory will collect all these arrays, merge them into one, and use it for wiring services.

avatar HLeithner
HLeithner - comment - 5 Aug 2026

IMHO, this is not a good approach, as it couples classes with the DI container through container-related interfaces. Consequently, service configuration becomes scattered across the codebase.

I would suggest defining autowiring configuration via simple arrays tagged with special "autowire" tags. For example:

// services/provider.php
$container->share('autowire_some_id', fn () => [
    BaseController::class => [
        '__construct'               => true, // enables contructor autowiring
        'setDispatcher'             => DispatcherAwareInterface::class,
        'setLogger'                 => LoggerAwareInterface::class,
        'setCacheControllerFactory' => CacheControllerFactoryAwareInterface::class,
    ],
    BaseDatabaseModel::class => [
        '__construct'               => true,
        'setDispatcher'             => DispatcherAwareInterface::class,
        'setDatabase'               => DatabaseAwareInterface::class,
        'setMVCFactory'             => MVCFactoryInterface::class,
        'setCacheControllerFactory' => CacheControllerFactoryAwareInterface::class,
   ],
]);
$container->tag('autowire_some_id', 'autowire');

On the first call, the AutowireFactory will collect all these arrays, merge them into one, and use it for wiring services.

Sounds really wrong on several levels to me, you don't want to define class depending information in another file (in this case the service provider) also you don't want to inject magic names into the container (the scalar things is a not so nice workaround for our legacy code base, because our container is a service locator not a "information" storage).

I see no benefit from this, yes the Container provides 2 new Interfaces which tells you (the cms) that it supports autowiring (actually for the container only the AbstractAutowireInterface is relevant because it needs to inject the dependencies).

Normally (if we could do it right from the beginning) the way would be to use the constructor and you don't need to do any manual declaration but our codebase is old and should be move into a new direction without breaking everything.

Never the less, thanks you for your feedback.

avatar HLeithner HLeithner - change - 5 Aug 2026
Labels Added: Composer Dependency Changed PR-6.2-dev
avatar laoneo
laoneo - comment - 5 Aug 2026

To some degree I share the concern of @voronkovich, that the dependency declaration functions are placed in the classes itself. What about using annotations for dependency declaration? Just a thought, not sure if it is of practical use.

avatar HLeithner
HLeithner - comment - 5 Aug 2026

I think annotations are not really helpful, you still need a method in the class to set the dependencies, mostly because a simple attribute has no "value" (for example holding the setter method). for this I think we need properties. makes it a bit more complex.
But maybe I'm wrong with how to use the annotations.

Beside that you need to rebuild the inheritance manually and reflect each parent class, which is expensive.
I would like to use more attributes or properties in joomla but it should make the code nicer

Also I might have missed the point where the class is no longer responsible for the needed dependencies.

ymmv

avatar HLeithner
HLeithner - comment - 5 Aug 2026

Why not letting the base classes implement the interface and use the trait? So we don't have to touch all the MVC classes in each component to support auto wiring. It will be used only when the AutowireMVCFactory is used.

I implemented the interface and I think it's a good idea and works as expected.

Add a Comment

Login with GitHub to post a comment