Я работаю над базовым блоговое приложение в Codeigniter 3.1.8 и Bootstrap 4. posts
стол имеет slug
столбец, который я намерен использовать при создании SEO-дружественных URL.
Поскольку слаг каждого отдельного сообщения будет частью его URL, slug
колонка, конечно, уникальный. Я использую КИ url_title()
метод для сделать из заголовка поста:
$slug = url_title($this->input->post('title'), 'dash', TRUE);
Учитывая вышеописанную ситуацию, очевидно, что возникает проблема, когда 2 сообщения имеют одинаковый заголовок («Кто любит бабочку?»):
Duplicate entry 'who-loves-a-butterfly' for key 'slug'
Мне нужен способ заставить дублирующийся титульный пост генерировать «пронумерованный» слаг: «who-loves-a-butterfly-1» и так далее, если это необходимо.
Документация Codeigniter 3 не предоставляет такой способ для url_title()
метод? Есть ли способ, которым я мог бы изменить его или альтернативу?
Есть много творческих подходов, которые вы могли бы использовать. Все зависит от ваших личных предпочтений.
Первый, с включенным построителем запросов, будет использовать встроенный form_validation
и проверьте, соответствует ли ваш слаг is_unique
и если это не так, измените его немного и перепроверьте, пока проверка не пройдет. Даже если form_validation
используется в основном для проверки и дезинфекции пользовательского ввода, вы можете использовать его практически для чего угодно.
Другой подход заключается в том, чтобы всегда убедиться, что вы получаете уникальный слаг с первой попытки, добавив одноразовый номер, случайное число или какой-то другой уникальный параметр к сгенерированному слагу перед вставкой. Например:
$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.- передать слаг в простой запрос к базе данных (либо прямо в контроллере, либо внутри модели, на ваш выбор)
$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;
Если слаг действительно уникален, вам будет возвращено 0, если есть одна предыдущая запись, вам будет возвращено 1 и так далее.
После этого вы выбираете:
Когда вы в первый раз создаете слаг, добавьте «-0» или «-1» (в зависимости от того, что лучше для SEO)
Во второй раз вы добавляете «-1» или «-2» (в зависимости от того, что вы определили в предыдущем)
И так далее, и так далее
Так, например, вы бы изменили свой слизень с
$slug = $slug."-".$slugcount;
это будет работать?
Я использую пользовательскую функцию sanitize () — обычно в модели — для создания этой уникальной записи слага:
пожалуйста, прочитайте комментарий к коду, так как он документирует поток
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;
}
Вот полное решение, примененное в моем приложении блога:
в 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;
}