How to generate URL using Module, controller and view? - php

Is there a way of generating a full url in zend if the Module, controller and view names are known?

I'm assuming you mean module, controller, and action, since the view is determined by the action (usually).
In the view:
echo $this->url(array('module' => $module,
'controller' => $controller,
'action' => $action));
Any parameters not set, default to the current values, so in any given view:
echo $this->url(); //link for the current request
The function also accepts two additional arguments: url($urlOptions, $name, $reset). $name allows you to specify a route name, and $reset will clear the generated URL of any current parameters.
In the controller:
This actually isn't documented, but follows the structure of the redirector helper (in fact, I believe it is used by the redirector helper):
$url = $this->getHelper('url')->simple($action, $controller, $module, $params);
You can also use the url() method, which follows the View helper:
$url = $this->getHelper('url')->url(array('module' => $module,
'controller' => $controller,
'action' => $action));

Related

Phalcon php multilingual routing

Hi I'm new to the php world.
I'm wondering What is the best way to handle multilingual routing ?
I'm starting to create a website with Phalcon php.
I have the following routing structure.
$router->add('/{language:[a-z]{2}}/:controller/:action/:params', array(
'controller' => 2,
'action' => 3,
'params' => 4,
));
$router->add('/{language:[a-z]{2}}/:controller/:action', array(
'controller' => 2,
'action' => 3,
));
$router->add('/{language:[a-z]{2}}/:controller', array(
'controller' => 2,
'action' => 'index',
));
$router->add('/{language:[a-z]{2}}', array(
'controller' => 'index',
'action' => 'index',
));
My problem is for instance when I go on mywebsite.com/ I want to change my url in the dispatcher like mywebsite.com/en/ or other language. Is it a good practise to handle it in the beforeDispatchLoop ? I seek the best solutions.
/**Triggered before entering in the dispatch loop.
* At this point the dispatcher don't know if the controller or the actions to be executed exist.
* The Dispatcher only knows the information passed by the Router.
* #param Event $event
* #param Dispatcher $dispatcher
*/
public function beforeDispatchLoop(Event $event, Dispatcher $dispatcher)
{
//$params = $dispatcher->getParams();
$params = array('language' => 'en');
$dispatcher->setParams($params);
return $dispatcher;
}
This code doesn't work at all, my url is not change. The url stay mywebsite.com/ and not mywebsite.com/en/
Thanks in advance.
I try one solution above.
The redirect doesn't seems to work. I even try to hard-coded it for test.
use Phalcon\Http\Response;
//Obtain the standard eventsManager from the DI
$eventsManager = $di->getShared('eventsManager');
$dispatcher = new Phalcon\Mvc\Dispatcher();
$eventsManager->attach("dispatch:beforeDispatchLoop",function($event, $dispatcher)
{
$dispatcher->getDI->get('response')->redirect('/name/en/index/index/');
}
I think you are confusing something. If I understand correctly: you want to redirect users to a valid url if they open a page without specifying a language.
If that's the case you should verify in your event handler whether the language parameter is specified and redirect user to the same url + the default language if its missing. I am also assuming that your beforeDispatchLoop is located in your controller, which is also part of the problem, because your route without a language never matches and you never get into that controller. Instead you need to use it as an event handler with the event manager as per the documentation. Here is how you do the whole thing.
$di->get('eventsManager')->attach("dispatch:beforeDispatchLoop", function(Event $event, Dispatcher $dispatcher)
{
$params = $dispatcher->getParams();
// Be careful here, if it matches a valid route without a language it may go into a massive
// recursion. Really, you probably want to use `beforeExecuteRoute` event or explicitly
// check if `$_SERVER['REQUEST_URI']` contains the language part before redirecting here.
if (!isset($params['language']) {
$dispatcher->getDI->get('response')->redirect('/en' . $_SERVER['REQUEST_URI']);
return false;
}
return $dispatcher;
});

How check if action exsist in Controller Plugin preDispatch

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

how to call function of controller in cakephp framework with default function?

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.

Zend: The url assembled by the URL view helper is incorrect

I have a problem using my url view helper. I have defined custom routes like so:
; Index
routes.domain.type = 'Zend_Controller_Router_Route_Static'
routes.domain.route = '/'
routes.domain.defaults.controller = index
routes.domain.defaults.action = index
Everything works fine with the custom url's but I cannot assemble normal none.
I tried to add a link using the following code from the view:
$this->url(array('controller' => 'search', 'action' => 'index');
The problem is that when I use this code in my index page of index controller, the returned url is the url of the current controller/action, and not the one I need.
This is because the URL view helper picks to last active route. If you have multiple routes always define the route you are using:
$this->url(array('controller' => 'search', 'action' => 'index'), 'default');
The second parameter is the route to be used, an third optional parameter is if all params needs to be reset (true/false).
For that you need to setup a reverse route map like explained here.
The most recommended way to generate a URL is by using your own custom URL view helper.
class My_View_Helper_FullUrl extends Zend_View_Helper_Abstract {
public function fullUrl($url) {
$request = Zend_Controller_Front::getInstance()->getRequest();
$url = $request->getScheme() . "://" . $request->getHttpHost(). "/" . $url;
return $url;
}
}
So, to generate a URL, you'll just call,
$this->fullUrl('search');
which will output,
www.example.com/search

CakePHP - admin routing for /admin/, but not all the rest (way to set default admin false?)

I read the tutorial, and found that to use the "admin" prefix, you can just uncomment the:
Configure::write('Routing.prefixes', array('admin'));
config/core.php file.
I did that, and my admin routing works great - /admin/users/add hits the admin_add() function in my users_controller.
The problem is - it's also changing my normal links - ie. my "LOGOUT" button now tries to go to /admin/users/logout instead of just /users/logout. I realize I can add 'admin'=>false, but I'd rather not have to do that for every link in my site.
Is there a way to make it so ONLY urls with either 'admin'=>true or /admin/... to go to the admin, and NOT all the rest of the links?
Expanding on user Abba Bryant's edit, have a look at how to create a helper in the cook book : http://book.cakephp.org/view/1097/Creating-Helpers
If having to disable routing manually on all your links is an annoyance (it would be to me!), you could create a new helper MyCustomUrlHelper (name doesn't have to be that long of course), and have it use the core UrlHelper to generate the URLs for you.
class MyCustomUrlHelper extends AppHelper {
public $helpers = array('Html');
function url($controller, $action, $params ,$routing = false, $plugin = false) {
//Example only, the params you send could be anything
$opts = array(
'controller' => $controller,
'action' => $action
//....
);
}
//another option
function url($params) {
//Example only, the params you send could be anything
$opts = array(
'controller' => $params['controller'],
'action' => $params['action']
//....
)
}
//just fill up $opts array with the parameters that core URL helper
//expects. This allows you to specify your own app specific defaults
return $this->Html->url($opts); //finally just use the normal url helper
}
Basically you can make it as verbose or terse as you want. It's just a wrapper class for the the actual URL helper which will do the work from inside. This allows you to give defaults that work for your specific application. This would also allow you to make a change in one place and have the routing for the whole application be updated.
EDIT
You could also check whether the passed $opts array is a string. This way you can have the best of both worlds.
Make sure if you use the prefix routing that you handle it in the HtmlHelper::link calls like so
<?php
...
echo $html->link( array(
'controller' => 'users',
'action' => 'logout',
'plugin' => false,
'admin' => false,
));
...
?>
** EDIT **
You could extend the url function in your AppHelper to inspect the passed array and set the Routing.prefixes keys to false if they aren't already set in the url call.
You would then need to specify the prefix in your admin links every time.
The HtmlHelper accepts two ways of giving the URL: it can be a Cake-relative URL or an array of URL parameters.
If you use the URL parameters, by default if you don't specify the 'admin' => false parameter the HtmlHelper automatically prefixes the action by 'admin' if you are on an admin action.
IMHO, the easiest way to get rid off this parameter is to use the Cake-relative URL as a string.
<?php
//instead of using
//echo $this->Html->link(__('logout', true), array('controller' => 'users', 'action' => 'logout'));
//use
echo $this->Html->link(__('logout', true), '/users/logout');
Kind regards,
nIcO
I encountered this problem this week and this code seemed to fix it. Let me know if it doesn't work for you and I can try to find out what else I did to get it to work.
$this->Auth->autoRedirect = false;
$this->Auth->loginAction = array(Configure::read('Routing.admin') => false, 'controller' => 'users', 'action' => 'login');
$this->Auth->logoutRedirect = array(Configure::read('Routing.admin') => false, 'controller' => 'users', 'action' => 'logout');
$this->Auth->loginRedirect = array(Configure::read('Routing.admin') => false, 'controller' => 'users', 'action' => 'welcome');
This was really frustrating, so I'm glad to help out.
I'm late to the party, but I have a very good answer:
You can override the default behavior by creating an AppHelper class. Create app/app_helper.php and paste the following:
<?php
class AppHelper extends Helper{
function url($url = null, $full = false) {
if(is_array($url) && !isset($url['admin'])){
$url['admin'] = false;
}
return parent::url($url, $full);
}
}
?>
Unless it is specified when you call link() or url(), admin will be set to false.

Categories