How to set url for particular controller action - Magento - magento

If I have module mymodule in which I have index Controller. In which I have subaction as 'subaction'
Normally I access page as
http://www.mywebsite/index.php/mymodule/index/subaction
How can I set url from code such as
http://www.mywebsite/index.php/subaction
or
http://www.mywebsite/index.php/mymodule/subaction
Note :: I do not want to create new controller I want this in the same index controller.

Magento URL-to-controller matching works through the Standard router which expects URLs to have a specific form. If you want to change that you have a few options at your disposal:
Deprecated config-based URL rewrites
Create URL rewrite entries in core_url_rewrite table
Create a custom router class to match the URL patterns which you would like to use
When considering how URL matching should work, you need to consider how Magento will expect to build the URL using its native URL calculation tools as well as how to get requests to match.

You can do this by using routes
in your bootstrap do the following
protected function _initMyRoutes() {
$this->bootstrap('frontController');
$front = $this->getResource('frontController');
$router = $front->getRouter();
$config = new Zend_Config_Ini(APPLICATION_PATH . '/configs/routes.ini', APPLICATION_ENV);
$router->addDefaultRoutes();
$router->addConfig($config, 'routes');
return $router;
}
and in the configs directory create a file called routes.ini and in it place the following
routes.myRoute.type = "Zend_Controller_Router_Route_Static"
routes.myRoute.route = "/subaction/"
routes.myRoute.defaults.module = "mymodule"
routes.myRoute.defaults.controller = "index"
routes.myRoute.defaults.action = "subaction"
OR
you can add the route directly in your bootstrap with
protected function _initMyRoutes() {
$this->bootstrap('frontController');
$front = $this->getResource('frontController');
$router = $front->getRouter();
$router->addDefaultRoutes();
$route = new Zend_Controller_Router_Route_Static(
'subaction',
array('module' => 'mymodule', 'controller' => 'index', 'action' => 'subaction')
);
$router->addRoute('subaction', $route);
return $router;
}
That should do the trick but be adviced using routes can really be a pain.
More about routes in the ZF manual

Related

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 minimize URLs with extending controller and multilingual

I've configured Codeigniter 2.1 with i18n and extended controller.
I've hide the main controller "main" and I kept visible "admin" and "blog" controller.
This urls works fine:
www.mysite.com/ en / functionname
www.mysite.com/ en / blog /
This is my problem:
www.mysite.com/ it / blog / functionname
With the main controller "blog" everything after "/" is ignored.
Is it possible to do this?
My routes.php file:
$default_controller = "main";
$language_alias = array('it','en');
// exceptions
$controller_exceptions = array('admin','blog');
// route
$route['default_controller'] = $default_controller;
$route["^(".implode('|', $language_alias).")/(".implode('|', $controller_exceptions).")(.*)"] = '$2';
$route["^(".implode('|', $language_alias).")?/(.*)"] = $default_controller.'/$2';
$route["^((?!\b".implode('\b|\b', $controller_exceptions)."\b).*)$"] = $default_controller.'/$1';
foreach($language_alias as $language) {
$route[$language] = $default_controller.'/index';
}
$route['404_override'] = '';
// URI like '/en/about' -> use controller 'about'
$route['^(it|en)/(.+)$'] = "$2";
// '/it', '/en' URIs -> use default controller
$route['^(it|en)$'] = $route['default_controller'];
If I remove lang in my URL everything works fine:
www.mysite.com/ blog / functionname
I think you need another segment in your routes for accessing the controllers function.
so you'll need a second line:
// '/it', '/en' URIs -> use default controller
$route['^(it|en)$'] = $route['default_controller'];
// URI like '/en/about' -> use controller 'about'
$route['^(it|en)/(.+)$'] = "$2";
// URI like '/en/about/test' -> use controller 'about' with function 'test'
$route['^(it|en)/(.+)/(.+)$'] = "$2/$3";
I don't use the i18n or support multiple language in any project atm so I can't test but this should do the trick.

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

Passing variables before controller URI segment in CodeIgniter

I would like to pass some site-wide validated variables before controller segment in URL.
Example:
Default URL would be:
www.mysite.com/controller/method/variable/
Sometimes I'd like to have also URL like this to refer to user created sub-configuration of this site (theme, menus, ...), so user could share this site URL nicely and others would see the site though his custom configurations.
www.mysite.com/username/controller/method/variable
Here username is custom part of base_url. It should be validated against database and set as session variable to use it later in my controllers and change theme for example. Also all the links on the site would start to use www.mysite.com/username as base_url after website is entered with this username in the URL.
One way to solve this would be routing it like this:
controller/method/variable_name1/variable_value1/user_conf/username
...and the add the implementation to every single controller in my project. But this is not an elegant solution.
Is this what you're after:
$route['(:any)/(:any)'] = '$2/$1';
where all your function definitions have the username as the last parameter:
class Controller{function page(var1, var2, ..., varn, username){}}
Or, if you only want in on one specific page you could do something like this:
$route['(:any)/controller/page/(:any)'] = 'controller/page/$2/$1'; //This will work for the above class.
Or, if you want it for a number of functions in a controller you could do this:
$route['(:any)/controller/([func1|func2|funcn]+)/(:any)'] = 'controller/$2/$3/$1';
After messing with this problem for a day I ended up with adding custom router class to my project. I'm working in CodeIgniter 2.0, so the location of this file should be application/core/MY_Router.php
My code is following:
class MY_Router extends CI_Router {
// --------------------------------------------------------------------
/**
* OVERRIDE
*
* Validates the supplied segments. Attempts to determine the path to
* the controller.
*
* #access private
* #param array
* #return array
*/
function _validate_request($segments)
{
if (count($segments) == 0)
{
return $segments;
}
// Does the requested controller exist in the root folder?
if (file_exists(APPPATH.'controllers/'.$segments[0].EXT))
{
return $segments;
}
$users["username"] = 1;
$users["minu_pood"] = 2;
// $users[...] = ...;
// ...
// Basically here I load all the
// possbile username values from DB, memcache, filesystem, ...
if (isset($users[$segments[0]])) {
// If my segments[0] is in this set
// then do the session actions or add cookie in my cast.
setcookie('username_is', $segments[0], time() + (86400 * 7));
// After that remove this segment so
// rounter could search for controller!
array_shift($segments);
return $segments;
}
// So segments[0] was not a controller and also not a username...
// Nothing else to do at this point but show a 404
show_404($segments[0]);
}
}

Codeigniter global_xss_filtering

In my codeigniter config I have $config['global_xss_filtering'] = TRUE;. In my admin section I have a ckeditor which generates the frontend content.
Everything that is typed and placed inside the editor works fine, images are displayed nice, html is working. All except flash. Whenever I switch to html mode and paste a youtube code piece it is escaped and the code is visible on the frontpage instead of showing a youtube movie.
If I set $config['global_xss_filtering'] = FALSE; the youtube code is passed like it should. This is because 'object', 'embed' etc are flagged as "naughty" by CI and thus escaped.
How can I bypass the xss filtering for this one controller method?
Turn it off by default then enable it for places that really need it.
For example, I have it turned off for all my controllers, then enable it for comments, pages, etc.
One thing you can do is create a MY_Input (or MY_Security in CI 2) like the one in PyroCMS and override the xss_clean method with an exact copy, minus the object|embed| part of the regex.
http://github.com/pyrocms/pyrocms/blob/master/system/pyrocms/libraries/MY_Security.php
It's one hell of a long way around, but it works.
Perhaps we could create a config option could be created listing the bad elements for 2.0?
My case was that I wanted global_xss_filtering to be on by default but sometimes I needed the $_POST (pst you can do this to any global php array e.g. $_GET...) data to be raw as send from the browser, so my solution was to:
open index.php in root folder of the project
added the following line of code $unsanitized_post = $_POST; after $application_folder = 'application'; (line #92)
then whenever I needed the raw $_POST I would do the following:
global $unsanitized_post;
print_r($unsanitized_post);
In CodeIgniter 2.0 the best thing to do is to override the xss_clean on the core CI library, using MY_Security.php put this on application/core folder then using /application/config.php
$config['xss_exclude_uris'] = array('controller/method');
here's the MY_Security.php https://gist.github.com/slick2/39f54a5310e29c5a8387:
<?php
/**
* CodeIgniter version 2
* Note: Put this on your application/core folder
*/
class MY_Security extends CI_Security {
/**
* Method: __construct();
* magic
*/
function __construct()
{
parent::__construct();
}
function xss_clean($str, $is_image = FALSE)
{
$bypass = FALSE;
/**
* By pass controllers set in /application/config/config.php
* config.php
* $config['xss_exclude_uris'] = array('controller/method')
*/
$config = new CI_Config;
$uri = new CI_URI;
$uri->_fetch_uri_string();
$uri->_explode_segments();
$controllers_list = $config->item('xss_exclude_uris');
// we need controller class and method only
if (!empty($controllers_list))
{
$segments = array(0 => NULL, 1 => NULL);
$segments = $uri->segment_array();
if (!empty($segments))
{
if (!empty($segments[1]))
{
$action = $segments[0] . '/' . $segments[1];
}
else
{
$action = $segments[0];
}
if (in_array($action, $controllers_list))
{
$bypass = TRUE;
}
}
// we unset the variable
unset($config);
unset($uri);
}
if ($bypass)
{
return $str;
}
else
{
return parent::xss_clean($str, $is_image);
}
}
}
Simple do the following on the views when displaying embedded object code like from YouTube and etc:
echo str_replace(array('<', '>'), array('<', '>'), $embed_filed);
The global XSS Filtering is only escaping (or converting) certain "dangerous" html tags like <html>
Simple Workaround:
Set $config['global_xss_filtering'] = TRUE;
Run your POST data through HTMLPurifier to remove any nasty <script> tags or javascript.
HTMLPurifier Docs
HTMLPurifier Codeigniter Integration
On the page where you receive the forms POST data use html_entity_decode() to undo what XSS filtering did.
//by decoding first, we remove everything that XSS filter did
//then we encode all characters equally.
$content = html_entity_decode($this->input->post('template_content'))
Then immediately run it through htmlentities()
$content = htmlentities($content);
Store as a Blob in MySQL database
When you want to display the
information to the user for editing run html_entity_decode()
This is how I did it. If anyone knows of a major flaw in what I did, please tell me. It seems to be working fine for me. Haven't had any unexpected errors.

Resources