2009-05-19 5 views
2

Я использую эту функцию для генерации дружественных заголовков SEO, но я думаю, что ее можно улучшить, любой хочет попробовать? Он выполняет несколько действий: очищает распространенные буквы с акцентом, проверяет «запрещенный» массив и проверяет опцию против базы данных используемых заголовков.Улучшить мою функцию: генерировать SEO дружественный заголовок

/** 
    * Recursive function that generates a unique "this-is-the-title123" string for use in URL. 
    * Checks optionally against $table and $field and the array $forbidden to make sure it's unique. 
    * Usage: the resulting string should be saved in the db with the object. 
    */ 
    function seo_titleinurl_generate($title, $forbidden = FALSE, $table = FALSE, $field = FALSE) 
    { 
     ## 1. parse $title 
     $title = clean($title, "oneline"); // remove tags and such 

     $title = ereg_replace(" ", "-", $title); // replace spaces by "-" 
     $title = ereg_replace("á", "a", $title); // replace special chars 
     $title = ereg_replace("í", "i", $title); // replace special chars 
     $title = ereg_replace("ó", "o", $title); // replace special chars 
     $title = ereg_replace("ú", "u", $title); // replace special chars 
     $title = ereg_replace("ñ", "n", $title); // replace special chars 
     $title = ereg_replace("Ñ", "n", $title); // replace special chars 

     $title = strtolower(trim($title)); // lowercase 
     $title = preg_replace("/([^a-zA-Z0-9_-])/",'',$title); // only keep standard latin letters and numbers, hyphens and dashes 

     ## 2. check against db (optional) 
     if ($table AND $field) 
     { 
      $sql = "SELECT * FROM $table WHERE $field = '" . addslashes($title) . "'"; 
      $res = mysql_debug_query($sql); 
      if (mysql_num_rows($res) > 0) 
      { 
       // already taken. So recursively adjust $title and try again. 
       $title = append_increasing_number($title); 
       $title = seo_titleinurl_generate($title, $forbidden, $table, $field); 
      } 
     } 

     ## 3. check against $forbidden array 
     if ($forbidden) 
     { 
      while (list ($key, $val) = each($forbidden)) 
      { 
       // $val is the forbidden string 
       if ($title == $val) 
       { 
        $title = append_increasing_number($title); 
        $title = seo_titleinurl_generate($title, $forbidden, $table, $field); 
       } 
      } 
     } 
     return $title; 
    } 
    /** 
    * Function that appends an increasing number to a string, for example "peter" becomes "peter1" and "peter129" becomes "peter130". 
    * (To improve, this function could be made recursive to deal with numbers over 99999.) 
    */ 
    function append_increasing_number($title) 
    { 
     ##. 1. Find number at end of string. 
     $last1 = substr($title, strlen($title)-1, 1); 
     $last2 = substr($title, strlen($title)-2, 2); 
     $last3 = substr($title, strlen($title)-3, 3); 
     $last4 = substr($title, strlen($title)-4, 4); 
     $last5 = substr($title, strlen($title)-5, 5); // up to 5 numbers (ie. 99999) 

     if (is_numeric($last5)) 
     { 
      $last5++; // +1 
      $title = substr($title, 0, strlen($title)-5) . $last5; 
     } elseif (is_numeric($last4)) 
     { 
      $last4++; // +1 
      $title = substr($title, 0, strlen($title)-4) . $last4; 
     } elseif (is_numeric($last3)) 
     { 
      $last3++; // +1 
      $title = substr($title, 0, strlen($title)-3) . $last3; 
     } elseif (is_numeric($last2)) 
     { 
      $last2++; // +1 
      $title = substr($title, 0, strlen($title)-2) . $last2; 
     } elseif (is_numeric($last1)) 
     { 
      $last1++; // +1 
      $title = substr($title, 0, strlen($title)-1) . $last1; 
     } else 
     { 
      $title = $title . "1"; // append '1'  
     } 

     return $title; 
    } 
+0

Что вы основывая свои предположения здесь на? Почему пробелы в названиях не «дружественные к SEO»? Какова цель использования последовательных чисел для дифференциации названий? – Sparr

ответ

2

Вы можете потерять:

$title = ereg_replace(" ", "-", $title); 

и заменить эти строки с тем быстрее str_replace():

$title = str_replace(" ", "-", $title); 

На странице PHP вручную для str_replace():

Если вам не нужно причудливо заменяя правила (например, регулярные выражения), вы должны использовать эту функцию вместо ereg_replace() или preg_replace().

EDIT:

Я повысить вашу append_increasing_number($title) функцию, он делает то же самое, только без каких-либо ограничений на количество цифр в конце (и это похорошела :):

function append_increasing_number($title) 
{ 
    $counter = strlen($title); 
    while(is_numeric(substr($title, $counter - 1, 1))) { 
     $counter--; 
    } 
    $numberPart = (int) substr($title,$counter,strlen($title) - 1); 
    $incrementedNumberPart = $numberPart + 1; 
    return str_replace($numberPart, $incrementedNumberPart, $title); 
} 
2

После ответа karim79, первая часть может быть более удобным для чтения и легче поддерживать, как это:

Заменить

$title = ereg_replace(" ", "-", $title); // replace spaces by "-" 
$title = ereg_replace("á", "a", $title); // replace special chars 
$title = ereg_replace("í", "i", $title); // replace special chars 

с

$replacements = array(
    ' ' => '-', 
    'á' => 'a', 
    'í' => 'i' 
); 
$title = str_replace(array_keys($replacements, array_values($replacements), $title); 

Последняя часть, где append_increasing_number() используется плохо выглядит. Вы могли бы удалить всю функцию и просто сделать что-то вроде

while ($i < 99999){ 
//check for existance of $title . $i; if doesn't exist - insert! 
} 
+0

+1 для использования аргументов массива с str_replace, но идея цикла while() не является победителем. –

+0

Согласен, хотя и более читаемый, чем текущий код. Возможно, я неправильно понял, что он делает - трудно читать! –

4

Там, как представляется, состояние гонки, потому что вы делаете ОТБОРНОЕ, чтобы увидеть, если название использовалось ранее, то вернуть его, если нет (предположительно вызывающий код затем ВСТАВЛЯЕТ его в БД). Что делать, если другой процесс делает то же самое, но он вставляет между вашим SELECT и вашим INSERT? Ваша вставка не будет выполнена. Вероятно, вы должны добавить некоторый гарантированный уникальный токен URL (возможно, «каталог» в пути на один уровень выше, чем имя, подходящее для SEO, подобно тому, как это делает StackOverflow), чтобы избежать проблемы с URL-адресами, ориентированными на SEO, быть уникальным.

Я бы также переписал функцию append_increasing_number(), чтобы быть более читабельным ... попросите ее программно определить, сколько цифр на конце и работать соответственно, а не гигантский if/else, чтобы понять это. Код будет более четким, простым и, возможно, даже быстрее.

+1

Интересно видеть подход каждого к этому. Все сделали это быстрее и красивее, вы заставили его работать. Проголосовал. –

+1

Уникальный токен, предложенный rmeador, является хорошей идеей, это также может быть реализовано как уникальное ограничение для столбца базы данных, чтобы вызвать последующую вставку. – karim79

1

Вы также можете использовать массивы с str_replace(), так что вы могли бы сделать

$replace = array(' ', 'á'); 
$with = array('-', 'a'); 

Положение в массиве должно соответствовать.

Это должно сбрить несколько линий и несколько миллисекунд.

Вы также захотите учесть все знаки препинания, это удивительно, как часто, если набор наборов букв «» и т. Д. Попадают в URL-адреса. Я бы сделал preg_replace on \ W (not word)

.
preg_replace('/\w/', '', $title); 

Это должно помочь вам немного

Phil

4

The str_replace предложения выше превосходны Кроме того, вы можете заменить эту последнюю функцию с одной строкой:.

function append_increasing_number($title) { 
    return preg_replace('@([0-9]+)[email protected]', '\1+1', $title); 
} 

Вы можете сделать еще лучше и удалить идею запроса-в-петлю полностью, и сделать что-то вроде

"SELECT MAX($field) + 1 FROM $table WHERE $field LIKE '" . mysql_escape_string(preg_replace('@[0-9][email protected]', '', $title)) . "%'"; 

Идущие в SELECT, петли, как это просто некрасиво.

+0

+1 Очень умные предложения –

+0

+1, чтобы настроить недопущение этого ответа. Кармический баланс восстановлен. – karim79

3

Похоже, что другие ударили по большинству значимых точек (особенно в отношении увеличения суффикса и выполнения SQL-запросов рекурсивно/в цикле), но я все еще вижу пару больших улучшений, которые могут быть сделаны.

Во-первых, не беспокойтесь, пытаясь придумать замену вашей диакритики на ASCII; вы никогда их не поймаете и не появятся лучшие инструменты. В частности, я обращаю ваше внимание на функцию «TRANSLIT» iconv. Вы можете конвертировать из UTF-8 (или любой другой кодировки используется для заголовков) в простой старой 7-битного ASCII следующим образом:

$title = strtolower(strip(clean($title))); 
$title = iconv('UTF-8', 'ASCII//TRANSLIT', $title); 
$title = str_replace("'", "", $title); 
$title = preg_replace(array("/\W+/", "/^\W+|\W+$/"), array("-", ""), $title); 

Обратите внимание, что это также исправляет ошибку в исходном коде, где космос -dash была вызвана до trim() и заменяет все прогоны букв/-number/-underscores без пробелов. Например, " Héllo, world's peoples!" становится "hello-worlds-peoples". Это заменяет весь свой раздел 1.

Во-вторых, ваш $forbidden цикл может быть переписан, чтобы быть более эффективным и для устранения рекурсии:

if ($forbidden) 
{ 
    while (in_array($title, $forbidden)) 
    { 
     $title = append_increasing_number($title); 
    } 
} 

Это заменяет раздел 3.