I'm looking for help to know which route my Codeigniter application goes through.
In my application folder in config/routes.php i got some database generated routes, could look like this:
$route["user/:any"] = "user/profile/$1";
$route["administration/:any"] = "admin/module/$1";
If i for example to go domain.net/user/MYUSERNAME, then i want to know that i get through the route "user/:any".
Is it possible to know which route it follows?
One way to know the route could be using this:
$this->uri->segment(1);
This would give you 'user' for this url:
domain.net/user/MYUSERNAME
By this way you can easily identify the route through which you have been through.
I used #Ochi's answer to come up with this.
$routes = array_reverse($this->router->routes); // All routes as specified in config/routes.php, reserved because Codeigniter matched route from last element in array to first.
foreach ($routes as $key => $val) {
$route = $key; // Current route being checked.
// Convert wildcards to RegEx
$key = str_replace(array(':any', ':num'), array('[^/]+', '[0-9]+'), $key);
// Does the RegEx match?
if (preg_match('#^'.$key.'$#', $this->uri->uri_string(), $matches)) break;
}
if ( ! $route) $route = $routes['default_route']; // If the route is blank, it can only be mathcing the default route.
echo $route; // We found our route
looking at the latest version it's not possible without using custom router as ROUTEKEY is used and overwritten trying to parse the route
if you would like to create and use custom class it's only a matter of saving original $key to another variable and setting it as a class property for later use when you have a match (line 414 before "return" - you can get that key later as e.g. $this->fetch_current_route_key()) - other thing to remember is that this kind of code modification is easy to break if original class will change (update) so keep that in mind
For CodeIgniter 4:
var_dump(service('router')->getMatchedRoute());
It will return something like this:
[
"{locale}/(.*)",
"\App\Controllers\Home_controller::any/home"
];
Related
I've 2 routes in my web.php
1) Route::get('/{url}', 'MenuController#menu');
which provide url :
/menu
2) Route::get('/{name}', 'HomeSlideviewController#index')->name('promotiondetail');
which provide url :
/menu (different page but same name in route 1)
/food
I want to use 2 route if route = same name I want to use route 1 if route 1 dont have url It will use route 2 . In web.php is their anyway to do something like
if(Route::get('/{url}', 'MenuController#menu')) is null use
`Route::get('/{name}', 'HomeSlideviewController#index')->name('promotiondetail');`
now in my web.php I do this
Route::get('/{url}', 'MenuController#menu');
Route::get('/{name}', 'HomeSlideviewController#index')->name('promotiondetail');
when I go /food It will go page not found.
UPDATE
In my controller I try this
try {
// if find url
}
} catch (\Exception $e) {
//if not find url
return redirect()->route('promotiondetail', $url);
}
and It return Error redirected you too many times
UPDATE 3
$url = food
Your problem is that when you use
Route::get('/{url}', 'MenuController#menu');
Route::get('/{name}', 'HomeSlideviewController#index')->name('promotiondetail');
you are having the same request because {url} or {name} are optional parameters and what happens is that it will always match the first case. The best solution for you can be using this part of code:
Route::get('/menu', 'MenuController#menu');
Route::get('/{name}', 'HomeSlideviewController#index')->name('promotiondetail');
You should always have the one with only optional parameters last, because otherwise it will always be executed first because it will be matching. And what you should remember is that using /{name} it will match anything, it is like a variable and can contain a number also it can be a string, for instance a url might be domain/{anything}. If you use /name it will match only if you are having domain/name as request.
You might want to read Laravel routing for more information about routing.
The problem you have is that both routes are essentially the same, /{something}.
You have a couple of solutions.
Firstly, sort out your routes, make them slightly different so they don't match each other and correct the order.
For example;
Route::get('/promo/{name}', 'HomeSlideviewController#index')->name('promotiondetail');
Route::get('/{url}', 'MenuController#menu')->name('menu');
Another solution that may work for you is to place the promotiondetail route first, and do a check in that for the same name, if not then redirect to the other controller. So in your index function of HomeSlideviewController, try something like;
public function index($name) {
if ($name !== 'whatever you want it not to be') {
return redirect()->route('menu);
}
// continue
}
I got an error with redirecting I dont know why, i read the documentation of laravel 5.2 about redirecting and still not working pls help me thanks, here is my route in the routes.php
Route::get('/orders/view/{id}', 'OrderController#view');
here is my code in the controller for the redirecting
return redirect()->route('/orders/view/', ['id' => 5]);
and still it gives me this error
InvalidArgumentException in UrlGenerator.php line 314: Route
[/orders/view/] not defined.
The Problem
You're trying to redirect to a route by it's name, but you're passing an URL to the method.
return redirect() # Initialize a redirect...
->route(...); # to a route by it's name
The solutions
There are multiple ways to solve this. You can either redirect by path (that's
how you're trying to do at the moment), or by using route names.
Method 1: Redirect by path
You can redirect by path in two ways:
- concat the path by hand
- use the URL facade.
Concat the path by hand
$url = '/orders/view/' . $order->id;
return redirect($url);
Use the URL facade
# Remember to remove the trailing slash.
# Appending a trailing slash would lead to example.com/orders/view//1
$url = URL::to('/orders/view', [$order->id]);
return redirect($url);
You're done!
Method 2: Redirect by route name
To use route names, you need to prepare your routes and give them a name.
I recommend this way, because sometimes it's more clear but it also makes
maintaining your application easier when you need to change some paths, because
the names will be still the same. Read more about it here:
https://laravel.com/docs/5.2/routing#named-routes
This also allows you to use the easy-to-use and useful route() helper method.
Prepare your routes file
To assign your routes a name, you need to pass them to your router in your app/Http/routes.php.
# Example 1
Route::get('/orders/view/{id}', [
'as' => 'orders.view', 'uses' => 'OrderController#view'
]);
# Example 2
Route::get('/orders/view/{id}', 'OrderController#view')->name('orders.view');
For myself, I recommend to use the second syntax. It makes your code more
readable.
Redirect by route name
Now it's time to redirect! If you're using the method of route naming, you don't
even have to change much in your code.
return redirect()->route('orders.view', ['id' => $order->id]);
A note from my side
Have a look on route-model-binding in the documentation:
https://laravel.com/docs/5.2/routing#route-model-binding
This allows you to pass a model instance directly to the route() method and
it helps you fetching models by passing the proper model to your controller method
like this:
# Generate route URL
route('orders.view', $order);
# Controller
public function view(Order $order) {
return $order;
}
And in your app/Http/routes.php you would have {order} instead of {id}:
Route::get('/orders/view/{order}', 'OrderController#view');
You can use
return redirect()->action('OrderController#view', ['id' => 5]);
or
// $id = 5
return redirect()->to('/orders/view/'.$id);
I'm brand new to Laravel, and I'm tinkering with it in different ways to understand how it works.
One of the first things that I've tried is to create routes dynamically by creating a routes config file that is essentially an array of views, and loop through them to create the route. It looks like this:
// Loop through the routes
foreach( config("routes.web") as $route ){
$GLOBALS["tmp_route"] = $route;
// set the path for home
$path = ($route == "home" ? '/' : $route);
Route::get( $path, function() {
return view($GLOBALS["tmp_route"]);
});
// foreach
}
I know the loop is working fine, but what I get is 'Undefined index: tmp_route'.
I'm confused as to why this isn't working? Any ideas? If I echo out the tmp_route it echos out the value, but fails at the return view(.
We don't use loops in routes usually. Actually, I've never used a loop in routes if I remember correctly. My suggestion is create a route with paramater and assign it to a controller method. e.g:
// Note that if you want a route like this, just with one parameter,
// put it to end of your other routes, otherwise it can catch other
// single hard-coded routes like Route::get('contact')
Route::get('{slug}')->uses('PageController#show')->name('pages.show');
Then in your PageController
public function show($slug) {
$view = $slug == '/'?'home':$slug;
return view($view);
}
With this, http://example.com/my-page will render views/my-page.blade.php view. As you can see I also gave him a name, pages.show. You can use route helper to create links with this helper. e.g.
echo route('pages.show','about-us'); // http://example.com/about-us
echo route('pages.show','contact'); // http://example.com/contact
In blade templates:
About Us
Please look at the documentation for more and other cool stuff
I have decided to prefix all my routes with a $locale-variable. This is code found from googling:
$locale = Request::segment(1);
if (in_array($locale, Config::get('app.available_locales'))) {
App::setLocale($locale);
} else {
$locale = null;
}
Route::group(array('prefix' => $locale), function() {
//All my routes
});
Now, I would like to generate URL:s dynamically for jumping between locales. I want a way to generate the current url or route, but replace the $locale-parameter. You should be able to write something similar to this pseudocode:
route(Route::Current(), [$locale => 'foo'])
Question:
I want to take my current URL and replace one argument in it. How do I do that?
Update 1:
Giving my route a name, I'm able to do this:
route('index', 'foo') //Gives mywebsite.com?foo
This however, does not produce the wanted result, mywebsite.com/foo. It instead generates mywebsite.com?foo. My guess is that route doesn't understand that this route is nested and prefixed with a fragment, so it treats my argument as a parameter instead. Specifying that it is the locale I want to change does not help:
route('index', ['locale' => 'foo']) //Gives mywebsite.com?locale=foo
Update 2:
Changing the prefix to instead say:
Route::group(array('prefix' => '{locale?}'), function() {
Makes route() work:
route('index', ['locale' => 'foo']) //Gives mywebsite.com/foo
It does however ruin some url:s inside the group, as some of them start with variables. The following route inside the route-group stops working:
Route::get('/{id}', 'FooController#showFoo');
As routes.php interprets the url mywebsite.com/foo as 'foo' now being the language. If there is some way to set a default value in routes.php for locale so that you could write it as {route} instead of {route?} and have it redirect to a default locale if it was missing, the problem would be solved.
Update 3:
Moving in the direction of having 'prefix' => '{locale?}' instead leads into way too many sub-problems to be worth pursuing. The issue comes back to generating urls from the current url but inserting language into the url. I am currently considering doing this with just a regex replacement because it is the most straight-forward solution.
I didn't test this, but you could try to do it like this way.
If no parameter is given, you can easily redirect to the default locale route. If first parameter is given, you need to check if it's a correct locale.
use Illuminate\Support\Facades\Request;
$defaultLocale = 'en';
Route::get('/', function() use ($defaultLocale) {
return redirect('/' . $defaultLocale);
});
Route::group(array('prefix' => '{locale}'), function($locale) use ($defaultLocale) {
if(!in_array($locale, Config::get('app.available_locales'))) {
return redirect('/' . $defaultLocale . '/' . Request::path());
}
// All your routes
});
So I ended up not solving this with laravel magic, I wrote my own code.
The Route::Group remains the same, the code I use to create URL:s to different languages looks like this:
<a href="{{ change_locale_url('en') }}"</a>
The change_locale_url-function is just a regex function which uses URL::Current to get the current url and then either inserts or replaces the input string as a language parameter in the url.
When I'm on mywebsite.com/about, the function outputs mywebsite.com/en/about
When I'm on www.mywebsite.com/de/about, the function outputs www.mywebsite.com/en/about
When I'm on http://mywebsite.com, the function outputs http://mywebsite.com/en
As a reminder, when using this route group you need to create links using action('HomeController#index') to have the locale follow you to the next link. Linking to /about will remove any language currently selected.
I don't know much about the routing concept in codeigniter, I want to pass many parameters to a single method as explained in this http://www.codeigniter.com/userguide2/general/controllers.html tutorial page.
In the url I have this
http://localhost/code_igniter/products/display/2/3/4
In my routes.php I have written
$route['products/display/(:any)'] = 'Products_controller/display';
What I thought is it will pass all the parameters (here 2/3/4) to the method 'display' automatically but I am getting 404 page not found error.
In general I want to achieve something like, if the URI is controller/method I want to route to someother_controller/its_method and pass the parameters if any to that method. How can I do it?
In CI 3.x the (:any) parameter matches only a single URI segment. So for example:
$route['method/(:any)/(:any)'] = 'controller/method/$1/$2';
will match exactly two segments and pass them appropriately. If you want to match 1 or 2 you can do this (in order):
$route['method/(:any)/(:any)'] = 'controller/method/$1/$2';
$route['method/(:any)'] = 'controller/method/$1';
You can pass multiple segments with the (.+) parameter like this:
$route['method/(.+)'] = 'controller/method/$1';
In that case the $1 will contain everything past method/. In general I think its discouraged to use this since you should know what is being passed and handle it appropriately but there are times (.+) comes in handy. For example if you don't know how many parameters are being passed this will allow you to capture all of them. Also remember, you can set default parameters in your methods like this:
public function method($param=''){}
So that if nothing is passed, you still have a valid value.
You can also pass to your index method like this:
$route['method/(:any)/(:any)'] = 'controller/method/index/$1/$2';
$route['method/(:any)'] = 'controller/method/index/$1';
Obviously these are just examples. You can also include folders and more complex routing but that should get you started.
On codeigniter 3
Make sure your controller has first letter upper case on file name and class name
application > controllers > Products_controller.php
<?php
class Products_controller extends CI_Controller {
public function index() {
}
public function display() {
}
}
On Routes
$route['products/display'] = 'products_controller/display';
$route['products/display/(:any)'] = 'products_controller/display/$1';
$route['products/display/(:any)/(:any)'] = 'products_controller/display/$1/$2';
$route['products/display/(:any)/(:any)/(:any)'] = 'products_controller/display/$1/$2/3';
Docs For Codeigniter 3 and 2
http://www.codeigniter.com/docs
Maintain your routing rules like this
$route['products/display/(:any)/(:any)/(:any)'] = 'Products_controller/display/$2/$3/$4';
Please check this link Codeigniter URI Routing
In CodeIgniter 4
Consider Product Controller with Show Method with id as Parameter
http://www.example.com
/product/1
ROUTE Definition Should be
$routes->get("product/(:any)", "Com\Atoconn\Product::show/$1");