configuring dynamic url's in router - codeigniter

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');
}

Related

codeigniter3 controller to controller functions

Okay, so i have pages controller and user_authenticator controller.
pages controller is like a terminal to my views whilst the user_authenticator controller does the functions that relates to users like registration/logging in.
Whenever i'm done with a function in user_authenticator say for example logging in, how do i load the views via pages controller?
Login->user_auth(controller)->acc_model(model)->user_auth(controller)->view.
to
Login->user_auth->acc_model->pages(controller)->view.
It would be a boon for me if you guys can tell me if what i'm doing is impractical and a better way to do things. Or maybe i should just stick to loading views on the controller i used previously.
EDIT: so i may have forgotten the purpose of my pages controller but i remembered due to a moment of clarity from my foggy and tired mind.
I made a pages controller solely to load views, i guess in a sense, pages won't be loading ALL view but atleast most of the views, for example, if i had links in my views to other views, i would link them via the pages.
For specific functions that need specific controllers i guess i can let them handle loading some views.
Then again, if someone could tell me what i'm doing is a waste of time and should just delete pages controller please tell me so, i'd like to know why.
also if you have any suggestions for further uses of my pages controller thatd be great!
Also regarding session. I have a base controller.
<?php
class MY_Controller extends CI_Controller {
public function __construct()
{
parent::__construct();
}
public function is_logged_in($data){
$session = $this->session->userdata();
if($session['isloggedin']['username'] == ''){
return isset($session);
}else{
return FALSE;}
}
}
?>
How do i make it so that it automatically runs and checks for every controller i load if there are any session set?
Do i have to put it into a constructor? or do i have to call the base controller method from all controllers?
Here is the best solution for you.
You can use Hooks
Step1:
application/config/config.php
$config['enable_hooks'] = TRUE;//enable hook
Step2:
application/config/hooks.php
$is_logged_in= array();
$is_logged_in['class'] = '';
$is_logged_in['function'] = 'is_logged_in';//which function will be executed
$is_logged_in['filename'] = 'is_logged_in.php';//hook file name
$is_logged_in['filepath'] = 'hooks';//path.. default
$is_logged_in['params'] = array();
$hook['post_controller_constructor'][] = $is_logged_in;//here we decare a hook .
//the hook will be executed after CI_Controller construct.
//(also u can execute it at other time , see the CI document)
Step3:
application/hooks/is_logged_in.php //what u decared
<?php
//this function will be called after CI controller construct!
function is_logged_in(){
$ci =& get_instance();//here we get the CI super object
$session = $ci->session->userdata();//get session
if($session['isloggedin']){ //if is logged in = true
$ci->username = 'mike';//do what you want just like in controller.
//but use $ci instead of $this**
}else{
//if not loggedin .do anything you want
redirect('login');//go to login page.
}
}
Step4:application/controller/pages.php
<?php
class pages extends CI_Controller{
function construct ........
function index(){
echo $this->username;//it will output 'Mike', what u declared in hook
}
}
Hope it will help u.

Laravel 5.3 dynamic routing to multiple controllers

I'm using Laravel 5.3. I have a bunch of urls that I'd like to handle with a single route, to multiple controllers.
e.g.
GET /admin/foo => FooController#index
GET /admin/foo/edit/1 => FooController#edit($id)
GET /admin/bar => BarController#index
GET /admin/bar/edit/1 => BarController#item($id)
GET /admin/baz => BazController#index
GET /admin/baz/edit/1 => BazController#item($id)
etc.
I want to be able to detect if the controller exists, and if not throw a 404 or route to a default controller (which may throw a 404).
Below is what I've got so far, but I'm not sure what I'm doing. Shouldn't I be instantiating the controller using the service container? I don't think I should be hardcoding namespaces like this. And my handling of the id parameter is sketchy. Perhaps I should have two routes for these two patterns or something?
Route::get('/admin/{entityType}/{action?}/{id?}', function ($entityType, $action = 'index', $id = null) {
$controllerClass = 'App\Http\Controllers\\' . ucfirst($entityType) . 'Controller';
$controller = new $controllerClass;
$route = app(\Illuminate\Routing\Route::class);
$container = app(\Illuminate\Container\Container::class);
return (new Illuminate\Routing\ControllerDispatcher($container))->dispatch($route, $controller, $action);
abort(404);
});
I'd recommend you to define a route for every controller explicitly. This is the best way to build a maintainable app.
Also, if using one route and one method is an option (with right architecure it is) use one route:
Route::get('/admin/{entityType}/{action?}/{id?}', 'Controller#method');
And one entry point:
public function method($entity, $action = null, $id = null)
{
// Handle request here.
https://laravel.com/docs/5.3/routing#parameters-optional-parameters

Codeigniter - url segment replace or redirect

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...
}

How to route all module of HMVC to single controller CI

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).

Codeigniter - best routes configuration for CMS?

I would like to create a custom CMS within Codeigniter, and I need a mechanism to route general pages to a default controller - for instance:
mydomain.com/about
mydomain.com/services/maintenance
These would be routed through my pagehandler controller. The default routing behaviour in Codeigniter is of course to route to a matching controller and method, so with the above examples it would require an About controller and a Services controller. This is obviously not a practical or even sensible approach.
I've seen the following solution to place in routes.php:
$route['^(?!admin|products).*'] = "pagehandler/$0";
But this poses it's own problems I believe. For example, it simply looks for "products" in the request uri and if found routes to the Products controller - but what if we have services/products as a CMS page? Does this not then get routed to the products controller?
Is there a perfect approach to this? I don't wish to have a routing where all CMS content is prefixed with the controller name, but I also need to be able to generically override the routing for other controllers.
If you use CodeIgniter 2.0 (which has been stable enough to use for months) then you can use:
$route['404_override'] = 'pages';
This will send anything that isn't a controller, method or valid route to your pages controller. Then you can use whatever PHP you like to either show the page or show a much nicer 404 page.
Read me guide explaining how you upgrade to CodeIgniter 2.0. Also, you might be interested in using an existing CMS such as PyroCMS which is now nearing the final v1.0 and has a massive following.
You are in luck. I am developing a CMS myself and it took me ages to find a viable solution to this. Let me explain myself to make sure that we are on the same page here, but I am fairly certain that we area.
Your URLS can be formatted the following ways:
http://www.mydomain.com/about - a top level page with no category
http://www.mydomain.com/services/maintenance - a page with a parent category
http://www.mydomain.com/services/maintenace/server-maintenance - a page with a category and sub category.
In my pages controller I am using the _remap function that basically captures all requests to your controllers and lets you do what you want with them.
Here is my code, commented for your convenience:
<?php
class Pages extends Controller {
// Captures all calls to this controller
public function _remap()
{
// Get out URL segments
$segments = $this->uri->uri_string();
$segments = explode("/", $segments);
// Remove blank segments from array
foreach($segments as $key => $value) {
if($value == "" || $value == "NULL") {
unset($segments[$key]);
}
}
// Store our newly filtered array segments
$segments = array_values($segments);
// Works out what segments we have
switch (count($segments))
{
// We have a category/subcategory/page-name
case 3:
list($cat, $subcat, $page_name) = $segments;
break;
// We have a category/page-name
case 2:
list($cat, $page_name) = $segments;
$subcat = NULL;
break;
// We just have a page name, no categories. So /page-name
default:
list($page_name) = $segments;
$cat = $subcat = NULL;
break;
}
if ($cat == '' && $subcat == '') {
$page = $this->mpages->fetch_page('', '', $page_name);
} else if ($cat != '' && $subcat == '') {
$page = $this->mpages->fetch_page($cat, '', $page_name);
} else if ($category != "" && $sub_category != "") {
$page = $this->mpages->fetch_page($cat, $subcat, $page_name);
}
// $page contains your page data, do with it what you wish.
}
?>
You of course would need to modify your page fetching model function accept 3 parameters and then pass in info depending on what page type you are viewing.
In your application/config/routes.php file simply put what specific URL's you would like to route and at the very bottom put this:
/* Admin routes, login routes etc here first */
$route['(:any)'] = "pages"; // Redirect all requests except for ones defined above to the pages controller.
Let me know if you need any more clarification or downloadable example code.

Resources