? No Code Attached Yet
avatar Elfangor93
Elfangor93
3 Apr 2023

FormFactory can not be overwritten.

A php error with message Key Joomla\CMS\Form\FormFactoryInterface is protected and can't be overwritten. stating that FormFactoryInterface has the 'isProtected' flag in the container and can not be overwritten.

Steps to reproduce the issue

  1. Install Joomla
  2. Create a new article
  3. Copy the Joomla\CMS\Service\Provider\Form to Joomla\Component\Content\Administrator\Service\Provider\Form and change the namespace of the file accordingly
  4. Edit the file /administrator/components/com_content/services/provider.php
    • Add use Joomla\Component\Content\Administrator\Service\Provider\Form as FormFactoryProvider;
    • Add $container->registerServiceProvider(new FormFactoryProvider('\\Joomla\\Component\\Content')); after line 53
  5. Open any backend form view of com_content

Expected result

Loading the view using the custom FormFactoryProvider.

Actual result

php error: Key Joomla\CMS\Form\FormFactoryInterface is protected and can't be overwritten.

System information (as much as possible)

  • Wampserver 3.2.9 on Windows 10
  • Apache 2.4.46
  • PHP 7.4.27
  • mysql 5.7.37
  • Joomla 4.2.9

Additional comments

avatar Elfangor93 Elfangor93 - open - 3 Apr 2023
avatar joomla-cms-bot joomla-cms-bot - change - 3 Apr 2023
Labels Added: No Code Attached Yet
avatar joomla-cms-bot joomla-cms-bot - labeled - 3 Apr 2023
avatar Elfangor93 Elfangor93 - change - 3 Apr 2023
Title
Php error when overriding FormFactory
Php error when overriding FormFactory in component
avatar Elfangor93 Elfangor93 - edited - 3 Apr 2023
avatar Elfangor93 Elfangor93 - change - 3 Apr 2023
The description was changed
avatar Elfangor93 Elfangor93 - edited - 3 Apr 2023
avatar laoneo
laoneo - comment - 3 Apr 2023

@wilsonge thoughts?

avatar Elfangor93 Elfangor93 - change - 3 Apr 2023
The description was changed
avatar Elfangor93 Elfangor93 - edited - 3 Apr 2023
avatar HermanPeeren
HermanPeeren - comment - 4 Apr 2023

Joomla's DI-container has the odd feature that you can register a resource as protected. That key can not be overriden anymore then (at least not without some tricks).

I say odd, because:

  • one of the main reasons to use a DI container is that one implementation of a dependency can easily be exchanged by another (for testing purposes or whatever). This is prevented by that protected flag.
  • I'm not aware of such a feature being used on a large scale by other DI containers in other frameworks (but counter examples would be interesting).

Maybe we should just stop using that protected flag. It is now mainly used in the core service providers in /libraries/src/Service/Provider. What harm do you think it could possibly do to be able to override any resource in the local clone of the DI container in your own component?

avatar rdeutz
rdeutz - comment - 5 Apr 2023

@Elfangor93 Could ou explain what you are trying to achive?

avatar Elfangor93
Elfangor93 - comment - 5 Apr 2023

I am developing a custom component for Joomla 4.
There I would like to have my own Form class which is initialized in the Model::getForm() method such that I can access all the protected properties of the Form class and modify them as I like during the loading process of the form.

The only way I see achieving that is by overriding the FormFactory and initialize my own Form class there.

avatar richard67 richard67 - change - 5 Apr 2023
Labels Added: ?
avatar richard67 richard67 - labeled - 5 Apr 2023
avatar Fedik
Fedik - comment - 5 Apr 2023

I would like to have my own Form class

I had similar issue in one of my projects, I made own MVCFactory and set my FormFactory there.
Not perfect but works.

But solving this in core, would be nice.

avatar Elfangor93
Elfangor93 - comment - 7 Apr 2023

Oke, I tried to analyse the current state here.

The first time Joomla\CMS\Factory::getContainer() is called during app runtime the method Joomla\CMS\Factory::createContainer() is called. This method registers all containers available under Joomla\CMS\Service\Provider.
All of them are set using the method Joomla\DI\Container::share() and all of them with the third argument to be true making them a protected container thenceforth. Since Joomla\CMS\Factory::getContainer() is normally called the first time before a component is booted they are all protected and can not be overridden by components.

grafik

To conclude:
All containers registered by the providers located in Joomla\CMS\Service\Provider can not be overridden by components.

My proposition:
All important containers which may be overridden by components should not be registered with the protected flag.
In my opinion these should be

  • Dispatcher
  • Document
  • Form
  • Language
  • Menu
  • Router
  • Toolbar

What are your opinions? Which of these containers may be overidden by components?
If you are developing components, which containers have you tried to overwrite in the past?

avatar laoneo
laoneo - comment - 11 Apr 2023

Honestly I would allow to override all of them.

avatar richard67
richard67 - comment - 14 Apr 2023

Closing as having a pull request. See #40388 .

avatar richard67 richard67 - close - 14 Apr 2023
avatar richard67 richard67 - change - 14 Apr 2023
Status New Closed
Closed_Date 0000-00-00 00:00:00 2023-04-14 14:27:46
Closed_By richard67

Add a Comment

Login with GitHub to post a comment