Reputation: 646
I am developing multiple websites based on Yii2 framework and I was wondering if there is any good way or if it's even good idea or not to create a shared basic config main.php
file.
The reason behind this is that all my projects are based on same system, have a lot of similarities and I simply want to keep things DRY. Configs are also mostly same - the only differences actually are database names and few other values. Even urlManager rules are not so different.
The problem is that when for example I would want to add additional FileTarget
to logger targets for all websites I have to do this for each project separately and I can never be sure if all project configs are up to date and have everything set up properly.
So I was wondering if there is any Yii way of creating default config file shared in multiple projects or if it's simply a bad idea. For example I could create bootstrap component which sets defaults or add default config as first item in the list of merged configs in frontend\web\index.php
file. I have private packages added in composer so it's not a problem adding file that will be shared in all projects.
Upvotes: 6
Views: 2911
Reputation: 646
What I've ended up doing was creating a ConfigHelper
class that helps merging local configs with global ones. I'm posting it just for other people to see the idea. This might not be the utlimate solution but it worked with my existing setup.
The ConfigHelper
along with default config files are included in one of the packages (private repository) that I am including in all my yii2 based projects by using composer.
And now instead of the default fronted/web/index.php
config merging from the yii2 template:
$config = yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/../../common/config/main.php'),
require(__DIR__ . '/../../common/config/main-local.php'),
require(__DIR__ . '/../config/main.php'),
require(__DIR__ . '/../config/main-local.php')
);
$application = new yii\web\Application($config);
$application->run();
I am using my helper class:
$config = ConfigHelper::build(
__DIR__ . '/../..', //project root path
ConfigHelper::TIER_FRONTEND, // fronted, console or backend
'my-unique-app-name', //could be any other param that you need
);
$application = new yii\web\Application($config);
$application->run();
The helper class which also has default configs in files next to it:
class ConfigHelper
{
const TIER_FRONTEND = 'frontend';
const TIER_CONSOLE = 'console';
const TIER_BACKEND = 'backend';
public static function build($root, $tier, $website)
{
// Notice that local files are included so in case they don't exist there won't be errors
return ArrayHelper::merge(
require(__DIR__ . "/../config/common/main.php"), // global basic config file for all projects
require("{$root}/common/config/main.php"),
include("{$root}/common/config/main-local.php"),
require(__DIR__ . "/../config/{$tier}/main.php"), // global basic config file for all projects
require("{$root}/{$tier}/config/main.php"),
include("{$root}/{$tier}/config/main-local.php")
);
}
}
The global default config files are same as the ones used in Yii2. They simply contain common settings excluding unique settings that you can add per app as you normally do.
Upvotes: 0
Reputation: 5291
As a simpler alternative you can just put a file somewhere and include it from all the configs i.e.
$commonConfig = require '/var/www/common/config.php';
$appConfig = require 'configs/main.php';
$config = array_merge($commonConfig, $appConfig);
// ...
Upvotes: 5
Reputation: 101
I am working on the same question for a pretty long time and tried several ideas.
At the moment I've developed nice solution for the issues you describe. The heart of the solution is hiqdev/composer-config-plugin - composer plugin which merges configs from extensions.
For example we have extension that is base for all our web projects hiqdev/hisite-core it contains basic Yii application config and params:
return [
'id' => 'hisite',
'name' => 'HiSite',
'aliases' => [
'@bower' => '@vendor/bower-asset',
...
These configs are enabled in composer.json with such lines:
"extra": {
"config-plugin": {
"params": "src/config/params.php",
"hisite": "src/config/hisite.php"
}
},
And that's it. You require hiqdev/hisite-core and after running composer update you have assembled configs (you may have multiple config) in vendor/hiqdev/config/hisite.php
Then you use it from your index.php like this:
$config = require dirname(dirname(__DIR__)) . '/hiqdev/config/hisite.php';
You can achieve similar behaviour with Yii extension bootstrapping but bootstrap have to run on every page request.
The beauty of the solution is that you can have lots of components every one of them providing own part of config and it works without slowing page rendering time because the config is merged once on composer install/update. (And you can force merging of config with composer dump-autoload, don't forget to run it after changing config).
Using this technique we've creating auto plugging extensions: themes, modules and more that are not required to be configured in main config - you just require them in composer.json and you have it working.
This solution is still work in progress and it's going to evolve and change but we use it for really big Yii2 based application with 30+ extensions and it is already tested and stable enough.
Upvotes: 6