Codeigniter and .htaccess mod rewrite - .htaccess

I am having an issue with mod rewrite. I am also a total beginner to it. I am using CodeIgniter and trying to rewrite the following:
http://url.dev/news/news_selection?item=59
to look like this:
http://url.dev/news/news_selection/59/
I have followed a tutorial on: https://www.addedbytes.com/articles/for-beginners/url-rewriting-for-beginners/ (more specifically the : "Patterns and Replacements" section)
The issue is I write my RewriteRule as below and it still does not rewrite the url after going to the page (eg. http://url.dev/news/news_selection?item=59)
RewriteRule ^news/news_selection/([0-9]+)/?$ news_selection?item=$1 [NC,L]
Any advice on where I am going wrong? Thank you.
I am not sure if the routes and controller affect this issue but I added them for reference below.
In my routes for codeIgniter I have
//_News Folder
$route['news/(:any)'] = 'pages/view2/_news/$1';
1: _news is the folder
2: news_selection is the php file
3: pages is the controller
My controller has the following function for view2:
public function view2($sub ='', $page='')
{
if ( ! file_exists(APPPATH.'/views/pages/'.$sub.'/'.$page.'.php'))
{
// Whoops, we don't have a page for that!
show_404();
}
$data['title'] = ucfirst($page); // Capitalize the first letter
$this->load->view('templates/header', $data);
$this->load->view('pages/'.$sub.'/'.$page.'.php', $data);
$this->load->view('templates/footer', $data);
}
The rest of my .htaccess:
Options -Indexes
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
#Removes access to the system folder by users.
#Additionally this will allow you to create a System.php controller,
RewriteCond %{REQUEST_URI} ^system.*
RewriteRule ^(.*)$ index.php?/$1 [L]
#When your application folder isn't in the system folder
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]
# 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

You just need this to use url as above:
RewriteEngine on
RewriteCond $1 !^(index\.php|images|captcha|css|js|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]
You can use this for all controller. This file .htaccess is in application folder.

I figured it out after about 10 hours of trying everything today.
I decided that it may be a routing issue with CI and decided to try passing my variable from the url in the cleaned up format. So...
If I enter: http://url.dev/news/news_selection/59
It will work with the following route:
//_News Folder
$route['news/news_selection/(:num)'] = 'pages/view_test/_news/news_selection/$1';
and controller:
public function view_test($sub='', $page='', $var1='')
{
if ( ! file_exists(APPPATH.'/views/pages/'.$sub.'/'.$page.'.php'))
{
// Whoops, we don't have a page for that!
show_404();
}
$data['item'] = $var1;
$this->load->view('templates/header');
$this->load->view('pages/'.$sub.'/'.$page.'.php', $data);
$this->load->view('templates/footer');
}
By using these I can pass the page number as $var1 and then pass it on to my view via $data. Then I picked up $data['item'] as $item in my news_selection.php page and passed it to my model for processing. Reference to CI Manual for this.
After that the page processes like it normally would have.

Related

Rewrite url to pretty after redirect to folder - htaccess laravel

Hello I have a "protected" folder on my server. In its .htaccess file for conditional redirect of some users I use the following rules:
RewriteCond %{REMOTE_ADDR} ^1\.2\.3\.4*
RewriteCond %{REQUEST_URI} !^/special
RewriteRule ^$ /special [R,NE,NC]
In the /special folder I have a .htaccess file with the following rules:
RewriteCond %{REMOTE_ADDR} !^1\.2\.3\.4$
RewriteRule ^(.*)$ / [R=301,NE,NC,L]
The application in the folder will be laravel based so my content will have to be served from index.php file residing in /special/laravel/public/index.php
I want the URL to look like /special/.
What rules should I put and where for this to happen?
This is a follow up to my previous question:
https://stackoverflow.com/questions/24487012/redirecting-specific-ip-to-special-content-htaccess-vs-php
Simply rewrite the URL with .htaccess: (goes in /)
DirectoryIndex index.php
#Redirect to /special/laravel/public if you haven't already and the IP is okay
RewriteCond %{REMOTE_ADDR} ^1\.2\.3\.4*
RewriteCond %{REQUEST_URI} !^/special/laravel/public
RewriteRule ^(/special)(/laravel)?(.+) /special/laravel/public$2 [L]
#if IP does not match and you ARE in the folder, then Redirect to root
RewriteCond %{REMOTE_ADDR} !^1\.2\.3\.4*
RewriteCond %{REQUEST_URI} ^/special/laravel/public
RewriteRule .? / [R=301,L]
I think that'll work. I didn't test it though. I can add to it if you need me to. And of course for your use case you may need to add some more RewriteConds in there for validating the REMOTE_ADDR.
The way I handle it:
.htaccess:
RewriteCond %{REQUEST_URI} !^/load_page.php$
RewriteRule ^(.+)$ /load_page.php [QSA, L]
That causes the server to redirect internally to load_page.php if the requested URL is not load_page. Without the RewriteCond, I believe it would cause an infinite redirect. This should work, but I didn't test it because it's different from my implementation, since mine also handles rewriting URLS to have trailing slashes and never show .php which makes it a bit more complex and quite different.
load_page.php:
$SITE_ROOT = $_SERVER['DOCUMENT_ROOT'];
$URL = $_SERVER['REQUEST_URI'];
ob_start();
if (conditionOne){
//change $URL here if you need to or do nothing
} else if (conditionTwo){ //check the IP or whatever you want to here
if (aCondition){//if $URL starts with '/special'
$URL = str_ireplace('/special/','/special/laravel/public/',$URL,1);
}
if (is_dir($SITE_ROOT.$URL))$URL .='index.php';
}
if (!file_exists($SITE_ROOT.$URL))$URL = '/error/404.php';
include($SITE_ROOT.$URL);
$content = ob_get_clean();
echo $content;
It's something to that affect. The user doesn't see load_page.php and they don't see that you changed the URL to special/laravel/public, but you include the correct file.

can't remove index.php with .htaccess

i have installed codeigniter and i want to remove the index.php from url when i access localhost/aplication/index.php. i have set uncomment mod_rewrite.so from httpd.conf en this is my .htaccess file :
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
its succes when i acces url from localhost/aplication/index.php/data/users/12 but not with this url localhost/aplication/data/users/12.
how can i fix this??
Try to follow this page about codeignitor pretty urls. Your rules look correct, but I'm terrible with regex.
Some things to look into would be checking if mod_rewrite is available by using phpinfo();. Also step three in that link talks about enabling mod_rewrite using a2enmod. And make sure you restart Apache.
check your config file there should be a line that says:
$config['index_page'] = 'index.php';
You can either set this variable to just '' or you can comment this line out completely, either way it is part of the process of removing the index.php from your codeigniter urls.
this is how you remove the index.php:
htaccess file in the root folder:
RewriteBase /
RewriteEngine on
RewriteCond $1 !^(index\.php|images|js|css|robots\.txt)
RewriteRule ^(.*)$ index.php/$1 [L]
for managing some static pages like: example.com/about , example.com/contact, example.com/terms etc
got to config routes file and edit:
//the controller that will be when it is exampl.com
$route['default_controller'] = 'YOUR_MAIN_CONTROLLER_NAME_HERE';
//I creted this for pages that are created dynamically or for displaying error when I want
$route['404_override'] = 'friendlyPages';

Htaccess rule to make urls like this ?page=1 look like /page/1 in Codeigniter

This is how my urls currently look:
http://mysite.com/?page=1
How can I make this work?:
http://mysite.com/page/1
There is a post on StackOverflow that asks the same question. But the accepted solution isn't working for me. Because I am using Codeigniter and my page results in a 404 perhaps because since the url pattern of a CI site is:
domain/controller/method
The system is assuming that I am requesting a controller called "page" and a method called "1" both of which of course doesn't exist. Or maybye it's due to a conflict with the other code in my htaccess file (which I downloaded from the CI wiki, it gets rid of index.php and does a few security things). Here is my entire htaccess file:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
#Removes access to the system folder by users. Additionally this will allow you to create a System.php controller, '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. 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]
#Pretty urls for pagination links
RewriteRule (.*) index.php?page=$1
</IfModule>
The non indented bit is the solution I got from that other SO question that isn't working for me.
Any solutions to this CI pagination issue?
UPDATE
Ok, read some of the docs and now I have this working:
http://mysite.com/home/index/2
What would be the htaccess rule to turn that into?:
http://mysite.com/page/2
You should make this configuration at /application/config/routes.php (and let the .htaccess just for hide the index.php as you are already doing).
$route['page/(:any)'] = 'home/index/$1';
Or better, like #zaherg remembered (ensures that only numbers could by matched):
$route['page/(:num)'] = 'home/index/$1';
This way all the requests to http://mysite.com/page/2 will be treated internally as http://mysite.com/home/index/2 and so forth.
I suggest you take a look at CodeIgniter User Guide - URI Routing and CodeIgniter User Guide - Tutorial − Introduction.
Good luck.
RewriteEngine on
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]
from CodeIgniter docs
That will handle removing the index.php, but what happens after that depends how CodeIgniter's query string handling is set up: it can be configured to use a query string rather than a path. See the link for more details.

htaccess rewrite rule for subfolder [duplicate]

I have the following structure
-www
\-subfolder
In www I have my main site's index.php.
In subfolder I have a sort of admin UI and in there I'd like to have another index.php for the admin UI.
Currently my requests from within /subfolder/index.php get redirected to www/index.php and basically the pages of my admin UI don't show up.
This is my .htaccess file:
RewriteEngine On
RewriteRule ^$ index.php [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/(.*)$ index.php?lang=$1&page=$2 [L]
Can you help me? I've tried several options in other answers but as I'm no so advanced a web developer, I couldn't get any to work.
#TerryE, Sorry if I have come off as crude.
I am using a local setup for testing.
I have installed Vertrigo server, which gives me Apache server.Running on Windows7 OS. The server is installed in Program files\VertrigoServ\Apache folder.
My public folder is www. In there I have my main site definition. . The site is accessed locally via 127.0.0.1/index.php or 127.0.0.1/
I have site localization so URLs are constructed as /$lang/$page e.g. HOME
In index.php of main site I have the following:
$page = trim( ( isset( $_GET[ 'page' ] ) ? $_GET[ 'page' ] : 'home' ), '/' );
$lang = trim( ( isset( $_GET[ 'lang' ] ) ? $_GET[ 'lang' ] : 'en' ), '/' );
$langs = array( 'en', 'fr', 'ru' );
And upon this data I get to open the pages this way:
include 'html/'. $lang . '/' . $page . '.php';
All my main site's pages lie in www/html/$lang/
$_SERVER['REQUEST_URI']) gives /en/home for page HOME.
127.0.0.1/en/home WORKS
All navigation works perfectly for the main site.
However I have created an admin UI which lies in folder www/admin - one level below in www.
And in there I don't have any localization. I just have EN as language.
So at the top of the index.php in admin folder I have again
$page = trim( ( isset( $_GET[ 'page' ] ) ? $_GET[ 'page' ] : 'home' ), '/' );
However, here navigation is as follows HOME
and upon this I get to construct the pages in the index.php in admin folder as follows:
include 'html/ . $page . '.php';
the pages lie in www/admin/html
This does not work at all. Whenever I press home link in admin UI, I get redirected to my main site (non-existing page). If I add RewriteRule ^subfolder/ - [L] in .htaccess, I get HTTP 404 NOT Found error.
127.0.0.1/admin/home DOES NOT WORK. Neither does any other navigation from within admin. Thank you for your willingness and patience to help me!
I assume from this that you only have a single .htaccess file in your www directory.
Think about what the rule
RewriteRule ^(.*)/(.*)$ index.php?lang=$1&page=$2 [L]
does when interpreted in a Perdir context from www: take any URI of the form someDir/somePage and replace it by index.php?lang=someDir&page=somePage, so this will intercept and rewrite any /subfolder/index.php.
This isn't well documented but Perdir processing will preferentially use the lowest .htaccess file setting RewriteEngine On on the request path. So if you add an admin-specific .htaccess file in the "subfolder" subfolder, this will preempt the www one and circumvent this problem.
Postscript comments
Veni and other posters get in a Q&A when the real issue is one of "how do I debug my .htaccess rules if I my website is hosted by a shared service?" The reason that I add the shared service qualification is that if you have root access to your LAMP config then you can turn on Rewrite logging and the logfile at a debug level of 4-6 will give you enough forensics to work out what is going on.
However, the large majority of hobby / small service users buy their services on a shared basis and here they don't have root access and the hosting provider disables such logging for performance reasons so they have a binary feedback -- the rules work or they don't. I use a shared service and my approach (described here) is to set up a VM which mirrors this configuration for as a test and integration environment -- and in this I have such root access. However, this is probably far too complicated for most users. This is really a wider topic that merits its own Q / discussion.
On specific points:
If your structure is /(lang|admin)/page, then why do you have this rule because it can cause havoc on perdir retries.
RewriteRule ^$ index.php [QSA,L]
Better something like the following to force a redirect to a default language (assume the lang list is EN and IT in this example:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond $1 !^/(en|it|admin)/
RewriteRule ^(.*) http://yourdomain/en/$1 [R=301,L]
Are you aware of the redirect restart /looping issues? (search for REDIRECT_STATUS)
I'm new to Stackoverflow, but not to sorting out this sort of s**t. I've got a couple of detailed articles on my blog on this.
Postscript comments -- yet more
OK some general help.
Don't us fixed IPs put an alias for 127.0.0.1 in your windows\system32\drivers\etc\hosts
You can turn on rewrite logging in your VertrigoServ Apache config and this gives you a detailed audit of where you have problems
It also helps if you have a little diagnostic stub to help you understand what is going on and this is what I came up with for index.php in the test directories:
<?php header( "Content-type: text.plain" ); echo "main: "; var_export($_GET);
But you really need for each of the following cases:
- to handle the URI exists (and stop rewrite loops)
- the defaults for / and /admin/
- admin/*
- */*
- * (and the language defaults)
and this is what I came up with. I've kept it simple. We could use complex regexps to fold some of these but why bother. You may need to add more QSAs if needed.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule . - [L]
RewriteRule ^$ index.php [QSA,L]
RewriteRule ^admin/?$ admin/index.php [QSA,L]
RewriteRule ^admin/(.*)$ admin/index.php?page=$1 [L]
RewriteRule ^(.*)/(.*)$ index.php?lang=$1&page=$2 [L]
RewriteRule ^(.*)$ index.php?lang=en&page=$1 [L]
RewriteEngine On
RewriteRule ^$ index.php [QSA,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^subfolder/(.*)$ subfolder/index.php?page=$2 [L]
RewriteRule ^(.*)/(.*)$ index.php?lang=$1&page=$2 [L]
You could prevent requests to you subfolder from being rewritten with the change below
RewriteEngine On
RewriteRule ^$ index.php [QSA,L]
#prevent requests to your subfolder from being rewritten
RewriteCond %{REQUEST_URI} !^/subfolder/ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/(.*)$ index.php?lang=$1&page=$2 [L]

How to pass-through requests not going to specific directories to index.php/path?

In my present project I've got several directories: application (my MVC files, which mustn't be accessed), images, css, and js. Effectively I want all requests to images/css/js to proceed unchanged, but all others I wish to call index.php/my/path.
My .htaccess currently looks like this, and is wreaking havoc with my routing.
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond $1 !^(index\.php|images|js|css|robots\.txt)
RewriteRule ^(.*)$ http://example.com/index.php/$1 [L]
</IfModule>
This isn't working as relative URLs start stacking up, such as: example.com/blog/view/1/blog/view/2.
When I attempt something like,--
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/(index\.php|images|js|css|robots\.txt)
RewriteRule ^ index.php%{REQUEST_URI} [PT]
</IfModule>
I get this error with any request: No input file specified.
How can I force all requests not to my whitelisted directories to call, not redirect to (redirection murders posting, I found), index.php/path? IE, when /blog/view/1 is requested by the browser, .htaccess calls index.php/blog/view/1. The reference files at Apache's site aren't too clear about how to do this sort of thing—that, or, I am just missing the point of what I'm reading about RewriteRule.
And, I really want to understand this. Why will your answer work? Why are my attempts failing?
This is what I have in my .htaccess for my framework:
<IfModule mod_rewrite.c>
RewriteEngine on
#This will stop processing if it's images
RewriteRule \.(css|jpe?g|gif|png|js)$ - [L]
#Redirect everything to apache
#If the requested filename isn’t a file….
RewriteCond %{REQUEST_FILENAME} !-f
#and it isn’t a folder…
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?$1 [L,QSA]
#L = (last - stop processing rules)
#QSA = (append query string from requeste to substring URL)
</IfModule>
Hope this helps.
PS: Maybe you want to remove the lines to stop redirecting if it's a file or folder ;)
Antonio helped me get on the right track, so here's the resulting .htaccess:
<IfModule mod_rewrite.c>
RewriteEngine on
# skip if whitelisted directory
RewriteRule ^(images|css|js|robots\.txt|index\.php) - [L]
# rewrite everything else to index.php/uri
RewriteRule . index.php%{ENV:REQUEST_URI} [NE,L]
</IfModule>
You're going to have to do that using PHP. For example, if you wanted to split your URI into something like domain.tld/controller/action/param, then you could use the following PHP code as a start:
<?php
// Filter URI data from full path
$uri_string = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['REQUEST_URI']);
$uri_string = trim($uri_string, '/'); // Make sure we don't get empty array elements
// Retrieve URI data
$uri_data = explode('/', $uri_string);
In that case, $uri_data[0] is the controller, $uri_data[1] is the action, and beyond that are parameters. Note that this isn't a foolproof method, and it's never a great idea to trust user-entered input like this, so you should whitelist those controllers and actions which can be used.
From here, knowing the controller and having a consistent directory structure, you can require_once the proper controller and call the action using variable variables.
This is what I use in my .htaccess file for my CMS:
Options -Indexes
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php/$1 [NC,L]
And then in my index.php file I have:
$path_info = '';
$path_info = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : $path_info;
$path_info = isset($_SERVER['ORIG_PATH_INFO']) ? $_SERVER['ORIG_PATH_INFO'] : $path_info;
$request = explode('/', trim($path_info, '/'));
// if $request[0] is set, it's the controller
// if $request[1] is set, it's the action
// all other $request indexes are parameters
Hope this helps.

Resources