EllisLab text mark
Advanced Search
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 01:08 PM   [ Ignore ]
Joined: 2009-07-27
5 posts

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.

 
Posted: 27 July 2009 07:45 PM   [ Ignore ]   [ # 1 ]   [ Rating: 0 ]
Avatar
Joined: 2008-09-07
119 posts

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

 Signature 

Branson Web Design
Handmade Fashion Jewelry

 
Posted: 27 July 2009 07:49 PM   [ Ignore ]   [ # 2 ]   [ Rating: 0 ]
Joined: 2009-07-27
5 posts

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

 
Posted: 27 July 2009 11:18 PM   [ Ignore ]   [ # 3 ]   [ Rating: 0 ]
Avatar
Joined: 2009-03-21
679 posts

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.

 
Posted: 28 July 2009 04:28 AM   [ Ignore ]   [ # 4 ]   [ Rating: 0 ]
Joined: 2009-07-27
5 posts

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.

 
Posted: 28 July 2009 05:22 AM   [ Ignore ]   [ # 5 ]   [ Rating: 0 ]
Avatar
Joined: 2008-09-11
758 posts

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

http://ellislab.com/codeigniter/user-guide/general/routing.html

 Signature 

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

 
Posted: 28 September 2009 11:54 PM   [ Ignore ]   [ # 6 ]   [ Rating: 0 ]
Joined: 2006-03-10
2 posts

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.

 
Posted: 29 September 2009 12:16 AM   [ Ignore ]   [ # 7 ]   [ Rating: 0 ]
Avatar
Joined: 2009-07-06
50 posts

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://ellislab.com/forums/viewthread/85901/#623512

 
Posted: 13 October 2009 11:09 AM   [ Ignore ]   [ # 8 ]   [ Rating: 0 ]
Joined: 2009-10-13
10 posts

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

 
Posted: 30 November 2010 09:41 AM   [ Ignore ]   [ # 9 ]   [ Rating: 0 ]
Joined: 2009-11-20
8 posts

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

 
Posted: 01 December 2010 03:57 AM   [ Ignore ]   [ # 10 ]   [ Rating: 0 ]
Avatar
Joined: 2006-12-26
727 posts

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

 
Posted: 22 March 2011 09:24 AM   [ Ignore ]   [ # 11 ]   [ Rating: 0 ]
Avatar
Joined: 2010-10-23
160 posts
b3nst3wart - 29 September 2009 03: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

 
Posted: 22 March 2011 06:01 PM   [ Ignore ]   [ # 12 ]   [ Rating: 0 ]
Avatar
Joined: 2009-06-19
6267 posts

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 

Ceritfied State of CT Computer Programming Teacher.
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

 
Posted: 25 March 2011 09:11 AM   [ Ignore ]   [ # 13 ]   [ Rating: 0 ]
Joined: 2010-08-18
1 posts

use url_title() for this purpose.

 
Posted: 27 April 2011 11:20 PM   [ Ignore ]   [ # 14 ]   [ Rating: 0 ]
Joined: 2011-04-27
7 posts

Does this work with CI 2.0.2?

 
Posted: 08 May 2011 07:31 AM   [ Ignore ]   [ # 15 ]   [ Rating: 0 ]
Joined: 2011-05-08
2 posts

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.

 
1 of 2
1