I'm working on a Zend 1.11 webapp. I built a language-selector plugin for switching language (it & en) depending on the user input.
This is what I have:
class LS_Controller_Plugin_LangSelector extends Zend_Controller_Plugin_Abstract
{
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
if($request->getParam('lang'))
{
$lang=$request->getParam('lang');
setcookie('lang', $lang, time() + (3600));
echo "we just set a cookie";
}
else if (isset($_COOKIE['lang']))
{
$lang=$_COOKIE['lang'];
echo $lang;
}
else
{ echo 'We are here.But I can't understand why';
$lang='en';
var_dump($_COOKIE);
}
switch(strtolower($lang))
{
case 'en':
$locale="en_US";
break;
case 'it':
$locale="it_IT";
break;
default:
$locale="en_US";
}
$zl=new Zend_Locale();
$zl->setLocale($locale);
Zend_Registry::set('Zend_Locale',$zl);
$translate=new Zend_Translate(
array(
'adapter' => 'gettext',
'content' => APPLICATION_PATH.'/configs/languages/'.$locale.'.mo',
'locale' => 'en'
)
);
Zend_Registry::set('Zend_Translate',$translate);
}
}
[bootstrap.php]
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initRoutes()
{
$frontController=Zend_Controller_Front::getInstance();
$router=$frontController->getRouter();
$router->removeDefaultRoutes();
$router->setGlobalParam('lang','en');
$router->addRoute(
'lang',
new Zend_Controller_Router_Route('/:lang/:controller/:action',
array('lang'=>':lang',
'module'=>'default',
'controller'=>'index',
'action'=>'index'
)
)
);
$router->addRoute(
'langController',
new Zend_Controller_Router_Route('/:controller/:action',
array(
'module'=>'default',
'controller'=>'index',
'action'=>'index'
)
)
);
$router->addRoute(
'langIndex',
new Zend_Controller_Router_Route('/:lang',
array('lang'=>':lang',
'module'=>'default',
'controller'=>'index',
'action'=>'index'
)
)
);
$router->addRoute(
'langNothing',
new Zend_Controller_Router_Route('',
array('lang'=>'en',
'module'=>'default',
'controller'=>'index',
'action'=>'index'
)
)
);
}
}
The point is that:
I type in my browser the full URL mysite.com/it/index/index and I get echo out "we just set a cookie"..wich is fine I should be able to browse my website with the italian cookie set but I don't. Whenever I click over a link (Ex. /index/contactus..links do not specify the 'lang' parameter!) I navigate to that page but it's in english again (I get echoed out the message:"we are here.but I can't understand why").
Shouldn't the cookie be set?
The problem is, that you don't specify the path for your cookie. So it will set for the current page only.
If you browse to another (sub)site, then your cookie is not valid for this path and doesnt get transmitted. You should set your lang-cookie to the "/" Path.
See setcookie() documentation:
The path on the server in which the cookie will be available on. If set to '/', the cookie will be available within the entire domain. If set to '/foo/', the cookie will only be available within the /foo/ directory and all sub-directories such as /foo/bar/ of domain. The default value is the current directory that the cookie is being set in.
Related
I wanted to change the pages 'register user', 'change password' and 'user edit'.
This is not possible in the Drupal frontend, and you also have to pay a lot of attention in the code.
In forums you will usually find little help and if then rather not
satisfactory.
Therefore, I like to share my solution to save the one or other headache.
The three forms are already available from Drupal standard, if you want to change them you have to access the route and redirect.
For this you first create a module like 'my_forms'.
Second the form or a page that you want to hook into the website. e.g.
'ForgotPasswordForm'
Create a folder inside your my_forms 'Routing' and a file like 'RouteSubscriber.php'
code:
<?php
namespace Drupal\my_forms\Routing;
class RouteSubscriber extends RouteSubscriberBase{
protected function alterRoutes( RouteCollection $collection ){
//enter code here
}
}
Now you can change the route to the diffrent pages by adding following -
code:
//edit the 'forgot password' page
if ( $route = $collection->get( 'user.pass' ) ){
$route->setDefault( '_form', '\Drupal\my_forms\Form\ForgotPasswordForm' );
}
The keyword 'user.pass' allows you to change the routing. setDefault redirects the route to your own form.
//edit the 'register' page
if ( $route = $collection->get( 'user.register' ) )
{
$route->setDefaults( array(
'_title' => 'Register',
'_controller' => '\Drupal\myy_forms\Controller\LocalTaskController::offerRegistrationPage'
)
);
}
The keyword for the registration is 'user.register'. By setting the route with setDefaults you can also change the name of the link/button. In this case I used a controller to print out a normal page inside the registration. (more at the end of the post)
if ( $route = $collection->get( 'entity.user.edit_form' ) ){
//enter code here
}
For the 'user edit' page you need to use the keyword 'entity.user.edit_form'.
Last step is to clear your cashes, to register the changes in your Drupal website and refresh your page.
Load simple page with a Drupal Controller:
namespace Drupal\my_forms\Controller;
class LocalTaskController extends ControllerBase{
/** #var NodeStorage $nodeStorage */
protected $nodeStorage;
/** #var EntityViewBuilder $viewBuilder */
protected $viewBuilder;
function __construct( $nodeStorage, $viewBuilder )
{
$this->nodeStorage = $nodeStorage;
$this->viewBuilder = $viewBuilder;
}
public static function create( ContainerInterface $container )
{
$nodeStorage = $container->get( 'entity.manager' )->getStorage( 'node' );
$viewBuilder = $container->get( 'entity_type.manager' )->getViewBuilder( 'node' );
return new static( $nodeStorage, $viewBuilder );
}
public function offerRegistrationPage()
{
$node = $this->nodeStorage->load( 24 );
$renderArray = $this->viewBuilder->view( $node );
return [
'#type' => '#markup',
'#markup' => render( $renderArray ),
];
}
The '24' is the nid of the simple page, which should be displayed instead of the standard registration.
I've got a problem ith redirect after successful login.
App.php file (part of it):
<?php
use Silex\Application;
/** ... */
use Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder;
$app = new Application();
/** ... */
$app['security.encoder.digest'] = $app->share(function ($app) {
return new PlaintextPasswordEncoder();
});
$app['security.firewalls'] = array(
'secured' => array(
'pattern' => '^/admin/',
'form' => array(
'login_path' => '/login',
'check_path' => '/admin/login_check',
'default_target_path' => '/admin/news',
'always_use_default_target_path' => true,
),
'logout' => array(
'logout_path' => '/admin/logout',
),
'users' => array(
'admin' => array('ROLE_ADMIN', 'test'),
),
),
);
My controllers.php file:
<?php
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
$app->get('/login', function(Request $request) use ($app) {
return $app['twig']->render('login.html.twig', array(
'error' => $app['security.last_error']($request),
'last_username' => $app['session']->get('_security.last_username'),
));
});
$app->get('/admin/news', function(Request $request) use ($app) {
if ($app['security.authorization_checker']->isGranted('ROLE_ADMIN')) {
echo 'admin';
}
});
I am logged in (after passing correct login data in form), I have access to /admin/news route, but I have to go to that address manually. I'd like to be redirected there automatically after successful login. Now I'm kept in /login page. When I change default_target_path to 'http://google.com', it works properly.
I use homestead (vagrant) with nginx. Silex 1.3.0.
I'll appreciate any help.
The solution (or rather workaround) which worked was:
change 'default_target_path' to '/admin';
add new route:
$app->get('/admin', function() use ($app) {
return $app['twig']->render('admin/loggedIn.html.twig');
});
in admin/loggedIn.html.twig template I've added js redirect to admin/news
I don't have any idea why wasn't it working. If anyone knows - please leave a comment.
I'm just new with Zend and I have a little trouble with Zend Routers. I've searched about it, but nothing found...
I want to be able to define a router for each defined variable at uri level to point to a different action in one controller.
I'm working with lang and modules so I defined at bootstrap application the next initRoutes function:
protected function _initRoutes()
{
$front = Zend_Controller_Front::getInstance();
$router = $front->getRouter();
$defaultRoute = new Zend_Controller_Router_Route(
':lang/:module/:controller/:action',
array(
'lang' => 'es',
'module' => 'default',
'controller' => 'index',
'action' => 'index'
),
array(
'lang' => '^(en|es)$',
'module' => '^(default|admin)$'
)
);
$router->addRoute('defaultRoute', $defaultRoute);
return $router;
}
I want to be able to access forum sections and forum topics by their defined action.
Something like :
mydomain/forum -> forum/index
mydomain/forum/section -> forum/sectionAction
mydomain/forum/section/topic -> forum/topicAction
and also with the lang and module defined at uri level like :
mydomain/lang/module/forum
mydomain/lang/module/forum/section
mydomain/lang/module/forum/section/topic
So I have this :
class ForumController extends Zend_Controller_Action
{
public function indexAction()
{
}
public function sectionAction()
{
}
public function topicAction()
{
}
Then I created the next routes inside the Default_Bootstrap :
$forumRoutes = new Zend_Controller_Router_Route(
':lang/:module/forum',
array(
'lang' => 'es',
'module' => 'default',
'controller' => 'forum',
'action' => 'index'
)
);
$sectionRoutes = new Zend_Controller_Router_Route(
':lang/:module/forum/:section',
array(
'lang' => 'es',
'module' => 'default',
'controller' => 'forum',
'action' => 'section',
'section' => ''
)
);
$topic = new Zend_Controller_Router_Route(
':lang/:module/forum/:section/:topic',
array(
'lang' => 'es',
'module' => 'default',
'controller' => 'forum',
'action' => 'topic',
'section' => '',
'topic' => ''
)
);
$router->addRoute('forumTopics', $topic);
$router->addRoute('forumSections', $section);
$router->addRoute('forum', $forumRoutes);
Now, this only works if I define the lang and module at uri level, but doesn't work if I defined like => mydomain/forum/section | section/topic. This also brings me another problem with my navigation->menu. If I define "forum" as a static variable at router definition, when I hover over at any label defined at navigatoin.xml, the uri level have the same value for every one of them.
I've tried to make a chain like this:
$forumRoutes = new Zend_Controller_Router_Route(
':lang/:module/forum',
array(
'lang' => 'es',
'module' => 'default',
'controller' => 'forum',
'action' => 'index'
)
);
$section = new Zend_Controller_Router_Route(
':section',
array(
'action' => 'section',
'section' => ''
)
)
$topic = new Zend_Controller_Router_Route(
':topic',
array(
'action' => 'topic',
'topic' => ''
)
)
$chainedRoute = new Zend_Controller_Router_Route_Chain();
$chainedRoute->chain($topic)
->chain($section)
->chain($forumRoutes);
$router->addRoute($chainedRoute);
But this doesn't work as I expected.
Any help would be appreciated, thanks.
You are new to Zend. You said it. So here are some explanations:
Ideally the URL on Zend application is:
example.com/controller/action/param-name/:param-value
So in which case, if there is an action called Edit under UsersController, it will be:
example.com/users/edit
if action is add, it will be :
example.com/users/add
when you specify first parameter as a variable, it will collide with controller requests. Example: if you say controller is User but first parameter accepts a value and puts it in emplyees then a request as example.com/employees and example.com/user will both point towards employees controller even if the usercontroller exists! which again is a theory!
What you might want to do is, leave the routes to only accept dynamic values rather routing! You do not want users to route your application but, route user to different sections of the application.
About language then you need to use Zend_Locale which will check for HTML language that is
<html lang="nl"> or <html lang = "en">
Hope things are clear! :)
Here's a quick example which should help you work with routes like that in ZF.
If you are using a default project structure like the one you get when starting a new project using Zend Tool go into the Application folder.
In your Bootstrap.php set up something like this:
protected function _initRouteBind() {
// get the front controller and get the router
$front = Zend_Controller_Front::getInstance();
$router = $front->getRouter();
// add each custom route like this giving them a descriptive name
$router->addRoute(
'addTheDescriptiveRouteNameHere',
new Zend_Controller_Router_Route(
'/:controller/:id/:action/:somevar',
array(
'module' => 'default',
'controller' => ':controller',
'action' => ':action',
'id' => ':id',
'somevar' => ':somevar'
)
)
);
}
My example above is just to illustrate how you would use a route where the controller, the action and a couple of parameters are set in the url.
The controller and action should be resolved without any additional work however to get the 'id' or 'somevar' value you can do this in your controller:
public function yourAction()
{
// How you get the parameters to pass in to a function
$id = $this->getRequest()->getParam('id');
$somevar = $this->getRequest()->getParam('somevar');
// Using the parameters
$dataYouWant = $this->yourAmazingMethod($id);
$somethingElse = $this->yourOtherAmazingMethod($somevar);
// Assign results to the view
$this->view->data = $dataYouWant;
$this->view->something = $somethingElse;
}
So while you will want to make sure your methods handle the parameters being passed in with care (after all it is user supplied info) this is the principle behind making use of the route parameter binding. You can of course do things like '/site' as the route and have it direct to a CMS module or controller, then another for '/site/:id' where 'id' is a page identifier.
Also just to say a nice alternative to:
$id = $this->getRequest()->getParam('id');
$somevar = $this->getRequest()->getParam('somevar');
which wasn't that nice itself anyway since it was assuming a parameter was going to be passed, using shorthand conditional statement in conjunction with action helpers is:
$id = ($this->_hasParam('id')) ? $this->_getParam('id') : null;
$somevar = ($this->_hasParam('somevar')) ? $this->_getParam('somevar') : null;
If you are not familiar with this, the
($this->_hasParam('id'))
is the conditional test which if true assigns the value of whatever is on the left of the ':' and which if false assigns the value of whatever is on the right of the ':'.
So if true the value assigned would be
$this->_getParam('id')
and null if false.
Does that help? :-D
I have a module-based arhitecture in Zend Framework 1.11 (site.com/module/controller/action).
I've setup my site to have a default module, so that if I have the site module as default, and you go to site.com/something1/something2, it will actually take you to site.com/site/something1/something2.
I want to achieve the same thing 1 level further: say if you go to site.com/something, it should take you to site.com/site/index/something. I'm not talking about a redirect, just a re-routing.
Would something like this be possible?
If I understand correctly, it is possible and here is an example you can put in your Bootstrap:
protected function _initControllerDefaults()
{
$this->bootstrap('frontcontroller');
$front = Zend_Controller_Front::getInstance();
// set default action in controllers to "something" instead of index
$front->setDefaultAction('something');
// You can also override the default controller from "index" to something else
$front->setDefaultControllerName('default');
}
If you need the default action name to be dynamic based on the URL accessed, then I think you are looking for a custom route. In that case try:
protected function _initRoutes()
{
$router = Zend_Controller_Front::getInstance()->getRouter();
// Custom route:
// - Matches : site.com/foo or site.com/foo/
// - Routes to: site.com/site/index/foo
$route = new Zend_Controller_Router_Route_Regex(
'^(\w+)\/?$',
array(
'module' => 'site',
'controller' => 'index',
),
array(1 => 'action')
);
$router->addRoute('actions', $route);
}
In my IndexController, I currently have indexAction (homepage), loginAction and logoutAction. I'm trying to remove "/index/" from the URL to get domain.com/login instead of domain.com/index/login.
What is the cleanest way to achieve this? Is there a RegEx we can use? I don't ever want /index/ in the URL.
My current solution, which I believe can be improved upon, is below. Also, what does the first parameter in addRoute() do?
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initViewHelpers()
{
$front = Zend_Controller_Front::getInstance();
$router = $front->getRouter();
$router->addRoute('login',
new Zend_Controller_Router_Route('login/*', array(
'controller' => 'index',
'action' => 'login'
))
);
$router->addRoute('logout',
new Zend_Controller_Router_Route('logout/*', array(
'controller' => 'index',
'action' => 'logout'
))
);
}
}
There is nothing to impove, you have to create route for every action. This will allow you to change route defaults (module/controller/action) without modifying your code.
First parameter is the route name, which you have to use with url() helper in your views:
Login
Update. You can use such route, if you want only one route without "index" in url:
$router->addRoute('default',
new Zend_Controller_Router_Route(':action/*', array(
'controller' => 'index',
))
);