Приложение блога Codeigniter: избегайте повторяющихся ошибок ввода для слаг - PullRequest
0 голосов
/ 12 октября 2018

Я работаю над базовым приложением для блога в Codeigniter 3.1.8 и Bootstrap 4. В таблице posts есть столбец slug, который я собираюсь использовать для создания SEO-дружественных URL-адресов.

Поскольку слаг каждого отдельного сообщения будет частью его URL, столбец slug, конечно, уникален .Я использую метод CI 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() метода?Есть ли способ, которым я мог бы изменить его или альтернативу ему?

Ответы [ 3 ]

0 голосов
/ 13 октября 2018

Есть много творческих подходов, которые вы могли бы использовать.Все зависит от ваших личных предпочтений.

Первый, с включенным построителем запросов, будет использовать встроенный 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.-передайте 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 и т. д.

После этого вы выбираете: При первом создании слаг добавьте «-0» или «-1» (в зависимости от того, что лучше для SEO).во второй раз вы добавляете «-1» или «-2» (в зависимости от того, что вы определили в предыдущем) и т. д. и т. п.

Так, например, вы изменили бы свой слаг с помощью

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

это будет работать?

0 голосов
/ 13 октября 2018

Вот полное решение, примененное в моем приложении блога:

В модели 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);
}

В контроллере Posts :

// 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;
}
0 голосов
/ 12 октября 2018

Я использую пользовательскую функцию 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;                    
}
...