I am trying to create a single rule for routing that will accept any of the following
domain.com/backend/controller
domain.com/backend/controller/var
domain.com/backend/controller/var/var/etc
I want to automatically determine the controller from the url and be able to work no matter how many params are in the url
$route['backend/(:any)/(.*)'] = "admin/$1";
So one rule, that will mean that
domain.com/backend/members
domain.com/backend/members/var
domain.com/backend/members/var/var/etc
and
domain.com/backend/blogs
domain.com/backend/blogs/var
domain.com/backend/blogs/var/var/etc
will all locate the correct controller and forward have every other param availabe using
$this->uri->segment(x)
you can use uri class, in routes
$route['backend/(:any)'] = "admin/index";
in controller:
$n = $this->uri->total_rsegments() //gets total number of segments
$segs = $this->uri->segment_array(); //Returns an array containing the URI segments.
foreach ($segs as $segment)
{
echo $segment;
echo '<br />';
}
Related
In Laravel (5.6) I want to see what route would be called by a given url string. Say the url was "report/sales" I would like to check what function from what controller would be called, eg could be "ReportController#salesreport". It's sort of the opposite of the action() function but I can't find anything like it.
Would be wonderful if anyone has a solution.
Laravel doesn't provide a direct means of checking for a Route matching a URI, likely because it performs multiple assertions for host, method, etc. during matching. Almost all matching uses a Request object for comparison.
The quickest way to use existing functionality is to manually create a Request object with the details you wish to match against (HTTP method, URI, etc.). Once you've done that, you can grab the Router and look:
$request = \Illuminate\Http\Request::create('/report/sales');
$routes = Route::getRoutes(); // Or, you can get the Router directly, through app(), etc.
try {
$route = $routes->match($request);
$action = $route->getActionName();
} catch (\Symfony\Component\HttpKernel\Exception\NotFoundHttpException $e) {
// No matching route was found.
} catch (\Symfony\Component\Routing\Exception\MethodNotAllowedException $e) {
// The URI matches a route for a different HTTP method
}
You could retrive the Router instance through the Container and retrive all routes, then filter the retrived routes to match only the ones that has url attribute equal to the given url string. Finally, pluck the matching controller action for each route.
$routes = app('router')->getRoutes()->getRoutes();
$target = 'report/sales';
$actions = collect($routes)->filter(function($route) use ($target) {
return $route->uri == $target;
})->pluck('action.controller');
dd($actions);
If you only need to get one route only (eg: no routes with the same URL but different verbs), just replace filter with first to stop at the first matching occurence. As a result you will no longer need pluck, as you will be given a Route instance, not a collection:
$routes = app('router')->getRoutes()->getRoutes();
$target = 'report/sales';
$action = collect($routes)->first(function($route) use ($target) {
return $route->uri == $target;
})->action['controller'];
dd($action);
I'm using Codeigniter. Basically what I want is to remove the Controller name (Home) from the url.
Those urls look like:
http://localhost/mechanicly/Home
http://localhost/mechanicly/Home/about
http://localhost/mechanicly/Home/contactus
now there are two ways I can remove the Home controller:
static definition of every url inside route:
$route['about'] = "Home/about";
$route['contactus'] = "Home/contactus";
I can use call backs in routes in Codeigniter:
$route['(.+)'] = function ( $param ) {
if( strpos( $param, "Admin" ) !== false ) {
echo $param;
return "Admin/".$param;
}
else{
echo $param;
return "Home/".$param;
}
};
this logic is much better as it is generic and I don't have to create new routes every time for new method inside the controller.
It is working fine for the client controller which is Home but I have another controller named as Admin and I want to redirect Admin requests to the Admin controller and Home request to the Home Controller.
Why does above code work fine for the Home controller but returns
not found
when I validate for the Admin controller?
I am using CI version 3.x
If you really want to get crazy, you could parse the methods from the controller file and programatically create the "static" approach.
Pseudo code here
$controller_file_contents = file_get_contents('path/to/controller.php');
$controller_methods = function_that_parses_methods_from_file($controller_file_contents);
foreach ($controller_methods as $controller_method) {
$route[$controller_method] = "Home/" . $controller_method;
}
How function_that_parses_methods_from_file works is probably gonna involve a regex, something like function \w+. If you go with this approach, try to keep the controller as small as possible by offloading as much logic as possible into models, which is often a good idea anyways. That way the performance impact in the router is as small as possible.
Alternatively, you may be able to parse the controller using get_class_methods if you can figure out how to load the controller into memory inside the router without conflicting when you need to load the controller using the router or causing too much performance issues.
Pretty goofy, but every method you create in that controller will automatically create a route.
you can create your menu(url´s) from db like
tbl_menu tbl_level
---------- -------------
id id
fk_level level
name dateUP
dateUP active
active
In your controllers you need to call the correct menu by session or wherever you want
then you can has this in your route.php
$route['(.+)'] = 'int_rout/routing/' . json_encode($1);
in your controller Int_rout.php
public function routing ( $param ) {
$routing = json_decode($param);
$routing = explode('/', $routing);
//$menu -> get menu from model
foreach($menu as $item){
if($routing[0] === $item->name){
//$level -> get level from model
$redirect = $level->level;
}
}
//the final redirect will be like
//admin/user or admin/user/12
//public/us
$params = ( empty($routing[1])) ? '' : '/' . $routing[1];
redirect($redirect . '/' . $routing[0] . $params, 'refresh');
}
I have a base controller (base) which all other controllers extend from.
Anything placed here will override other controllers, the redirects will be here.
URLs example:
http://domain.com/controllerone/function
http://domain.com/controllertwo/function
http://domain.com/controllerthree/function
Using the code below. will give me the controller name
$this->uri->segment(1);
Each of the above controllers need to be redirected to separate URLs, but the funcation part should not change:
http://domain.com/newcontrollerone/function
http://domain.com/newcontrollertwo/function
http://domain.com/newcontrollerthree/function
In my base controller i want the following logic:
$controller_name = $this->uri->segment(1);
if($controller_name === 'controllerone'){
// replace the controller name with new one and redirect, how ?
}else if($controller_name === 'controllertwo'){
// replace the controller name with new one and redirect, how ?
}else{
// continue as normal
}
i was thinking i should use redirect() function and str_replace(), but dont know how efficient these would be. Ideally i do not want to use the Routing class.
thanks.
try
header("Location:".base_url("newcontroller/".$this->uri->segment(2)));
Simple Solution using segment_array:
$segs = $this->uri->segment_array();
if($segs[1] === 'controllerone'){
$segs[1] = "newcontroller";
redirect($segs);
}else if($segs[1] === 'controllertwo'){
$segs[1] = "newcontroller2";
redirect($segs);
}else{
// continue as normal
}
CodeIgniter's URI Routing, should be able to help in this case. However, if you have a good reason not to use it, then this solution may help.
The potential redirects are in an array, where the key is the controller name being looked for in the URL and the value is the name of the controller to redirect to. This may not be the most efficient but I think it should be easier to manage and read than a potentially very long if-then-else statement.
//Get the controller name from the URL
$controller_name = $this->uri->segment(1);
//Alternative: $controller_name = $this->router->fetch_class();
//List of redirects
$redirects = array(
"controllerone" => "newcontrollerone",
"controllertwo" => "newcontrollertwo",
//...add more redirects here
);
//If a redirect exists for the controller
if (array_key_exists($controller_name, $redirects))
{
//Controller to redirect to
$redirect_controller = $redirects[$controller_name];
//Create string to pass to redirect
$redirect_segments = '/'
. $redirect_controller
. substr($this->uri->uri_string(), strlen($controller_name)); //Function, parameters etc. to append (removes the original controller name)
redirect($redirect_segments, 'refresh');
}
else
{
//Do what you want...
}
i use HMVC with CI last version andi want to route all module of HMVC to a controller CI
If i use
$route[‘admin/(:any)’] = “admin/”;
$route[’(:any)’] = “index/index/$1”;
$route[’(:any)/(:any)’] = “index/index/$1/$2”;
$route[’(:any)/(:any)/(:any)’] = “index/index/$1/$2/$3”;
is not a solution, because a url can have many segments
i want to route the controller, method, and all parameters, like this:
$route[’(:any)/(:any)/ *all parameters *’] = “index/index/$1/$2/ *array($parameters)*”;
or how can stop the route of HMVC, i don`t need the route of HMVC.
Pls help.
Thanks, Jhon.
You don't need routing, codeigniter does this already.
From a fresh CI install, playing with the welcome controller:
public function index()
{
$args = $this->uri->uri_to_assoc();
echo "<pre>";
print_r($args);
echo "</pre>";
// $this->load->view('welcome_message');
}
Visiting [http://localhost/codeigniter2.1.2/index.php/welcome/index/param1/param1_value/param2/param2_value/param3/etc]
yields this:
Array
(
[param1] => param1_value
[param2] => param2_value
[param3] => etc
)
So you have your controller [welcome], your function [index] and everything after are parameters; no need to mess with routing.
You don't need to account for every possible parameter that might be routed.
You can use a route like this:
$route[‘admin/(:any)’] = “admin/”;
$route[’(:any)/(:any)/(:any)’] = “index/index/$1/$2/$3”;
Then every URL except admin/* will be routed to index/index. From that point, you can grab the parameters like I posted above or via $this->uri->segment(n); where n is the segment you want (so, $this->uri->segment(3) would return $1 from the route above).
Normally I would just use URL GET parameters but CodeIgniter doesn't seem to like them and none of the URL helper functions are designed for them, so I'm trying to do this the 'CodeIgniter way'.
I would like to build a page where the model can accept a number of different URI paramters, none necessarily present, and none having to be in any particular order, much like a regular URL query string with get parameters.
Let's say I have the following url:
http://example.com/site/data/name/joe/
Here not including the controller or the method there would be one parameter:
$params = $this->uri->uri_to_assoc(1);
print_r($params);
// output
array( [name] => [joe] )
If I wanted 'joe' to change to 'ray' I could do this:
echo anchor('name/ray');
Simple enough but what if there are more parameters and the position of the parameters are changing? Like:
http://example.com/site/data/town/losangeles/name/joe/
http://example.com/site/data/age/21/name/joe/town/seattle
Is there a way to just grab the URL and output it with just the 'name' parameter changed?
Edit: As per landons advice I took his script and set it up as a url helper function by creating the file:
application/helpers/MY_url_helper.php
Basically I rewrote the function current_url() to optionally accept an array of parameters that will be substituted into the current URI. If you don't pass the array the function acts as originally designed:
function current_url($vars = NULL)
{
$CI =& get_instance();
if ( ! is_array($vars))
{
return $CI->config->site_url($CI->uri->uri_string());
}
else
{
$start_index = 1;
$params = $CI->uri->uri_to_assoc($start_index);
foreach ($vars as $key => $value)
{
$params[$key] = $value;
}
$new_uri = $CI->uri->assoc_to_uri($params);
return $CI->config->site_url($new_uri);
}
}
It works OK. I think the bottom line is I do not like the 'CodeIgniter Way' and I will be looking at mixing segment based URL's with querystrings or another framework altogether.
You can use the assoc_to_uri() method to get it back to URI format:
<?php
// The segment offset to use for associative data (change me!)
$start_index = 1;
// Parse URI path into associative array
$params = $this->uri->uri_to_assoc($start_index);
// Change the value you want (change me!)
$params['name'] = 'ray';
// Convert back to path format
$new_uri = $this->uri->assoc_to_uri($params);
// Prepend the leading segments back to the URI
for ($i=1; $i<$start_index; $i++)
{
$new_uri = $this->uri->segment($i).'/'.$new_uri;
}
// Output anchor
echo anchor($new_uri);
I'd recommend wrapping this in a helper function of some sort. Happy coding!
Why not use CodeIgniter's built in URI Class? It allows you to select the relevant segments from the URL which you could use to create the anchor. However, unless you created custom routes, it would mean that your methods would need to accept more parameters.
To use the URI Class, you would have the following in your method:
echo anchor($this->uri->segment(3).'/ray');
Assuming /site/data/name are all CodeIgniter specific (/controller/method/parameter)
Now, I think this could be made a lot easier if you were using routes. Your route would look like this:
$route['site/data/name/(:any)'] = 'site/data/$1';
Effictively, your URL can be as detailed and specific as you want it to be, but in your code the function is a lot cleaner and the parameters are quite descriptive. You method would defined like this:
function data($name) { }
To extend your route to accept more parameters, your route for the the example URL "http://example.com/site/data/age/21/name/joe/town/seattle" you supplied would look like this:
$route['site/data/age/(:num)/name/(:any)/town/(:any)'] = 'controller/data/$1/$2/$3';
And your function would look like this:
function data($age, $name, $town) { }