Skip to content

Config cache gets overwritten to null by provider stub (custom merge) when using env() #2126

@0grim

Description

@0grim

Versions:

  • laravel-modules Version: 12.0.4
  • Laravel Version: 12.34.0
  • PHP Version: 8.4.10

Description:

The default service provider stub generated by php artisan module:make merges module config at runtime using a custom merge_config_from() inside boot(). When the application config is cached (php artisan config:cache), this code path overwrites the baked values with null for any keys that come from env().

Replacing the custom merge with $this->mergeConfigFrom() (in register()) resolves the issue.

Steps To Reproduce:

1 Create a new Laravel project: composer create-project laravel/laravel test-project
2 Require this package: composer require nwidart/laravel-modules
3 Generate a module: php artisan module:make TestModule
4 In Modules/TestModule/config/config.php add a test env backed key:

[
    'name'    => 'TestModule',
    'env_test' => env('ENV_TEST'),
]

5 Add the corresponding value to .env: ENV_TEST='test'
6 Build config cache:

php artisan optimize:clear
php artisan config:cache

7 Inspect using Tinker:

php artisan tinker
>>> app()->configurationIsCached();  // true
>>> config('testmodule');
/*
Expected: values from .env
Actual:   ["name" => "TestModule", "env_test" => null]
*/

8 Compare with the cached file:

>>> (require base_path('bootstrap/cache/config.php'))['testmodule'];
/*
Shows the correct baked values:
['name' => 'TestModule', 'env_test' => 'test']
*/

Possible cause

The stub’s boot() calls registerConfig() which requires each module config file (require $path) and then calls config([$key => array_replace_recursive($existing, $module_config)]).
When config is cached, Laravel does not read .env at runtime. env('...') inside a required config file returns null.
The custom merge runs after the cached config is loaded and replaces previously correct values with these nulls (module array takes precedence over existing config).
Commenting out the $this->registerConfig(); call inside TestModuleServiceProvider::boot(), placing

$this->mergeConfigFrom(
    __DIR__ . '/../../config/config.php', 'testmodule'
);

inside TestModuleServiceProvider::register(), reloading the code and rebuilding the cache:

php artisan optimize:clear
composer dump-autoload -o
php artisan config:cache  

restores the expected behaviour:

php artisan tinker
>>> config('testmodule');
/*
Shows the correct baked values:
['name' => 'TestModule', 'env_test' => 'test']
*/

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions