-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bug: BaseConfig issue on registrar #9231
Comments
Please give us an example of the problem: a config file and a registrar. Are you defining the same registrar in many modules? |
class MyModuleRegistrar {
public static function MyModule() {
return [
'database' => 'mysql',
'cache' => ['enabled' => true, 'driver' => 'file'],
];
}
} |
The problem is visible on the Filters. Try disabling only the Toolbar or adding filters to the previous config. They will be overwritten from the module |
I will assume this is the proper example: <?php
namespace Config;
use CodeIgniter\Config\BaseConfig;
class Example extends BaseConfig
{
public array $arrayNested = [
'key1' => 'val1',
'key2' => ['val2' => 'subVal2', 'val3' => 'subVal3'],
];
} <?php
namespace Modules\MyModule\Config;
class Registrar
{
public static function Example(): array
{
return [
'arrayNested' => [
'key2' => ['val4' => 'subVal4']
],
];
}
} Now, you will get this: public 'arrayNested' -> array (2) [
'key1' => string (4) "val1"
'key2' => array (1) [
'val4' => string (7) "subVal4"
]
] But you expect this: public 'arrayNested' -> array (2) [
'key1' => string (4) "val1"
'key2' => array (3) [
'val2' => string (7) "subVal2"
'val3' => string (7) "subVal3"
'val4' => string (7) "subVal4"
]
] This is not a bug, but a feature request. Personally, I'm not a fan of this change. You can avoid this problem very simply - by defining the structure of the config file differently. |
how? let's say I initially want to disable the toolbar filter in app/Registrar.php, and add middlewares in other modules modules/auth, modules/job? |
If we start using If modules add new options, they can use the Publisher class to add them to the main config. I could be wrong, but I think the intention was to prevent everything from being easily overwritten from within modules, as there should be a "single source of truth" for some options. |
Yes, this is BC. Therefore, another solution is needed. How about passing the current configuration properties to the Config? // in registerProperties()
static::$registrars[] = new $className();
//...
// in foreach()
$callable->__parentProps = get_class_vars($this);
// in Registrars, delete some keys
$parentProps = $this->__parentProps;
unset($parentProps['key1']);
return [
'arrayNested' => [
'key2' => array_merge_recursive($parentProps, ['val4' => 'subVal4'])
],
]; This is about the order of work, code is inaccurate |
Certainly! Let's explore this issue in detail, starting with examples of the problem. Example of the Problem: Config File and RegistrarIn a typical modular CodeIgniter 4 application, you might have several independent modules, each with its own Example Configuration Files
These files define filters that are supposed to be registered into the main configuration. The expectation is that all these configurations should be combined, so the application uses filters from all modules. The Problem: Overwriting Instead of MergingThe issue arises due to the way the For example, if the Are You Defining the Same Registrar in Many Modules?Yes, in this context, the same registrar method ( Solution: Deep MergingTo solve this issue, a deep merge function is needed. This function should recursively merge arrays to ensure that all configurations are retained and integrated properly. Here's a simple example of how I implement a deep merge function in PHP: function deep_merge(array &$array1, array &$array2)
{
$merged = $array1;
foreach ($array2 as $key => &$value) {
if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
$merged[$key] = deep_merge($merged[$key], $value);
} else {
$merged[$key] = $value;
}
}
return $merged;
} Applying the SolutionIn the Solution Output: After applying the // Combined configuration
$combinedFilters = [
'aliases' => [
'blogFilter' => \Modules\Blog\Filters\BlogFilter::class,
'shopFilter' => \Modules\Shop\Filters\ShopFilter::class,
'paypalFilter' => \Modules\Paypal\Filters\PaypalFilter::class,
],
'globals' => [
'before' => ['blogFilter', 'shopFilter', 'paypalFilter'],
],
]; Explanation of the Output
This method guarantees that all configuration data is retained, allowing each module to seamlessly contribute to the overall application setup. By using a deep merge function, the solution ensures that nested arrays are combined effectively, thereby preserving the unique configurations intended by each module's developer. This approach respects the configurations from all modules and integrates them cohesively, maintaining the integrity of the application's intended settings. |
I think filter aliases can be configured in module, but all filters should be configured in |
What about the |
What of the case the registrar it was stated in the doc that this should be better option |
Explain your question better |
This is a solution option. New methods will add or replace Config properties. // merge recursive
// 'aliases' => ['blogFilter' => BlogFilter::class, 'paypalFilter' => PaypalFilter::class]
'aliases' => $this->appendAfterProps([
'paypalFilter' => \Modules\Paypal\Filters\PaypalFilter::class,
])
// merge recursive
// 'aliases' => ['paypalFilter' => PaypalFilter::class, 'blogFilter' => BlogFilter::class]
'aliases' => $this->appendBeforeProps([
'paypalFilter' => \Modules\Paypal\Filters\PaypalFilter::class,
])
// full replace array
// 'aliases' => ['paypalFilter' => PaypalFilter::class]
'aliases' => $this->replaceProps([
'paypalFilter' => \Modules\Paypal\Filters\PaypalFilter::class,
]) |
PHP Version
8.2
CodeIgniter4 Version
4.5.5
CodeIgniter4 Installation Method
Manual (zip or tar.gz)
Which operating systems have you tested for this bug?
Windows, Linux
Which server did you use?
apache
Database
MySQL
What happened?
New registrar with the same method with other registrars replaces their contents on array_merge which works on only first level array. I hope array_merge_recursive will be better for modules
Steps to Reproduce
\Codeigniter\Config\BaseConfig
Expected Output
Expected merge the old contents array with the new one
Anything else?
Yes i used array_merge_recursive. I discovered the issue to so i extend the base config to child class today fix this but i think the usage of array_merge_recursive is a better option help on this to update the core code
\Codeigniter\Config\BaseConfig
The text was updated successfully, but these errors were encountered: