i would like to match all requests where user is unlogged to controller Admin\Controller\Sign and action in. I wrote this code in onBootstrap() method in Module.php file :
if (!$authService->hasIdentity()) {
$routeMatch = new RouteMatch(
array(
'controller' => 'Admin\Controller\Sign',
'action' => 'in'
)
);
$event->setRouteMatch($routeMatch);
}
I don't get any errors, but code doesn't work, why?
The problem here is that the application route event (MvcEvent::EVENT_ROUTE) is triggered after the (MvcEvent::EVENT_BOOTSTRAP).
Which means even if you're setting the route match at the bootstrap level, the application is going to override it with the route match of the request after the MvcEvent::EVENT_ROUTE.
If you want to avoid this overriding you need to add a listener for the route event with a very low priority to make sure it will not be overridden:
$e->getApplication()->getEventManager()->attach(MvcEvent::EVENT_ROUTE, array($this, 'onRouteEvent'), -1000000);
Note : the onRouteEvent would be the method of your Module class that handles the route event (similar to your code).
If you want to short-circuit your application running at the bootstrap level, what you can do is to send the headers with redirection code to the client:
//get the url of the login page (assuming it has route name 'login')
$url = $e->getRouter()->assemble(array(), array('name' => 'login'));
$response=$e->getResponse();
$response->getHeaders()->addHeaderLine('Location', $url);
$response->setStatusCode(302);
$response->sendHeaders();
add a route entry sign_in as below in the routes section of the module.config.php under admin module
'sign_in' => array(
'type' => 'Segment',
'options' => array(
'route' => '/admin/sign/in',
'defaults' => array(
'controller' => 'sign',
'action' => 'in',
),
),
),
and call the route in the controller like this
$this->redirect()->toRoute('sign_in');
Related
I'm struggling on this for 2 hours now. I've managed to create a route with parameter (named url) like /login/url:
'login' => array(
'type' => 'segment',
'options' => array(
'route' => '/login[/:url]',
'defaults' => array(
'controller' => 'my_controller',
'action' => 'login',
),
),
),
However I'd like to have an URL which looks like /login?url=foo. I've tried something like:
'route' => '/login[?url=:url]',
But it does not work. Any idea how to achieve this on Zend Framework 2 ?
Thanks a lot!
EDIT:
Trying something else like:
// onBootstrap method --> redirect to login page with request url as param
$url = $router->assemble(
array('url', $e->getRequest()->getRequestUri()),
array('name' => 'login')
);
In controller (login action):
$request = $this->getRequest();
var_dump($request); exit;
I don't see the requested URL anywhere... any suggestion?
I don't think you should put your query string segment in your route. It would seem reasonable to have your route to be just /login and then manage your query string parameter in the controller.
Otherwise, but I don't recommend it since it is deprecated, you could try to use the Query router.
In my bootstrap file, I have the following routing chain. The desired behaviour is to send any request through /usa/:controller/:action to the local module.
For instance, when http://{hostname}/usa/index/index is called, the request goes through the local module, index controller, index action.
The problem I am having is adding parameters. For instance, when I request http://{hostname}/usa/index/index/id/5 to try to get the id parameter, I get the following error message:
An Error occurred. Page not found. Exception information: Message: Invalid controller specified (usa) with the following request params:
array (
'controller' => 'usa',
'action' => 'index',
'id' => '5',
'module' => 'default',
)
How can I set up the chain routing in order to still utilize other parameters?
Here is my code in the application bootstrap:
protected function _initRouting(){
$router = Zend_Controller_Front::getInstance()->getRouter(); // Get the main router from the front controller.
$router->addDefaultRoutes(); // Don't forget default routes!
//get default local route (directs to the local module)
$defaultLocalRoute = new Zend_Controller_Router_Route(
'/:controller/:action',
array(
'module' => 'local',
'controller' => 'index',
'action' => 'index'
)
);
$regionRoute = new Zend_Controller_Router_Route(
'/usa/',
array('region' => 'usa')
);
//chain this region route to the default local route that directs to the local module
$fullRegionRoute = $regionRoute->chain($defaultLocalRoute);
//add the full route to the router (ie. hamiltonRoute, atlanticcaRoute)
$regionRouteName = 'usaRoute';
$router->addRoute($regionRouteName, $fullRegionRoute);
}
Adding a * to the end of the $defaultLocalRoute was able to fix this issue for me.
//get default local route (directs to the local module)
$defaultLocalRoute = new Zend_Controller_Router_Route(
'/:controller/:action/*',
array(
'module' => 'local',
'controller' => 'index',
'action' => 'index'
)
);
Now when going to http://{hostname}/usa/product/view/id/5, the request goes to the desired location ->
module: 'local',
controller: 'product',
action: 'view',
params: array('id'=>5)
Recently, I've been studying cake, I've seen the auth library which said to be will take care of the access control over your app, but, it seems like, you can't initialize or even use this auth library when you're not in the 'UsersController', i did not want that, what if it has some admin part wherein i want the URI to be admin/login, or just simply /login, i've been scratching my head over this one, please help.
Another question, why it seems like the functionality of the '$this->redirect' is not effective when i'm putting this one at any method that contains nothing but redirection, or even in the __construct()?
thanks guys, hoping someone could clearly explain to me those things.
you can use the Auth component inside any controller in the application. If you want it will only effect with the admin section then you can add condition in the beforeFilter funciton in you application AppController on Auth initialization like.
// for component initialization.
public $components = array(
'Auth' => array(
'authenticate' => array(
'userModel' => 'Customer', // you can also specify the differnt model instead of user
'Form' => array(
'fields' => array('username' => 'email')
)
)
)
}
and you can bind this on the admin routing like
function beforeFilter(){
// only works with admin routing.
if(isset($this->request->params['prefix']) && ($this->request->params['prefix'] == 'admin')){
$this->Auth->loginRedirect = array('admin' => true, 'controller' => 'pages', 'action' => 'index');
$this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login', 'admin' => true);
$this->Auth->loginAction = array('admin' => true, 'controller' => 'customers', 'action' => 'login');
}
}
If you're using cake 2.3.x or later then make sure you have specified the redirect action in correct format like.
return $this->redirect('action_name'); // you can also specify the array of parameters.
I'm using Zend Framework 1.12 and have this route:
$router->addRoute('item_start',
new Zend_Controller_Router_Route_Regex(
'(foo|bar|baz)',
array(
'module' => 'default',
'controller' => 'item',
'action' => 'start'
),
array(
1 => 'area'
),
'%s'
)
);
Problem is, when I call '/foo' and use the Url Helper in the View, it doesn't give me any parameters:
$this->url(array("page"=>1));
// returns '/foo' (expected '/foo/page/1')
$this->url(array("page"=>1), "item_start", true);
// also returns '/foo'
Any idea how to get the page-parameter into the URL? I can't use the wildcard like in the standard route, can't I?
In addition to David's suggestions, you could change this route to use the standard route class, and then keep the wildcard option:
$router->addRoute('item_start',
new Zend_Controller_Router_Route(
':area/*',
array(
'module' => 'default',
'controller' => 'item',
'action' => 'start'
),
array(
'area' => '(foo|bar|baz)'
)
)
);
// in your view:
echo $this->url(array('area' => 'foo', 'page' => 1), 'item_start');
Your Regex route doesn't have a page parameter, so when the url view-helper ends up calling Route::assemble() with the parameters you feed it, it ignores your page value.
The two choices that come to mind are:
Modify your regex to include a (probably optional with default value) page parameter
Manage the page parameter outside of your route in the query string.
Firstly, Kohana's documentation is terrible, before people go "read the docs" I have read the docs and they don't seem to make much sense, even copying and pasting some of the code doesn't work for some things in the documentation.
With that in mind, I have a route like so:
//(enables the user to view the profile / photos / blog, default is profile)
Route::set('profile', '<userid>(/<action>)(/)', array( // (/) for trailing slash
"userid" => "[a-zA-Z0-9_]+",
"action" => "(photos|blog)"
))->defaults(array(
'controller' => 'profile',
'action' => 'view'
))
This enables me to go http://example.com/username and be taken to the users profile, http://example.com/username/photos to be taken to view the users photos and http://example.com/username/blog to view the blog.
If somebody goes http://example.com/username/something_else I want it to default to the action view for the user specified in <userid> but I can't seem to find any way of doing this.
I could do it like this:
Route::set('profile', '<userid>(/<useraction>)(/)', array(
"userid" => "[a-zA-Z0-9_]+",
"useraction" => "(photos|blog)"
))->defaults(array(
'controller' => 'profile',
'action' => 'index'
))
then in the controller do this:
public function action_index(){
$method = $this->request->param('useraction');
if ($method && method_exists($this, "action_{$method}")) {
$this->{"action_{$method}"}();
} else if ($method) {
// redirect to remove erroneous method from url
} else {
$this->action_view(); // view profile
}
}
(it might be better in the __construct() function but you get the gist of it.)
I'd rather not do that though if there is a better method available (which there really should be)
I think the answer might be in the regex but the following does not work:
$profile_functions = "blog|images";
//(enables the user to view the images / blog)
Route::set('profile', '<id>/<action>(/)', array(
"id" => "[a-zA-Z0-9_]+",
"action" => "($profile_functions)",
))->defaults(array(
'controller' => 'profile'
));
Route::set('profile_2', '<id>(<useraction>)', array(
"id" => "[a-zA-Z0-9_]+",
"useraction" => "(?!({$profile_functions}))",
))->defaults(array(
'controller' => 'profile',
'action' => 'view'
));
although it does match when nothing is after the ID.
I would set up the route like this:
Route::set('profile', '<userid>(/<action>)(/)', array(
"userid" => "[a-zA-Z0-9_]+",
"action" => "[a-zA-Z]+"
))->defaults(array(
'controller' => 'profile',
'action' => 'index'
))
And then in the controllers before() method:
if(!in_array($this->request->_action, array('photos', 'blog', 'index')){
$this->request->_action = 'view';
}
Or somethig similiar, just validate the action in the controller...
EDIT:
This could also work:
if(!is_callable(array($this, 'action_' . $this->request->_action))){
$this->request->_action = 'view';
}