Part of the EllisLab Network
   
1 of 2
1
So close with a mod_rewrite that changes underscores to hyphens for SEO. Can anyone close it out?
Posted: 27 July 2009 12:08 PM   [ Ignore ]  
Summer Student
Total Posts:  5
Joined  07-27-2009

Hello,

I’ve been using CI for a while and love it. However, many clients are asking for hyphens in URLs instead of underscores which helps with SEO. I partner with two SEO firms, both of which confirm while having hyphens over underscores is not monumental it does help.

As you know, CI controllers must use underscores as hyphens will not work. I have a mod_rewrite in place that ALMOST works in getting everything converted. Yet the first hyphen in a URL (for the class name) doesn’t work. The mod_rewrite looks like this:

Options +FollowSymLinks
RewriteEngine On
RewriteBase /

RewriteRule ([^-]*)-([^-]*)-([^-]*)-?([^-]*)-?([^-]*)-?([^-]*)-?([^-]*)-?([^-]*)-?([^-]*) $1_$2_$3_$4_$5_$6_$7_$8_$9 [L]
RewriteRule ^(.*?)__+(.*) $1$2 [L]
RewriteCond $1 !^(index\.php|css|emails|favicon\.php|flash|img|p\.php|public|scripts|robots\.txt|tmp)
RewriteRule ^(.*)$ index.php?$1 [L]

The issue is that:

/class-name/

throws a 404 while:

/class-name/function-name/

does not. So even though a class name works fine when the URL contains children segments, it does not when it’s loaded on its own.

If anyone knows how to get CI controllers to behave when hyphens are used instead of underscores, I would GREATLY appreciate the advice.

Thanks in advance for your time.

Profile
 
 
Posted: 27 July 2009 06:45 PM   [ Ignore ]   [ # 1 ]  
Lab Assistant
Avatar
RankRank
Total Posts:  119
Joined  09-07-2008

Does class-name/index work for any of them?

 Signature 

Condos in Saint Louis
Branson Getaway Trips

Profile
 
 
Posted: 27 July 2009 06:49 PM   [ Ignore ]   [ # 2 ]  
Summer Student
Total Posts:  5
Joined  07-27-2009

You mean /class-name/index.php ? No, that also throws a 404.

Profile
 
 
Posted: 27 July 2009 10:18 PM   [ Ignore ]   [ # 3 ]  
Research Assistant
Avatar
RankRankRank
Total Posts:  683
Joined  03-21-2009

While I don’t quite understand why hyphens are more SEO friendly than underscores, I wonder if other characters would suffice for your SEO purposes.  If your controllers/functions have underscores you can substitute them with periods or pluses (and probably a few others) in the URL and CI translates automatically, no mod_rewrite needed.  Just a though, maybe it’ll save you some time and server overhead.

Profile
 
 
Posted: 28 July 2009 03:28 AM   [ Ignore ]   [ # 4 ]  
Summer Student
Total Posts:  5
Joined  07-27-2009

Based on what I’ve read, it appears that it doesn’t have a huge impact one way or the other. That said, Matt Cutts (Google software engineer) just recently mentioned (http://www.youtube.com/GoogleWebmasterHelp#play/uploads/81/Q3SFVfDIS5k) that while it doesn’t make much sense to convert a site from underscores to hyphens, it would be best to use hyphens with any new development. Coupled with a client’s request to use hyphens, it’s time to figure out how to get CI to oblige.

Does anyone have suggestions about how to get hyphens to work with CI’s class names using mod_rewrite? What I posted seems to work with any given URL segment except for the class name (first segment).

Also, thanks for the suggestion about using dots or plus signs. While they may save some time/overhead, as you’ve mentioned, they won’t help at all for SEO purposes.

Profile
 
 
Posted: 28 July 2009 04:22 AM   [ Ignore ]   [ # 5 ]  
Research Assistant
Avatar
RankRankRank
Total Posts:  743
Joined  09-11-2008

hi if you want to replace _ with - you can use CI route check this user guide

http://codeigniter.com/user_guide/general/routing.html

 Signature 

CI,JQuery,Google Maps | widget with CI loader | Thumbnail, Image Resize, Image Crop Helper | CI shortcode

Profile
 
 
Posted: 28 September 2009 10:54 PM   [ Ignore ]   [ # 6 ]  
Summer Student
Total Posts:  2
Joined  03-10-2006

Finally solved…

First create a “pre-system” hook by adding these lines to your ‘config/hooks.php’ file:

$hook['pre_system'= array(
    
'class'    => '',
    
'function' => 'prettyurls',
    
'filename' => 'myhooks.php',
    
'filepath' => 'hooks',
    
'params'   => array()
); 

Now create a ‘myhooks.php’ file within the ‘application/hooks’ folder and add this function (don’t forget to open a PHP tag if this is the first hook):

<?php
function prettyurls() {
    
if (is_array($_GET) && count($_GET) == && trim(key($_GET), '/') != ''{
        $newkey 
str_replace('-','_',key($_GET));
        
$_GET[$newkey] $_GET[key($_GET)];
        unset(
$_GET[key($_GET)]);
    
}
    
if (isset($_SERVER['PATH_INFO'])) $_SERVER['PATH_INFO'str_replace('-','_',$_SERVER['PATH_INFO']);
    if (isset(
$_SERVER['QUERY_STRING'])) $_SERVER['QUERY_STRING'str_replace('-','_',$_SERVER['QUERY_STRING']);
    if (isset(
$_SERVER['ORIG_PATH_INFO'])) $_SERVER['ORIG_PATH_INFO'str_replace('-','_',$_SERVER['ORIG_PATH_INFO']);
    if (isset(
$_SERVER['REQUEST_URI'])) $_SERVER['REQUEST_URI'str_replace('-','_',$_SERVER['REQUEST_URI']);

You will probably need to edit your ‘config/config.php’ file to enable hooks (around line 91 for me):

$config['enable_hooks'TRUE

Good luck.

Profile
 
 
Posted: 28 September 2009 11:16 PM   [ Ignore ]   [ # 7 ]  
Grad Student
Avatar
Rank
Total Posts:  56
Joined  07-06-2009

Another solution is here, using one small MY_Router.php file in application/libraries/ with an updated function to override the issue at the source:
http://codeigniter.com/forums/viewthread/85901/#623512

Profile
 
 
Posted: 13 October 2009 10:09 AM   [ Ignore ]   [ # 8 ]  
Summer Student
Total Posts:  10
Joined  10-13-2009

b3nst3wart, I’ve been looking all over trying to figure this out. Your solution worked perfectly! Thanks for sharing!

Profile
 
 
Posted: 30 November 2010 08:41 AM   [ Ignore ]   [ # 9 ]  
Summer Student
Total Posts:  8
Joined  11-20-2009

Here is my solution
http://stackoverflow.com/questions/2428134/codeigniter-routes-regex/2432405

Profile
 
 
Posted: 01 December 2010 02:57 AM   [ Ignore ]   [ # 10 ]  
Research Assistant
Avatar
RankRankRank
Total Posts:  749
Joined  12-26-2006

Once the URL’s are all working then check that Google Webmaster Tools is happy with your changes.

Yahoo, Bing, Google, etc all use Canonical Links for the preferred URL.

SEO may also be happier if you set your Canonical Links:

<head>
  ... 
  ... 
  <
link rel='canonical' href='http://<?php echo base_url(). $this->uri->uri_string(); ?>' />
  ... 
  ... 
  ... 
</
head

 
 
 

 Signature 

Joke of the day - Bulletin Board Ideas     (ongoing development site)

My Hippy Trail    Source code   

Latest Project

Profile
 
 
Posted: 22 March 2011 08:24 AM   [ Ignore ]   [ # 11 ]  
Lab Assistant
Avatar
RankRank
Total Posts:  142
Joined  10-23-2010
b3nst3wart - 29 September 2009 02:54 AM

Finally solved…

First create a “pre-system” hook by adding these lines to your ‘config/hooks.php’ file:

$hook['pre_system'= array(
    
'class'    => '',
    
'function' => 'prettyurls',
    
'filename' => 'myhooks.php',
    
'filepath' => 'hooks',
    
'params'   => array()
); 

Now create a ‘myhooks.php’ file within the ‘application/hooks’ folder and add this function (don’t forget to open a PHP tag if this is the first hook):

<?php
function prettyurls() {
    
if (is_array($_GET) && count($_GET) == && trim(key($_GET), '/') != ''{
        $newkey 
str_replace('-','_',key($_GET));
        
$_GET[$newkey] $_GET[key($_GET)];
        unset(
$_GET[key($_GET)]);
    
}
    
if (isset($_SERVER['PATH_INFO'])) $_SERVER['PATH_INFO'str_replace('-','_',$_SERVER['PATH_INFO']);
    if (isset(
$_SERVER['QUERY_STRING'])) $_SERVER['QUERY_STRING'str_replace('-','_',$_SERVER['QUERY_STRING']);
    if (isset(
$_SERVER['ORIG_PATH_INFO'])) $_SERVER['ORIG_PATH_INFO'str_replace('-','_',$_SERVER['ORIG_PATH_INFO']);
    if (isset(
$_SERVER['REQUEST_URI'])) $_SERVER['REQUEST_URI'str_replace('-','_',$_SERVER['REQUEST_URI']);

You will probably need to edit your ‘config/config.php’ file to enable hooks (around line 91 for me):

$config['enable_hooks'TRUE

Good luck.

OMG That’s Fantastic!!!!

I am currently trying to optimize one of my sites for SEO and this worked perfectly! My site only had 4 pages and am trying to expand with more tier 3 pages that use SEO friendly url’s. I put this fix in place in no more than 5 min and also used redirects in my old controllers to point to the new url’s so that existing links to my site are not broken.

Thank you for providing such a great fix!

 Signature 

Scott, K2ZS
My amateur radio page

Profile
 
 
Posted: 22 March 2011 05:01 PM   [ Ignore ]   [ # 12 ]  
Research Scientist
Avatar
RankRankRankRankRankRank
Total Posts:  5458
Joined  06-19-2009

I know you have solved this but here is the Apache .htacces way of doing it!

The Apache .htaccess underscore to hyphen conversion code

Options +FollowSymLinks
RewriteEngine On
RewriteBase 
/
 
RewriteRule !\.(html|php)$ - [S=6]
RewriteRule 
^([^_]*)_([^_]*)_([^_]*)_([^_]*)_([^_]*)_([^_]*)_(.*)$ $1-$2-$3-$4-$5-$6-$7 [E=underscores:Yes]
RewriteRule 
^([^_]*)_([^_]*)_([^_]*)_([^_]*)_([^_]*)_(.*)$ $1-$2-$3-$4-$5-$6 [E=underscores:Yes]
RewriteRule 
^([^_]*)_([^_]*)_([^_]*)_([^_]*)_(.*)$ $1-$2-$3-$4-$5 [E=underscores:Yes]
RewriteRule 
^([^_]*)_([^_]*)_([^_]*)_(.*)$ $1-$2-$3-$4 [E=underscores:Yes]
RewriteRule 
^([^_]*)_([^_]*)_(.*)$ $1-$2-$3 [E=underscores:Yes]
RewriteRule 
^([^_]*)_(.*)$ $1-$2 [E=underscores:Yes]
 
RewriteCond 
%{ENV:underscores} ^Yes$
RewriteRule (.*) http://www.yourdomain.com/$1 [R=301,L] 

InsiteFX

 Signature 

Custom Designed Icons, eBook Covers Software Boxes. CD, DVD Etc. New iPhone® Tab Bar Icons and iPhone® Applications Icons.

STOP! Before posting your questions, remember the WWW Golden rule:
What did you try? What did you get? What did you expect to get?

Input -> Controller | Processing -> Model | Output -> View

Profile
 
 
Posted: 25 March 2011 08:11 AM   [ Ignore ]   [ # 13 ]  
Summer Student
Total Posts:  1
Joined  08-18-2010

use url_title() for this purpose.

Profile
 
 
Posted: 27 April 2011 10:20 PM   [ Ignore ]   [ # 14 ]  
Summer Student
Total Posts:  7
Joined  04-27-2011

Does this work with CI 2.0.2?

Profile
 
 
Posted: 08 May 2011 06:31 AM   [ Ignore ]   [ # 15 ]  
Summer Student
Total Posts:  2
Joined  05-08-2011

Another solution, which has been posted although it modifies all the segments, is as follows.

Create the MY_Router.php file in /application/core and in it place the following code:

<?php
public function _set_request($segments){
    
// Fix only the first 2 segments
    
for($i 0$i 2; ++$i){
        
if(isset($segments[$i])){
            $segments[$i] 
str_replace('-''_'$segments[$i]);
        
}
    }
    
    
// Run the original _set_request method, passing it our updated segments.
    
parent::_set_request($segments);
}
?> 

This just modifies the first 2 segments in your URL, but only if they are set. Hopefully that helps someone.

Profile
 
 
   
1 of 2
1