MongoDB + Doctrine + Zend - php

I'm integrating Zend and Doctrine 2 to work with MongoDB.
I'm using the quickstart skeleton.
Here is the Doctrine.php
<?php
use Doctrine\MongoDB\Connection;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ODM\MongoDB\Mapping\Annotations;
use Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
class Resource_Doctrine extends Zend_Application_Resource_ResourceAbstract
{
protected $_options = array();
private $manager;
public function __set($config, $null) {
$this->_options = array(
'connection' => array(
'dbname' => $config['connection']['dbname'],
),
'modelDir' => $config['modelDir'],
'proxyDir' => $config['proxyDir'],
'proxyNamespace' => $config['proxyNamespace'],
'hydratorDir' => $config['proxyDir'],
'hydratorNamespace' => $config['proxyNamespace'],
'autoGenerateProxyClasses' => $config['autoGenerateProxyClasses']
);
}
public function init()
{
$zendConfig = $this->getOptions();
if(!empty($zendConfig)) Zend_Registry::set('config', $zendConfig);
$options = Zend_Registry::get('config');
$this->__set($options,null);
$config = new \Doctrine\ODM\MongoDB\Configuration;
$config->setDefaultDB($options['connection']['dbname']);
$config->setProxyDir($this->_options['proxyDir']);
$config->setProxyNamespace($this->_options['proxyNamespace']);
$config->setHydratorDir($this->_options['hydratorDir']);
$config->setHydratorNamespace($this->_options['hydratorNamespace']);
$config->setMetadataDriverImpl(AnnotationDriver::create($this->_options['modelDir']));
Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver::registerAnnotationClasses();
$dm = DocumentManager::create(new Connection(), $config);
return $dm;
}
}
The class
<?php
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
/** #ODM\Document */
class Application_Model_Guestbook
{
/**
* #ODM\Id
*/
public $id;
/** #ODM\String */
public $email;
/** #ODM\String */
public $comment;
/** #ODM\Date */
public $created;
public function setGuestbook($comment)
{
$this->email = $comment['email'];
$this->comment = $comment['comment'];
$this->created = date('d-m-Y H:i:s');
}
public function getGuestbook()
{
return $this;
}
}
And the action
public function signAction()
{
$request = $this->getRequest();
$this->getHelper('loadResource')->form('sign', 'Guestbook');
$form = new Application_Form_Guestbook();
if ($this->getRequest()->isPost()) {
if ($form->isValid($request->getPost())) {
$guestbook = new Application_Model_Guestbook;
$guestbook->setGuestbook($form->getValues());
try
{
$this->em->persist($guestbook);
$this->em->flush($guestbook);
return $this->_helper->redirector('index');
}
catch (Exception $e)
{
throw new Exception($e);
}
}
}
$this->view->form = $form;
}
I'm geting the error: Catchable fatal error: Argument 3 passed to Doctrine\ODM\MongoDB\Hydrator\HydratorFactory::hydrate() must be of the type array, null given, called in /home/gabiru/www/twitradar_mongo/library/Doctrine/ODM/MongoDB/UnitOfWork.php on line 2518
I've searched and don't find any result of anyone with the same problem, anyone have any idea about it?
The 3rd argument is the variable $hint, and I don't know where the argument is set.

Related

How do you set up Session Namespaces?

I'm fairly new to Zend and I am trying to set a session namespace variable. I am receiving an error message stating "Configuration is missing a "session_config" key, or the value of that key is not an array".
I've followed the documentation provided by Zend on the subject but I'm coming up a bit short on how it all ties together.
I've configured the session manager in the global config file as follows:
'session_manager' => [
'config' => [
'class' => Session\Config\SessionConfig::class,
'options' => [
'name' => 'user',
],
],
'storage' => Session\Storage\SessionArrayStorage::class,
'validators' => [
Session\Validator\RemoteAddr::class,
Session\Validator\HttpUserAgent::class,
],
],
I created the session manager in the Module class as follows
use Zend\Session\SessionManager;
use Zend\Session\Config\SessionConfig;
use Zend\Session\Container;
use Zend\Session\Validator;
use Zend\Mvc\ModuleRouteListener;
class Module implements ConfigProviderInterface
{
public function onBootstrap($e)
{
$eventManager = $e->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
$this->bootstrapSession($e);
}
public function bootstrapSession($e)
{
$session = new SessionManager();
$session->start();
$container = new Container('initialized');
if (isset($container->init)) {
return;
}
$serviceManager = $e->getApplication()->getServiceManager();
$request = $serviceManager->get('Request');
$session->regenerateId(true);
$container->init = 1;
$container->remoteAddr = $request->getServer()->get('REMOTE_ADDR');
$container->httpUserAgent = $request->getServer()->get('HTTP_USER_AGENT');
$config = $serviceManager->get('Config');
if (! isset($config['session'])) {
return;
}
$sessionConfig = $config['session'];
if (! isset($sessionConfig['validators'])) {
return;
}
$chain = $session->getValidatorChain();
foreach ($sessionConfig['validators'] as $validator) {
switch ($validator) {
case Validator\HttpUserAgent::class:
$validator = new $validator($container->httpUserAgent);
break;
case Validator\RemoteAddr::class:
$validator = new $validator($container->remoteAddr);
break;
default:
$validator = new $validator();
}
$chain->attach('session.validate', array($validator, 'isValid'));
}
}
public function getServiceConfig()
{
return [
'factories' => [
SessionManager::class => function ($container) {
$config = $container->get('config');
if (! isset($config['session'])) {
$sessionManager = new SessionManager();
Container::setDefaultManager($sessionManager);
return $sessionManager;
}
$session = $config['session'];
$sessionConfig = null;
if (isset($session['config'])) {
$class = isset($session['config']['class'])
? $session['config']['class']
: SessionConfig::class;
$options = isset($session['config']['options'])
? $session['config']['options']
: [];
$sessionConfig = new $class();
$sessionConfig->setOptions($options);
}
$sessionStorage = null;
if (isset($session['storage'])) {
$class = $session['storage'];
$sessionStorage = new $class();
}
$sessionSaveHandler = null;
if (isset($session['save_handler'])) {
// class should be fetched from service manager
// since it will require constructor arguments
$sessionSaveHandler = $container->get($session['save_handler']);
}
$sessionManager = new SessionManager(
$sessionConfig,
$sessionStorage,
$sessionSaveHandler
);
Container::setDefaultManager($sessionManager);
return $sessionManager;
},
],
];
}
I defined the session container namespace in the module.config.php file as follows:
'session_containers' => [
'UserNamespace'
],
I try to access the namespace in the factory of the controller as follows:
namespace User\Factory;
use Interop\Container\ContainerInterface;
use Zend\Authentication\AuthenticationService;
use Zend\ServiceManager\Factory\FactoryInterface;
use Zend\Session\Container;
use User\Controller\AuthController;
use User\Model\UserRepositoryInterface;
use User\Form\LoginForm;
class AuthControllerFactory implements FactoryInterface
{
/**
* #param ContainerInterface $container
* #param string $requestedName
* #param null|array $options
* #return AuthController
*/
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$formManager = $container->get('FormElementManager');
$sessionContainer = $container->get('UserNamespace');
return new AuthController(
$container->get(UserRepositoryInterface::class),
$formManager->get(LoginForm::class),
$sessionContainer
);
}
}
And finally I try to call the session namespace variable in the controller as follows:
namespace User\Controller;
use User\Form\LoginForm;
use User\Model\User;
use User\Model\UserRepositoryInterface;
use Zend\Session\Container;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class AuthController extends AbstractActionController
{
/**
* #var UserRepositoryInterface
*/
private $userRepository;
/**
* #var LoginForm
*/
private $loginForm;
private $sessionContainer;
/**
* #param UserRepositoryInterface $userRepository
* #param LoginForm $loginForm
*/
public function __construct(
UserRepositoryInterface $userRepository,
LoginForm $loginForm,
$sessionContainer
) {
$this->userRepository = $userRepository;
$this->loginForm = $loginForm;
$sessionContainer;
}
public function loginAction()
{
$request = $this->getRequest();
$viewModel = new ViewModel(['form' => $this->loginForm]);
if (! $request->isPost()) {
return $viewModel;
}
$this->loginForm->setData($request->getPost());
if (! $this->loginForm->isValid()) {
return $viewModel;
}
$loginAttempt = $this->loginForm->getData();
// var_dump($loginAttempt); die;
try {
$user = $this->userRepository->retrieveUserByUsername($loginAttempt['username']);
} catch (\Exception $ex) {
throw $ex;
}
// var_dump($user); die;
try {
$isLogin = $this->userRepository->validatePassword($user, $loginAttempt['password']);
} catch (\Exception $ex) {
throw $ex;
}
// var_dump($isLogin); die;
if($isLogin == true) {
$sessionContainer->test = "This is a test";
}
var_dump($sessionContainer->test); die;
}
I'm sure I'm a bit mixed up on my execution to make this work so any assistance or advice you can provide will be greatly appreciated.

ZF3: How to get view of an action from another action in the controller?

In my controller action, I want to grap a rendered full page of another action:
class MycontrollerController extends AbstractActionController
{
public function firstactionAction()
{
$html = some_function_to_get_the_rendered_page_of_secondaction();
}
public function secondactionAction()
{
return new ViewModel();
}
}
Be careful to use setTemplate()
MycontrollerControllerFactory.php
<?php
namespace Application\Controller\Service;
use Application\Controller\MycontrollerController;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
class MycontrollerControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$controller = new MycontrollerController();
$controller->setRenderer($container->get('Zend\View\Renderer\PhpRenderer'));
return $controller;
}
}
MycontrollerController.php
<?php
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class MycontrollerController extends AbstractActionController
{
/**
* #var \Zend\View\Renderer\PhpRenderer
*/
protected $renderer;
/**
* #return \Zend\View\Renderer\PhpRenderer
*/
public function getRenderer()
{
return $this->renderer;
}
/**
* #param \Zend\View\Renderer\PhpRenderer $renderer
* #return self
*/
public function setRenderer($renderer)
{
$this->renderer = $renderer;
return $this;
}
public function firstAction()
{
if ($this->yourMethod()) {
$secondView = $this->secondAction();
$html = $this->getRenderer()->render($secondView);
}
$view = new ViewModel();
$view->setTemplate('namespace/my-controller/first');
return $view;
}
public function secondAction()
{
$view = new ViewModel();
$view->setTemplate('namespace/my-controller/second');
return $view;
}
}
So, I suggest to create a new plugin 'htmlRender' :
module.config.php
'controller_plugins' => [
'factories' => [
'htmlRender' => Application\Mvc\Controller\Plugin\Service\HtmlRenderFactory::class,
],
],
HtmlRenderFactory.php
<?php
namespace Application\Mvc\Controller\Plugin\Service;
use Application\Mvc\Controller\Plugin\HtmlRender;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
use Zend\View\Renderer\PhpRenderer;
class HtmlRenderFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$plugin = new HtmlRender();
$plugin->setRenderer($container->get(PhpRenderer::class));
return $plugin;
}
}
HtmlRender.php
<?php
namespace Application\Mvc\Controller\Plugin;
use Zend\Mvc\Controller\Plugin\AbstractPlugin;
use Zend\View\Renderer\RendererInterface;
class HtmlRender extends AbstractPlugin
{
/**
* #var \Zend\View\Renderer\PhpRenderer
*/
protected $renderer;
/**
* #param string|\Zend\View\Model\ModelInterface $nameOrModel
* #param null|array|\Traversable $values
* #param string|bool|\Zend\View\Model\ModelInterface $layout
* #return string
*/
public function __invoke($nameOrModel, $values = null, $layout = false)
{
$content = $this->getRenderer()->render($nameOrModel, $values);
if (!$layout) {
return $content;
}
if (true === $layout) {
$layout = 'layout/layout';
}
return $this->getRenderer()->render($layout, [
'content' => $content,
]);
}
/**
* #return \Zend\View\Renderer\PhpRenderer
*/
public function getRenderer()
{
return $this->renderer;
}
/**
* #param \Zend\View\Renderer\PhpRenderer|RendererInterface $renderer
* #return self
*/
public function setRenderer(RendererInterface $renderer)
{
$this->renderer = $renderer;
return $this;
}
}
Use in the MycontrollerController.php
<?php
class MycontrollerController extends AbstractActionController
{
public function firstAction()
{
if ($this->yourMethod()) {
// Option 1 without layout
$html = $this->htmlRender($secondView);
// Option 2 without layout
$html = $this->htmlRender('namespace/my-controller/second', $yourVariables));
// Option 1 with layout
$html = $this->htmlRender($secondView, null, true);
//$html = $this->htmlRender($secondView, null, 'layout/my-custom-layout');
// Option 2 with layout
$html = $this->htmlRender('namespace/my-controller/second', $yourVariables, true));
//$html = $this->htmlRender('namespace/my-controller/second', $yourVariables, 'layout/my-custom-layout');
}
$view = new ViewModel();
$view->setTemplate('namespace/my-controller/first');
return $view;
}
public function secondAction()
{
$view = new ViewModel();
$view->setTemplate('namespace/my-controller/second');
return $view;
}
}

ZF - Doctrine2 Cannot Retrieve Repository

whats this wrong with this? I'm new in zend framework...........................................................................................................................
this is my folder struct
UserControllerFactory.php
<?php
namespace Admin\Controller\Factory;
use Admin\Controller\UserController;
use User\Entity\User;
use Admin\Form\UserForm;
use User\Model\UserTable;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\Entity;
use Interop\Container\ContainerInterface;
class UserControllerFactory
{
public function __invoke(ContainerInterface $container)
{
/** #var EntityManager $entityManager */
$entityManager = $container->get(EntityManager::class);
$repository = $entityManager->getRepository(User::class);
$userForm = $container->get(UserForm::class);
return new UserController($entityManager, $repository, $userForm);
}
}
UserController.php
<?php
namespace Admin\Controller;
//use User\Entity\User;
use Admin\Form\UserForm;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
use Zend\Hydrator\ClassMethods;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\Http\Request;
use Zend\View\Model\ViewModel;
class UserController extends AbstractActionController
{
/**
* #var EntityRepository
*/
private $repository;
/**
* #var EntityManager
*/
private $entityManager;
private $form;
public function __constructor(EntityManager $entityManager, EntityRepository $repository, UserForm $form){
$this->form = $form;
$this->repository = $repository;
$this->entityManager = $entityManager;
}
public function indexAction()
{
return new ViewModel([
'users' => $this->repository->fetchAll()
]);
}
public function addAction()
{
$form = $this->form;
$form->get('submit')->setValue('Adicionar');
$request = $this->getRequest();
if (!$request->isPost()) {
return ['form' => $form];
}
$form->setData($request->getPost());
if (!$form->isValid()) {
return ['form' => $form];
}
$post = $form->getData();
$this->entityManager->persist($post);
$this->entityManager->flush();
return $this->redirect()->toRoute('admin/user');
}
public function editAction()
{
$id = (int)$this->params()->fromRoute('id', 0);
if (!$id || !($post = $this->repository->find($id))) {
return $this->redirect()->toRoute('admin/user');
}
$form = $this->form;
$form->bind($post);
$form->get('submit')->setAttribute('value', 'Edit Post');
$request = $this->getRequest();
if (!$request->isPost()) {
return [
'id' => $id,
'form' => $form
];
}
$form->setData($request->getPost());
if (!$form->isValid()) {
return [
'id' => $id,
'form' => $form
];
}
$this->entityManager->flush();
return $this->redirect()->toRoute('admin/user');
}
public function deleteAction()
{
$id = (int)$this->params()->fromRoute('id', 0);
if (!$id || !($post = $this->repository->find($id))) {
return $this->redirect()->toRoute('admin/user');
}
$this->entityManager->remove($post);
$this->entityManager->flush();
return $this->redirect()->toRoute('admin/user');
}
}
UserTable.php
<?php
/**
* Created by PhpStorm.
* User: jho
* Date: 24/06/2017
* Time: 18:55
*/
namespace User\Model\Factory;
use Zend\Db\Exception\RuntimeException;
use Zend\Db\TableGateway\TableGatewayInterface;
class UserTable
{
private $tableGateway;
public function find($id)
{
$id = (int)$id;
$rowset = $this->tableGateway->select(['id' => $id]);
$row = $rowset->current();
if (!row) {
throw new RuntimeException(sprintf(
'Could not retrieve the row %d', $id
));
}
return $row;
}
public function fetchAll(){
return $this->tableGateway->select();
}
public function save(User $user){
$data = [
'username'=>$user->username,
'fullname'=>$user->fullname,
'password'=>$user->password,
];
$id = (int) $user->id;
if((int)$user->id === 0){
$this->tableGateway->insert($data);
return;
}
if(!$this->find($id)){
throw new RuntimeException(sprintf(
'Could not retrieve the row %d', $id
));
}
$this->tableGateway->update($data, ['id'=>$id]);
}
}
User.php
<?php
namespace User\Model;
class User
{
public $id;
public $fullname;
public function exchangeArray(array $data){
$this->id = (!empty($data['id'])) ? $data['id']: null;
$this->title = (!empty($data['fullname'])) ? $data['fullname']: null;
}
public function getArrayCopy(){
return[
'id'=>$this->id,
'fullname'=>$this->fullname,
];
}
}
You are mixing up two different approaches of retrieving data from your database.
You can either use the Zend approach as in TableGateway's or you can go with Doctrine (EntityManager/Repositories).
So you've got to make a choice between one of the methods you want to use within your controller.
So if you want to stick with Doctrine, you could take a look at the following slides of Ocramius: http://ocramius.github.io/presentations/doctrine-orm-and-zend-framework-2/#/59
So you pretty much have to update your User model:
namespace User\Model;
use Doctrine\ORM\Mapping AS ORM;
/**
* #ORM\Entity()
*/
class User
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
public $id;
/** #ORM\Column(type="string") */
public $fullname;
public function exchangeArray(array $data){
$this->id = (!empty($data['id'])) ? $data['id']: null;
$this->title = (!empty($data['fullname'])) ? $data['fullname']: null;
}
public function getArrayCopy(){
return[
'id'=>$this->id,
'fullname'=>$this->fullname,
];
}
}
Update the following file module.config.php of your User module and add the following to your configuration:
array(
'doctrine' => array(
'driver' => array(
'application_entities' => array(
'class' =>'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(__DIR__ . '/../src/User/Model')
),
'orm_default' => array(
'drivers' => array(
'User\model' => 'application_entities'
)
),
)
),
Notice that this requires the Doctrine-ORM-module. See: https://github.com/doctrine/DoctrineORMModule

How do mock for viewHelper in zf2

I'm trying to do mock for viewHelper and can't do this.
When I am trying to run phpunit I get the assert error "Failed asserting that two strings are equal." because the analiticHelper hasn't been overwriten. I wrote setAllowOverride(true) for my ServiseManager, but this didn't help.
Could you please tell me how can I do mock for viewHelper in Zend Framework 2?
I will appreciate your time and help!
Thanks!
# module\Application\test\Controller\IndexControllerTest.php
<?php
namespace ApplicationTest\Controller;
use Application\Controller\IndexController;
use PHPUnit_Framework_TestCase as TestCase;
use ApplicationTest\Bootstrap;
class HttpTest extends TestCase {
/**
* #var IndexController
*/
// private $indexController;
protected $traceError = false;
public function setUp() {
$this->sm = Bootstrap::getServiceManager();
$this->em = $this->sm->get('Doctrine\ORM\EntityManager');
}
public function testAction() {
$mockAnaliticHelper = $this->getMockBuilder(\Application\View\Helper\AnaliticHelper::class)
->disableOriginalConstructor()
->disableOriginalClone()
->disableArgumentCloning()
->disallowMockingUnknownTypes()
->getMock();
$mockAnaliticHelper->method('getKey')
->willReturn('some-value');
$this->assertEquals('some-value', $mockAnaliticHelper->getKey()); // it's ok
$this->sm->setAllowOverride(true);
$this->sm->setService('analiticHelper', $mockAnaliticHelper); // before
$viewHelperManager = $this->sm->get('ViewHelperManager');
$analiticHelper = $viewHelperManager->get('analiticHelper');
$this->sm->setService('analiticHelper', $mockAnaliticHelper); // after
$key = $analiticHelper->getKey(); // return 'web'
$this->assertEquals('some-value', $analiticHelper->getKey()); // return error
}
}
# Module.php
<?php
....
public function getViewHelperConfig()
{
return array(
'factories' => array(
...,
'analiticHelper' => function($sm){
$locator = $sm->getServiceLocator();
$config = $locator->get('config');
$em = $locator->get('Doctrine\ORM\EntityManager');
$viewHelper = new \Application\View\Helper\AnaliticHelper($em, $locator, $config);
return $viewHelper;
},
),
);
}
# module\Application\src\Application\View\Helper\AnaliticHelper.php
<?php
namespace Application\View\Helper;
use Zend\View\Helper\HelperInterface;
use Zend\View\Renderer\RendererInterface as Renderer;
use Doctrine\ORM\EntityManager;
use ZfcUser\Entity\UserInterface;
use Zend\Session\Container;
class AnaliticHelper implements \Zend\View\Helper\HelperInterface{
protected $_em;
protected $_serviceLocator;
protected $_config;
const SESSION_CONTANIER = 'analitic';
const SESSION_KEY = 'analiticKey';
const DEFAULT_KEY = 'web';
public function __construct(EntityManager $em, $serviceLocator, $config) {
$this->_em = $em;
$this->_serviceLocator = $serviceLocator;
$this->_config = $config;
$router = $this->_serviceLocator->get('router');
$request = $this->_serviceLocator->get('request');
$this->routeMatch = $router->match($request);
}
public function __invoke(){
return $this;
}
public function getKey(){
// some actions
return self::DEFAULT_KEY;
}
/**
* Set the View object
*
* #param Renderer $view
* #return HelperInterface
*/
public function setView(Renderer $view)
{
$this->view = $view;
return $this;
}
/**
* Get the View object
*
* #return Renderer
*/
public function getView()
{
return $this->view;
}
}

ZF2 getServiceLocator in ControllerPlugin class

I am trying to get service locator/entity manager in plugin class, How can I get that.
In my controller I am getting it like this.
public function getEntityManager()
{
if(null === $this->em){
$this->em = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default');
}
return $this->em;
}
public function setEntityManager(EntityManager $em)
{
$this->em = $em;
}
but in plugin class I am getting error on $this->getServiceLocator() line. because this is not available in plugin class.
How can I do the same so that I can fetch some records and insert few in database in plugin.
I do have MvcEvent $e object in my plugin class, I can make use of this to get entity manager?
I have used this plugin to create my plugin
Any guide will be appriciated.
update:
namespace Auth\Controller\Plugin;
use Zend\Mvc\Controller\Plugin\AbstractPlugin;
use Zend\EventManager\EventInterface as Event;
use Zend\Authentication\AuthenticationService;
use Doctrine\ORM\EntityManager;
use Auth\Entity\User;
use Zend\Mvc\MvcEvent;
class AclPlugin extends AbstractPlugin
{
/*
* #var Doctrine\ORM\EntityManager
*/
protected $em;
public function checkAcl($e)
{
$auth = new AuthenticationService();
if ($auth->hasIdentity()) {
$storage = $auth->getStorage()->read();
if (!empty($storage->role))
$role = strtolower ( $storage->role );
else
$role = "guest";
} else {
$role = "guest";
}
$app = $e->getParam('application');
$acl = new \Auth\Acl\AclRules();
$matches = $e->getRouteMatch();
$controller = $matches->getParam('controller');
$action = $matches->getParam('action', 'index');
$resource = strtolower( $controller );
$permission = strtolower( $action );
if (!$acl->hasResource($resource)) {
throw new \Exception('Resource ' . $resource . ' not defined');
}
if ($acl->isAllowed($role, $resource, $permission)) {
$query = $this->getEntityManager($e)->createQuery('SELECT u FROM Auth\Entity\User u');
$resultIdentities = $query->execute();
var_dump($resultIdentities);
exit();
return;
} else {
$matches->setParam('controller', 'Auth\Controller\User'); // redirect
$matches->setParam('action', 'accessdenied');
return;
}
}
public function getEntityManager($e) {
var_dump($this->getController()); // returns null
exit();
if (null === $this->em) {
$this->em = $this->getController()->getServiceLocator()->get('doctrine.entitymanager.orm_default');
}
return $this->em;
}
public function setEntityManager(EntityManager $em) {
$this->em = $em;
}
}
I am calling above class in module.php
public function onBootstrap(Event $e)
{
$application = $e->getApplication();
$services = $application->getServiceManager();
$eventManager = $e->getApplication()->getEventManager();
$eventManager->attach('dispatch', array($this, 'loadConfiguration'),101);
}
public function loadConfiguration(MvcEvent $e)
{
$e->getApplication()->getServiceManager()
->get('ControllerPluginManager')->get('AclPlugin')
->checkAcl($e); //pass to the plugin...
}
I am registering this plugin in module.config.php
return array(
'controllers' => array(
'invokables' => array(
'Auth\Controller\User' => 'Auth\Controller\UserController',
),
),
'controller_plugins' => array(
'invokables' => array(
'AclPlugin' => 'Auth\Controller\Plugin\AclPlugin',
),
),
);
What do you mean with "Plugin Class"? In case you're talking abount controller plugins, you can access it using (from the controller plugin's scope): $this->getController()->getServiceLocator()->get('doctrine.entitymanager.orm_default');.
For other classes, I usually create a factory that injects the ServiceManager instance automatically. For example, in the Module class:
public function getServiceConfig()
{
return array(
'factories' => array(
'myServiceClass' => function(ServiceManager $sm) {
$instance = new Class();
$instance->setServiceManager($sm);
// Do some other configuration
return $instance;
},
),
);
}
// access it using the ServiceManager where you need it
$myService = $sm->get('myService');
changed the above AclPlugin class as below
namespace Auth\Controller\Plugin;
use Zend\Mvc\Controller\Plugin\AbstractPlugin;
use Zend\EventManager\EventInterface as Event;
use Zend\Authentication\AuthenticationService;
use Doctrine\ORM\EntityManager;
use Auth\Entity\User;
use Zend\Mvc\MvcEvent;
use Zend\ServiceManager\ServiceManagerAwareInterface;
use Zend\ServiceManager\ServiceManager;
class AclPlugin extends AbstractPlugin implements ServiceManagerAwareInterface
{
/*
* #var Doctrine\ORM\EntityManager
*/
protected $em;
protected $sm;
public function checkAcl($e)
{
$this->setServiceManager( $e->getApplication()->getServiceManager() );
$auth = new AuthenticationService();
if ($auth->hasIdentity()) {
$storage = $auth->getStorage()->read();
if (!empty($storage->role))
$role = strtolower ( $storage->role );
else
$role = "guest";
} else {
$role = "guest";
}
$app = $e->getParam('application');
$acl = new \Auth\Acl\AclRules();
$matches = $e->getRouteMatch();
$controller = $matches->getParam('controller');
$action = $matches->getParam('action', 'index');
$resource = strtolower( $controller );
$permission = strtolower( $action );
if (!$acl->hasResource($resource)) {
throw new \Exception('Resource ' . $resource . ' not defined');
}
if ($acl->isAllowed($role, $resource, $permission)) {
$query = $this->getEntityManager($e)->createQuery('SELECT u FROM Auth\Entity\User u');
$resultIdentities = $query->execute();
var_dump($resultIdentities);
foreach ($resultIdentities as $r)
echo $r->username;
exit();
return;
} else {
$matches->setParam('controller', 'Auth\Controller\User'); // redirect
$matches->setParam('action', 'accessdenied');
return;
}
}
public function getEntityManager() {
if (null === $this->em) {
$this->em = $this->sm->getServiceLocator()->get('doctrine.entitymanager.orm_default');
}
return $this->em;
}
public function setEntityManager(EntityManager $em) {
$this->em = $em;
}
/**
* Retrieve service manager instance
*
* #return ServiceManager
*/
public function getServiceManager()
{
return $this->sm->getServiceLocator();
}
/**
* Set service manager instance
*
* #param ServiceManager $locator
* #return void
*/
public function setServiceManager(ServiceManager $serviceManager)
{
$this->sm = $serviceManager;
}
}
Actually getting ServiceManager in controller plugin is quite easy!
Just use: $this->getController()->getServiceLocator()
Example:
namespace Application\Controller\Plugin;
use Zend\Mvc\Controller\Plugin\AbstractPlugin;
class Translate extends AbstractPlugin
{
public function __invoke($message, $textDomain = 'default', $locale = null)
{
/** #var \Zend\I18n\Translator\Translator $translator */
$translator = $this->getController()->getServiceLocator()->get('translator');
return $translator->translate($message, $textDomain, $locale);
}
}

Categories