PHP代码生成安全的URL?

时间:2010-10-21 06:51:19

标签: php regex string url-rewriting sanitization

我们需要从书名中生成一个唯一的URL - 标题可以包含任何字符。我们如何搜索 - 替换所有“无效”字符,以便生成有效且整洁的查找URL?

例如:

"The Great Book of PHP"

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

"The Greatest !@#$ Book of PHP"

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

"Funny title     "

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

9 个答案:

答案 0 :(得分:15)

啊,捣蛋

// 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;
}

这很好用,因为它首先使用每个字符的unicode属性来确定它是否是一个字母(或者是一个数字的\ n) - 然后它将那些不是 - 的转换为 - 然后它音译到ascii,做其他事情的另一个替代品,然后自己清理。 (Fabrik的测试返回“arvizturo-tukorfurogep”)

我还倾向于添加一个停用词列表 - 这样就可以从slug中删除它们。 “the”“of”或“”“a”等等(但不要长篇大论,或者你删除像“php”这样的东西)

答案 1 :(得分:7)

如果“无效”表示非字母数字,则可以执行以下操作:

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 !@#$ Book of PHP") === 'the-greatest-book-of-php');
var_dump(foo("Funny title     ") === 'funny-title');

答案 2 :(得分:2)

您可以使用简单的正则表达式来实现此目的:

<?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 !@#$ Book of PHP" );
    echo "<br>www.mysite.com/book/12345/" . safeurl( "  Funny title  " );
    echo "<br>www.mysite.com/book/12345/" . safeurl( "!!Even Funnier title!!" );
?>

答案 3 :(得分:1)

如果您只想允许字母,数字和下划线(通常的单词字符),您可以这样做:

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

它首先用\W替换任何非单词字符(-)。
接下来它用一个-替换任何连续的-
接下来它删除任何前导或尾随-

Working link

答案 4 :(得分:1)

此代码来自CodeIgniter的网址助手。应该这样做。

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

答案 5 :(得分:0)

替换空格的特殊字符,然后将“ - ”替换为空格。 str_replace函数?

答案 6 :(得分:0)

使用正则表达式替换删除所有非单词字符。例如:

  

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

答案 7 :(得分:0)

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

这会修剪尾随破折号,并且不像大多数解决方案那样执行"it's raining" -> "it-s-raining"之类的操作。

答案 8 :(得分:-3)

清理特殊字符不是一件容易的事。看看WordPress真棒sanitize_title函数,看看它是source

<强>更新 对不起,伙计们,我应该回答每一个没有处理重音字符的答案。你明白“标题可以包含任何字符”意味着什么?

更新2: 伙计们,去!请尽可能多地向我投票!

注意:当你遇到一个特殊的角色时,请不要感到惊讶。只需用str_replace消除它!