Incorrect routing via /config/routes.php - php

I have the following (basic) route set up in a CI-based web app:
$route['sms/resend/(:num)/(:any)'] = 'sms/resend/$1/$2';
The controller + 'resend' method:
class Sms extends CI_Controller {
public function resend($to, $message) {
// my code
}
}
Logically speaking, anything that doesn't fit the route should be directed to a 404 page instead of the resend() method within the sms controller. This isn't the case, however. The following URL, for example, isn't redirected correctly, it goes to the same controller+method:
http://myapp/sms/resend/uuuu/WhateverMessage
What could be the problem?

After a bit of digging, I've come to understand that CI's default routing does not get deactivated when a default route related to a specific controller/method pair is added. That being said, if a URL does not fit the route $route['sms/resend/(:num)/(:any)'] = 'sms/resend/$1/$2', then the same URL is run through CI's default routing mechanism as a fallback, so it still takes me to the resend method of the sms controller. To prevent this from happening, I needed to add another custom route that follows all others related to the sms resending, that redirects any other url to a different controller+method. If this controller doesn't exist, you get the default 404 page.
So the final /config/routes.php file:
$route['sms/resend/(:num)/(:any)'] = 'sms/resend/$1/$2';
$route['sms/checkoperator/(:num)'] = 'sms/checkoperator/$1';
$route['sms/(:any)'] = 'somewhereovertherainbow';

I think the rout file is just for rerouting. Your URL don't fits the routing Conditions so it don't gets rerouted! So it goes the normal way wich is the same (in this case!)
Something like this could work!
(! :num) /(:any) '] = error page (or not existing page)
So every request wich doesn't start with a number gets redirected to the error page!
The syntax might be wrong!
This would work great :
$route['sms/resend/[^0-9]/(:any)'] = 'errorpage';
You have to replace the error page by something ;)

Related

using routes in Codeigniter to get to one of two controllers

I have two controllers Configure.php and Users.php. In my routes.cfg I have:
$route['default_controller'] = 'Users/login';
$route['404_override'] = '';
$route['translate_uri_dashes'] = FALSE;
$route['registration'] = 'registration';
$route['login'] = 'login';
$route['subit_backend']['GET']='subit_backend/register';
$route['save_userinput']='Users/save_userinput';
When a user brings up the website the following page comes up in the browser bar https://www.stantiation.com/sub_crud/Users/login/ which is perfect.
The problem is that if a user has forgotten their password I am having trouble routing them to method where they can create a new one. I have the user send an email to themselves where I have placed a "code" that will allow them to update their password. The email has a link to this form:
https://www.stantiation.com/sub_crud/Users/resetPassword?fp_code=492c8bbd3841xxx8201f3a01d77fd.
I also have a view file called view/Users/resetPassword.php which is form that allows the user to enter a new password. That pops up fine. This is the post method of the form.
When the user presses submit, I get https://www.stantiation.com/sub_crud/Users/save_userinput in the toolbar and a 404 error, because there is no save_userinput.php file. I am trying to get the save_userinput() method in the Users.php controller to run, not save_userinput.php in the view/Users/directory. I agree with the 404 because that file doesn't exist.
How can I specify in a form that I want the method in controller Users, not the file view/Users/save_userinput.php? That is why I put the last $route in but that doesn't seem to help.
It seems that you might be understanding the CodeIgniter URL scheme. Read about it HERE.
Basically, it boils down to http:doman.tld/controller/function[/var1 ...[/varN]]
So, after the domain you have multiple segments that are interpreted like so:
The first segment represents the controller that should be invoked.
The second segment represents the class function, or method, that should be called.
The third, and any additional segments, represent any variables that will be passed to the controller.
So the URL https://www.stantiation.com/sub_crud/Users/save_userinput would go to the controller Users (which appears to be in the folder of /application/controllers/sub_crud) and call the controller method save_userinput. It is not looking for a file named save_userinput.php.
The 404 could be because the controller is not in a sub-folder or because some other file the controller tries to load, i.e. a "view" file, cannot be found.
It's hard to offer better advice without seeing the html for the form and knowing exactly how you have your file layout structured.
(Side note: I avoid putting controllers in sub-folders because it messes with the URL "look" and IMO, in terms of "controllers", it's not that hard to track what-is-what.)
You really only need routes when you want to override CodeIgniter's segment-based approach to URLs. With that in mind, it appears (based on a general lack of understanding about your app) that the following "routes" don't make sense.
$route['registration'] = 'registration';
$route['login'] = 'login';
$route['subit_backend']['GET']='subit_backend/register';
$route['save_userinput']='Users/save_userinput';

CodeIgniter - Select controller based on database

I'm building a simple CMS using Code Igniter version 3.0.0
The site's URLs are all customizable by the user and so do not follow the standard MVC structure of /controller/method/parameter-1/parameter-2/. Instead, all frontend traffic gets directed to PublicController's index method. This method searches the database for the current URL to return the correct page, and also the page type. Each page type corresponds to a controller.
How do I call that controller from the PublicController without doing a redirect?
I can't use the redirect() method because that would change the URL in the browser window and cause an un-need additional page request.
if you look at the url /about/who-we-are/
about is the controller and who-we-are is a function in the controller that loads one or more views.
The same for /locations/stores/
the functions stores in the controller locations.
read the documentation and it will be easy to understand.
http://www.codeigniter.com/user_guide/overview/mvc.html
I am pretty sure that configuring a route is your answer:
// routes.php
$route['(:any)'] = "PublicController/index/$1";
// PublicController.php
public function index()
{
var_dump(func_get_args());
}

Codeigniter shorten urls

Is it possible to create such urls in codeigniter?
http://site.com/shorturl/
Where shorturl isn't a physical controller file, but a variable.
I expect the algorythm for parsing url query to be like this:
1) Search for physical controller file. If exists, do standard codeigniter routine. If not
2) Try to load special controller file, where "shorturl" is a variable. Do further stuff inside that controller.
Thanks in advance
The previous answer seems quite good, but thought I'd share what I'd though of.
If you set your 404_override to point to a controller you have set up as follows:
$route['404_override'] = 'welcome/short';
Any URL that doesn't exist (any short URL for example) would get sent there, where you could do the following to check the value:
public function short() {
$shortCode = $this->uri->segment(1);
}
That would give you the value you need to check. If all is well, do the redirect, if the code doesn't exist, you can then use the show_404 method to actually show the 404 page.

Only allow URL's specified in routes to be seen in Codeigniter

If I have a controller called articles, which has a method called view_articles, a user can type in http://example.com/articles/view_articles/some-post and have it return a page.
I have specified a route to be http://example.com/article/post-name. How can I make it so that only the URL specified in the route is visible? Is there a way for articles/view_articles/some-post to show a 404 instead of showing the same page as the route URL?
I am trying to prevent duplication for SEO purposes.
You can always make default routing to a 404 page by correctly defining routes in your routes.php file:
$routes['article/(:any)'] = 'articles/view_articles/$1';
$routes['(:any)'] = 'main/e404';
As stated by CodeIgniter user guide:
Routes will run in the order they are defined. Higher routes will always take precedence over lower ones.
So you can basically define all you want to be seen at the beginning of the file and block everything else on the last line.
As for your main(can be any other) controller's 404 method -
function e404() {
show_404();
}
Use $this->uri->segment(n) as part of the URI class inside of view_articles to redirect traffic to your route if the URI contains view_articles as it's second segment.
I'v done that in other tricky way, first of all you should add some code to __construct function in sys/core/Controller.php
you can check whether the requested url is in routes or not by this code
if(!isset($this->router->routes[uri_string()])){
show_404(); // Or whatever you want ...
}

How to set controller/action to Page Not Found

I have a controller and action which I'm accessing through a custom URL. The original route is still accessible though at the default location
zend.com/controller/action
How can I change this to simulate a "Page not found" when the user tries to access this URL? Is it possible?
If the action handler is used to respond to both URLs, you would first have to detect which URL is being requested (using $this->_request->getRequestUri()). If the default URL is detected I think the easiest way to create a "page not found" would be to use
$this->_redirect("/path/to/simulated/404/page")
and set up a controller and action to respond.
This won't actually send an HTTP 404, though. To do that, I think you would have to raise an exception within your action handler. I don't know what the official "zendy" way of doing this is, but this seems to work:
throw new Zend_Controller_Action_Exception('Not Found', 404);
You could change the main controller script to redirect a certain controller name and action name to a new page. But it's probably easier to add a new rule to the .htaccess file, indicating that this specific URL should be redirected to an error page. Example:
RewriteRule ^controller/action/?$ / [R=404,L]
Or redirect the page to an error page within your site:
RewriteRule ^controller/action/?$ /error/page-not-found/ [L]
You need to use:
$this->getResponse()->setHttpResponseCode(404);
And build your own 404 view
$this->view->message = 'Page not found';
Or you could forward to an error controller for example
$this->_forward('page-not-found', 'error');
Finally, if you have in your error controller
//...
switch ($errors->type) {
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
// 404 error -- controller or action not found
$this->getResponse()->setHttpResponseCode(404);
$this->view->message = 'Page not found';
break;
//...
You can just do as #bogeymin said:
throw new Zend_Controller_Action_Exception('Not Found', 404);
If you are looking other solutions than mod_rewrite based, you may create a Regex Route to match the actions you need to hide.
The other solution is to restrict access to Actions using Zend_Acl, treating each action as an ACL resource.
But the simplest and most lightweight solution is still mod_rewrite in .htaccess.
Edit:
As you can see, this may be done in numerous ways. But probably, you will need some kind of the switch, to still allow somehow to access the "hidden" action. In this case, use:
mod_rewrite for quick implementation (switching requires the person to know the .htaccess rules)
Zend_Router - the person who knows the right route can still access the feature
Zend_Acl + Zend_Auth for scalable and secure solution.
If you don't need to have authenticated users, Zend_Acl combined with Zend_Router might be the solution.
For smart handling the exceptions and building ACL's, see this (and other posts on this blog):
Handling errors in Zend Framework | CodeUtopia - The blog of Jani Hartikainen
By default the router includes default routes for :module/:controller/:action/ and :controller/:action/. You can disable these with:
$router->removeDefaultRoutes();
then only routes you setup will work. If you still want to use the default routes for some other things, you'll either have to go with one of the other answers posted or add your own 'default' routes which will match all but the modules/controllers you have custom routes for.
If you don't want to remove the default route as #Tim Fountain suggests, you should do something like this in your controller (either preDispatch or whateverAction methods)
$router = $this->getFrontController()->getRouter();
$route = $router->getCurrentRouteName();
// if we reached this controller/action from the default route, 404
if ($route == 'default')
{
throw new Zend_Controller_Action_Exception('Not Found', 404);
}
I think, all answers above are incorrect. Those show ways to achieve the same thing, but present logic at the wrong place in your application, which eventually can cause trouble later on.
The correct part of your route logic is, how extremely simple, in the routes. What is missing is that the default route Zend_Controller_Router_Route_Module does not allow you to add exceptions to specific routes. So what you need to do, is remove the default route from your routes, and add a new custom route (which should function exactly as the default route, but allows excludes) at it's place.
You can write the new route by extending the class of the default route.
class My_Custom_Route extends Zend_Controller_Router_Route_Module
{
protected $_excludes = array();
public function exclude($abc)
{
//add to $_excludes here the controller/action you want to exclude
}
public function match($abc)
{
//add functionality here that denies if the mod/contr/action is in $_excludes
//you can also add this in a separate method
//re-use parent code
}
}
You can now add add the excludes for example in a config file, and load + add the excludes at the place you initiate the new Route (and add it to the router). Off you go.

Categories