Melhorar a minha função: gerar título SEO amigável

votos
2

Eu estou usando esta função para gerar títulos SEO amigável, mas eu acho que pode ser melhorado, ninguém quer tentar? Ele faz algumas coisas: limpa letras acentuadas comuns, verificar contra uma matriz proibido, e verificar opcionalmente contra um banco de dados de títulos em uso.

    /**
    * 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;
    }
Publicado 19/05/2009 em 22:14
fonte usuário
Em outras línguas...                            


6 respostas

votos
4

As sugestões str_replace acima são excelentes. Além disso, você pode substituir essa última função com uma única linha:

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

Você pode fazer ainda melhor e remover a idéia consulta-in-a-ciclo inteiramente, e fazer algo como

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

Correndo SELECTs em um loop como esse é apenas feio.

Respondeu 19/05/2009 em 22:51
fonte usuário

votos
4

Parece haver uma condição de corrida, porque você está fazendo um SELECT para ver se o título foi usado antes, em seguida, devolvê-lo se não for (presumivelmente o código de chamada irá inserir ignorá-lo no DB). E se outro processo faz a mesma coisa, mas ele insere entre o seu SELECT e seu INSERIR ignorar? Sua inserção falhará. Você provavelmente deve adicionar algum sinal garantido-exclusivo para o URL (talvez um "diretório" no caminho um nível mais elevado do que o nome SEO-friendly, semelhante à forma como StackOverflow faz isso) para evitar o problema da URL SEO-friendly necessidade de ser único em tudo.

Eu também reescrever a append_increasing_number()função para ser mais legível ... tê-lo programaticamente determinar quantos números estão no final e trabalhar de forma adequada, em vez de um gigante if / else para descobrir isso. O código será mais clara, mais simples e, possivelmente, ainda mais rápido.

Respondeu 19/05/2009 em 22:39
fonte usuário

votos
3

Parece que os outros têm atingido a maioria dos pontos importantes (especialmente em relação a incrementar o sufixo e execução de consultas SQL recursiva / em um loop), mas eu ainda vejo um par de grandes melhorias que poderiam ser feitas.

Em primeiro lugar, não se incomode a tentar chegar com suas próprias substituições diacríticos-to-ASCII; você nunca vai pegá-los todos e melhores ferramentas existem. Em particular, eu direcionar sua atenção para iconv's recurso 'TRANSLIT'. Você pode converter de UTF-8 (ou qualquer codificação é usada para seus títulos) para ASCII 7-bit velho liso como segue:

$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);

Note que isto também corrige um bug em seu código original onde a substituição espaço-traço foi chamado antes trim()e substitui todas as corridas de não-carta / -número / -underscores com traços individuais. Por exemplo, " Héllo, world's peoples!"torna-se "hello-worlds-peoples". Isso substitui toda sua seção 1.

Em segundo lugar, o $forbiddenloop pode ser reescrita para ser mais eficiente e para eliminar a recursão:

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

Esta seção 3 substitui.

Respondeu 19/05/2009 em 23:30
fonte usuário

votos
2

Após a resposta de karim79, a primeira parte pode ser mais legível e mais fácil de manter como esta:

Substituir

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

com

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

A última parte onde append_increasing_number () é usado parece ruim. Você provavelmente poderia eliminar toda a função e apenas fazer algo como

while ($i < 99999){
//check for existance of $title . $i; if doesn't exist - insert!
}
Respondeu 19/05/2009 em 22:38
fonte usuário

votos
2

Você poderia perder a:

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

E substituir as linhas com o mais rápido str_replace():

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

A partir da página manual do PHP para str_replace () :

Se você não precisa de regras extravagantes substituindo (como expressões regulares), você deve sempre usar esta função em vez de ereg_replace()ou preg_replace().

EDITAR:

I reforçada a sua append_increasing_number($title)função, ele faz exatamente a mesma coisa, só que sem limite para o número de dígitos no final (e é mais bonito :):

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);
}
Respondeu 19/05/2009 em 22:33
fonte usuário

votos
1

Você também pode usar matrizes com str_replace () para que você poderia fazer

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

A posição na matriz deve corresponder.

Isso deve raspar algumas linhas, e algumas millisceonds.

Você também vai querer ter em consideração toda a pontuação, é incrível como muitas vezes, conjuntos IFERENTES de "aspas` 'e!? Etc entrar em urls. Eu faria um preg_replace em \ W (não palavra)

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

Isso deve ajudá-lo um pouco.

Phil

Respondeu 19/05/2009 em 22:43
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more