Snippets with slots
Templating on another level
<?php snippet('article', slots: true) ?>
<?php slot('header') ?>
<h1>This is the title</h1>
<?php endslot() ?>
<?php slot('body') ?>
<p>This is some body text</p>
<?php endslot() ?>
<?php endsnippet() ?>
<article>
<?php if ($header = $slots->header()): ?>
<header>
<?= $header ?>
</header>
<?php endif ?>
<?= $slots->body() ?>
</article>
$slots variable. Snippets can have multiple slots and you can even combine slots with data variables.
Structure field improvements
New row & delete all buttons
PHP 8.2 support
PHP moves forward, we do too
Satellite Releases
Ecosystem improvements
Kirby CLI 1.1.0
Kirby::plugin('your/plugin', [
'commands' => [
'your-plugin:test' => [
'description' => 'Nice command',
'args' => [],
'command' => function ($cli) {
$cli->success('My first plugin command');
}
]
]
]);
$ kirby your-plugin:test
# My first plugin command
Kirby KQL 2.0.0
Staticache 1.0.0
Staticache is our alternative page cache plugin for Kirby that stores responses as fully static files. This helps you to increase your site performance even more.
With version 1.0.0 it is finally ready for prime time for a lot of common site setups. It now comes with support for multi-language sites and content representations as well as with a new mode that caches custom HTTP response headers as well.
return [
'cache' => [
'pages' => [
'active' => true,
'type' => 'static',
'root' => '/path/to/your/cache/root',
'comment' => '<!-- your custom cache comment -->',
'headers' => true
]
]
];
Eleventykit 🎈
The Eleventykit is a very simple (unstyled) example for a site, built with Kirby and 11ty.
Kirby’s query language (KQL) is used to fetch articles from our KQL playground: https://kql.getkirby.com
Use your own Kirby installation with the KQL plugin to provide a powerful headless CMS for your static 11ty site.
const { $fetch } = require("ofetch");
module.exports = async function () {
const api = "https://kql.getkirby.com/api/query";
const response = await $fetch(api, {
method: "post",
body: {
query: "page('notes').children.sortBy('date', 'desc')",
select: {
title: true,
text: "page.text.toBlocks.toHtml",
slug: true,
date: "page.date.toDate('d.m.Y')"
}
}
});
return response.result;
}
Changelog
Features
Enhancements
Image\Imageuses its model'saltcontent field as fallback for rendering thealtattribute to better provide accessible defaults (we already did it for direct image objects, but now it also works for thumbs etc.) #4915- Pages section: the status flag button’s tooltip now includes the non-customised label of the current status for better accessibility #4928
- The license registration dialog now displays an info field for which domain the license will be registered, including a warning when registering a local domain #4930
Dimensions::forSvg()supports percentages and better viewport fallbacks #4921Xml::attr()andHtml::attr()accept non-associative values (e.g.Xml::attr(['attrA'])), which get rendered like passingtrue(e.g.attrA="attrA"/attrA) #4935- The
Dir::copy()method now supportsfalseas the argument for$ignore. In this mode, all files are copied, including those listed in the globalDir::$ignorelist. #4872 F::move()now ensures that the parent directory exists, which is consistent withF::copy()#4943File::create(),$parent->createFile()and$file->replace()support a new mode that moves the source file instead of copying it #4943- Sensitive information like passwords is redacted in logs when using PHP 8.2+ #4945
Bug fixes
- Dynamic options for the select field (from API or query) are no longer displayed with double-escaping in the Panel #4974
- Options from API in options fields (e.g. select, checkboxes) now support simple key/value data like
{"key": "value"}again #4987 - Using options from API in options fields (e.g. select, checkboxes) also works without the
querysetting again #4985 - Writer: links now fully wrap inline styling instead of generating multiple link parts #4866
- Kirby queries: optional chaining on non-null values now works properly #4901
- Escaping quotes inside query arguments with
\"and\'now behaves like it does in PHP (only the same type of quote used for the string can be escaped) #4976 - Uploaded files are deleted from the temporary directory after they have been successfully stored in the content directory. #2476
- Fixed focus for checkboxes and radio input with no options #4917
- Fixed
undefinederror when paginating the structure field #5000 - The
page.changeSlughook now receives the correct$languageCode#4983 - Files field: for
store: idonly the name is stored again when the current model is the file's parent #4870 - Fixed prepending redundant
mailto:ink-link#4882 Toolkit\Xml::attr()is case-sensitive now #4911- Now treating paths with trailing dot as non-existing content representation #4920
- Fixed console errors for failed
lockrequest when deleting page with unsaved changes #4919 - Fixed error message for missing field type #4929
->words()field method works as expected onnullvalues #4905- Fixed false-positive blocked requests by ModSecurity (OWASP rules) #4933
- Panel: load development icons file when in dev mode #4900
- I18n: English translation had
Februaryset toFeburary#4903
Refactoring
- Improvements for
Toolkit\Localecode quality #4926 - Improvements for
Toolkit\Escapecode quality #4925 - Improvements for
Toolkit\Objcode quality #4923 - Improvements for
Toolkit\Acode quality #4942 - Improvements for
Toolkit\I18ncode quality #4939 - Improvements for
Toolkit\Silocode quality #4922 - Improvements for
Toolkit\Controllercode quality #4937 - Improvements for
Toolkit\Iteratorcode quality #4938 - Improvements for
Toolkit\HtmlandToolkit\Xmlcode quality #4959 - Improvements for
Toolkit\Strcode quality #4961 - Improvements for
Textcode quality #4956 - Improvements for
BlueprintandOptioncode quality #4974 - Upgraded to Vite 4 and some other JS dependencies #4912
- Updated Composer dependencies #4946
- PHP 8.2 prep: Fix dynamic properties in search component #4888
- PHP 8.2 prep: Fix
mb_convert_encoding()deprecation in Parsedown #4887 - The
Kirby\Cms\Templateclass moved toKirby\Template\Template. An alias has been added. #4910 - Our unit tests now always trigger our own deprecation warnings, which allows us to find uses of deprecated code in our own code. #4948
- Use of the null coalescing assignment operator
??=where possible #4957 - Use of
instanceof, the.=operator,array_key_exists()and property defaults where possible #4958 - Nested
ifstatements have been combined/removed #4958 - More of our PHPUnit tests use a temporary directory now to prevent tests from creating a stray
sitedirectory in the top-level of the project #4973 - Fixed type hints and docblocks throughout the codebase #4971
- Fixed broken link in the contribution guide #4960
- Our PHPUnit tests consistently use
assertSameinstead ofassertEqualswhere possible and use more specific assertions (e.g.assertTrue,assertNull,assertFileExists,assertArrayHasKey) #4975 - Fixed ghost output during PHPUnit test runs #4964
Deprecated
- Manually passing
$slotor$slotsas data variables to snippets is deprecated. In a future Kirby version, those variables will be overridden with theSlotandSlotsobjects. #4963 - The
Toolkit\Queryclass has been deprecated and will be removed in a future version. UseQuery\Queryinstead. #4944 - Passing an empty string as value to
Xml::attr()/Html::attr()has been deprecated and will throw a warning. In a future version, passing an empty string won't omit the attribute anymore but render it with an empty value. To omit the attribute, please passnull. #4934 - The
.k-offscreenCSS class has been deprecated. Use.sr-onlyinstead. #4944
Breaking changes
We try to avoid breaking changes as much as we can. But we also put a lot of effort in keeping our technical debt in Kirby as low as possible. Sometimes such breaking changes are necessary to move forward with a clean code base.
You might wonder why there are breaking changes in a minor release according to Semantic Versioning.
We stick to the following versioning scheme:
{generation}.{major}.{minor}(.{patch})
This release is Kirby 3.9.0.0 (major release 9 of Kirby 3)
Traditionally, we combine patch and minor releases though and only need the fourth versioning level for regression fixes.
$kirby->impersonate()doesn't bind the app instance to the$callbackclosure anymore. You can access the app instance withKirby\Cms\App::instance()or thekirby()helper. #4944- The
snippetcore component receives an additional parameterbool $slotsand needs to returnKirby\Template\Snippetorstringfor slot support. If you override thesnippetcomponent, please adapt the logic to the new core component. #4910 $kirby->snippet()and thesnippet()helper returnKirby\Template\Snippetorstringornull#4910Html::rel()now consistently returnsnullinstead of an empty string when norelattribute is needed #4948A::missing()no longer treats an existing array key with anullvalue as missing #4942
Removed deprecated code
- Deprecated method
Kirby\Cms\App::server()has been removed. UseKirby\Cms\App::environment()instead. #4944
Migration from Kirby 3.8.x
There are not many steps needed to migrate from Kirby 3.8 to Kirby 3.9. To ease the transition, we have compiled everything you need to know in migration guides:
Migration guide for site developers →
Migration guide for plugin developers →