【问题标题】:Codeigniter blog application: avoid duplicate entry error for slugCodeigniter 博客应用程序:避免 slug 的重复输入错误
【发布时间】:2019-03-18 00:58:18
【问题描述】:

我正在使用 Codeigniter 3.1.8 和 Bootstrap 4 开发一个基本的博客应用程序posts 表有一个 slug 列,我打算用它来制作 SEO 友好的 URL。

因为每个帖子的 slug 都将成为其 URL 的一部分,所以slug 列当然是唯一的。我使用 CI 的 url_title() 方法来从帖子标题中删除 slug

$slug = url_title($this->input->post('title'), 'dash', TRUE);

鉴于上述情况,当两个帖子的标题完全相同(“谁爱蝴蝶?”)时,很明显会出现问题:

Duplicate entry 'who-loves-a-butterfly' for key 'slug'

如果需要,我需要一种方法让重复的标题帖子生成一个“编号”的 slug:“who-loves-a-butterfly-1”等等。

Codeigniter 3 文档没有为其url_title() 方法提供这种方法?有没有办法可以修改它或替代它?

【问题讨论】:

  • 据我了解,您的问题是数据库中的重复键。 url_title 只需将字符串转换为 url 格式,对数据库不做任何事情。您必须编写一个自定义函数来检查 slug 是否存在于 DB 上。
  • Nonce 蛞蝓你就是金子

标签: php codeigniter slug slugify


【解决方案1】:

您可以使用很多创造性的方法。这完全取决于您的个人喜好。

第一个启用查询生成器的方法是使用内置的 form_validation 并检查您的 slug 是否符合 is_unique,如果不符合,请稍微更改并重新检查,直到验证通过.尽管form_validation 主要用于验证和清理用户输入,但您几乎可以将它用于任何事情。

另一种方法是始终确保在第一次尝试时获得唯一的 slug,方法是在插入之前向生成的 slug 附加随机数或随机数或其他一些唯一参数。例如:

$slug = url_title($this->input->post('title'), 'dash', TRUE).strtotime(date('Y-m-d H:i:s'));

上述方法可能是最简单的方法,只要没有两个标题完全相同的帖子在同一秒创建即可。这将(几乎)完全减少碰撞的机会。

第三种解决方案有点麻烦,需要使用$slug = url_title($this->input->post('title'), 'dash', TRUE); 计算基本段,然后:

1.- 将 slug 传递给一个简单的数据库查询(在控制器中或模型中,您可以选择)

$this->db->select('count(*) as slugcount');
$this->db->from('your_table');
$this->db->where('slug', $slug);

$query = $this->db->get();
return $query->row(0)->slugcount;

如果 slug 确实是唯一的,则返回 0,如果之前有一个条目,则返回 1,依此类推。

之后您选择: 第一次创建 slug 时,附加“-0”或“-1”(取决于最适合 SEO 的内容) 第二次附加“-1”或“-2”(取决于您在前一个中定义的内容) 等等等等

因此,例如,您可以使用

$slug = $slug."-".$slugcount;

这行得通吗?

【讨论】:

  • 一个简单、有创意的解决方案。不过,对 SEO 不友好。
  • 只是好奇...您认为什么是 SEO 友好的?我正在休息,也许我可以帮你解决这个问题
  • 添加了第三种非本地替代方案,我相信它更符合您正在寻找的最终结果
  • 效果很好。看看我如何在我的应用程序 HERE 中应用您的解决方案。非常感谢!
【解决方案2】:

我正在使用自定义函数 sanitize() - 通常在模型中 - 来创建唯一的 slug 条目: 请阅读代码注释,因为它记录了流程

function sanitize($string,$table='posts'){
    // sanitize string, remove Latin chars like 'ç ' and add - instead of white-space
    // based on: http://stackoverflow.com/a/2103815/2275490
    $str= strtolower(trim(preg_replace('~[^0-9a-z]+~i', '-', html_entity_decode(preg_replace('~&([a-z]{1,2})(?:acute|cedil|circ|grave|lig|orn|ring|slash|th|tilde|uml);~i', '$1', htmlentities($string, ENT_QUOTES, 'UTF-8')), ENT_QUOTES, 'UTF-8')), '-'));
    // check how often header exists in table "posts"
    // add counted suffix to pretty_url if already exists
    $query = $this->db  ->where('slug', $string)
                        ->get($table);
    if($query->num_rows()>0) 
        $str=$str.'-'.$query->num_rows(); // allways returns the latest number for same slug

    return $str;                    
}

【讨论】:

    【解决方案3】:

    这是我的博客应用程序中应用的完整解决方案:

    Posts_model 模型中:

    public function slug_count($slug){
        $this->db->select('count(*) as slugcount');
        $this->db->from('posts');
        $this->db->where('slug', $slug);
        $query = $this->db->get();
        return $query->row(0)->slugcount;
    }
    
    public function create_post($post_image, $slug) {
        $data = [
            'title' => $this->input->post('title'),
            'slug' => $slug,
            'description' => $this->input->post('desc'),
            'content' => $this->input->post('body'),
            'post_image' => $post_image,
            'author_id' => $this->session->userdata('user_id'),
            'cat_id' => $this->input->post('category'),
            'created_at' => date('Y-m-d H:i:s')
        ];
        return $this->db->insert('posts', $data);
    }
    

    帖子 控制器中:

    // Create slug (from title)
    $slug = url_title($this->input->post('title'), 'dash', TRUE);
    $slugcount = $this->Posts_model->slug_count($slug);
    if ($slugcount > 0) {
        $slug = $slug."-".$slugcount;
    }
    

    【讨论】:

      【解决方案4】:

      这是一个为任何表创建始终唯一的 slug 的函数。 在模型中

      function get_unique_slug($slug,$table)
      {
      $slug = url_title($this->input->post('title'), 'dash', TRUE);
      $this->db->select('count(*) as slugcount');
      $this->db->from($table);
      $this->db->where('slug like', $slug.'%');
      
      $query = $this->db->get();
      if($query->row(0)->slugcount>0)
      {
          return $slug.'-'.$query->row(0)->slugcount;
      }
      else
      {
          return $slug;
      }
      }
      

      在控制器中

      $slug = $this->crud_model->get_unique_slug($slug,'category');
      

      【讨论】:

        猜你喜欢
        • 2017-02-12
        • 1970-01-01
        • 1970-01-01
        • 2020-01-16
        • 1970-01-01
        • 1970-01-01
        • 2018-10-01
        • 2013-09-05
        • 1970-01-01
        相关资源
        最近更新 更多