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.php using the generator objects. This is the example from Getting started.
  • config.php returning a plain PHP array. The keys of the array are the same as the values which are set by the generator methods below.
  • config.yaml as 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 example https://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 no og:url is set, setMainURL will also set the default og:url.
  • With enableWWW() and disableWWW() you can force or forbid the www prefix. Please note that www is a subdomain: if your project runs on a subdomain already, www needs to be disabled. This setting also affects the generated .htaccess file when you use the Kiwa Console.
  • With enableSSL() and disableSSL() you can force or forbid the use of HTTPS. This affects what generated URLs look like and also the generated .htaccess file.
  • setPageSuffix(false|string $pageSuffix) defines the suffix of your page URLs. Allowed values are false (no suffix), htm, html and php. Please note that a suffix may cause pages to fail loading in environments without the Apache mod_rewrite enabled; in these cases, disable the suffix.
  • setURLStructure(string $position1, string $position2, string $position3 = null) defines where the three URL fragments languageCode, name and subname are 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 example de or de-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 is width=device-width, initial-scale=1.
  • setDefaultRobots(string $robots) sets the robots meta tag, for example index, follow.
  • setDefaultOGURL(string $ogURL) sets the default og:url. If not set, it will be equal to the mainURL.
  • setDefaultOGSiteName(string $ogSiteName) sets the default og:site_name.
  • setDefaultOGImage(string $ogImage) sets the default og:image. Use a relative URL, for example /build/images/image.png.
  • setDefaultOGTitle(string $languageCode, string $title) sets the default og:title for a specific language.
  • setDefaultDescription(string $languageCode, string $description) sets the default meta description for a specific language. It also sets the og:description if none has been defined yet.
  • setDefaultOGDescription(string $languageCode, string $description) sets the default og:description for 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 with setStrictTransportSecurity(int $maxAge, bool $includeSubDomains = true, bool $preload = false). The $maxAge is given in seconds; build it with the bitandblack/duration library for more readable code, for example setStrictTransportSecurity((int) Duration::createFromDays(365)->getSeconds()).
  • X-Content-Type-Options, set with setXContentTypeOptionsNoSniff().
  • X-Frame-Options, set with setXFrameOptionsDeny() or setXFrameOptionsSameOrigin().
  • Referrer-Policy, set with one of setReferrerPolicyNoReferrer(), setReferrerPolicyNoReferrerWhenDowngrade(), setReferrerPolicyOrigin(), setReferrerPolicyOriginWhenCrossOrigin(), setReferrerPolicySameOrigin(), setReferrerPolicyStrictOrigin(), setReferrerPolicyStrictOriginWhenCrossOrigin() or setReferrerPolicyUnsafeUrl().
  • Content-Security-Policy, set with setContentSecurityPolicy(string ...$contentSecurityPolicy). Multiple directives are chained with a semicolon; for example setContentSecurityPolicy('default-src \'none\'', 'script-src https://kiwa.io') results in Content-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_ENV defines the environment, for example dev or prod. It controls the error handling and logging behaviour.
  • useHtpasswd, htpasswdUser, htpasswdPassword configure 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.