Reputation: 41
Good day, dear people. I'm new in the community, but not that much in programming. Let me bring the short story.
I'm creating a little application based on the CodeIgniter Framework (v 2.1.4). I already configured the whole code so I don't have to write the "index.php" part on the URL, and also I configured the default controller to not be written in the URL as well. I also ensured that each method of each controller was linked to a view which featured div able to show an error message, thanks to the '$this->session->flashdata()' method.
So, let's say, my default controller is called 'inicio'. In order to run it from my local server, I go to my browser and write the following line in the address bar:
URL: http://localhost/vga/
And configured the application/config/routes.php so I could avoid unnecessary writting
$route['default_controller'] = 'inicio';
$route['404_override'] = '';
$route['inicio'] = '';
I put the setup of the .htaccess
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php/$0 [PT,L]
And that's all. That will bring me to the default controller, which is controlled by a session manager which forces me to fill a login form, in order to access to the inner part of this page.
URL: http://localhost/vga/acceso
This login has a link to a basic registration form, which works like a charm.
URL: http://localhost/vga/acceso/registro
There is even a profile controller, which lets me see and edit my own profile. Good stuff, I don't even need a URI segment parameter since the ID is being passed by session.
I didn't touch the application/config/routes.php for anything more than the configuration of the default controller. Everything is cool until this point.
Now, here comes my headache.
I created a new controller to control 'roles' in this page. This controller has 3 methods:
class Roles extends CI_Controller {
function index() {}
function editar() {}
function usuarios() {}
}
The basic idea behind each method is rather simple.
'index' should list the roles existing in this web system (such as admin, user, ect), and also tell me how much users are there, categorized by roles. 'editar' should let me edit the basic aspects of each role. 'usuarios' should show me list the users existing in each role.
I programmed each method, and they work just fine. The problem relies in a damn flashdata that is being shown under strange circumstances, specifically in the 'editar' and 'usuarios' methods.
Why are they special? Well, compared to every other method, they possess 3 URI Segments: Controller, Method, and just One Parameter.
This is the scenario:
Both 'editar' and 'usuarios' have certain common lines of code:
/*
I'll be trying to edit a specific numeric entry,
and force it to be zero in case of empty segment.
The page should be redirected in this case.
*/
$id = $this->uri->segment(3, 0);
if( $id == 0 ){
$this->session->set_flashdata('message', 'Error #X' ); /* Only these controllers have this Error Code */
redirect( 'roles' , 'refresh');
}
Looks good, right? Well, the thing is, when I'm in the 'roles' index and go to 'roles/usuario/1' (which is existing data) or to 'roles/editar/1' (which also is existing data), those pages shows clean as expected. The trouble comes when I press 'refresh' on my browser, or when I go to any page from this point... because in all the cases the system throws a 'Error #X' message... and the page IS NOT REDIRECTED, as I should expect in case of $id = 0. So, I'm assuming that the flow bypassed the if statement, enough to set the $this->session->flashdata('message') variable, but not enough to command the redirect method.
Awful headache here. Then, I started to think a bit and tried to further exploit the application/config/routes.php feature, so I set some rules, and the file became like this:
$route['default_controller'] = 'inicio';
$route['404_override'] = '';
$route['inicio'] = '';
$route['roles_usuarios/(:any)'] = 'roles/usuarios/$1';
$route['roles_editar/(:any)'] = 'roles/editar/$1';
And voilà, the damn message stopped to be shown under strange circumstances, and only showed when I expected to be shown ( when $this->uri->segment(3) was not inserted in the URL, or when its value didn't exist in my database, in case of using it as a parameter for a database query ).
How is it possible for the $this->uri->segment(3) to bypass the if statement?
I managed to discover that this could be a routing issue, since replacing
$route['roles_usuarios/(:any)'] = 'roles/usuarios/$1';
$route['roles_editar/(:any)'] = 'roles/editar/$1';
by
$route['roles/usuarios/(:any)'] = 'roles/usuarios/$1';
$route['roles/editar/(:any)'] = 'roles/editar/$1';
triggers again the anomaly, and I really do not want to use underscores in my urls.
I'd gladly give thanks to any helping hand out here.
Update: Solved it. Let me share my knowledge.
Using @AdrienXL 's guide, I managed to find a way for the htaccess to work, among with expliciting the lines of code for 3-segmented uri routes in routes.php, and setting a generic rule for any other route in the roles controller after the previous ones.
These are the files now:
.htaccess
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
routes.php
$route['default_controller'] = 'inicio';
$route['404_override'] = '';
$route['inicio'] = '';
$route['roles/editar/(:num)'] = 'roles/editar/$1';
$route['roles/usuarios/(:num)'] = 'roles/usuarios/$1';
$route['roles/(:any)'] = 'roles/index';
Now the system works flawlessly. Thanks!
Upvotes: 2
Views: 772
Reputation: 41
Update: Solved it. Let me share my knowledge.
Using @AdrienXL 's guide, I managed to find a way for the htaccess to work, among with expliciting the lines of code for 3-segmented uri routes in routes.php, and setting a generic rule for any other route in the roles controller after the previous ones.
These are the files now:
.htaccess
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
routes.php
$route['default_controller'] = 'inicio';
$route['404_override'] = '';
$route['inicio'] = '';
$route['roles/editar/(:num)'] = 'roles/editar/$1';
$route['roles/usuarios/(:num)'] = 'roles/usuarios/$1';
$route['roles/(:any)'] = 'roles/index';
Now the system works flawlessly. Thanks!
Upvotes: 2