views:

33

answers:

3

I have an Apache web server that usually handles mod_rewrite fine. I have a directory called /communications/q/ and I want to rewrite any URI to insert "index.php" before the rest of the entered URI.

For example, /communications/q/something/else should actually serve communications/q/index.php/something/else. It's the standard PHP CodeIgniter setup.

I placed a .htaccess file in the /q/ directory and put the following in it:

RewriteEngine On
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]

When I even try to go to /communications/q/, I get a 404 Not Found error. Which makes no sense at all because if I comment the .htaccess stuff out, I get the index.php page if I go to /communications/q/, but with the code, I get 404 Not Found.

Anyone spot what I'm doing wrong?

FYI I have a controller called hello, so technically /communications/q/hello should work, but it's a 404, also. But with .htaccess commented out, /communications/q/index.php/hello works fine.

..

==== ADDED NOTE #1 ====

Using CodeIgniter, I should be able to call controllers and functions using the URI structure. So I have a controller called welcome, actually, and then a function called index() which is the default, and a function called hello().

The way CI works, I would write /communications/q/index.php/welcome and I would get the output of the index() function from the welcome controller. And in fact, this works perfectly right now.

Unfortunately, having that weird index.php in the URI is unwieldy and unnecessary, so CI suggests using .htaccess to allow the URI to omit that section of the URI and silently reenter it in the background, using mod_rewrite.

When I add the RewriteRule above, however, it doesn't work. So:

/controller/q/welcome returns a 404 error when it should return exactly the same thing as /controller/q/index.php/welcome. That's the problem. Shouldn't the RewriteRule above make that work?

..

A: 

When you use a ^ at the beginning of your regular expressions, it anchors your pattern match to the beginning of the request string, and even though your .htaccess file is within a folder, the request string mod_rewrite is matching against is still the entire local URI. You might try matching like this:

RewriteEngine On
RewriteCond $1 ~(index\.php|images|robots\.txt)$
RewriteRule ^/communications/q/(.*)$ /communications/q/index.php/$1 [L]
pjmorse
Doesn't seem to help. I've even added RewriteBase /communications/q/ and it doesn't help either. Strange behavior.
Jason Rhodes
hmm. Two other things that might be worth a look: Is your Apache configured to allow `.htaccess` files? (Some aren't for performance reasons. If you have other working `.htaccess` files, this isn't the problem.) The second option - the first, really, because that's what I was trying with the answer above - is that something's wrong with the regex. Can you break it down to something simpler to prove it's matching?
pjmorse
Yes, I mentioned that I have other .htaccess files working, and I verified with the server admin that .htaccess is permitted and enabled.I tried to break down what the regex is doing in my "Added Note #1" above, hope that helps. Thanks!
Jason Rhodes
A: 

The answer was in the CodeIgniter wiki, in the end. I replaced my .htaccess code with the following:

<IfModule mod_rewrite.c>

RewriteEngine On
RewriteBase /communications/q/

# Removes access to the system folder by users.
# Additionally this will allow you to create a System.php controller,
# previously this would not have been possible.
# 'system' can be replaced if you have renamed your system folder.

RewriteCond %{REQUEST_URI} ^system.*
RewriteRule ^(.*)$ /index.php?/$1 [L]

# When your application folder isn't in the system folder
# This snippet prevents user access to the application folder
# Submitted by: Fabdrol
# Rename 'application' to your applications folder name.

RewriteCond %{REQUEST_URI} ^application.*
RewriteRule ^(.*)$ /index.php?/$1 [L]

# Checks to see if the user is attempting to access a valid file,
# such as an image or css document, if this isn't true it sends the
# request to index.php

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]

</IfModule>

<IfModule !mod_rewrite.c>

# If we don't have mod_rewrite installed, all 404's
# can be sent to index.php, and everything works as normal.
# Submitted by: ElliotHaughin

ErrorDocument 404 /index.php

</IfModule>

And everything worked perfectly. The major relevant change, I think, was adding a ? to the RewriteRule after index.php -- does anyone understand why that's necessary?

Source: http://codeigniter.com/wiki/mod_rewrite/

Jason Rhodes
The main difference isn't the question mark, it's because the substitution is `index.php` not `/index.php`. Whilst the above solution will work, I'd recommend you use the option in my answer because it doesn't need to scan the directory for if the file exists every single time. That is, you're better off defining which files to ignore (index.php, robots.txt and images are the examples.) Also, put your system/application folders outside of the `DocumentRoot` and you don't need to bother about them either!
chigley
A: 

The substitution in a RewriteRule is relative to the DocumentRoot. Based on this, I'd suggest you try:

RewriteEngine On
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /communications/q/index.php/$1 [L]
chigley