1. Есть мнение что в canonical лучше писать абсолютную ссылку вместе с доменом
2. Мы сделали достаточно "тупое" решение в каждом контролере:
$app->vars->seo->canonical = ... ; //определяем ссылку
...
if (isset($app->vars->seo->canonical) && ($_SERVER['REQUEST_URI'] != $app->vars->seo->canonical) )
{
header('HTTP/1.1 301 Moved Permanently');
header('Location: '.$app->vars->seo->canonical);
die();
}
Наверное это не очень красиво, но с учетом того что сеошники свои хотелки присылают регулярно, - городить что то более унифицированное я пока не вижу смысла.