Minggu, 08 Maret 2015

Minimize your URLs in Codeigniter

Don’t wait until your customer or … your browser(!) start to mention that your URL is way to big from the usually title.
Well the first thing that you realize when you install Codeigntier is that the URLs are really huge, not SEO friendly and not user friendly.
Let’s try to minimize as much as we can for your dynamic created URLs. Below we will explain and give solutions to minimize the URLs as much as possible with htaccess, some route tricks and the _remap() method of Codeigniter.

1. Removing the index.php

Let’s start with our big URL:
http://mycustomproject.com/index.php/webpages/view/my-url-title-of-the-post
The first thing that you usually do for your Codeigniter project is to remove the index.php file from the URL. To do it so, it’s really easy:
1st step
Add this code to your .htaccess file to your root of your project.
<IfModule mod_rewrite.c>
# Turn on URL rewriting
RewriteEngine On

# If your website begins from a folder e.g localhost/my_project then 
# you have to change it to: RewriteBase /my_project/
# If your site begins from the root e.g. example.local/ then
# let it as it is
RewriteBase /

# Protect application and system files from being viewed when the index.php is missing
RewriteCond $1 ^(application|system|private|logs)

# Rewrite to index.php/access_denied/URL
RewriteRule ^(.*)$ index.php/access_denied/$1 [PT,L]

# Allow these directories and files to be displayed directly:
RewriteCond $1 ^(index\.php|robots\.txt|favicon\.ico|public|assets|css|js|images)

# No rewriting
RewriteRule ^(.*)$ - [PT,L]

# Rewrite to index.php/URL
RewriteRule ^(.*)$ index.php/$1 [PT,L]
</IfModule>
After the creation of the .htaccess file your project structure will have to look like this:
website_folder/ 
–––– application/ 
–––– assets/ 
–––– system/ 
–––– user_guide/ 
---- .htaccess <-------------------------
–––– index.php 
–––– license.txt
2nd step
Now go to : application/config/config.php and change the:
$config['index_page'] = 'index.php';
to
$config['index_page'] = '';
So now your URL will look like this:
http://mycustomproject.com/webpages/view/my-url-title-of-the-post
Note 1: If you are running in your local machine and your don't have configured the virtual host for example to be :
http://mycustomproject.com/webpages/view/my-url-title-of-the-post
but your URLs looks more than this:
http://localhost/website_folder/webpages/view/my-url-title-of-the-post
don't forget to change your RewriteBase from:
RewriteBase /
to
RewriteBase /mycustomproject/
or something similar it depends of where your Codeigniter project starts.
Note 2: In some cases perhaps you will realize that your .htaccess simply doesn't work and all the webpages URLs show the index webpage. If this happens to you then go to application/config/config.php and change the:
$config['uri_protocol'] = 'AUTO';
to:
$config['uri_protocol'] = 'PATH_INFO';
or:
$config['uri_protocol'] = 'REQUEST_URI';
it depends of your server's configuration. To try it just change it and see if the URL works for you correctly
Note 3: If you prefer to add a less secure .htaccess for your project, much more minimal and you don't want to write each time the exceptions of the files that you don't want to included them to the rules, you can simply use this code:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
This is the most common .htaccess (it is also used from the default installation of WordPress) thought it is not suggested as you don't protect your folders if the index.php is missing or a new file/folder is added to your project without knowing it.

2. Removing 1st URL segment

So now that we removed the annoying index.php from URL let's minimize our URLs with the routes.
Our basic example that we will work with is the below:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Webpages extends CI_Controller {
 
 function __construct()
 {
  parent::__construct();
 } 
 
 function index()
 {
 
 }
 
 function about()
 {
 
 }
 
 function blog($url_title = '')
 {
 
 }
 
 function view($url_title = '')
 {
 
 } 
 
}
To remove our first segment we have to choose which our base Controller will be. In our case we will choose that Webpages will be our basic Controller. The Controllers Admin and Forums will be our secondary let's say Controllers
There are two ways to minimize your URLs:
  • Routing by hand
  • Routing automatically (I always prefer this one)

Routing by hand

So let's see how we can can minimize our URLs by hand. This means that everytime we add or edit a function at our Controller we have to go to : application/config/routes.php
and change the routes in each case. So let's have an example of our basic controller:
Go to application/config/routes.php and add something like this:
$route['default_controller'] = 'webpages'; //Our default Controller

//Get rid of the first segment (in our case we get rid of webpages)
$route["about"] = 'webpages/about'; 
$route["blog/(.*)"] = 'webpages/blog/$1';
$route["view/(.*)"] = 'webpages/view/$1';
So now with this simple code we have get rid of the first controller name from our basic webpages.

Routing automatically

Many of you probably already know it but it is really boring to create the routes every time by hand. So that's why I created an automatically routing that actually removes the controller of your default controller. The below code is written to handle all the scenarions. Simple URLs and multilingual URLs. Let's go and take a look of our routes how it will look like.
If you don't have a multilingual website the routes are easy. You can simply copy the below code to application/config/routes.php:
$default_controller = "webpages";
$controller_exceptions = array('admin','forums');

$route['default_controller'] = $default_controller;
$route["^((?!\b".implode('\b|\b', $controller_exceptions)."\b).*)$"] = $default_controller.'/$1';
$route['404_override'] = '';
If you are having a multilingual website, it is a bit more complicated as you have lot of scenarios to cover. However don't worry about it as you can simply copy the below lines of code to application/config/routes.php:
$default_controller = "webpages";
$language_alias = array('gr','fr');
$controller_exceptions = array('admin','forums');

$route['default_controller'] = $default_controller;
$route["^(".implode('|', $language_alias).")/(".implode('|', $controller_exceptions).")(.*)"] = '$2';
$route["^(".implode('|', $language_alias).")?/(.*)"] = $default_controller.'/$2';
$route["^((?!\b".implode('\b|\b', $controller_exceptions)."\b).*)$"] = $default_controller.'/$1';
foreach($language_alias as $language)
 $route[$language] = $default_controller.'/index';
$route['404_override'] = '';
So let me explain how it works.
The only thing that you will actually care to change is the first three lines of code:
$default_controller = "webpages";
$language_alias = array('gr','fr');
$controller_exceptions = array('admin','forums');
As it is the only one that you actually need to change. So how it works? It's really easy.
You add your default controller to your variable $default_contoller.
The $language_alias is the language element that you want to add if you have a multilingual website for example:
http://mycustomproject.com/blog
http://mycustomproject.com/gr/blog
http://mycustomproject.com/fr/blog
And of course the http://mycustomproject.com/gr and http://mycustomproject.com/fr are routing to the index of your basic Controller.
The $controller_exceptions are the controllers that will NOT follow this routing structure. For example:
http://mycustomproject.com/admin/
http://mycustomproject.com/forums/
So you can easily use the controller with name Admin and controller with name Forums with the same way as you used it before.
Now we removed our first segment so our dynamic URLs will look like this:
  • http://mycustomproject.com/about
  • http://mycustomproject.com/view/my-url-title-of-the-post
  • http://mycustomproject.com/blog/url-title-of-post

3. Removing 2nd URL segment

One way to do it is by using the _remap() method of Codeigniter. For more go to Controllers User Guide and search for the _remap() method. Let's have an example of how to use it:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Webpages extends CI_Controller {
 
 function __construct()
 {
  parent::__construct();
 }

function _remap()
{  
 $segment_1 = $this->uri->segment(1);

 switch ($segment_1) {
  case null:
  case false:
  case '':
   $this->index();
  break;

  case 'about':
   $this->about();
  break;
  
  case 'blog':
   $this->blog($this->uri->segment(2));
  break;   
 
 default:
  //This is just an example to show 
  //the 404 page if the page doesn't exist
  $this->db->where('url_title',$segment_1);
  $db_result = $this->db->get('webpages');
  
  if($db_result->num_rows() == 1)
  {
   $this->view($segment_1);
  }
  else
  {
   show_404();
  }
 break;
 }
} 

 function index()
 {

 }

 function about()
 {

 }

 function blog($url_title = '')
 {

 }

 function view($url_title = '')
 {

 } 
 
}
So when you are using the _remap function of Codeigniter you have to decide which method will use every time. The good part is that you will have full control of what to do with each method. However it can take lot of time if you have many functions in your controller. So now your URLs will look like this:
  • http://mycustomproject.com/my-url-title
  • http://mycustomproject.com/about
  • http://mycustomproject.com/blog/url-title-of-post

Are you done with reading? Well you can now download the files that we used at this post or you can view the files from github

Ref

0 komentar:

Posting Komentar