[cp 2] generate slug when saving collection

Reason for this topic: The addons BetterSlugs and Unique Slug do not work yet with our new and improved codebase. Secondly, I need slugs for my routes.

Purpose for this topic: I want to have a simple bootstrap.php file in my config folder to generate the slug for me.

My idea: Having a field of type ‘text’ named ‘slug’ and in its options a key ‘slugField’ with the name of the field to generate the slug from. When I create/update an entry, cockpit needs to generate and save the (unique) slug if field slug is empty.

I have cockpit-core (2.0.2) installed and created different collections like posts, pages, etc.
In my pages collection, there are several fields like title and slug. (top part of picture)
And in the options of the ‘slug’ field, I added ‘slugField’ as the key and ‘title’ as the value. (bottom part of picture)

This was rather simple thanks you our devs of cockpit.

Help needed:
I have tried to put together a ‘bootstrap.php’ to act when a collection is being saved, but it still isn’t generating a slug.
Simple slugs for collections in Cockpit CMS

What am I missing here? Somebody push me in the right direction please :slight_smile:

1 Like

:rotating_light: NOT TESTED :rotating_light:

in your config/bootstrap.phpadd the following snippet:


$app->on('content.item.save', function($modelName, $data) {

    $model = $this->module('content')->model($modelName);
    $collection = $model['type'] == 'singleton' ? 'content/singletons' : "content/collections/{$modelName}";
    $fields = $model['fields'] ?? [];

    foreach ($fields as $field) {

        // check if slug field and referenced field is in data
        if (isset($field['opts']['slugField'], $data[$field['opts']['slugField']])) {
            $data[$field['name']] = $this->helper('utils')->sluggify($data[$field['opts']['slugField']]);
            $this->dataStorage->save($collection, $data);
1 Like

Thank you @artur for your time.
I can confirm this works.

next step for me is to make sure the slug is unique within the model and then update my gist so others can use this if needed. :smiley:

Is this still working in v2.3.0 ?
I tried, but without any success.


Hi 314!
I updated my file a little.
Check the last version on my gist (link in first post).

It checks if the generated slug is unique in the collection.
if not then adds an incremental count.

to do: when i hit ‘save’ i would like to trigger a ‘page refresh’. so it updates the slug-field. Now i need to go back to the list-view of the collection.
Any help is appreciated :slight_smile:

Hey thank you!
I tried with the updated script but still without luck.

Not sure if i’am using it correctly.

Should i really just be named bootstrap.php and then put in the folder config?
There is no file named bootstrap.php in the config folder. I do have to create it.

Or do i have to enable external script somehow in cockpit?

Update would be nice yeah, but seems difficult without js…
The redirect, you thought of in your script seems like a viable way.
Doesn’t it work?

Yes, just create it in the config folder and it should just work.

make sure you have a field (type = ‘text’) named ‘slug’ in your collection and in the fields options add a json key ‘slugField’ with the value of the field you want to generate the slug from (example => “slugField: ‘name’,”)

Hey thank you very much.
I got it working in the end.
Silly me put it in the wrong cockpit installation.

Works perfectly!


1 Like

I changed my “bootstrap.php”-file a little.
When i updated an item, it would add a -1 to the slug.


  1. When it searches for the slug in the collection, it checks if the ‘_id’ is the same as the one you want to update. (no more unneccesary ‘-1’)
  2. If the field named ‘slug’ already has a value, it uses this value for the search in the collection. (now you can change it yourself if you want)

Make sure to grab the latest version on my gist (link in first post).

@artur i would be very greatful if you could help me with my ‘page-refresh’-problem (line 69 and 70).
i tried for instance several versions of “$this->reroute(‘/content/items/pages’);” and even \header(“Location:…”) to no avail.

Please make sure to update to the latest Cockpit version.

Now hook into the content.item.save.before event:

$app->on('content.item.save.before', function($modelName, &$data, $isUpdate) {
  $data['slug'] = 'xyz';

As you can see, you can now update/modify the data before it is saved.

This does the job!
I changed the gist accordingly (link in first post).

Thank you for your help!

Hi everybody,
I have updated my code to include the ‘sluggification’ of localized fields if applicable.
Grab the updated code if you are interested (link in first post).
Enjoy the rest of your day!