views:

1106

answers:

5

I have a PHP web app located on shared hosting. My goal is to modify .htaccess file from PHP code when the PHP page is running. I need that .htaccess to insert a couple of mod_rewrite lines into it.

The problem is that on Windows+Apache I can dinamically modify .htaccess file but the same code on Linux reports a problem when I try to access this file in any way (copy or fopen): "failed to open stream: Permission denied"

I have given .htaccess file 777 permissions - still no result. WHat prevents me from doing this? How can I develop a workaround?

P.S. My initial goal was to be able to add a new RewriteRule into .htaccess that maps a newly added category_id with new category_name. If it wasn't shared hosting, I would use something like RewriteMap (in main Apache config) and would be able to access the map file.

This is the first real limitation I've been unable to tackle with PHP+Apache, but I hope it's circuventable too.

+7  A: 

This seems like an overly-complex solution to just having a general "load category" page that takes the category name from the URL and loads the corresponding ID.

For example, if the URL is:

http://yoursite.com/category/programming

I would remap that to something like:

http://yoursite.com/category.php?name=programming
Chad Birch
+1 for that idea... having the web server write to .htaccess files (or any files under the document root) is nearly always a bad design.
David Zaslavsky
Are you talking about some kind of universal Front Controller page?So thatt whatever new category I have, e.g. IT/programming or 1/2/3/subcat4I just send them people to main controller page that reads SEO link from REQUEST_URI variable and redirects user to accoding page.php?id=x.
PHP thinker
It doesn't have to be a single front controller for everything. You could have /category/programming redirect to category.php?name=programming and /post/hello-world redirect to post.php?name=hello-world, if you wanted. It's up to you how to do that part, anything is better than changing .htaccess.
Chad Birch
A: 

I agree with Chad Birch. In case you can't be dissuaded, though, in your situation I would first be looking for parent directories with locked-down permissions.

FYI, one of the reasons that rewriting the .htaccess is a bad idea is that any requests that come in while the .htaccess is being rewritten will not have any of your redirects applied.

chaos
+3  A: 

You only need a small set of rewrite rules. To do what Chad suggests:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/category/.*$ category.php [QSA]

Thus, anytime someone navigates to /category/category_id, the request will be directed to category.php, which will be handed the /category/ URI in $_SERVER['REQUEST_URI'], from which you can easily get the category ID, and you don't need to bother with editing the .htaccess file every time you add a category.

greyfade
+4  A: 

I want to suggest something else that also works. Instead of writing a rule for every 'special' url, why not use one for all?

I found it a whole lot easier to use what wordpress uses: every url is redirected to the index.

All you have to do is, set up the index file, read in the directory that was loaded (perhaps using $_SERVER['URI_REQUEST']), and deal with it.

add to .htaccess this:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

Thanks to that chunck you have a system somewhat unlimited at your disposal. If you ever feel like renaming you categrory url, or add another special case, it's already ready!

Jasper
A: 

While I agree with the above comments, it can definitely be done. PHP apps like WordPress do exactly this based on changes made on the settings page. It should be as simple as writing the file out however the parent directory NEEDS to have permission for the web server user to write to it.

If it isn't working for you the trick will be making the parent directory either 777 or 775 and having the group set to whatever group Apache runs under (usually "apache" or "www" or something similar)

Adam (commented on your question) is quite correct though, some other security layer on your server might be preventing you from doing this, and this is probably a good indication that you might be approaching the problem the wrong way.

bjeanes