I have two modules (default and mobile) the module mobile is a rewrite the default portal in jquery mobile but with much less controllers and actions!
I thought of write a controller plugin that check if controller and action exist in module mobile, if not I would like overwrite the module mobile to default.
I try this:
public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
{
$dispatcher = Zend_Controller_Front::getInstance()->getDispatcher();
if ($request->getModuleName() == 'mobile') {
if (!$dispatcher->isDispatchable($request)) {
// Controller or action not exists
$request->setModuleName('default');
}
}
return $request;
}
but $dispatcher->isDispatchable($request) return always true though the action not exist! :S
and i receive "Action foo does not exist and was not trapped in __call()"
How can I do?
Thanks
Have you ever wondered how to check if a controller/action exist in zend FM from any side of app ? Here is the code
$front = Zend_Controller_Front::getInstance();
$dispatcher = $front->getDispatcher();
$test = new Zend_Controller_Request_Http();
$test->setParams(array(
'action' => 'index',
'controller' => 'content',
)
);
if($dispatcher->isDispatchable($test)) {
echo "yes-its a controller";
//$this->_forward('about-us', 'content'); // Do whatever you want
} else {
echo "NO- its not a Controller";
}
EDIT
Check like this way
$classMethods = get_class_methods($className);
if(!in_array("__call", $classMethods) &&
!in_array($this->getActionMethod($request), $classMethods))
return false;
and also please see detail link
I would suggest you make a static or dynamic routes either via config resource manager, bootstrap or via front controller plugin:
Example of defining static routes in Bootstrap.php:
public function _initRoutes()
{
$front = Zend_Controller_Front::getInstance();
$router = $front->getRouter(); // default Zend MVC routing will be preserved
// create first route that will point from nonexistent action in mobile module to existing action in default module
$route = new Zend_Controller_Router_Route_Static(
'mobile/some-controller/some-action', // specify url to controller and action that dont exist in "mobile" module
array(
'module' => 'default', // redirect to "default" module
'controller' => 'some-controller',
'action' => 'some-action', // this action exists in "some-controller" in "default" module
)
);
$router->addRoute('mobile-redirect-1', $route); // first param is the name of route, not url, this allows you to override existing routes like default route
// repeat process for another route
}
This would effectively route request for /mobile/some-controller/some-action to /default/some-controller/some-action
some-controller and some-action should be replaced with proper controller and action names.
I was using static routing which is ok if you route to exact urls, but since most applications use additional params in url for controller actions to use, it is better to use dynamic routes.
In above example simply change route creation class to Zend_Controller_Router_Route and route url to "mobile/some-controller/some-action/*" and every request will be routed dynamically like in example:
/mobile/some-contoller/some-action/param1/55/param2/66
will point to
/default/some-controller/some-action/param1/55/param2/66
For more info about routing in ZF1 check this link
Related
So the title describes my problem pretty well I think, but let me explain why I want to do this as theremight be an other solution to my problem that I haven't thought about.
Let's say that I have a route specifying the class of the object it will patch:
Route::patch('{class}/{id}', array(
'as' => 'object.update',
function ($class, $id) {
$response = ...;
// here I want to call the update action of the right controller which will
// be named for instance CarController if $class is set to "car")
return $response;
}
));
This is something pretty easy to do with $app->make($controllerClass)->callAction($action, $parameters); but doing it this way won't call the filters set on the controller.
I was able to do it with laravel 4.0 with the callAction method, passing the app and its router, but the method has changed now and the filters are called in the ControllerDispatcher class instead of the Controller class.
If you have routes declared for your classes then you may use something like this:
$request = Request::create('car/update', 'POST', array('id' => 10));
return Route::dispatch($request)->getContent();
In this case you have to declare this in routes.php file:
Route::post('car/update/{id}', 'CarController#update');
If you Use this approach then filters will be executed automatically.
Also you may call any filter like this (not tested but should work IMO):
$response = Route::callRouteFilter('filtername', 'filter parameter array', Route::current(), Request::instance());
If your filter returns any response then $response will contain that, here filter parameter array is the parameter for the filter (if there is any used) for example:
Route::filter('aFilter', function($route, $request, $param){
// ...
});
If you have a route like this:
Route::get('someurl', array('before' => 'aFilter:a_parameter', 'uses' => 'someClass'));
Then the a_parameter will be available in the $param variable in your aFilter filter's action.
So I might have found a solution to my problem, it might not be the best solution but it works. Don't hesitate to propose a better solution!
Route::patch('{class}/{id}', array(
'as' => 'object.update',
function ($class, $id) {
$router = app()['router']; // get router
$route = $router->current(); // get current route
$request = Request::instance(); // get http request
$controller = camel_case($class) . 'Controller'; // generate controller name
$action = 'update'; // action is update
$dispatcher = $router->getControllerDispatcher(); // get the dispatcher
// now we can call the dispatch method from the dispatcher which returns the
// controller action's response executing the filters
return $dispatcher->dispatch($route, $request, $controller, $action);
}
));
My yii PHP project has UserController and it has an action called actionView. I can access user view page using following URL
mysite.com/user/view/id/1
I want to change that one to
mysite.com/username
How Can I do it.
I know that i can simply create rule to be more user friendly to get url such as
mysite.com/user/username
But url scheme with database resource name as direct param (mysite.com/username) is whole different story.
Url rule:
array(
'<username:\w+>'=>'user/view',
)
Note that in such scheme, you must also create rules for all your controllers and place above rule at the end, so better prefix it with user:
array(
'user/<username:\w+>'=>'user/view',
)
Resulting url will be example.com/user/username
In action:
public function actionView($username) ...
Update:
To make rule which reacts on any input variable create custom url rule class, here is some example, modify to your needs:
class PageUrlRule extends CBaseUrlRule
{
public function createUrl($manager, $route, $params, $ampersand)
{
// Ignore this rule for creating urls
return false;
}
public function parseUrl($manager, $request, $pathInfo, $rawPathInfo)
{
// Ignore / url or any controller name - which could conflict with username
if($pathInfo == '/')
{
return true;
}
// Search for username or any resource in db
// This is for mongo so it should be tuned to your db,
// just check if username exists
$criteria = new EMongoCriteria();
$criteria->url->$lang = $url;
$criteria->select(['_id']);
$criteria->limit(1);
$model = PageItem::model();
$cursor = $model->findAll($criteria);
// Create route, instead of $url id can be used
$route = sprintf('content/page/view/url/%s', urlencode($url));
// If found return route or false if not found
return $cursor->count() ? $route : false;
}
}
Then place this rule in beginning of urlmanager config
'rules' => [
[
'class' => 'application.modules.content.components.PageUrlRule'
],
// Other rules here
Important: If user has username same as your controller, it will match username and controller will be inaccessible. You must forbid registering users with same names as controllers.
i am new comer for cakephp framework. i can not call functions of controller.
Controller-
class PagesController extends AppController {
public $name = 'Pages';
public $uses = array();
public function display() {
$path = func_get_args();
$count = count($path);
if (!$count) {
$this->redirect('/');
}
$page = $subpage = $title_for_layout = null;
if (!empty($path[0])) {
$page = $path[0];
}
if (!empty($path[1])) {
$subpage = $path[1];
}
if (!empty($path[$count - 1])) {
$title_for_layout = Inflector::humanize($path[$count - 1]);
}
$this->set(compact('page', 'subpage', 'title_for_layout'));
$this->render(implode('/', $path));
}
public function register() {
$this->set('fdf', 'chandan');
$this->render('home1');
}
}
But i am calling display(). but i am not calling register(). my routes.php file like-
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
Please help me. how to call controller function from view in cakephp.
and what setting have to done for it ?.
A few points I would make, the routes file is for defining custom slugs/url, take a look at your first route definition here:
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
This is saying that "www.mysite.com/" should link to the controller pages, the action display and pass the first parameter as home.
This can be accessed by doing "www.mysite.com/pages/display/home" in short - but using "/" as a route is tidier. The general rule is "www.mysite.com/controller/action/param1/param2/etc.."
So following this logic you would access your new action method like such:
"www.mysite.com/pages/register"
That being said... When using MVC you should really follow the conventions set out, if you're going to create a register method you should really contain it within a controller which deals with user accounts i.e. "UsersController" - "www.mysite.com/users/register"
Also, you shouldn't really need to use $this->render() unless you have to render a separate view under special conditions.
To sum up, contain all actions within a relevant controller (i.e. www.mysite.com/users/login and www.mysite.com/users/register), never directly specify $this->render unless you really need to render something other than the default (/users/register.ctp would be the default for www.mysite.com/users/register) and routes are used to create tidier or custom urls.
I would highly recommend you read and follow the blog tutorial to grasp these concepts.
In Yii, I am finding a way how to restrict the url that accesses my controller actions to 'http' only. I am thinking about how to get the url in a Yii way so that I can place my code in the 'expression' attribute of the array.
You can write a filter method in your base controller (components/Controller.php):
public function filterOnlyHttp($filterChain = null) {
if (Yii::app()->request->isSecureConnection) {
$this->redirect('http://'.$_SERVER['HTTP_HOST'].Yii::app()->request->requestUri);
}else
$filterChain->run();
}
It will redirect your https:// to http:// requests. You can configure this filter for specific controller actions in a filters() method in a controller:
public function filters()
{
return array(
'httpOnly',
);
}
If you generally want that redirect all your https requests, then you could also put the if above (without the else part) into the init() method of your base controller in components/Controller.php.
Try defaultScheme/validSchemes
array('url', 'url','defaultScheme' => 'http')
array('url', 'url','validSchemes' => array('http'));
Check this for more info http://www.yiiframework.com/wiki/56/#hh23
I am experiencing some difficulty setting up the functionality for an admin to edit an items values. I have created the editAction() function in the AdminItemController class. This is contained within a module called catalog. My routing is configured as the following:
resources.router.routes.admin-catalog-edit.route = "/admin/catalog/item/edit/:id"
resources.router.routes.admin-catalog-edit.defaults.module = "catalog"
resources.router.routes.admin-catalog-edit.defaults.controller = "admin.item"
resources.router.routes.admin-catalog-edit.defaults.action = "edit"
I have created a custom Zend_Form class and within this class I set the action and method for the form:
class My_Form_ItemAdd extends Zend_Form
{
public function init()
{
$this->setAction('/admin/catalog/item/edit')
->setMethod('post');
...
Within my controller action I have instantiated the form and pass it to the view to be rendered. I also test if it's a POST (if so validate and save to database), otherwise, test for GET (if so, extract ID and populate()):
class Catalog_AdminItemController extends Zend_Controller_Action
{
...
public function editAction()
{
$form = new My_Form_ItemEdit();
$this->view->form = $form;
...
The form loads just fine in the browser when I supply an ID at the end for GET request... however, when I submit the form an exception is thrown with the following request parameters:
array (
'controller' => 'admin',
'action' => 'catalog',
'item' => 'edit',
'module' => 'default',
...
I have no idea why the it would be doing this... is there something I'm not seeing??? Any advice would be much appreciated!
The problem lies in your route. The default behavior for /admin/catalog/item/edit/:id is to process it like /controller/action/:param/:param/:param which puts both item and edit as parameters instead of your intended purpose. Try adding something like this to your bootstrap:
protected function _initRoutes()
{
// Get front controller
$front = Zend_Controller_Front::getInstance();
// Get router
$router = $front->getRouter();
// Add route
$router->addRoute(
'admin_item_edit',
new Zend_Controller_Router_Route('admin/catalog/item/edit/:id',
array('controller' => 'item',
'action' => 'edit'))
);
}
This allows you to define the specific controller and action from the route.