Skip to content
← Back to Functions
Code

Canonical Url Builder

Builds protocol-relative canonical URLs from route type, ID, and slug.

Function signature

ogBuildCanonicalUrl(route_type, id = 0, slug = '', host = 'phpog.com')

Categories

  • SEO and Routing

Parameters

route_typeApproved route type used to choose the canonical or SEF URL pattern.idPositive database item ID required for detail URLs.slugSEF slug to clean and place into the URL path.hostSite host to normalize into a protocol-relative, non-www canonical URL.

Return value

Public-safe status string returned by the function for controller branching or logging.

  • success
  • message
  • data

Compatibility

Existing function name, slug, path, and call order preserved; advertised metadata corrected to the actual source behavior.

Minimum PHP version: 7.4

Security notes

Use caller-owned allowlists and context-specific escaping; validate file paths, routes, email tokens, cart totals, discount rules, and tax-region rules before production use.

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.
 */

/**
 * Builds protocol-relative canonical URLs from route type, ID, and slug.
 *
 * Primary use case: SEO tags for list/detail pages.
 * Typical inputs: route type, id, slug, site host.
 * Typical output: canonical URL.
 *
 * Implementation note: Use SEF URLs only; never include tracking params.
 *
 * @return array Structured result data with success, message, and data keys.
 */
function ogBuildCanonicalUrl($route_type, $id = 0, $slug = '', $host = 'phpog.com') {
	$result = array(
		'success' => false,
		'message' => '',
		'data' => array()
	);

	$route_type = trim((string)$route_type);
	$id = (int)$id;
	$slug = trim((string)$slug);
	$host = strtolower(trim((string)$host));
	$host = preg_replace('/^https?:\/\//i', '', $host);
	$host = preg_replace('/^\/\//', '', $host);
	$host = preg_replace('/^www\./i', '', $host);
	$host = trim($host, '/ ');

	if (empty($host) || !preg_match('/^[a-z0-9.-]+$/', $host)) {
		$result['message'] = 'Invalid canonical host.';
		return $result;
	}

	$list_routes = array(
		'snippets' => 'snippets',
		'functions' => 'functions',
		'objects' => 'objects',
		'scripts' => 'scripts',
		'resources' => 'resources',
		'portfolio' => 'portfolio',
		'turnkey' => 'turnkey'
	);
	$detail_routes = array('snippet', 'function', 'object', 'portfolio', 'script', 'turnkey', 'resource');

	if (isset($list_routes[$route_type])) {
		$url = '//' . $host . '/' . $list_routes[$route_type];
		$result['success'] = true;
		$result['message'] = 'List canonical URL built.';
		$result['data'] = array('url' => $url);
		return $result;
	}

	if (!in_array($route_type, $detail_routes, true)) {
		$result['message'] = 'Invalid route type.';
		return $result;
	}
	if ($id <= 0) {
		$result['message'] = 'Detail canonical URL requires a positive ID.';
		return $result;
	}

	$slug = strtolower($slug);
	$slug = preg_replace('/[^a-z0-9]+/', '-', $slug);
	$slug = trim($slug, '-');
	if (empty($slug)) {
		$result['message'] = 'Detail canonical URL requires a valid slug.';
		return $result;
	}

	$url = '//' . $host . '/' . $route_type . '/' . $id . '/' . $slug;
	$result['success'] = true;
	$result['message'] = 'Detail canonical URL built.';
	$result['data'] = array('url' => $url);

	return $result;
}