Slug Creation Pipeline
Creates a clean SEF slug from a title while preserving readability and uniqueness support.
Function signature
ogCreateSeoSlug(title, max_length = 90, options = array())
Categories
- SEO and Routing
Parameters
titleSource title.max_lengthMaximum slug length.optionsOptional stop_words and fallback_slug values. Recognized keys: `fallback_slug`, `stop_words`.Return value
Short public-safe status message.
- slug
Compatibility
Existing function name and call order preserved; metadata signature corrected to source.
Minimum PHP version: 7.4
Security notes
Validate request method, identity, permissions, and caller-owned allowlists before use; keep secrets and internal paths out of public output.
Code
<?php
/*
* Copyright (c) 2026 Jeffery L. Paris <jparis@phpog.com>.
* Free for personal and internal use. Paid project use requires visible credit
* to Jeffery L. Paris. Corporate use requires a paid license fee unless a
* separate written license states otherwise.
*/
/**
* Creates a clean SEF slug from a title while preserving readability and uniqueness support.
*
* Primary use case: SEO URLs for snippets, functions, scripts, articles.
* Typical inputs: title string, max length, stop word options.
* Typical output: slug string.
*
* Implementation note: Normalize Unicode carefully and avoid duplicate slugs.
*
* @param string $title Source title.
* @param int $max_length Maximum slug length.
* @param array $options Optional stop_words and fallback_slug values.
* @return array Structured slug creation result.
*/
function ogCreateSeoSlug($title, $max_length = 90, $options = array()) {
$result = array(
'success' => false,
'message' => '',
'data' => array('slug' => '')
);
$title = trim((string)$title);
$max_length = (int)$max_length;
if (!is_array($options)) {
$options = array();
}
if ($max_length < 20) {
$max_length = 20;
}
if ($max_length > 180) {
$max_length = 180;
}
if (empty($title)) {
$result['message'] = 'Missing title.';
return $result;
}
$source = $title;
if (function_exists('iconv')) {
$converted = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $source);
if ($converted !== false) {
$source = $converted;
}
}
$slug = strtolower($source);
$slug = preg_replace('/[^a-z0-9]+/i', '-', $slug);
$slug = trim($slug, '-');
$slug = preg_replace('/-+/', '-', $slug);
if (!empty($options['stop_words']) && is_array($options['stop_words'])) {
$parts = explode('-', $slug);
$filtered = array();
foreach ($parts as $part) {
if (!in_array($part, $options['stop_words'], true)) {
$filtered[] = $part;
}
}
if (!empty($filtered)) {
$slug = implode('-', $filtered);
}
}
if (strlen($slug) > $max_length) {
$slug = substr($slug, 0, $max_length);
$slug = trim($slug, '-');
$last_dash = strrpos($slug, '-');
if ($last_dash !== false && $last_dash > 20) {
$slug = substr($slug, 0, $last_dash);
}
}
if (empty($slug)) {
$slug = 'item';
if (!empty($options['fallback_slug'])) {
$slug = ogCreateSeoSlug($options['fallback_slug'], $max_length);
$slug = $slug['data']['slug'];
}
}
$result['success'] = true;
$result['message'] = 'SEO slug created.';
$result['data'] = array('slug' => $slug);
return $result;
}