The configuration
This page is about the configuration of a website made with Kiwa. Kiwa stores all its configuration inside the config folder.
Table of contents
Configuration file formats
Kiwa supports three different formats for the main configuration file. All of them are loaded from the config folder:
config.phpusing the generator objects. This is the example from Getting started.config.phpreturning a plain PHP array. The keys of the array are the same as the values which are set by the generator methods below.config.yamlas a YAML file containing the same structure as the PHP array.
You can convert between these formats with the Kiwa Console using the config:convert command.
Basic settings
The ConfigGenerator class helps to create the configuration by providing simple setter methods. Let's have a look at a full example:
<?php
use BitAndBlack\Duration\Duration;
use Kiwa\Config\Generator\CacheControlGenerator;
use Kiwa\Config\Generator\ConfigGenerator;
use Kiwa\Config\Generator\SecurityHeadersGenerator;
$configGenerator = new ConfigGenerator();
$configGenerator
->setMainURL('https://www.example.org')
// URL handling
->enableSSL()
->enableWWW()
->setPageSuffix('html')
->setURLStructure('languageCode', 'name', 'subname')
// Language handling
->enableStrictLanguageHandling()
->setDefaultLanguageCode('en-gb')
// Meta tags
->setDefaultViewport('width=device-width, initial-scale=1')
->setDefaultRobots('index, follow')
->setDefaultOGSiteName('Company Name')
->setDefaultOGTitle('en', 'My page title')
->setDefaultDescription('en', 'My meta description')
->setDefaultOGDescription('en', 'My og description')
->setDefaultOGURL('https://www.example.org')
->setDefaultOGImage('/build/images/og-image.png')
// Caching
->setCacheControl(CacheControlGenerator::create()
->setMaxAgeImmutableFiles((int) Duration::createFromDays(365)->getSeconds())
->setMaxAgeUnknownFiles((int) Duration::createFromDays(7)->getSeconds())
->setMaxAgeAssetFiles((int) Duration::createFromDays(60)->getSeconds())
)
// Security
->setSecurityHeaders(SecurityHeadersGenerator::create()
->setReferrerPolicyStrictOriginWhenCrossOrigin()
->setXContentTypeOptionsNoSniff()
->setXFrameOptionsSameOrigin()
)
->addPage(PageGenerator::create()
// ...
);
In the following sections, each group of methods is explained in detail.
The URL structure
- The method
setMainURL(string $mainURL)defines the base URL of your project, for examplehttps://www.example.org. While your assets may be referenced with relative URLs, this absolute URL is needed in some cases, for example for meta information (og:url), canonical and alternate links, and sitemaps. If noog:urlis set,setMainURLwill also set the defaultog:url. - With
enableWWW()anddisableWWW()you can force or forbid thewwwprefix. Please note thatwwwis a subdomain: if your project runs on a subdomain already,wwwneeds to be disabled. This setting also affects the generated.htaccessfile when you use the Kiwa Console. - With
enableSSL()anddisableSSL()you can force or forbid the use of HTTPS. This affects what generated URLs look like and also the generated.htaccessfile. setPageSuffix(false|string $pageSuffix)defines the suffix of your page URLs. Allowed values arefalse(no suffix),htm,htmlandphp. Please note that a suffix may cause pages to fail loading in environments without the Apachemod_rewriteenabled; in these cases, disable the suffix.setURLStructure(string $position1, string $position2, string $position3 = null)defines where the three URL fragmentslanguageCode,nameandsubnameare placed inside a URL.
Read more about the URL structure under the section URLs and Links.
Language handling
enableStrictLanguageHandling()forces a strict handling: a page may NOT link to another page in a different language.disableStrictLanguageHandling()allows pages to link to other language versions.setDefaultLanguageCode(string $languageCode)sets the default language code, for exampledeorde-de. This one is important as a fallback for projects where the language code is not part of the URL.
Read more about language handling under the section Languages and Translations.
Search engine optimization
These methods define the default meta tags, which are used on every page unless a page defines its own values (see Page settings):
setDefaultViewport(string $viewport)sets the viewport. The recommended value iswidth=device-width, initial-scale=1.setDefaultRobots(string $robots)sets the robots meta tag, for exampleindex, follow.setDefaultOGURL(string $ogURL)sets the defaultog:url. If not set, it will be equal to themainURL.setDefaultOGSiteName(string $ogSiteName)sets the defaultog:site_name.setDefaultOGImage(string $ogImage)sets the defaultog:image. Use a relative URL, for example/build/images/image.png.setDefaultOGTitle(string $languageCode, string $title)sets the defaultog:titlefor a specific language.setDefaultDescription(string $languageCode, string $description)sets the default meta description for a specific language. It also sets theog:descriptionif none has been defined yet.setDefaultOGDescription(string $languageCode, string $description)sets the defaultog:descriptionfor a specific language.
Read more about this under the section Search engine optimization.
Cache control
The cache control configuration defines how long a browser may keep a file in its cache. It is set up with the CacheControlGenerator class and added with setCacheControl(CacheControlGenerator $cacheControlGenerator).
The generator provides three values, all of them are seconds:
| Method | Default value | Description |
|---|---|---|
setMaxAgeAssetFiles(int $seconds) |
60 days | All asset files like JavaScript, CSS, images. |
setMaxAgeImmutableFiles(int $seconds) |
365 days | Versioned files found in the manifest.json. |
setMaxAgeUnknownFiles(int $seconds) |
7 days | All other files. |
Writing the seconds as plain numbers is error-prone. The bitandblack/duration library provides factory methods for durations which are much easier to read. It is a dependency of Kiwa, so it is available in every project without further installation:
<?php
use BitAndBlack\Duration\Duration;
use Kiwa\Config\Generator\CacheControlGenerator;
use Kiwa\Config\Generator\ConfigGenerator;
$config = new ConfigGenerator();
$config
->setCacheControl(CacheControlGenerator::create()
->setMaxAgeAssetFiles((int) Duration::createFromDays(60)->getSeconds())
->setMaxAgeImmutableFiles((int) Duration::createFromDays(365)->getSeconds())
->setMaxAgeUnknownFiles((int) Duration::createFromDays(7)->getSeconds())
)
;
return $config->getConfig();
Available factory methods are createFromNanoSeconds(), createFromMicroSeconds(), createFromMilliSeconds(), createFromSeconds(), createFromMinutes(), createFromHours(), createFromDays() and createFromWeeks(). Each of them can be converted with getters like getSeconds(). In fact, Kiwa uses this library internally to create its default values.
Versioned assets (their file name appears in a manifest.json inside the public/build folder) are additionally marked as immutable. Read more about caching under the section Caching and Cache Control.
Security headers
The security headers configuration is created with the SecurityHeadersGenerator class and added with setSecurityHeaders(SecurityHeadersGenerator $securityHeadersGenerator). It is responsible for the following headers:
Strict-Transport-Security, set withsetStrictTransportSecurity(int $maxAge, bool $includeSubDomains = true, bool $preload = false). The$maxAgeis given in seconds; build it with the bitandblack/duration library for more readable code, for examplesetStrictTransportSecurity((int) Duration::createFromDays(365)->getSeconds()).X-Content-Type-Options, set withsetXContentTypeOptionsNoSniff().X-Frame-Options, set withsetXFrameOptionsDeny()orsetXFrameOptionsSameOrigin().Referrer-Policy, set with one ofsetReferrerPolicyNoReferrer(),setReferrerPolicyNoReferrerWhenDowngrade(),setReferrerPolicyOrigin(),setReferrerPolicyOriginWhenCrossOrigin(),setReferrerPolicySameOrigin(),setReferrerPolicyStrictOrigin(),setReferrerPolicyStrictOriginWhenCrossOrigin()orsetReferrerPolicyUnsafeUrl().Content-Security-Policy, set withsetContentSecurityPolicy(string ...$contentSecurityPolicy). Multiple directives are chained with a semicolon; for examplesetContentSecurityPolicy('default-src \'none\'', 'script-src https://kiwa.io')results inContent-Security-Policy: default-src 'none'; script-src https://kiwa.io.
Per default, the following behaviour is applied: script-src 'unsafe-inline' 'self' (extended by https: when SSL is enabled), Referrer-Policy: strict-origin-when-cross-origin, HSTS for 365 days with includeSubDomains, X-Content-Type-Options: nosniff and X-Frame-Options: SAMEORIGIN.
Authentication
With enableAuthentication(string $user, string $password) you can add a basic authentication to your website. The setting only takes effect when you have the Kiwa Console installed, which generates the .htaccess and the .htpasswd files from it (and mod_rewrite is enabled).
Please note that we don't recommend adding sensitive values to your config file. A better way is to add them to the .env.local file:
useHtpasswd=true
htpasswdUser=USER_NAME
htpasswdPassword=USER_PASSWORD
Page settings
Each page is defined by the PageGenerator class and added with addPage(PageGenerator $config) from the ConfigGenerator. A minimal page configuration looks like that:
<?php
use Kiwa\Config\Generator\ConfigGenerator;
use Kiwa\Config\Generator\PageGenerator;
$configGenerator = new ConfigGenerator();
$configGenerator
->addPage(PageGenerator::create()
->setLanguageCode('en')
->setName('imprint')
->setFile('imprint')
);
The following methods are available:
| Method | Description |
|---|---|
setName(string $name) |
Sets the page name. This will be part of the URL. (required) |
setFile(string $fileName) |
Sets the phtml file which should be loaded for this page. (required) |
setLanguageCode(string $languageCode) |
Sets the language code of this page. (required) |
setChildOf(string $parentPageName) |
Defines this page as a subpage of the given page name. |
setDynamicChild(string $childPageName) |
Allows this page to have dynamic subpages which are routed into the given child page. |
setPageTitle(string $pageTitle) |
Sets the page title. If no og:title is set, this value will be used for it, too. |
enableCaching(int $lifetimeSeconds = null) |
Enables the page cache. The optional lifetime, given in seconds, defines when the cache file gets renewed. null means never. Build the value with the bitandblack/duration library, for example enableCaching((int) Duration::createFromHours(12)->getSeconds()). |
disableCaching() |
Disables the page cache. |
Read more about setChildOf and setDynamicChild under the section Routing, and more about enableCaching under the section Caching and Cache Control.
Meta tags for pages
Every page can define its own meta tags which override the defaults defined in the basic settings:
| Method | Description |
|---|---|
setOGTitle(string $title) |
Sets the og:title. |
setDescription(string $description) |
Sets the meta description and the og:description, if none is set. |
setOGDescription(string $description) |
Sets the og:description. |
setOGImage(string $imagePath) |
Sets the og:image. Use a relative path like /build/images/foo.png. |
setPageType(string $pageType) |
Sets the og:type. Allowed values: website, article, book, profile. |
Please note that setChildOf and setDynamicChild exclude each other: a page can either be a subpage or have dynamic subpages. Defining both will throw a Kiwa\Exception\Config\MisleadingConfigException.
Environment variables
Kiwa loads environment variables from the .env file and its environment-specific variants (.env.local, .env.{APP_ENV}, .env.{APP_ENV}.local). The most important variables are:
APP_ENVdefines the environment, for exampledevorprod. It controls the error handling and logging behaviour.useHtpasswd,htpasswdUser,htpasswdPasswordconfigure the basic authentication without having to store sensitive data inside the config file.
All other settings can be accessed in your code through the DI class:
<?php
use Kiwa\DI;
$config = DI::getConfig();
/** Get a single value, for example the main URL. */
echo $config->getValue('mainURL');
/** Get the whole config as an array. */
var_dump($config->getAllValues());
/** Check if a value exists. */
var_dump($config->hasValue('securityHeaders'));
You can find more information about reading the config in the section Page handling.