I am working on a basic blog application in Codeigniter 3.1.8 and Bootstrap 4.
I have been working for some time on this application and consequently, it has a lot of features. Most of these rely on the ids of posts, pages, etc.
For SEO purposes, I would like to use friendly URLs, instead of ids to display the individual posts, so I have added a slug
column to the posts
table.
The slugs are made from post titles, with this chunks of code in the Posts_model model and the Posts controller, respectively.
From the 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);
}
From the controller:
// 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;
}
To achieve my SEO goal, I have considered and tried out the approach in this tutorial but since there are numerous functionalities needing ids (deleting posts via AJAX, for example) and other that do not require slugs (editing posts) I am unable (and unwilling) to substantially modify the post viewing method in the controller,
public function post($id) {
$data = $this->Static_model->get_static_data();
$data['pages'] = $this->Pages_model->get_pages();
$data['categories'] = $this->Categories_model->get_categories();
$data['posts'] = $this->Posts_model->sidebar_posts($limit=5, $offset=5);
$data['post'] = $this->Posts_model->get_post($id);
if ($data['categories']) {
foreach ($data['categories'] as &$category) {
$category->posts_count = $this->Posts_model->count_posts_in_category($category->id);
}
}
if (!empty($data['post'])) {
// Overwrite the default tagline with the post title
$data['tagline'] = $data['post']->title;
// Get post comments
$post_id = $data['post']->id;
$data['comments'] = $this->Comments_model->get_comments($post_id);
$this->load->view('partials/header', $data);
$this->load->view('post');
} else {
$data['tagline'] = "Page not found";
$this->load->view('partials/header', $data);
$this->load->view('404');
}
$this->load->view('partials/footer');
}
and the corresponding code in the model:
public function get_post($id) {
$query = $this->db->get_where('posts', array('id' => $id));
if ($query->num_rows() > 0) {
$data = $query->row();
// run separate query for author name
$author_query = $this->db->get_where('authors', array('id' => $data->author_id));
if ($author_query->num_rows() == 1) {
$author = $author_query->row();
$data->first_name = $author->first_name;
$data->last_name = $author->last_name;
} else {
$data->first_name = 'Unknown';
$data->last_name = '';
}
return $data;
}
}
What would be a simple, less “intrusive” approach to replace post id with slug in the singe post view only?
3
Answers
Well, I think you can have both the id and the slug on the same function/url eg
/id/slug
. This way, you always have yourid
and seo is happy too because the url has the page title(slug). Then on your function, you can havepublic function post($id,$slug="") {
.Update in model
replace
with
Update in Controller
replace
with
and replace
with
Also update your routes for better user friendly url.