Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用PHP生成唯一的url slug_Php_Mysql - Fatal编程技术网

用PHP生成唯一的url slug

用PHP生成唯一的url slug,php,mysql,Php,Mysql,我正在开发一个小型CMS系统。目前,在试图生成唯一url时,大脑已经死亡。我根据页面标题生成url。有一个很好的脚本来实现这一点,但我不能解决重复的问题 类似的问题,但得到确切的输出 我设法做到以下几点: this-is-the-slug this-is-the-slug-2 但是如果我第三次创建相同的帖子,它只会重复:this-is-the-slug-2 $i = 1; $baseurl = $url; //$check database here if($thereisamatch){ $

我正在开发一个小型CMS系统。目前,在试图生成唯一url时,大脑已经死亡。我根据页面标题生成url。有一个很好的脚本来实现这一点,但我不能解决重复的问题

类似的问题,但得到确切的输出

我设法做到以下几点:

this-is-the-slug
this-is-the-slug-2
但是如果我第三次创建相同的帖子,它只会重复:
this-is-the-slug-2

$i = 1;
$baseurl = $url;
//$check database here
if($thereisamatch){
$url = $baseurl . "-" . $i++;  
}
我绕不开它,非常感谢你的帮助

if(isset($_POST['save'])) {
    $title = mysqli_real_escape_string($db, $_POST['title']);
    $url = toAscii($title);
    // check url
    $content = $_POST['content'];
    $author = $_SESSION['thelab_username'];
    $type = $_POST['type'];
    $showtitle = $_POST['showtitle'];
    $saveas = $_POST['status'];

    $insert = $connection->query(" INSERT INTO lab_pages (title, permalink, content, author, status, type, showtitle)
    VALUES ('$title', '$newslug', '$content', '$author', '$saveas', '$type', '$showtitle') ");

    if($insert === TRUE) {
        echo '<div id="success">Page added. <button id="close">Close</button></div>';
    }

    else {
        echo '<div id="error">Failed. Try again. <button id="failed">Close</button></div>';
        printf("Errormessage: %s\n", $db->error);
    }
}

function toAscii($str, $replace=array(), $delimiter='-') {
 if( !empty($replace) ) {
  $str = str_replace((array)$replace, ' ', $str);
 }

 $clean = iconv('UTF-8', 'ASCII//TRANSLIT', $str);
 $clean = preg_replace("/[^a-zA-Z0-9\/_|+ -]/", '', $clean);
 $clean = strtolower(trim($clean, '-'));
 $clean = preg_replace("/[\/_|+ -]+/", $delimiter, $clean);

 return $clean;
}
if(设置($\u POST['save'])){
$title=mysqli\u real\u escape\u字符串($db,$\u POST['title']);
$url=toAscii($title);
//检查url
$content=$_POST['content'];
$author=$\u会话['thelab\u用户名];
$type=$_POST['type'];
$showttitle=$_POST['showttitle'];
$saveas=$_POST['status'];
$insert=$connection->query(“插入到实验室页面(标题、永久链接、内容、作者、状态、类型、showtitle))
值(“$title”、“$newslug”、“$content”、“$author”、“$saveas”、“$type”、“$showttitle”);
如果($insert==TRUE){
echo“添加页面。关闭”;
}
否则{
echo“失败。重试。关闭”;
printf(“错误消息:%s\n”,$db->error);
}
}
函数toAscii($str,$replace=array(),$delimiter='-')){
如果(!空($replace)){
$str=str_replace((数组)$replace,,$str);
}
$clean=iconv('UTF-8','ASCII//TRANSLIT',$str);
$clean=preg_replace(“/[^a-zA-Z0-9\/+-]/”,“”,$clean);
$clean=strtolower(修剪($clean,“-”);
$clean=preg\u replace(“/[\/\u124;+-]+/”,$delimiter,$clean);
退回$clean;
}

使用数据库匹配的值(通过
选择计数(*)
)并增加它以获得新的后缀

PHP脚本彼此不通信,因此
$i
在开始时总是设置为
1
,然后再增加
1
,因此
2

谢谢你的源代码。因此,代码的开头应该是:

if(isset($_POST['save'])) {
    $title = mysqli_real_escape_string($db, $_POST['title']);
    $url = toAscii($title);
    // check url
    $content = $_POST['content'];
    $author = $_SESSION['thelab_username'];
    $type = $_POST['type'];
    $showtitle = $_POST['showtitle'];
    $saveas = $_POST['status']; // no modifications until here

    // count entries with permalink like our slug
    $urlmask = $url.'%';
    $sql = 'SELECT COUNT(*) FROM lab_pages WHERE permalink LIKE ?';
    $stst =  $db->stmt_init();
    $stst->bind_param('s', $urlmask);
    $stst->execute();
    $stst->store_result();
    $stst->bind_result($count);
    $stst->fetch();
    $stst->free_result();
    $newslug = sprintf('%s-%d', $url, $count+1);

    $insert = $connection->query(" INSERT INTO lab_pages (title, permalink, content, author, status, type, showtitle)
    VALUES ('$title', '$newslug', '$content', '$author', '$saveas', '$type', '$showtitle') ");
    :
重要的是使用SQL语句(如
selectcount(*)从实验室页面获取当前slug的数量,其中permalink(如“$url%”)
。然后你可以增加它并创建一个新的独特的slug。由于性能原因,应为列permalink编制索引

但是,对于类似的东西,我宁愿使用
uniqid()

为了演示,我使用了准备好的语句,但是您当然可以通过正常的query-fetch\u array-free\u结果序列运行查询

此代码不安全,无法投入生产(sql注入)


我加入了我自己的slug函数,因为我发现它非常有用,我希望其他人也会这么做。

你可以用两种方法解决它

  • 将检查数据库移到函数中并使用循环
  • 像这样:

    function check_into_database($url){
        //if isset - return true else false
    }
    $i = 1; $baseurl = $url;
    while(check_into_database($url)){
        $url = $baseurl . "-" . $i++;        
    }
    
    第二条路

    使用带有计数(id)的查询检查所有URL

    查询应如下所示:

    SELECT COUNT(id) FROM tbl_name WHERE url LIKE "$url%"
    

    此查询将返回URL的计数,这是slug%。

    我也遇到了永久链接的问题。特别是当我想从url中删除俄语、汉语和除英语以外的任何其他字符时。试试下面的函数。我用了PDO,但差别不大

            function FilterPermalink($link){
                $db = new Connect;
                $link = strtolower(trim($link));
                $link = preg_replace('/[^a-z0-9-]/', '-', $link);
                $link = preg_replace('/-+/', "-", $link);
                $link = rtrim($link, '-');
                $link = preg_replace('/\s+/', '-', $link);
                if(strlen($link) > 30)
                    $link = substr($link, 0, 30);
                $existing_lnk = $db->prepare("SELECT id FROM posts WHERE permalink = :permalink");
                $existing_lnk->execute(array('permalink' => $link));
                $num = $existing_lnk->fetchAll(PDO::FETCH_COLUMN);
                $first_total = count($num);
                for($i=0;$first_total != 0;$i++){
                    if($i == 0){
                        $new_number = $first_total + 1;
                        $newlink = $link."-".$new_number;
                    }
                    $check_lnk = $db->prepare("SELECT id FROM posts WHERE permalink = :permalink");
                    $check_lnk->execute(array('permalink' => $newlink));
                    $other = $check_lnk->fetchAll(PDO::FETCH_COLUMN);
                    $other_total = count($other);
                    if($other_total != 0){
                        $first_total = $first_total + $other_total;
                        $new_number = $first_total;
                        $newlink = $link."-".$new_number;
                    }elseif($other_total == 0){
                        $first_total = 0;
                    }           
                }
                if($i > 0)
                    return $newlink;
                else
                    return $link;
            }
    

    它对我很有效。

    试试这段代码,这对我很有效

    //检查slug是否已经存在

    $post_slug = preg_replace('/[^a-z0-9]+/i', '-', trim(strtolower($_POST['post_title'])));
    
    $query = "SELECT * FROM `posts` WHERE post_slug = '$post_slug'";
    $result = mysqli_query($conn, $query) or die(mysql_error());
    $ifExist = mysqli_num_rows($result);
    if ($ifExist >= 1) {
    
        $post_slug = $post_slug . '-' . $ifExist++;
    } else {
        $post_slug = $post_slug;
    }
    

    match缺少$,这只是一个输入错误吗?另外,您应该执行类似while([此url存在于数据库中]){$url=$baseurl.-“$i++;”的操作。即使这是危险的,如果$i失控,你也应该有触发的东西@Jim_M只是用“匹配”来演示。@Devrim$连接是PDO连接吗?@OlegSamorai不,这是mysqli连接。@Devrim尝试将“从slug=“$slug”的表中选择计数(id)”更改为“从slug类似于“$slug%”的表中选择计数(id)”@Devrim您能给出完整的代码吗,为了发现错误?@OlegSamorai我在问题中添加了我的代码(删除了建议的答案)。我也尝试过这种方法。但是,即使我做了一个“喜欢”的查询,它也不会超过2。如果我找不到解决方案,我想我会在slug的末尾添加唯一的id。@Devrim你能给出一个你使用的查询示例吗?因为我不熟悉PDO,我很难理解这里发生了什么,因为它给了我一个致命的错误“不能通过引用传递参数”<代码>$stst->bind_参数('s',$url.%')它不是PDO,而是mysqli的语句对象。我更正了错误。我使用了您在这里编写的确切查询(您想要一个示例)。
    $post_slug = preg_replace('/[^a-z0-9]+/i', '-', trim(strtolower($_POST['post_title'])));
    
    $query = "SELECT * FROM `posts` WHERE post_slug = '$post_slug'";
    $result = mysqli_query($conn, $query) or die(mysql_error());
    $ifExist = mysqli_num_rows($result);
    if ($ifExist >= 1) {
    
        $post_slug = $post_slug . '-' . $ifExist++;
    } else {
        $post_slug = $post_slug;
    }