CakePHP 4: Slugged Behavior

Slug is the part of the URL which identifies a particular page on web or system in an easy reading form. Slug is generated based on a specific field such as article title, name, event or any relevant field. If you have a document title (CakePHP Note 2020) and you upload it into your system the uploaded document will get its own unique ID which will be used as a reference ID to access the document. A standard URL to access the uploaded document will be eg: localhost/myCake/documents/11 which 11 is an ID (auto-generated) for the uploaded document (CakePHP Note 2020). Let say that the documents table have (id, title and year), so the slug can be generated based on the title of the documents which will generate the URL as localhost/myCake/documents/cakephp-note-2020. Use the CakePHP Tools Plugin to easily generate the slug.


Download the CakePHP Tools Plugin

Download CakePDF plugin via composer:

composer require dereuromark/cakephp-tools


Load the plugin using the console:

bin/cake plugin load Tools


or manually add the following code to ...\src\Application.php

$this->addPlugin('Tools');


Configuration

Make sure your database table has 'slug' column eg table documents [id, title, year, slug]. If you need to store the slug in the different column name, use 'slug' => 'columnName' in the configuration.

Attach the following codes to your model in initialize() section:

$this->addBehavior('Tools.Slugged');


Then add the following configuration codes to set the slug label:

$this->addBehavior('Tools.Slugged',
    ['label' => 'title', 'unique' => true, 'mode' => 'ascii']
);


You can change the 'label' => 'title' to any field that is suitable for your requirement. The slugged will be automatically stored into your database field eg name input: CakePHP Note 2020, so it will be processed and stored as cakephp-note-2020. This slug normally will remain as the original even you edited your title to preserve the access link. However, you can overwrite the slug if it is necessary by adding the following checkbox into your edit page:

echo $this->Form->field('overwrite_slug', ['type' => 'checkbox']); 


To access your record based on slug instead of the ID, the controller should look like these:

public function view($slug)
{
	$document = $this->Documents
		->findBySlug($slug)
		->firstOrFail();
	$this->set(compact('document'));
}


The view button should navigate based on slug as shown below:

<?= $this->Html->link(__('View'), ['action' => 'view', $user->slug], ['class' => 'btn btn-primary', 'escape' => false]) ?>


Now you should be able to access the records based on the slugs. It also makes the URL more readable and easy.

That all. Happy coding :)