How to share zfcuser across subdomain in zend framework 2 - zend-framework2

I have in my application installed zfcuser module and everything works fine. I configured hostname router and here my problem starts, when I log in on main domain (http://example.com) everything is ok, but when I go to any subdomain (http://test.example.com, http://anysubdomain.example.com) I'm loosing logged state and on every subdomain I have to login again. How to share login state across subdomains? In ZF1 i just set 'cookie_domain' and it works but how make it in ZF2? Of course I'm using also Bjyauthorize and I want to keep bjyauthorize guards on subdomains...

Ok I found solution, in ZfcUser Module.php I've added:
use Zend\Session\Config\SessionConfig;
use Zend\Session\SessionManager;
use Zend\Session\Container;
use Zend\EventManager\EventInterface;
public function onBootstrap(EventInterface $e)
{
$config = $e->getApplication()
->getServiceManager()
->get('Configuration');
$sessionConfig = new SessionConfig();
$sessionConfig->setOptions($config['session']);
$sessionManager = new SessionManager($sessionConfig);
$sessionManager->start();
Container::setDefaultManager($sessionManager);
}
and in ZfcUser module.config.php:
return array(
'session' => array(
'use_cookies' => true,
'cookie_domain'=>'example.com',
)
);
Hope it will help somebody.

Related

ZF2 resolver could not resolve to a file (but works on development environment)

I've gone through the other similar questions on here and have tried numerous things though to no avail.
I have a dashboard controller that works correctly on my development machine, though when it is uploaded to the production server it reports:
Zend\View\Renderer\PhpRenderer::render: Unable to render template "Dashboard\Dashboard\Index"; resolver could not resolve to a file
I've checked my module.config.php file for the view-template (and it's correctly listed on there)
'template_path_stack' => array(
'dashboard' => __DIR__ . '/../view',
),
And the file is also at that physical location...
I'm not sure what I am missing in terms of this, so any pointers would be great.
UPDATE:
Here is the code for the controller:
public function indexAction() {
//check the users authenticity
$userId = null;
$auth = $this->getServiceLocator()->get('zfcuser_auth_service');
if ($auth->hasIdentity()) {
$user = $auth->getIdentity();
$userId = $user->getId();
} else {
$this->redirect()->toUrl('/user/login');
}
//set the view model to improve performance
//http://samminds.com/2012/11/zf2-performance-quicktipp-1-viewmodels/
$viewModel = new ViewModel();
$viewModel->setTemplate('Dashboard\Dashboard\Index');
//return the amount of counts the various items have outstanding
$dbAdapter = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter');
$systemRepo = $this->getSystemRepo($dbAdapter);
$internalContacts = $systemRepo->widgetAlphabetList("Internal Contacts", $systemRepo->getInternalContacts(), 'firstname', 'surname');
return $viewModel->setVariables(array(
'internalContacts' => $internalContacts
));
}
And the full path to the file is (add index.phtml on the end of the below):
/var/www/html/module/Dashboard/view/dashboard/dashboard
I'm going to guess dev machine is not a case sensitive file system and prod is case sensitive. Try this:
$viewModel->setTemplate('dashboard/dashboard/index')

zf2 how to use 3rd party module in my own specific module (based on route)?

I'm developping a website by ZendFramework 2. I have 2 modules: module for administration called Administration(route defined like www.mysite.com/admin/...) et module public site called Application(route defined like www.mysite.com/...) I distinguish the 2 modules by the route.
I don't know how to distinguish the two modules based on route.
To make it clear, I have 2 questions for example:
I use Zfcuser for the login system for the module Administration et in Administration/Module.php I added the following code to the purpose that if one user doesn't have identity the layout will change to the login form.
namespace Administration;
use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
class Module {
public function onBootstrap(MvcEvent $e) {
$eventManager = $e->getApplication ()->getEventManager ();
$moduleRouteListener = new ModuleRouteListener ();
$moduleRouteListener->attach ( $eventManager );
$eventManager->attach('dispatch', array($this, 'checkLoginChangeLayout'));
}
public function checkLoginChangeLayout(MvcEvent $e) {
if (! $e->getApplication ()->getServiceManager ()->get ( 'zfcuser_auth_service' )->hasIdentity ()) {
$controller = $e->getTarget ();
$controller->layout ( 'layout/authentication.phtml' );
}
}
public function getConfig() {
return include __DIR__ . '/config/module.config.php';
}
public function getAutoloaderConfig() {
return array (
'Zend\Loader\StandardAutoloader' => array (
'namespaces' => array (
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__
)
)
);
}
}
But all the 2 modules are affected by the function checkLoginChangeLayout(). I want to use the module ZfcUser just in the module Administration but not the module Application.
Can I do something about the Module Manager or Event Manager to solve the problem?
I've found a 3rd party module called BjyAuthorize which is used for ACL by "guard". When I active the module in application.config.php , all my 2 modules are controlled by it. But I just want to use the 3rd party module in the module Administration but not the other modules.
your first approach is fail
because (as you found) there is another module for doing such a thing called BJYAUTHORIZE
it has a config for allowing different type of users access which controller/action/module/route/...
plz review it's documentation for more information and also there is a blog post for How to join ZFCUser and BJY together .
http://samminds.com/2013/03/zfcuser-bjyauthorize-and-doctrine-working-together/

How to make a layout dependent on the domain, and not on the module?

I have an application in which there are several sub-domains. I redirect to modules based on domains. Each module have a different layout. Is based on evandotpro/edp-module-layouts :
public function onBootstrap($e)
{
$e->getApplication()->getEventManager()->getSharedManager()->attach('Zend\Mvc\Controller\AbstractActionController', 'dispatch', function($e) {
...
...
In addition i have authentication module - it is global.
client.app.com/auth/login
handheld.app.com/auth/login
are associated with the same module
However, I would keep the layout of the module associated with the domain.
Of course I have an idea for a couple of hacks that solve this problem, but I'm interested in whether there is any "clean" solution.
Dirty hack that i used.:
I have module Terminal with own layout. And conected with own
domain ( route type Zend\Mvc\Router\Http\Hostname )
for example http://termina.example.com/
and I have module Auth that add authorization in whole
application and redirect to login page
so when not authorized uset try to acces to terminal module is redirect to:
http://terminal.example.com/login (route connected with Auth module)
So to force Terminal layout in that situation I add Terminal Module.php:
public function onBootstrap(MvcEvent $e)
{
$e->getApplication()->getEventManager()->getSharedManager()->attach('Zend\Mvc\Controller\AbstractActionController', 'dispatch', function($e) {
$controller = $e->getTarget();
$controllerClass = get_class($controller);
$moduleNamespace = substr($controllerClass, 0, strpos($controllerClass, '\\'));
if ($_SERVER['HTTP_HOST'] ==
$e->getApplication()->getServiceManager()->get('config')['router']['routes']['terminal']['options']['route']
&& $moduleNamespace=='Auth') {
$controller->layout('layout/terminal');
}
}, 1);
}
and, as always, sorry for my english...

ZF2 - Injecting pages to navigation before controller is called

I'm creating a dynamic Application in which the content is added through a CMS. Inside the CMS, I'm setting a db entry which states what module to use for each content page.
NodeId,
ParentNodeId,
Name_de,
Name_en,
ModuleName,
foreignkey_ContentLinks,
in this table entries look as follows:
6,
1,
Veranstaltung-21-02-2013,
Event-21-02-2013,
Events,
682
The entire tree should end up in my navigation (and perfectly also in my routing). I do not want to add it in some controller, because my Application consists of a whole bunch of Modules and I want to access that Info across all my Modules.
I already tried injecting it in the global.php, but to no avail because I can't my db adapter or any other important classes at that stage.
Any ideas or links to best practices?
The navigation containers are composed by factory classes. The easiest approach is to write your own factory and have the getPages() method fetch pages from a database instead of from config. If you extend from the AbstractNavigationFactory you only need to write a couple of methods.
<?php
namespace Application\Navigation\Service;
use Zend\Navigation\Service\AbstractNavigationFactory;
use Zend\ServiceManager\ServiceLocatorInterface;
class CmsNavigationFactory extends AbstractNavigationFactory
{
/**
* #param ServiceLocatorInterface $serviceLocator
* #return array
* #throws \Zend\Navigation\Exception\InvalidArgumentException
*/
protected function getPages(ServiceLocatorInterface $serviceLocator)
{
if (null === $this->pages) {
$application = $serviceLocator->get('Application');
$routeMatch = $application->getMvcEvent()->getRouteMatch();
$router = $application->getMvcEvent()->getRouter();
// get your pages from wherever...
$pages = $this->getPagesFromDB();
$this->pages = $this->injectComponents($pages, $routeMatch, $router);
}
return $this->pages;
}
public function getName()
{
// this isn't used if fetching from db, it's just here to keep the abstract factory happy
return 'cms';
}
}
Add the factory to the service manager, just like you would for other containers
'service_manager' => array(
'factories' => array(
'CmsNavigation' => 'Application\Navigation\Service\CmsNavigationFactory',
),
),
And use it with the navigation view helpers in the same way
<?php echo $this->navigation()->menu('CmsNavigation'); ?>
Responding to your comment on #Crisp's answer, and for future googlers, I'll explain how to do something similar for routing.
Typically you would want to create a custom router that can match URLs to the pages in your database, similarly to the standard Segment router. To do this, you will have to implement the Zend\Mvc\Router\RouteInterface interface. For example:
namespace Application\Router;
use Zend\Mvc\Router\RouteInterface;
use Application\Model\CMSTable;
class CmsRoute implements RouteInterface, ServiceLocatorAwareInterface
{
protected $table;
// Service locator injection code
public function getCmsTable()
{
// Retrieve the table from the service manager
}
public function match(Request $request)
{
// Match the request on some route field, etc.
}
public function assemble(array $params = array(), array $options = array())
{
// Assemble a URL based on the given parameters (e.g. page ID).
}
public static function factory($options = array())
{
// Construct a new route, based on the options.
}
}
You could then register this route as an invokable for the RoutePluginManager in your module configuration:
'route_manager' => array(
'invokables' => array(
'Cms' => 'Application\Router\CmsRoute'
),
),
Then, you can create a new route (just as you would for any other route) with type Cms. The route plugin manager will create your route instance, and since CmsRoute implements ServiceLocatorAwareInterface, the plugin manager will inject itself in the route. In turn, the plugin manager has the main service manager set, so that you can get the database table from there!
Of course you can match on page ID, but if you have a hierarchical structure, it's nicer to reflect that in your URLs. I would therefore recommend adding a route field to the database schema and match on that, beginning with the tree root and working down.

Zend Framework 2 - Hide login link when logged in and vice versa for logout

I'm pretty new to ZF2 and I'm trying to find a simple way to allow the login link to be hidden within the view a user has been logged in, and show it again when the user logs out. I have taken a look at ZF2's ACL examples, but I am still a little confused and I am unsure if this is actually what is needed to achieve such a simple thing.
If somebody could share some knowledge on how this is done, I would be eternally greatful. Thank you
The standard Identity view helper that can help you with this. This will work out of the box if you add your authentication service to the service manager, for instance in your module's config/module.config.php like this:
/* Some configuration omitted */
return array(
'service_manager' => array(
'Zend\Authentication\AuthenticationService' => function($sm) {
$authService = new \Zend\Authentication\AuthenticationService();
$authService->setStorage(new \Zend\Authentication\Storage\Session('user', 'details'));
return $authService;
},
),
);
Then you can do like this in your view script:
if ($this->identity() == null) {
// User is not logged in; show login link here
}
else {
// User is logged in; show profile link here or do nothing
}

Resources