Force Pretty URLs/More Consistent URLs

I've noticed that sometimes in concrete5, the URL suddenly has index.php in it again (usually from some redirect or a plugin that doesn't build URLs correctly), or a client will advertise a link at as opposed to (<-- the latter has an ending slash).

I'm the sort of guy that doesn't like putting www before a URL because is technically a subdomain of, even though it's 99.99999% of the time not treated that way.

/about-us looks for the object "about-us" in /. /about-us/ looks for the index file in the folder about-us in /.

Google at this point probably treats /about-us/ as the same as /about-us, but it's still a bit of a pet peeve, so I thought I'd do something about it.

First, copy /concrete/libraries/request.php to /libraries/request.php and paste the following code right before return $path at the end of the parsePathFromRequest() function.

// Cam Spear - added so url never has index.php in it and always ends in a slash
global $u;
if (!$u->isLoggedIn()) 
   $request_uri = trim($_SERVER['REQUEST_URI'], '/');
   if(isset($_SERVER['PATH_INFO'])) $path_info = $_SERVER['PATH_INFO'];
   else if(isset($_SERVER['ORIG_PATH_INFO'])) $path_info = $_SERVER['ORIG_PATH_INFO'];
   else $path_info = 'ends-in-slash/';
      if(stripos($request_uri, DISPATCHER_FILENAME) === 0 || $path_info[strlen($path_info) - 1] != '/')
         $redirect = '/' . $path . '/' . (!empty($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : '');
         // die($redirect);
         header('Location: ' . $redirect);

It works good for what I'm doing. It redirects to /about-us/ if it's /index.php/about-us/ or /about-us, etc, it handles the special case of /.

If you're logged in, it disables the whole system, otherwise you'd never be able to edit anything!

It also works to maintain the query string in the process.

I haven't been able to test it in a plethora of environments, but it worked great in my Web Hosting Hub shared hosting. It DEFINITELY is NOT going to work unless concrete5 is installed in the root (but without too much modification, it could handle that, too, I just didn't want to set it up to test it and I didn't want to post code without testing it).

I know I talk a lot, but I wanted to see what you all thought, and if anyone had improvements. I think my next step would be to redirect if it's "index.php?cID=111," etc. [edit2] I made a tweak and it seems to do this now, mostly on its own (i.e. it was already in the system if pretty links were enabled).


[edit] TL;DR: I wanted to post some examples.

When not logged in, which you go to the link on the left, it redirects to the link on the right. Try it by clicking on the link on the left and seeing that it (should) show the link on the right when it resolves. -> -> ->

View Replies:
jbx replied on at Permalink Reply
Have you tried just setting URL_REWRITING_ALL to true in your site.php file? That may do most of what you're after with much less work...

CWSpear replied on at Permalink Reply
Yep, and it does nothing in regards to what I'm talking about.

I put define('URL_REWRITING_ALL', true); in config/site.php, but when I go to /buyers, it shows /buyers when what I want is to forward it to /buyers/ (always ends in slash and always removes index.php, even if you type it in).
russgrue replied on at Permalink Reply
I just tried this in and it works until I try to click on the link;

When I do that either nothing happens or I get redirected to a error page (browser not C5).

The above url is whats produced when you add a link to a page inside a content block.

I'll have a try at hacking this myself but I'm not yet familiar with the intricacies of your hack or C5's internals when it comes to links and URL's.

CWSpear replied on at Permalink Reply
I'm not sure the workaround will always works for pages in the form "index.php?cID=81." I've been noticing a few quirks.

But it definitely should redirect to the page with the actual friendly URL. I'll take a look in the next day or two and let you know what I find out.

But for now, I know it is (or at least was) handling turning /index.php/about, /index.php/about/, and /about into /about/
russgrue replied on at Permalink Reply
Ok more info...

In Crome - Nothing happens, a request is made but the page never refreshes.

In Firefox - The page loads normally using the same url.

In IE - A "Cannot display page" error is thrown up.

...If I remove your code they all work again.

russgrue replied on at Permalink Reply
Ok I found a sollution to my problem. Andrew Embler thought of this and posted about it here:

So becuase it does it's thing before your code the broken part for dealing with cID url's never plays out so in combination both hacks work together happilly.

I would love it if you could modify your code to also support the cID url's I'd like to use a single hack over multiple ones per problem.

eljhonb replied on at Permalink Reply
hi, sorry to reviving this thread.
It is a nice post but there is a problem. When you redirect, the current POST variables are lost. How to deal with this problem?
thx in advance
jbx replied on at Permalink Reply
Actually, the best way to deal with this issue by far is to post to the
correct URL in the first place, simply by changing the action of your form.
Is this possible in your situation?


On 5 June 2013 11:31, concrete5 Community <[email protected]>wrote:
eljhonb replied on at Permalink Reply
hi jon,
no, it is not possible. the app is working since a long time and i cannot modify it.

any other suggestion?

eljhonb replied on at Permalink Reply
Solved. I post the solution, maybe can be useful to someone.
I have added a validation at the begin of the script. If is a post method saves the post data in a session array and then read it from the form.
if (!$u->isLoggedIn()) 
        if(isset($_POST)) $_SESSION['postvariables'] = $_POST;
gerkwil replied on at Permalink Reply
Sorry for re-opening the thread.

This is a great solotion to my problem, elsewise i have to put all seperate rules in the htaccess wich is not ideal.

But the request.php file in version looks like

<?php  defined('C5_EXECUTE') or die("Access Denied.");
class Request extends Concrete5_Library_Request {}

so i can not use your codefragment now. any ideas?