Context
I’m building a directory using Kirby CMS in combination with Illuminate/Database (as ORM for a MySQL database).
I’m using Kirby ^4.0
and have integrated Eloquent via Composer.
Composer Dependencies
{
"require": {
"php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0",
"getkirby/cms": "^4.0",
"getkirby/staticache": "^1.0",
"arnoson/kirby-vite": "^5.3",
"ext-zend-opcache": "*",
"ext-gd": "*",
"illuminate/database": "^12.19"
}
}
Relevant Project Structure
site/models/Company.php
: Model for DB interaction (Eloquent)site/config/hooks.php
: Used to sync Kirby content to databasesite/blueprints/pages/company.yml
: Company content typesite/config/database.php
: DB configuration
Goal
Each time an Entry
page is created, updated, or deleted in the Panel, the data should be synced to a MySQL table listings
via Eloquent.
The Problem
When editing or updating or deleting an listing
page in the Kirby Panel (triggering page.update:after
), I get this error:
“The page slug is required”
Even though:
slug
is in the databaseslug
is used in the model or$fillable
slug
is used in the hook- the page has a valid title
Hook Snippet –
page.update:after
'page.update:after' => function (Kirby\Cms\Page $newPage, Kirby\Cms\Page $oldPage) {
if ($newPage->intendedTemplate()->name() !== 'listing') {
return;
}
Listing::query()->updateOrCreate(
['uuid' => $oldPage->uuid()->id()],
[
'name' => $newPage->title()->value(),
'slug' => $newPage->slug(),
'street' => $newPage->street()->value(),
'house_number' => $newPage->house_number()->value(),
'zipcode' => $newPage->zipcode()->value(),
'city' => $newPage->city()->value(),
'email' => $newPage->email()->value(),
'phone' => $newPage->phone()->value(),
'fax' => $newPage->fax()->value(),
'website' => $newPage->website()->value(),
'description' => $newPage->description()->value(),
'tags' => explode(',', $newPage->tags()->value() ?? ''),
'logo' => $newPage->logo()->toFile()?->url(),
'status' => $newPage->status()
]
);
}
Blueprint Snippet –
listing.yml
title: Entry
icon: 📢
fields:
street:
width: 1/3
label: Straße
type: text
house_number:
width: 1/3
label: Hausnummer
type: text
zipcode:
width: 1/3
label: PLZ
type: text
city:
width: 1/3
label: Ort
type: text
email:
width: 1/3
label: E-Mail
type: email
phone:
width: 1/3
label: Telefon
type: tel
fax:
width: 1/3
label: Fax
type: tel
website:
width: 1/3
label: Website
type: url
description:
width: 1/3
label: Beschreibung
type: writer
tags:
width: 1/3
label: Tags
type: tags
logo:
width: 1/3
label: Logo
type: files
layout: cards
template: image
Databse Schema:
Capsule::schema()->create('listings', function ($table) {
$table->id();
$table->uuid('uuid')->unique();
$table->string('name')->unique();
$table->string('slug')->nullable();
$table->string('street')->nullable();
$table->string('house_number')->nullable();
$table->string('zipcode')->nullable();
$table->string('city')->nullable();
$table->string('email')->nullable()->unique();
$table->string('phone')->nullable();
$table->string('fax')->nullable();
$table->string('website')->nullable()->unique();
$table->text('description')->nullable();
$table->string('logo')->nullable();
$table->json('tags')->nullable();
$table->enum('status', ['draft', 'unlisted', 'listed']);
$table->timestamps();
});
Model for Listing
use Illuminate\Database\Eloquent\Model;
use Kirby\Cms\Pages;
class Listing extends Model
{
protected $table = 'listings';
protected $fillable = [
'uuid',
'name',
'slug',
'street',
'house_number',
'zipcode',
'city',
'email',
'phone',
'fax',
'website',
'description',
'logo',
'status',
'tags',
];
protected $casts = [
'tags' => 'array',
];
public static function listed()
{
return Listing::all()->where('status', 'listed');
}
}
class ListingPage extends Kirby\Cms\Page
{
public function children(): Pages
{
if ($this->children instanceof Pages) {
return $this->children;
}
return $this->children = Pages::factory((array)Listing::all(), $this);
}
}
What works:
page.create:after
: syncs to DB correctly includingslug
Column
What fails:
Saving Updates or Delete Page:
“The page slug is required”
Even though I use or don’t use slug
anywhere in my database or PHP logic.
Question
What am I missing?
- Why is Kirby enforcing a required slug on update even though the page exists and has a valid title?
- Could this be caused by
title()->value()
being temporarily empty? - Do I need to manually handle the slug in the update hook even if I don’t store it?
Any advice or ideas are greatly appreciated