Custom route in Code Igniter being overwritten - php

I have these routes:
$route['shop/(:any)/(:any)'] = 'product/category_listing/$1/$2';
$route['shop/(:any)/(:any)/(:any)'] = 'product/product_listing/$1/$2/$3';
When I call this url:
http://mysite.com/shop/mens/trainers/a-product
the product_listing method should be called but instead the first method (category_listing) gets called and product_listing is never invoked.
How can I make this work as required?

Order of array elements matters!
Keyword (:any) matches everything, even slashes, so in your example CodeIgniter finds the first matching route and doesn't look any further.
So, if we do like this:
$route['shop/(:any)/(:any)/(:any)'] = 'product/product_listing/$1/$2/$3';
$route['shop/(:any)/(:any)'] = 'product/category_listing/$1/$2';
...then product listing is matched first, then everything else.
Even more, you can use regular expressions (e.g. ([a-z0-9]+)) to create rules you need.

Related

Laravel 5.2 Routing with optional params

I am creating a simple product search engine in Laravel 5.2. I can use either get or post, whichever can accomplish what I'm wanting, even if I need to do some backend processing then pass the pretty URL to another method to show the products.
My parameters are
- query
- merchant
- brand
- page
- sort
All of these parameters can be used on their own or separately.
I'm wanting to use pretty URLs if at all possible.
Basically I want the URLs to look something like this:
/shop/query/shoes
/shop/query/shoes/brand/nike
/shop/query/sort/price
/shop/merchant/amazon
There can be many different routes formed by these 5 parameters, but they are all optional. So what is the best solution to making this route work how I'm wanting, without coding for every single possible route.
I'm sure I am overlooking something. I've used Zend Framework before and just use a * after shop and then I can pass anything in regardless.
If you need any other information, let me know. I appreciate any help.
Try something like this
Route::get('shop/{params?}', function(Request $request, $params = '') {
// everything after "shop/" will be in $params
// you need to add custom logic to parse and handle $params string
return $params;
})->where('params', '(([a-zA-Z0-9-_]+)\/?)+');
{params?} is Optional Parameter
Occasionally you may need to specify a route parameter, but make the presence of that route parameter optional. You may do so by placing a ? mark after the parameter name. Make sure to give the route's corresponding variable a default value
->where('params', ...) is Regular Expression Constraint
You may constrain the format of your route parameters using the where method on a route instance. The where method accepts the name of the parameter and a regular expression defining how the parameter should be constrained
NOTE
Make sure that you tweak (([a-zA-Z0-9-_]+)/?)+ regular expression to cover all of your cases, as this is something that I added to quickly test your examples

Codeigniter complex wildcard Routing

Hi guys I am trying to achieve something that I hope is possible but couldn't find the right way to find.
I am using codeigniter 2.2.0
I want to use an url in codeigniter like
domain/username/controller/method/$args
Let me explain When user types an url like
domain/mike/job/editJob/12/urgent/
Here "mike" is someone's user name
"job" will be a controller alias
"editJob" will be a method
"12" and "urgent" will be parameter of editJob method.
editJob method will have three parameters.
I want "mike" as 1st parameter,
then "12" and "urgent" as second and third parameter.
So far what I have done in my routes
$route['(:any)/job/(:any)'] = 'job_c/$2/$1';
When I type in the url
domain/mike/job/editJob/12/urgent
in Job controller I get
"12" as first parameter
"urgent" as second parameter
and "mike" as third parameter
**
Is there any possible way to get "mike" as first parameter and then the rest is okay**
Edited:
One more thing if I pass three parameters after method then I am not
getting the username!!
I need to have the username as first parameter because there may have multiple parameters in any method and there is a possibility to have conditional parameters as well.
One more thing I want to know. Is it possible to make such route that will work the same as my given route but the controller alias will also be wildcard. Or if there is any way to check if a segment in url is a controller then one route and if not a controller then something else should happen.
I am not a well describer still tried to keep it simple. If anyone knows something that will help me a lot.
Thanks
UPDATE
Is there any way to keep the username "mike" in session from routes.php file thus I don't have to pass this as a parameter.
Updating Again
I have solved the issue somehow.
I am using
$route['(:any)/garage/([^/]*)/([^/]*)/(.*)'] = '$2/$3/$1/$4';
Here garage is nothing but a simple identifier for the route. This route will work when it gets garage as a second segment in url. It will work like
domain/user/garage/anyControler/anyMethod/manyParameters
It's completely dynamic only the garage is used as identifier. If you want you can use your controller name instead of using any identifier. then you don't have to declare same thing multiple times for multiple controllers but it will work fine. It will work for any controller and any method. In addition it supports dynamic number of parameters.
I don't know if there is any better way to do this but it solves my issue. If anyone know something better then this then please share.
I think what is happening is that you are accessing
domain/mike/job/editJob/12/urgent
and its being parsed like:
job_c/editJob/12/urgent/mike
Because:
$route['(:any)/job/(:any)'] = 'job_c/$2/$1';
$2 = (:any)/job/(:any) = editJob/12/urgent
$1 = (:any)/job/(:any) = mike
Substituting:
job_c/editJob/12/urgent/mike
You could try to keep your route as similar as your current one:
$route['(:any)/job/(:any)/(:any)'] = 'job_c/$2/$1/$3';
This will allow you to match $2 to any method name, and have $1 as the first parameter and $3 as the rest of params.
But, I would suggest, if this is a very specific route, substituting the $2 :any, with the actual method name and the expected type of the params, otherwise, you might receive unexpected values to every method in the matching controller.
I would use something like:
$route['(:any)/job/editJob/(:num)/(:any)'] = 'job_c/editJob/$1/$2/$3';
Hope this helps.
Update:
For the controller matching: Code Igniter uses the form controller/method/param1/param2/...
As long as you create routes that matches controllers, methods and params in that order, you can do anything.
$route['(:any)/(:any)/(:any)'] = '$1/$2/$3';
or just
$route['(:any)'] = '$1';
and hopefully it will contain a controller and method and the required params.
I think this will totally be missing the point of having a routing system.

routes in codeigniter/pyrocms

I saw this route I downloaded from sample module at pyrocms
$route['sample(/:num)?'] = 'sample/index$1';
I tried to removed the '$1' above and the site runs smooth. I am wondering what's that for, and can I remove it.
$1 would be whatever matched by (:num) group - which is, really, any valid numbers. Whatever you add will get passed as the parameter for view method in pages controller. for example
$route['sample(/:num)?'] = 'sample/index/$1';
now in sample controller
function index($id){
// $id something that matched by group (:num)
}
$1 in the sense anything comes dynamically after the url sample/index

CodeIgniter route overridden by controller/method

I have in my routes.php:
$route['ctrller1/method1/video/(:num)'] = 'ctrller2/method2/$1';
I also have a controller that is named ctrller1 that has a method:
function method1 ($str = NULL) {
// do something
}
The problem is I have to use controller2 coz I can't or shouldn't edit controller1. What I want is seemingly simple but, apparently, CI doesn't want to work with me.
When the url:
domain.com/ctrller1/method1/edit
is invoked, I want the method inside ctrller1 to be called, if domain.com/ctrller1/method1/videos/1
is invoked I want the method in ctrller2 called.
It all seems correct to me but it won't work. So, I must be missing something. I've tried adding this to the routing:
$route['ctrller1/method1/(edit)'] = 'ctrller1/method1/($1)';
But it's a no go. Anyone see anything wrong here?
At any time when you work with routes, just like permissions (firewall, etc;) order is important. Typically you want to organize your routes in this order:
MOST DEFINED
LESS DEFINED
GENERAL / FALLBACK
To clarify, that means your order for routes should be like this:
$route['ctrller1/method1/videos/view/(:num)'] = 'ctrller2/method3/$1';
$route['ctrller1/method1/videos/(:num)'] = 'ctrller2/method2/$1';
$route['ctrller1/(:num)'] = 'ctrller2/method1/$1';
When the URL is called, the route table goes through and finds the FIRST closest match, ELSE it traverses to the next route.
In this case what you want is something like this:
domain.com/ctrller1/method1/videos/1
domain.com/ctrller1/method1/edit
Reasoning for that is, the video's route is more specific, and also is a SPECIAL CASE, as you route it to another controller behind the scenes.
Here is what your routes should look like then (not tested, but should be it):
$route['ctrller1/method1/videos/(:num)'] = 'ctrller2/method2/$1';
$route['ctrller1/method1/edit'] = 'ctrller1/method1';
As a side, note, I am curious why you format it ctrller1/method1/videos/ and not something like ctrller1/videos/view/12355 or ctrller1/videos/edit/12355, the method1 seems confusing. But again I don't have all the details here.
Hope that works for you, if not comment, and I will revisit your question if you clarify it a little more.
Well you have video on one place and videos on another?
Either change to
$route['ctrller1/method1/videos/(:num)'] = 'ctrller2/method2/$1';
or try url: domain.com/ctrller1/method1/video/1

URI re-routing in codeigniter

I'm using URI re-routing in CI to make better URLS. An example here would be:
$route['users/(:any)'] = "users/index/$1";
The aim here is to get rid of the index from URL. This works well. However it stops me from being able to access any functions in the users controller, for example
mywebsite.com/users/messages
Just redirects to the users/index. Is there a way around this?
Define the list of methods you wish to keep then let the rest wildcard match:
$route['users/(messages|login|something)'] = "users/$1";
$route['users/(:any)'] = "users/index/$1";
Hi I'm not familiar with CI but i have a similar routing system. The (:any) works as a sort of catch all. When my router checks the routing rules it stops checking if it has found an exact match. So then the answer would be to just add another functions route before the catch all. Like
$route['users'] = "users/index/";
$route['users/messages/(:any)'] = "users/checkmessages/$1";
$route['users/(:any)'] = "users/$1";
Not sure how CI handles this but i can think of something like the first URL part is the class and the second the function. The router or the controller module should have the intelligence to start calling the function even without the routing table.
The routing table should only be used in case of "other callable names" like i did above with the messages/checkmessages thingy.
hope that gets you going.

Categories