PHP-код для создания безопасного URL-адреса?

Нам нужно создать уникальный URL-адрес из названия книги - где заголовок может содержать любой символ. Как мы можем выполнить поиск - заменить все "недопустимые" символы, чтобы создать правильный и аккуратный URL-адрес для просмотра?

Например:

"The Great Book of PHP"

www.mysite.com/book/12345/the-great-book-of-php

"The Greatest [email protected]#$ Book of PHP"

www.mysite.com/book/12345/the-greatest-book-of-php

"Funny title     "

www.mysite.com/book/12345/funny-title

Ответ 1

Ah, slugification

// This function expects the input to be UTF-8 encoded.
function slugify($text)
{
    // Swap out Non "Letters" with a -
    $text = preg_replace('/[^\\pL\d]+/u', '-', $text); 

    // Trim out extra -'s
    $text = trim($text, '-');

    // Convert letters that we have left to the closest ASCII representation
    $text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);

    // Make text lowercase
    $text = strtolower($text);

    // Strip out anything we haven't been able to convert
    $text = preg_replace('/[^-\w]+/', '', $text);

    return $text;
}

Это работает довольно хорошо, так как сначала использует свойства юникода каждого символа, чтобы определить, является ли это буквой (или\d против числа), - тогда она преобразует те, которые не принадлежат, - тогда она транслитерирует на ascii, делает другую замену для чего-либо еще, а затем очищает после себя. (Тест Fabrik возвращает "arvizturo-tukorfurogep" )

Я также стараюсь добавить список стоп-слов - так что они удаляются из пули. "из" "или" а "и т.д. (но не делайте этого по длине, или вы удаляете такие вещи, как" php")

Ответ 2

Если "invalid" означает не буквенно-цифровое выражение, вы можете сделать это:

function foo($str) {
    return trim(preg_replace('/[^a-z0-9]+/', '-', strtolower($str)), '-');
}

Это превратит $str в нижний регистр, заменит любую последовательность одного или нескольких не алфавитно-цифровых символов на один дефис, а затем удалит передние и конечные дефисы.

var_dump(foo("The Great Book of PHP") === 'the-great-book-of-php');
var_dump(foo("The Greatest [email protected]#$ Book of PHP") === 'the-greatest-book-of-php');
var_dump(foo("Funny title     ") === 'funny-title');

Ответ 3

С этой целью вы можете использовать простое регулярное выражение:

<?php
    function safeurl( $v )
    {
        $v = strtolower( $v );
        $v = preg_replace( "/[^a-z0-9]+/", "-", $v );
        $v = trim( $v, "-" );
        return $v;
    }
    echo "<br>www.mysite.com/book/12345/" . safeurl( "The Great Book of PHP" );
    echo "<br>www.mysite.com/book/12345/" . safeurl( "The Greatest [email protected]#$ Book of PHP" );
    echo "<br>www.mysite.com/book/12345/" . safeurl( "  Funny title  " );
    echo "<br>www.mysite.com/book/12345/" . safeurl( "!!Even Funnier title!!" );
?>

Ответ 4

Если вы хотите разрешить только буквы, цифры и символы подчеркивания (обычные слова), вы можете сделать:

$str = strtolower(preg_replace(array('/\W/','/-+/','/^-|-$/'),array('-','-',''),$str));

Сначала он заменяет любой символ без слова (\W) на -.
Затем он заменяет любой последовательный - одним -
Затем он удаляет любой ведущий или конечный -.

Рабочая ссылка

Ответ 5

Этот код исходит из CodeIgniter помощника URL. Он должен сделать трюк.

function url_title($str, $separator = 'dash', $lowercase = FALSE)
    {
        if ($separator == 'dash')
        {
            $search     = '_';
            $replace    = '-';
        }
        else
        {
            $search     = '-';
            $replace    = '_';
        }

        $trans = array(
                        '&\#\d+?;'              => '',
                        '&\S+?;'                => '',
                        '\s+'                   => $replace,
                        '[^a-z0-9\-\._]'        => '',
                        $replace.'+'            => $replace,
                        $replace.'$'            => $replace,
                        '^'.$replace            => $replace,
                        '\.+$'                  => ''
                      );

        $str = strip_tags($str);

        foreach ($trans as $key => $val)
        {
            $str = preg_replace("#".$key."#i", $val, $str);
        }

        if ($lowercase === TRUE)
        {
            $str = strtolower($str);
        }

        return trim(stripslashes($str));
    }

Ответ 6

Замените специальные символы для пробелов, а затем замените белые пробелы на "-". str_replace?

Ответ 7

Используйте замену регулярных выражений, чтобы удалить все символы без слова. Например:

str_replace ('[^ a-zA-Z] +', '-', $input)

Ответ 8

<?php
$input = "  The Great Book of PHP  ";
$output = trim(preg_replace(array("`'`", "`[^a-z]+`"),  array("", "-"), strtolower($input)), "-");
echo $output; // the-great-books-of-php

Это обрезает конечные тире и не делает такие вещи, как "it raining" -> "it-s-raining", как это обычно делают большинство решений.

Ответ 9

Санитация специальных символов не простая задача imho. Взгляните на WordPress awesome sanitize_title, также посмотрите source.

Update: Извините, ребята, я должен использовать каждый ответ, который не имеет отношения к ударным персонажам. Вы понимаете, что означает "название может содержать любой символ"?

Обновление 2: Иди, ребята, иди! Пожалуйста, соревнуйтесь со мной столько, сколько сможете!

Примечание: и не удивляйтесь, когда встретите специального персонажа. Просто исключите его с помощью str_replace!