Configuration
System Configuration
Before loading Resonance, your application should set a few PHP constants, preferably in the autoloaded file. Those constants are more system-related than application-related. They define hard-coded values that should not be changed in the app configuration maliciously or by accident.
The application loads those constants before it parses any other configuration file.
Those are the required constants:
constants.phpphp<?php // Root directory of your application define('DM_APP_ROOT', __DIR__.'/app'); // Root directory of the Resonance framework define('DM_RESONANCE_ROOT', __DIR__.'/vendor/distantmagic/resonance'); // Directory with publicly accessible files (like assets, images etc) define('DM_PUBLIC_ROOT', __DIR__.'/public'); // Project root directory define('DM_ROOT', __DIR__); // Coroutine timeouts define('DM_BATCH_PROMISE_TIMEOUT', 0.3); define('DM_GRAPHQL_PROMISE_TIMEOUT', 0.2); define('DM_POOL_CONNECTION_TIMEOUT', 0.1);
composer.jsonjson{ "require": {}, "autoload": { "files": [ "constants.php" ] } }
You should never use constants.php
to handle application-specific (domain
specific) configuration variables (like the database connection parameters
or such).
Application Configuration
You can configure Resonance's services by editing the config.ini
file.
Each section contains a configuration for a specific service.
Default Configuration
Sections are lazy-loaded and will only be loaded and validated if your code
uses a specific feature. For example, if your application does not use
Sessions (and does not use Redis anywhere else), then
the [redis]
section won't be loaded.
This is the default configuration file:
config.iniini[app] env = development esbuild_metafile = %DM_ROOT%/esbuild-meta-app.json scheme = https url = http://localhost:9501 [database] default[driver] = mysql default[host] = 127.0.0.1 default[port] = 3306 default[database] = distantmagic default[username] = distantmagic default[password] = distantmagic default[log_queries] = false default[pool_prefill] = false default[pool_size] = 8 [grpc] grpc_php_plugin_bin = %DM_ROOT%/grpc_php_plugin protoc_bin = /usr/bin/protoc [llamacpp] host = 127.0.0.1 port = 8081 [mailer] default[transport_dsn] = smtp://localhost ; default[dkim_domain_name] = example.com ; default[dkim_selector] = resonance1 ; default[dkim_signing_key_passphrase] = yourpassphrase ; default[dkim_signing_key_private] = dkim/private.key ; default[dkim_signing_key_public] = dkim/public.key [manifest] background_color = "#ffffff" theme_color = "#ffffff" [oauth2] encryption_key = %DM_ROOT%/oauth2/defuse.key jwt_signing_key_passphrase = yourpassphrase jwt_signing_key_private = %DM_ROOT%/oauth2/private.key jwt_signing_key_public = %DM_ROOT%/oauth2/public.key session_key_authorization_request = oauth2.authorization_request session_key_pkce = oauth2.pkce session_key_state = oauth2.state [openapi] description = description title = title version = 0.0.0 [redis] default[db_index] = 0 default[host] = 127.0.0.1 default[password] = null default[port] = 6379 default[prefix] = dm: default[timeout] = 1 default[pool_prefill] = false default[pool_size] = 8 [session] cookie_lifespan = 86400 cookie_name = dmsession redis_connection_pool = default [sqlite-vss] extension_vector0 = %DM_ROOT%/vector0.so extension_vss0 = %DM_ROOT%/vss0.so [static] base_url = https://resonance.distantmagic.com esbuild_metafile = %DM_ROOT%/esbuild-meta-docs.json input_directory = docs output_directory = %DM_ROOT%/docs/build sitemap = %DM_ROOT%/docs/build/sitemap.xml [swoole] host = 127.0.0.1 port = 9501 log_level = SWOOLE_LOG_DEBUG ssl_cert_file = %DM_ROOT%/ssl/origin.crt ssl_key_file = %DM_ROOT%/ssl/origin.key [translator] base_directory = %DM_APP_ROOT%/lang default_primary_language = en [websocket] max_connections = 10000
Environment Variables
You can follow the parse_ini_file interpolation rules. For example:
config.iniini; Interpolate the PATH environment variable path = ${PATH}
File Paths
For the sake of consistency, all file paths in the configuration file are absolute.
Interpolatable Constants
You can use DM_APP_ROOT
, DM_PUBLIC_ROOT
, DM_RESONANCE_ROOT
and DM_ROOT
constants in your configuration file by inserting them with %%
delimiters,
for example: %DM_APP_ROOT%
.
Configuration Providers
You can extend config.ini
by adding your configuration sections. Let's say
you want to add a new [manifest]
section that configures some values that
the Web App Manifest
will use.
For your config file to be able to have a section like this:
config.iniini; ... [manifest] background_color = "#000000" theme_color = "#000000" ; ...
First, you need to define your configuration model:
php<?php namespace App; readonly class ManifestConfiguration { public function __construct( public string $backgroundColor, public string $themeColor, ) {} }
Then you need to define the configuration provider. Constraints schema is used for config validation:
php<?php namespace App\SingletonProvider\ConfigurationProvider; use App\ManifestConfiguration; use Distantmagic\Resonance\Attribute\Singleton; use Distantmagic\Resonance\Constraint; use Distantmagic\Resonance\Constraint\ObjectConstraint; use Distantmagic\Resonance\Constraint\StringConstraint; use Distantmagic\Resonance\SingletonProvider\ConfigurationProvider; /** * @template-extends ConfigurationProvider<ManifestConfiguration, array{ * background_color: string, * theme_color: string, * }> */ #[Singleton(provides: ManifestConfiguration::class)] final readonly class ManifestConfigurationProvider extends ConfigurationProvider { public function getConstraint(): Constraint { return new ObjectConstraint( properties: [ 'background_color' => new StringConstraint(), 'theme_color' => new StringConstraint(), ], ); } protected function getConfigurationKey(): string { return 'manifest'; } protected function provideConfiguration($validatedData): ManifestConfiguration { return new ManifestConfiguration( backgroundColor: $validatedData['background_color'], themeColor: $validatedData['theme_color'], ); } }
Then you can use your configuration file in other services, for example:
php<?php namespace App\HttpResponder; use App\HttpRouteSymbol; use App\ManifestConfiguration; use Distantmagic\Resonance\Attribute\RespondsToHttp; use Distantmagic\Resonance\Attribute\Singleton; use Distantmagic\Resonance\ContentType; use Distantmagic\Resonance\HttpResponder; use Distantmagic\Resonance\HttpResponderInterface; use Distantmagic\Resonance\RequestMethod; use Distantmagic\Resonance\SingletonCollection; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; #[RespondsToHttp( method: RequestMethod::GET, pattern: '/manifest.webmanifest', routeSymbol: HttpRouteSymbol::Manifest, )] #[Singleton(collection: SingletonCollection::HttpResponder)] final readonly class Manifest extends HttpResponder { private string $manifest; public function __construct(ManifestConfiguration $manifestConfiguration) { $this->manifest = json_encode([ 'background_color' => $manifestConfiguration->backgroundColor, 'display' => 'standalone', 'id' => '/?source=pwa', 'name' => 'Resonance', 'scope' => '/', 'short_name' => 'Resonance', 'start_url' => '/?source=pwa', 'theme_color' => $manifestConfiguration->themeColor, ], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); } public function respond( ServerRequestInterface $request, ResponseInterface $response, ): ResponseInterface { return $response ->withHeader('content-type', ContentType::ApplicationJson->value) ->withBody($this->createStream($this->manifest)) ; } }
This configuration is going to be loaded only if the ManifestConfiguration
is used as a constructor parameter in a Singleton. See more at
Dependency Injection.