Codeigniter 博客应用程序:避免 slug 的重复输入错误
Codeigniter blog application: avoid duplicate entry error for slug
我正在 Codeigniter 3.1.8 和 Bootstrap 4 中开发一个基本的 博客应用程序。posts
table 有一个 slug
我打算用来使 SEO 友好的专栏 URLs.
因为每个人 post 的鼻涕虫都是 URL 的一部分,所以 slug
列当然是 独一无二的 .我使用 CI 的 url_title()
方法 从 post 标题 :
$slug = url_title($this->input->post('title'), 'dash', TRUE);
鉴于上述情况,当 2 post 具有完全相同的标题("Who loves a butterfly?")时,很明显会出现问题:
Duplicate entry 'who-loves-a-butterfly' for key 'slug'
我需要一种方法让重复的标题 post 生成一个 "numbered" slug:"who-loves-a-butterfly-1" 等等,如果需要的话。
Codeigniter 3 文档没有为其 url_title()
方法提供这样的方式?有什么方法可以修改它或替代它吗?
我正在使用自定义函数 sanitize() - 通常在模型中 - 来创建唯一的 slug 条目:
请阅读代码注释,因为它记录了流程
function sanitize($string,$table='posts'){
// sanitize string, remove Latin chars like 'ç ' and add - instead of white-space
// based on:
$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', '', 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;
}
您可以使用很多创造性的方法。这完全取决于您的个人喜好。
第一个启用查询构建器的方法是使用 built-in form_validation
并检查您的 slug 是否符合 is_unique
如果不符合,请稍微改变它和 re-check 直到验证通过。尽管 form_validation
主要用于验证和清理用户输入,但您几乎可以将其用于任何事情。
另一种方法是始终确保您在第一次尝试时获得唯一的 slug,方法是在插入之前将 nonce 或随机数或一些其他唯一参数附加到生成的 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);
计算基础 slug,然后:
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 = $slug."-".$slugcount;
这样行吗?
这是我的博客应用程序中应用的完整解决方案:
在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;
}
这是一个函数,它将为任何 table 创建始终唯一的 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');
我正在 Codeigniter 3.1.8 和 Bootstrap 4 中开发一个基本的 博客应用程序。posts
table 有一个 slug
我打算用来使 SEO 友好的专栏 URLs.
因为每个人 post 的鼻涕虫都是 URL 的一部分,所以 slug
列当然是 独一无二的 .我使用 CI 的 url_title()
方法 从 post 标题 :
$slug = url_title($this->input->post('title'), 'dash', TRUE);
鉴于上述情况,当 2 post 具有完全相同的标题("Who loves a butterfly?")时,很明显会出现问题:
Duplicate entry 'who-loves-a-butterfly' for key 'slug'
我需要一种方法让重复的标题 post 生成一个 "numbered" slug:"who-loves-a-butterfly-1" 等等,如果需要的话。
Codeigniter 3 文档没有为其 url_title()
方法提供这样的方式?有什么方法可以修改它或替代它吗?
我正在使用自定义函数 sanitize() - 通常在模型中 - 来创建唯一的 slug 条目: 请阅读代码注释,因为它记录了流程
function sanitize($string,$table='posts'){
// sanitize string, remove Latin chars like 'ç ' and add - instead of white-space
// based on:
$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', '', 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;
}
您可以使用很多创造性的方法。这完全取决于您的个人喜好。
第一个启用查询构建器的方法是使用 built-in form_validation
并检查您的 slug 是否符合 is_unique
如果不符合,请稍微改变它和 re-check 直到验证通过。尽管 form_validation
主要用于验证和清理用户输入,但您几乎可以将其用于任何事情。
另一种方法是始终确保您在第一次尝试时获得唯一的 slug,方法是在插入之前将 nonce 或随机数或一些其他唯一参数附加到生成的 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);
计算基础 slug,然后:
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 = $slug."-".$slugcount;
这样行吗?
这是我的博客应用程序中应用的完整解决方案:
在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;
}
这是一个函数,它将为任何 table 创建始终唯一的 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');