Create page slug from two fields

Hi,

I am building a music label website. I have a category “Releases” that contains all releases.
I set up the panel for the single release pages such that there is a structure field for the artists and a text field for the release title (among other).

I want the page’s slug be in the pattern “artistName-releaseTitle”.
However I do not trust other users to be consistent when creating new pages.

I tried the custom-add-field plugin by steirico (https://github.com/steirico/kirby-plugin-custom-add-fields) to skip the add dialog. But I am stuck in how to implement a fool-proof method for adding new releases.

Ideally the workflow would be

  1. Click “Add” –> new page opens
  2. Fill out the release page form: “Artists” / “Title” / write some text etc…
  3. Hit “Save”
  4. The release page get’s saved with the slug “artistName-releaseTitle”

Can anyone point me in a direction here?

:wave:
You can use a page model together with the plugin for the subpage in which your override the create method, example:

<?php
use Kirby\Cms\Page;
use Kirby\Toolkit\Str;

class ReleasePage extends Page
{

    public static function create(array $props): Page
    {
        $props['slug'] = Str::slug($props['content']['title']);
        
        return parent::create($props);
    }
}

If you use a structure field for the artist, then you won’t have a single artist, though, and would have to make sure to fetch the first or so…

Make sure to require the artist field in the add dialog to make sure you get the desired results.

Hi texnixe,

thank you very much for your kind and fast support.

I set up the addon with the ‘title’ field and an ‘release_artists’-structure field and wanted to go from there figuring out how to get the first two artists from the structure field in the page model. I created a file site/models/releases.php

However, Kirby doesn’t seem to recognise the file at all or it doesn’t affect the create method.
I copied your solution.

For testing I changed this

into

$props['slug'] = Str::slug('A new release page');

without any effect to the slug which remains the kirby default title of the page.

I really can’t figure out what I am doing wrong…

What is the blueprint/template name for a single release? Looks like you created the model for the parent page rather then the subpages?

The blueprint/template is called release.php
The parent page is called releases.php

release.php in site/models/ is like so:

<?php
    use Kirby\Cms\Page;
    use Kirby\Toolkit\Str;

    class ReleasePage extends Page
    {

    public static function create(array $props): Page
    {
        $props['slug'] = Str::slug($props['content']['title']);
        
        return parent::create($props);
    }
    }
?>

and release.yml in site/blueprints/pages/ has:

addFields:
    title:
        type: text
        label: Release Title
    release_artists:
        label: Artist
        type: structure
        fields:
            release_artist:
                label: Artist
                type: text
        required: true

And this sttill doesn’t work, not even if you use

$props['slug'] = Str::slug('Hallo Welt');

And the text files are created as release.txt? If so, then the model should work. It should in fact work completely independently from the custom add field.

On a side note, don’t use a closing php tag on php only files (has nothing to do with the issue).

Hi,

Yes, I tried this and checked twice and the slug remains the same – draft or published doesn’t matter.
It always takes the title as slug.

Hi,

I am still stuck here somehow. The problem that the slug wasn’t changing was solved by reinstalling Kirby. I don’t know why since I didn’t change anything in the Kirby folder nor did the version change (3.4.0) but it did the trick.

Right now the model models/release.php looks like this. (The slug is made up from to the title alone for testing purposes and shall be extended by the artist in the final version):

 <?php

    use Kirby\Cms\Page;
    use Kirby\Toolkit\Str;

    class ReleasePage extends Page
    {

        public static function create(array $props): Page
        {
            $props['slug'] = Str::slug($props['title']);

            return parent::create($props);
        }
    }

Blueprint release.php (excerpt):

title: Release

addFields:
    title:
        type: text
        label: Release Title
    release_artists:
        label: Artist
        type: structure
        fields:
            release_artist:
                label: Artist
                type: text
        required: true

However, when I try to create a page in the panel I get the error:

Undefined index: title

diregarding the error and clicking on OK in the dialog:

Undefined index: template

Any ideas? I am rather clueless at this point. Maybe a completely different approach?
All I want it a slug like Artists-Title from the title text field and the release_artists structure field. It doesn’t really matter when the slug is changed, just that it has this pattern when published.

1 Like

Should be

$props['slug'] = Str::slug($props['content']['title']);

:see_no_evil: thanks