// If your pages are .html, rename them to .php OR configure Apache/Nginx to parse .html as PHP.
function bc_base_url(): string {
$isHttps = (
(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ||
(!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) ||
(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https')
);
$scheme = $isHttps ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
// If your site is in a subdirectory, set it here (e.g., '/site')
$subdir = rtrim(dirname($_SERVER['SCRIPT_NAME'] ?? ''), '/\\');
if ($subdir === '/' || $subdir === '\\' || $subdir === '.') $subdir = '';
return $scheme.'://'.$host.$subdir;
}
function bc_segments(): array {
// Strip query/hash, normalize, remove leading subdir if present
$reqUri = $_SERVER['REQUEST_URI'] ?? '/';
$parsed = parse_url($reqUri);
$path = $parsed['path'] ?? '/';
// Normalize: remove subdir portion so crumbs start after your base path
$subdir = rtrim(dirname($_SERVER['SCRIPT_NAME'] ?? ''), '/\\');
if ($subdir && $subdir !== '.' && $subdir !== '/') {
// Ensure we only strip an actual prefix match
if (strpos($path, $subdir.'/') === 0) {
$path = substr($path, strlen($subdir));
}
}
$path = trim($path, '/');
if ($path === '' || $path === 'index.php' || $path === 'index.html') {
return []; // homepage → no segments
}
$raw = array_values(array_filter(explode('/', $path), function ($seg) {
return $seg !== '';
}));
// Remove a trailing index.* if present
$last = end($raw);
if ($last && preg_match('~^index\.(php|html|htm)$~i', $last)) {
array_pop($raw);
}
return $raw;
}
function bc_humanize(string $seg): string {
// Remove extensions, decode, replace separators, title-case lightly
$seg = preg_replace('~\.(php|html|htm)$~i', '', $seg);
$seg = urldecode($seg);
$seg = str_replace(['-', '_'], ' ', $seg);
$seg = trim($seg);
// Uppercase first letter of words without mangling acronyms too much
return preg_replace_callback('/\\b([a-z])/i', function ($m) { return strtoupper($m[1]); }, $seg);
}
function render_breadcrumb(array $title_map = [], bool $hide_on_home = true, string $home_label = 'Home'): void {
$base = rtrim(bc_base_url(), '/');
$segs = bc_segments();
if ($hide_on_home && empty($segs)) {
// On homepage: optionally print nothing. Flip flag to show just "Home" if you want.
return;
}
// Visible breadcrumb
echo '';
// JSON-LD schema
$items = [];
$position = 1;
$items[] = [
'@type' => 'ListItem',
'position' => $position++,
'name' => $home_label,
'item' => $base.'/'
];
$build = '';
foreach ($segs as $seg) {
$build .= '/'.$seg;
$name = $title_map[$seg] ?? bc_humanize($seg);
$items[] = [
'@type' => 'ListItem',
'position' => $position++,
'name' => $name,
'item' => $base.$build
];
}
$schema = [
'@context' => 'https://schema.org',
'@type' => 'BreadcrumbList',
'itemListElement' => $items
];
echo '';
}