Zend Navigation setting language parameter for route doesnt reflect in app - zend-framework

I have a zend xml config like so:
<design>
<navigation>
<frontend>
<company>
<label>Company</label>
<route>sitepage</route>
<pages>
<about>
<label>About us</label>
<route>sitepage</route>
<params>
<page>about-us</page>
<language>en</language>
</params>
</about>
Here is my sitepage route:
resources.router.routes.sitepage.type = Zend_Controller_Router_Route
resources.router.routes.sitepage.route = ":language/page/:page"
resources.router.routes.sitepage.defaults.module ="core"
resources.router.routes.sitepage.defaults.controller = "page"
resources.router.routes.sitepage.defaults.action = "view"
resources.router.routes.sitepage.defaults.page = "home"
resources.router.routes.sitepage.defaults.language = "en"
As you can see, what I do is set the page param within the <params> xml node. I tried adding the <language> parameter thinking it would automatically update to the application language, but it doesnt seem to work that way. My navigation menu just outputs, for example, http://localhost/en/page/about-us when It should be http://localhost/it/page/about-us (given that my application is registered as using the it language). How can I get my navigation to recognize the application language (it) ?

I worked this out a different way...
Here is an example for a main registration page:
routes.register_index.route = #lang/#register
routes.register_index.defaults.controller = register
routes.register_index.defaults.action = index
My navigation.xml is empty but you could use just a label and route.
You may have noticed # instead of : in my routes. This is designed mostly for i18n sites.
In my language folder, I have the regular en.php, etc. AND url-en.php, etc.
Here is what it looks like:
<?php
return array(
'lang' => 'en',
'register' => 'register',
'about' => 'about-us',
);
With this, the same route will be used for /en/register, /fr/inscription, etc. (one for each language file)
In my Bootstrap, I include these with the Rewrite initiation:
protected function _initRewrite()
{
$translator = new Zend_Translate('array', APPLICATION_PATH . '/language/url-fr.php', 'fr');
$translator->addTranslation(APPLICATION_PATH . '/language/url-en.php', 'en');
// Set the current locale for the translator
$locale = Zend_Registry::get('Zend_Locale');
$translator->setLocale($locale);
// Set it as default translator for routes
Zend_Controller_Router_Route::setDefaultTranslator($translator);
$front_controller = Zend_Controller_Front::getInstance();
$router = $front_controller->getRouter();
$config = new Zend_Config_Ini(APPLICATION_PATH . '/configs/routes.ini', APPLICATION_ENV);
$router->addConfig($config, 'routes');
$router->addDefaultRoutes();
}
This basically tells your application to translate #lang by its value from url-lang.php according to the current locale. Locale has to be set before this point in your bootstrap. You can either retrieve it from session, cookie, URL, anything.
Once this is done, you can call your route anywhere and it'll be in the current locale, using data from the special language files. Make sure your nav file has the same names as your routes and you should be fine.

Related

Create Email HTML Using Partial in Zend Framework 2?

I'm working on a system where we want to queue up a batch of emails and then send them using a queue (so I can't use \Zend\Mail directly). The goal is to not have HTML inside the models that are creating the emails but instead have them in a view file. I'm trying to call the partial view helper inside the models (which I did in ZF1) but can't find anything on the web on how to do this. Is this possible in ZF2 or is there a better way? I've managed it before where we've had the HTML inside the models and it's been a mess. :-)
You can just create a template somewhere, pull the renderer from your service locator, and render away:
<?php
// this assumes you're in some AbstractActionController,
// but you could be in some service class that has the
// renderer injected, etc.
// template vars
$vars = array(/* .... */);
// create a ViewModel
$vm = new \Zend\View\Model\ViewModel($vars);
// path to your email template, compatible with your template map config.
$tpl = 'mymodule/emails/some-email-template.phtml';
$vm->setTemplate($tpl);
// get the renderer from the ServiceManager, so it's all nicely configured.
$renderer = $this->getServiceLocator()->get('Zend\View\Renderer\RendererInterface');
// render some HTML
$html = $renderer->render($vm);
You could do it this way:
1. In the module.config define those HTML mail content template views.
'view_manager' => array(
(...)
'template_map' => array(
'mail_content_1' => __DIR__ . '/../view/<MODULE_NAME>/mail_content_1.phtml',
),
(...)
)
2. Load the Template View in your model and get the HTML.
use Zend\View\Model\ViewModel;
public function getMailHTML() {
$view = new ViewModel;
$variables = array( "parm1" => "value1" );
//SET THE VARIABLES, LIKE IN PARTIALS
$view->setVariables( $variables );
//SET THE TEMPLATE VIEW KEY DEFINED IN THE module.config
$view->setTemplate( 'mail_content_1' );
//YOU'LL HAVE TO BE ABLE TO USE THE ServiceManager IN YOUR MAIL MODELS.
//RENDERING THE VIEW YOU'LL GET THE HTML
return $this->serviceManager->get( 'viewrenderer' )->render( $view );
}

zend framework get id in /delete/2

I'm actually using zend, and I wonder how to get the id in such url :
/delete/2
I know I can do it using :
// if URL is /delete/id/2
$request->getParam('id');
But what I want is to have url like the first one /delete/2 which sounds more logical to me.
Ideas?
Thanks for your help
I think you should be able to solve this kind of problem using routes. You can create a route for
/delete/2
by adding this to for example your config.ini file:
[production]
routes.delete.route = "delete/:id"
routes.delete.defaults.controller = delete
routes.delete.defaults.action = index
routes.delete.id.reqs = "\d+"
Here you specify the URL to match, in which words starting with a colon : are variables. As you can see, you can also set requirements on your variables regex-style. In your example, id will most likely be one or more digits, resulting in a \d+ requirement on this variable.
This route will point the url to the index action of the delete controller and sets id as a GET-var. You can alter this .ini code to suit your specific needs.
The routes can be added by putting the following code inside your bootstrap:
$config = new Zend_Config_Ini('/path/to/config.ini', 'production');
$router = new Zend_Controller_Router_Rewrite();
$router->addConfig($config, 'routes');
See the docs for more information: here for the general documentation and here for the .ini approach I just described.
Try this: add the following function to your Bootstrap.php
protected function _initRoute(){
$this->bootstrap ('frontcontroller');
$front = $this->getResource('frontcontroller');
$router = $front->getRouter();
$deleteRoute = new Zend_Controller_Router_Route(
'delete/:id',
array(
'controller' => '{enter-your-controller-name-here}',
'action' => '{enter-your-action-name-here}'
)
);
$router->addRoute('delete', $deleteRoute);
}
Don't forget to replace {enter-your-controller-name-here} with controller name and {enter-your-action-name-here} with action name.
With this code added, $request->getParam('id'); should work just fine.

Full dynamic router in Zend Framework

By default you have the following URL-syntax in ZF: /module/controller/action. What i want, is to build an menu-system where i can use any URL I want.
Lets say I make an menu-item called 'news'. When i call http://www.site.com/news i want to have the folowing loaded:
module: news
controller: frontpage
action: display
These config-values must be configured in the database-record for the menu-item.
How can I do this in zend? I spend a lot of time searching for it, but I still can't figure out how to. Does anybody?
I'd suggest using a front controller plugin to scan your database for all the entries, create routing rules based on those entries and add them to the router (see this).
Of course caching strategy is recommended so that you don't do a lot of processing on every request.
You can create a plugin and in routeStartup define something that intercept your request and route /module/controller/action to /action, but for this all your action names must be unique :
class My_CustomRouterPlugin extends Zend_Controller_Plugin_Abstract
{
public function routeStartup(Zend_Controller_Request_Abstract $request)
{
$fc = Zend_Controller_Front::getInstance();
$action =$fc->getRequest()->getActionName();
$router = $fc->getRouter();
$model= new myModel();
$myPage = $model->getPageByAction($action);
$route = new Zend_Controller_Router_Route('/action', array(
'module' => $myPage->getModule();
'controller' => $myPage->getController();
'action' => $action;
));
$router->addRoute($action, $route);
return $router;
}
}
In myModel define a method can get you an object(or an array) that contains module, controller names (from you DB ).
and register this plugin in your bootstrap:
$front->registerPlugin(new My_CustomRouterPlugin());

Zend Route Regex and invalid controller

php i have method to add routes:
public function addRoutes()
{
$front = Zend_Controller_Front::getInstance();
$redirect = $front->getRouter();
$router = new Zend_Controller_Router_Route_Regex(
"p\/(a-zA-Z0-9)\.htm",
array(
'controller'=>'page',
'action'=>'index',
1=>'ja.htm'
),
array( 1 => 'page_name')
);
$route2 = new Zend_Controller_Router_Route_Regex("(a-zA-Z0-9)\.html",
array('controller'=>'page',
'action'=>'index',
1=>'ja.html'),
array(1=>'page_name'));
$redirect->addRoute('pages',$router);
$redirect->addRoute('hmtmled',$route2);
$front->setRouter($redirect);
}
I tried to enter url like: p/ja.htm but i get error: Invalid controller specified (p). I know its for reason of default route, but how to change that?
Is that method part of your Bootstrap class? If so, are you sure it is being run? Remember, the Bootstrap methods that get called automatically are those of the form _initXXX() (note the leading underscore).
Also, as #Tim Fountain astutely notes in the comments, the regex needs to be:
p/([0-9A-Za-z]+)\.htm
you try to remove the default routes:
//excerpt from ZF reference 24.5.4. Default Routes... If you do
not want this particular default route in your routing schema, you may
override it by creating your own 'default' route (i.e., storing it
under the name of 'default') or removing it altogether by using
removeDefaultRoutes():
// Remove any default routes
$router->removeDefaultRoutes();

Hostname and Custom routing in Zend Framework don't work together for me

I am building an application that uses hostname routing to detect subdomains like
user1.example.com
user2.example.com
and also have custom routes like user1.example.com/login
This works well so far, however when I add custom routes they do not work. I have searched and read a lot but seems there is something I am missing. Here is what I have so far:
//my routes in routes.ini
[development]
routes.login.type = "Zend_Controller_Router_Route"
routes.login.route = "/login"
routes.login.defaults.controller = "user"
routes.login.defaults.action = "login"
//This part in Bootstrap file
$this->bootstrap('frontController');
$router = $this->frontController->getRouter();
$routerConfig = new Zend_Config_Ini(
APPLICATION_PATH . '/configs/routes.ini',
'production'
);
//I create a default route
$routeDefault = new Zend_Controller_Router_Route_Module(
array(),
$this->frontController->getDispatcher(),
$this->frontController->getRequest()
);
$router->addConfig($routerConfig, 'routes');
// hostname route
$hostnameRoute = new Zend_Controller_Router_Route_Hostname(
':username.mysite.com',
array(
'module' => 'default',
'controller' => 'index',
'action' => 'index',
)
);
//I add the default route.
$router->addRoute('default', $routeDefault);
//I chain the routes so that all routes have subdomain routing too
foreach ($router->getRoutes() as $key => $theroute) {
$router->addRoute($key, $hostnameRoute->chain($theroute));
}
When I go to a custom route like http://user1.example.com/login I get the error: 'Invalid controller specified (login)' which means my custom route is not being recognized. I am also not sure if the way I am adding the default route is correct and necessary. If I remove that code then it doesn't work. So my problem really is that I would like my hostname matching, custom routes and default routes to all work. If you can spot where I'm going wrong please help, I have read previous related posts all over on routes, chaining, default routes etc (including this very related one: How do I write Routing Chains for a Subdomain in Zend Framework in a routing INI file?) but haven't found the solution so far.
You should be able to setup your routing using a custom param in the route:
routes.testdynamicsubdomain.type = "Zend_Controller_Router_Route_Hostname"
routes.testdynamicsubdomain.route = ":subdomain.domain.dev"
routes.testdynamicsubdomain.defaults.module = public
routes.testdynamicsubdomain.defaults.controller = index
routes.testdynamicsubdomain.defaults.action = index
If your apache/hostfile etc are configured correctly going to test.domain.dev should load the index action in your indexController where you could get the :subdomain param:
echo $this->getRequest()->getParam('subdomain');
Also, as you discovered, the order of the routes is very important. See also Zend Router precedence for more info about this.