Slug Generator
Last updated: 04/17/2026 · Written by Agent0
Slug Generator
StackCTL includes a generate_slug() global helper that converts any string into a URL-safe slug and automatically guarantees uniqueness by checking the database. It's available everywhere in the application — no imports needed.
How It Works
When called, the helper:
- Converts the input string to lowercase
- Replaces non-alphanumeric characters with hyphens
- Trims leading and trailing hyphens
- Caps the slug at 100 characters
- Queries the specified table to check for a duplicate slug
- If the slug is already taken, appends an incrementing suffix (
-1,-2, etc.) until a unique one is found
It uses the shared database connection from the App container — no PDO instance needs to be passed manually.
Basic Usage
$slug = generate_slug('Hello World', 'articles');
// → 'hello-world'
// If 'hello-world' already exists in the articles table:
// → 'hello-world-1'
// If 'hello-world-1' also exists:
// → 'hello-world-2'
Signature
generate_slug(string $value, string $table, string $column = 'slug'): string
- $value — The string to slugify (e.g. an article title or category name)
- $table — The table to check for uniqueness
- $column — The column to check against. Defaults to
'slug'
Example: Generating a Slug on Create
Call generate_slug() in your controller's save() method when creating a new record. Include the result in the data array passed to insert().
public function save()
{
$id = !empty($_POST['id']) ? (int)$_POST['id'] : null;
$data = [
'title' => trim($_POST['title']),
'content' => $_POST['content'],
'created_by' => auth('id'),
];
if ($id) {
// Updating — don't regenerate the slug
Query::table('articles')->where('id', $id)->update($data);
flash('success', 'Article updated.');
} else {
// Creating — generate a unique slug from the title
$data['slug'] = generate_slug($_POST['title'], 'articles');
Query::table('articles')->insert($data);
flash('success', 'Article created.');
}
redirect('/articles');
}
Important: Only generate a slug on create, not on update. Regenerating a slug on update would break any existing links or bookmarks pointing to the original URL.
Custom Column Name
If your table uses a different column name than slug, pass it as the third argument:
$slug = generate_slug($name, 'categories', 'url_key'); // Checks the 'url_key' column in the 'categories' table
Edge Cases
- If the input string is empty or produces no valid characters, the slug falls back to
'n-a' - Slugs are capped at 100 characters before the uniqueness suffix is added
- The helper is safe to call with any user-supplied input — special characters, Unicode, and symbols are all handled