A configuration is a set of data that determines the values of some variables for a computer program or an operating system, as Wikipedia defines it. In this article, we will explore the significance of configuration for an application.
These options are usually loaded when the program starts, and sometimes a restart is required to apply changes. Yii Framework offers a powerful tool for managing configurations: yiisoft/config.
1. Installation.
First, make sure you have PHP 8.0 or higher and Composer 2.0 or higher installed. Then run the following command to install the package.
composer require yiisoft/config:^1.4 --prefer-dist -vvv
The yiisoft/config package acts as a plugin. It scans installed packages for the config-plugin extra option in their composer.json files. It then creates a merge plan in the config/.merge-plan.php file, including configuration from each package.
3. Loading Configuration.
In your application’s entry point (usually index.php), create an instance of the configuration loader, example Yii2.
<?php declare(strict_types=1); use yii\web\Application; use Yiisoft\Config\Modifier\RecursiveMerge; use Yiisoft\Config\Config; use Yiisoft\Config\ConfigPaths; // comment out the following two lines when deployed to production defined('YII_DEBUG') or define('YII_DEBUG', false); if (getenv('YII_ENV')) { defined('YII_ENV') or define('YII_ENV', getenv('YII_ENV')); } else { defined('YII_ENV') or define('YII_ENV', 'prod'); } if (getenv('YII_C3')) { $c3 = dirname(__DIR__) . '/c3.php'; if (file_exists($c3)) { require_once $c3; } } require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../vendor/yiisoft/yii2/Yii.php'; $config = new Config( new ConfigPaths(dirname(__DIR__), 'config', 'vendor'), modifiers: [RecursiveMerge::groups('web', 'params', 'params-web')], paramsGroup: 'params-web', ); $container = Yii::$container->setSingleton(Application::class, $config->get('web')); $app = Yii::$container->get(Application::class); $app->run();
4. Configuration composer.json.
In the composer.json file, we add the extra section where we include configurations for our app. In this case, we specify that the configuration file is located at /config/config-plugin.php.
"extra": {
"config-plugin-file": "/config/config-plugin.php",
},
5. Configuration config-pluging.
The library's approach involves organizing configurations into arrays, which are subsequently merged to construct the complete configuration. In our scenario, we define three configuration groups: common for shared configurations, console for console-related configurations, and web for web-related configurations.
<?php declare(strict_types=1); return [ 'config-plugin' => [ 'common' => 'common/*.php', 'console' => [ '$common', 'console/*.php', ], 'web' => [ '$common', '$yii2-bootstrap5', '$yii2-debug', '$yii2-gii', '$yii2-localeurls', 'web/*.php' ], 'params' => 'params.php', 'params-console' => [ '$params', 'params-console.php' ], 'params-web' => [ '$params', 'params-web.php' ], ], 'config-plugin-options' => [ 'package-types' => [ 'composer-plugin', 'library', 'yii2-extension', ], 'source-directory' => 'config', ], ];
To implement this structure, we create three directories within the config directory. Each directory contains files with the configurations relevant to its designated group.
This is a basic example, but you can have your own custom configuration – that's the true essence of yiisoft/config. In my example, i'll have the directory structure of the config as follows:
root
└── config
├── Common Common configuration.
│ ├── components.php
│ └── container.php
├── Console Console configuration.
│ ├── app.php
│ └── components.php
├── Web Web configuration.
│ ├── app.php
│ ├── bootstrap.php
│ ├── components.php
│ ├── container.php
│ └── modules.php
├── build.php Build configuration codeception tests.
├── config-plugin.php Plugin configuration.
├── messages.php Translation configuration.
├── params-console.php Console parameters.
├── params-web.php Web parameters.
└── params.php Common parameters.
In common/container.php, we configure our definitions in the di container of Yii2, which will be used by both our console and web applications.
<?php
declare(strict_types=1);
use yii\symfonymailer\Mailer;
/**
* @var array $params
*/
return [
'container' => [
'definitions' => [
Mailer::class => [
'useFileTransport' => $params['common.mailer.useFileTransport'],
],
],
],
];
In the console, application configuration is simplified by leveraging yiisoft/config. Now, we define properties with configurable parameters, showcasing the full power of yiisoft/config.
console.php:
<?php
declare(strict_types=1);
/**
* @var array $params
*/
return [
'id' => $params['console.id'],
'aliases' => $params['common.aliases'],
'basePath' => dirname(__DIR__, 2),
'bootstrap' => $params['common.bootstrap'],
'controllerMap' => $params['console.controllerMap'],
'params' => $params['console.params'],
'runtimePath' => $params['common.runtime.path'],
];
Now, let's define our common parameters in params.php and console specific ones in params-console.php. These will configure our properties. The beauty is, we don't need to edit configuration files; just adjust parameters. A significant advantage with yiisoft/config.
params.php:
<?php declare(strict_types=1); $rootDir = dirname(__DIR__); return [ 'common.aliases' => [ '@app' => $rootDir, '@resource' => '@app/src/Framework/resource', ], 'common.bootstrap' => ['log'], 'common.log.levels' => ['error', 'warning', 'info'], 'common.log.logFile' => '@runtime/logs/app.log', 'common.mailer.useFileTransport' => true, 'common.root.dir' => $rootDir, 'common.runtime.path' => $rootDir . '/public/runtime', ];
<?php declare(strict_types=1); use App\UseCase\Hello\HelloController; use yii\console\controllers\ServeController; $rootDir = dirname(__DIR__); return [ 'console.id' => 'console.basic', 'console.controllerMap' => [ 'hello' => HelloController::class, 'serve' => [ 'class' => ServeController::class, 'docroot' => "$rootDir/public", ], ], 'console.params' => [], ];
#!/usr/bin/env php <?php declare(strict_types=1); use yii\console\Application; use Yiisoft\Config\Config; use Yiisoft\Config\ConfigPaths; use Yiisoft\Config\Modifier\RecursiveMerge; defined('YII_DEBUG') or define('YII_DEBUG', true); defined('YII_ENV') or define('YII_ENV', 'dev'); require __DIR__ . '/vendor/autoload.php'; require __DIR__ . '/vendor/yiisoft/yii2/Yii.php'; $config = new Config( new ConfigPaths(__DIR__, 'config', 'vendor'), modifiers: [RecursiveMerge::groups('console', 'params', 'params-console')], paramsGroup: 'params-console', ); $container = Yii::$container->setSingleton(Application::class, $config->get('console')); $app = Yii::$container->get(Application::class); $exitCode = $app->run(); exit($exitCode);
array:9 [
"components" => array:2 [
"cache" => array:1 [
"class" => "yii\caching\FileCache"
]
"log" => array:2 [
"traceLevel" => 3
"targets" => array:1 [
0 => array:3 [
"class" => "yii\log\FileTarget"
"levels" => array:3 [
0 => "error"
1 => "warning"
2 => "info"
]
"logFile" => "@runtime/logs/app.log"
]
]
]
]
"container" => array:1 [
"definitions" => array:1 [
"yii\symfonymailer\Mailer" => array:1 [
"useFileTransport" => true
]
]
]
"id" => "console.basic"
"aliases" => array:3 [
"@yii2-extension-datetime-picker" => "@vendor/yii2-extensions/datetime-picker"
"@app" => "K:\yii2-extensions\app-basic"
"@resource" => "@app/src/Framework/resource"
]
"basePath" => "K:\yii2-extensions\app-basic"
"bootstrap" => array:1 [
0 => "log"
]
"controllerMap" => array:2 [
"hello" => "App\UseCase\Hello\HelloController"
"serve" => array:2 [
"class" => "yii\console\controllers\ServeController"
"docroot" => "K:\yii2-extensions\app-basic/public"
]
]
"params" => []
"runtimePath" => "K:\yii2-extensions\app-basic/public/runtime"
]
Happy coding!
For more details, you can check out our repository app-basic and explore the complete demonstration of configuration using yiisoft/config.
Soon the second part of this post.