How to access config from local.php - php

I am moving my old password encrypt class from ZF1 to ZF2. In my original code I used the zend registry to store the encryption salt value pulled from the application.ini file. In ZF2 the logical place for this setting to go would be the local.php file in config/autoload folder.
My question is how do I access the salt setting specified in the local.php file?
I have tried
$this->getServiceLocator()->get('Config');
but all this does is produce the error
Call to a member function get() on a non-object
in C:\Users\Garry Childs\Documents\My Webs\freedomw\vendor\freedom\Zend\Filter\EncryptPassword.php on line 59
I have also tried to add the following function to my module.php file
public function getConfig()
{
return include __DIR__ . '/config/module.config.php';
}
and used
$this->getConfig();
to no avail.
Please can someone point me in the right direction, many thanks.

would say that you have to make a factory for your password encrypt class and get the salt from ServiceLocator in the factory and inject the salt from the config into your class (either in constructor or by using some setter).
So something like this:
In your module.config.php:
'service_manager' => array(
'factories' => array(
'My\Filter\EncryptPassword' => 'My\Filter\EncryptPasswordFactory',
)
)
And then in your My\Filter\EncryptPasswordFactory.php:
<?php
namespace My\Filter;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class EncryptPasswordFactory implements FactoryInterface
{
/**
* #param ServiceLocatorInterface $serviceLocator
* #return EncryptPasswordService
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
$config = $serviceLocator->get('config');
$salt = ...get salt from config...
$encryptPasswordService = new EncryptPasswordService($salt);
return $encryptPasswordService;
...or make a setSalt method or whatever you think is nicest...
}
}
Your My\Filter\EncryptPasswordService.php:
<?php
namespace My\Filter;
class EncryptPasswordSevice
{
/**
* #param ServiceLocatorInterface $serviceLocator
* #return EncryptPasswordService
*/
public function __construct($salt)
{
use your $salt
}
}
Now you can get your My\Filter\EncryptPassword anywhere where you have access to a serviceManager instance (or serviceLocator instance) like this:
$encryptPasswordService = $serviceManager->get('My\Filter\EncryptPassword');

Related

Cannot enable doctrine's entity manager

I wanted to use Doctrine in my project, but I am not able to use Entity Manager.
I have created entites, repositories, config files and dbconnect but it seems that it's not done correctly.
Can you please check this code? Maybe I'm missing something really small.
My dbconnect file(it is bootstrapped in init.php):
<?php
namespace Projekt\Config;
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;
$paths = array("Entity");
$isDevMode = false;
// the connection configuration
$dbParams = array(
'driver' => 'pdo_mysql',
'user' => 'root',
'password' => '',
'dbname' => 'projekt',
);
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode, null, null, false);
$em = EntityManager::create($dbParams, $config);
My Repository example:
<?php
namespace Projekt\Repository;
use Doctrine\ORM\EntityRepository;
/**
* Message
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class Message extends EntityRepository
{
public function getMessage($id)
{
$message = $this->find($id);
return $message;
}
public function getAllMessages()
{
}
public function createMessage()
{
}
public function updateMessage()
{
}
public function deleteMessage()
{
}
}
Now when I'm trying to access a default or custom repository method I get this error:
Warning: Missing argument 1 for Doctrine\ORM\EntityRepository::__construct(),
called in F:\xampp\htdocs\mvc\app\Controllers\Messages.php
on line 15 and defined in F:\xampp\htdocs\mvc\vendor\doctrine\orm\lib\Doctrine\ORM\EntityRepository.php on line 64
line 64 in EntityRepository.php is a __construct function that declares entitymanager, but it seems to not be working properly:
public function __construct($em, Mapping\ClassMetadata $class)
{
$this->_entityName = $class->name;
$this->_em = $em;
$this->_class = $class;
}
Two things that i noticed:
Your path is relative. Im not sure but i always use complete path to the Entity folder. You can use __DIR__ to achieve that easily. Depending on your namespace it should look Like:
$paths = array(__DIR__ . "/../Repository");
Doctrine needs to know where to find your entities and repositories. Depending on your namespace i would think your Repository file exists in a folder named "Repository" and not "Entity".
Have you correctly defined an Entity Class? Your Repository class looks ok to me but it can only work if you have a valid Entity class.
You should not name your repository "Message". The Entity should be named "Message" and the repository should be named "MessageRepository".

Zend Framework 2: Getting current controller name inside a module

I'm creating a module X that will be instantiated inside a controller module. How can I get the name of that controller in a method of module X?
This module is not a controller, nor a view or layout.
An example. This is an action in the controller:
public function indexAction {
$parser = new Parser();
}
And this my new module Parser, where I need to know the controller's name.
public function __construct() {
$controller_name = ???
}
For such dependencies you should use a factory to create your service instance. Then you can inject whatever you want in there, also a controller name. Your ParserFactory could for example look like this:
<?php
namespace Application\Factory;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Application\Service\Parser
class ParserFactory implements FactoryInterface
{
/**
* #param ServiceLocatorInterface $serviceLocator
* #return Parser
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
$routeMatch = $serviceLocator->get('Application')->getMvcEvent()->getRouteMatch();
$controllerName = $routeMatch->getParam('controller');
$parser = new Parser($controllerName);
return $parser;
}
}
Your Parser class:
<?php
namespace Application\Service;
class Parser
{
/**
* #param string $controllerName
*/
public function __construct($controllerName)
{
//... use your controller name ...
}
}
Register your factory in module.config.php like this:
'service_manager' => array(
'factories' => array(
'Parser' => 'Application\Factory\ParserFactory',
)
)
Get your service where you need it from the ServiceManager like this:
$parser = $serviceManager->get('Parser');
I think this has been asked before but I think you do:
$this->getEvent()->getRouteMatch()->getParam('controller', 'index');
You should just be able to grab it all from the router.
EDIT:
Yeah, check these out:
How to get the controller name, action name in Zend Framework 2
ZF2 - Get controller name into layout/views
ZF2: Get module name (or route) in the application layout for menu highlight

Load different config based on the result of a Service function in Zend Framework 2

Is it possible in ZF2 to load a different config file (or just manually add an array to the existing config) based on a function in a Service (or model)?
To be more precise, I have a (third party) module that needs a bunch of custom settings from the config.
In one of my own modules, in module.config.php I have a custom config setting:
'my_custom_config' => array(
'display_something' => true,
),
Then in an invokable service I have a function, say isDisplaySomething(), that will determine whether display_something is true or false.
My first try was to call that function in getConfig() of Module.php and then add it to the config as an array, but I can't figure out how to access the Service there.
Then I tried to overwrite Configuration in the onDispatch() in a controller, but I can't access the ServiceManager there (and it's probably not a very elegant solution anyway).
Any ideas how to solve this problem?
For dependencies on a value from config I would suggest you setup a factory to create your service. Something like this:
<?php
namespace My\Factory;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\FactoryInterface;
use My\Service\DisplayService;
/**
* Factory for creating the DisplayService
*/
class DisplayServiceFactory implements FactoryInterface
{
/**
* Create the DisplayService
*
* #param ServiceLocatorInterface $serviceLocator
* #return DisplayService
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
$config = array();
if ($serviceLocator->has('config')) {
$config = $serviceLocator->get('config');
}
// Default value in case nothing in config
// An alternative is to throw an exception if no value found in config.
$displaySomething = true;
if(isset($config['my_custom_config'] && isset($config['my_custom_config']['display_something'])){
$displaySomething = $config['my_custom_config']['display_something'];
}
// Use setter to set the value or use constructor dependency.
$displayService = new DisplayService();
$displayService->setDisplaySomething($displaySomething);
return $displayService
}
}
And then in your module.config.php:
'service_manager' => array(
'factories' => array(
'My\Service\DisplayService' => 'My\Factory\DisplayServiceFactory'
)
)
Now you can get your service from your service manager like this:
$serviceManager->get('My\Service\DisplayService');
and it will have your $displaySomething value.

How can I replace the PhpRenderer in a ZF2 application

I have extended the PhpRenderer class in my ZF2 application like this:
namespace MyLib\View\Renderer;
class PhpRenderer extends \Zend\View\Renderer\PhpRenderer
{
}
I don't want to add a new rendering strategy, I just extend the PhpRenderer to add some #method phpdoc for my viewhelpers.
How can I replace the standard PhpRenderer with my extended PhpRenderer so it will be used to render my viewscripts?
The php renderer is a service inside the service manager. You can override this service directly or do it via the view manager (which instantiates and configures the renderer).
Override the service
In your module you define an onBootstrap() method. The "old" php renderer is already registered, you have to redefine it.
public function onBootstrap($e)
{
$app = $e->getApplication();
$sm = $app->getServiceManager();
$old = $sm->get('ViewRenderer');
$new = new MyCustomViewRenderer;
$new->setHelperPluginManager($old->getHelperPluginManager());
$new->setResolver($old->getResolver());
$sm->setAllowOverride(true);
$sm->setService('ViewRenderer', $new);
$sm->setAllowOverride(false);
}
Override the view manager
There is an alternative where you can redefine the view manager where the php renderer is instantiated. You have to redefine the view manager's factory for this:
In your application.config.php (note it is the application config, as the module config will not work here!)
service_manager => array(
'factories' => array(
'HttpViewManager' => 'MyModule\Service\HttpViewManagerFactory',
),
);
Then create your MyModule\Service\HttpViewManagerFactory:
use MyModule\View\Http\ViewManager as HttpViewManager;
class HttpViewManagerFactory implements FactoryInterface
{
/**
* Create and return a view manager for the HTTP environment
*
* #param ServiceLocatorInterface $serviceLocator
* #return HttpViewManager
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
return new HttpViewManager();
}
}
And then you can finally update the factory of the php renderer itself:
use Zend\Mvc\View\Http\ViewManager as BaseViewManager;
class ViewManager extends BaseViewManager
{
public function getRenderer()
{
if ($this->renderer) {
return $this->renderer;
}
$this->renderer = new MyCustomViewPhpRenderer;
$this->renderer->setHelperPluginManager($this->getHelperManager());
$this->renderer->setResolver($this->getResolver());
$model = $this->getViewModel();
$modelHelper = $this->renderer->plugin('view_model');
$modelHelper->setRoot($model);
$this->services->setService('ViewRenderer', $this->renderer);
$this->services->setAlias('Zend\View\Renderer\PhpRenderer', 'ViewRenderer');
$this->services->setAlias('Zend\View\Renderer\RendererInterface', 'ViewRenderer');
return $this->renderer;
}
}
Conclusion
The first method instantiates the normal php renderer already, so you instantiate two of them and replace the default with your own.
An alternative is to circumvent the instantiation of the default Zend's php renderer, but you have to do this inside the view manager class. The problem here is you have to redefine the factory for the view manager as well. This sounds as a detour, but it is the only way to get this done.
If all your custom class contains is #method declarations then you don't need to replace the php renderer class. Just make sure to use the #var docblock and your IDE will know what to do:
Document the type for the $this variable in your view files:
<!-- in a view file -->
<?php /* #var $this MyLib\View\Renderer\PhpRenderer */ ?>
<?= $this->myCustomViewHelper() ?>
Document individual variables or properties for view helpers, classes, etc:
class SomeHelper extends AbstractHelper
{
/** #var \MyLib\View\Renderer\PhpRenderer */
protected $view;
public function __invoke()
{
$this->view->myCustomViewHelper();
}
}

Why is the Servicemanager injected in a invokable and not a service

I'm currently playing with the ZF2 serviceManager, and i'm trying to figure out why the serviceManager doesn't inject the sm in a class that implements ServiceLocatorAwareInterface.
My main question is am i doing it right or is the "services" key not for services that implement ServiceLocatorAwareInterface but for services that don't need injection?
in Module.php
public function getServiceConfig() {
return array(
'invokables' => array(
'myService1' => 'MyModule\Service\Service'
),
'services' => array(
'myService2' => new MyModule\Service\Service(),
),
);
}
in MyModule\Service\Service.php
namespace MyModule\Service;
use Zend\ServiceManager\ServiceManagerAwareInterface;
use Zend\ServiceManager\ServiceManager;
class Service implements ServiceManagerAwareInterface
{
/**
* #var ServiceManager
*/
protected $serviceManager = NULL;
/**
* Retrieve service manager instance
*
* #return ServiceManager
*/
public function getServiceManager()
{
return $this->serviceManager;
}
/**
* Set service manager instance
*
* #param ServiceManager $serviceManager
*/
public function setServiceManager(ServiceManager $serviceManager)
{
$this->serviceManager = $serviceManager;
}
}
When i call the service in a controller
<?php
namespace MyModule\Controller;
use Zend\Mvc\Controller\AbstractActionController;
class IndexController extends AbstractActionController
{
public function IndexAction() {
$service1 = $this->getServiceLocator()->get('myService1');
$sm1 = $service1->getServiceManager();
//$sm1 becomes a object of Zend\ServiceManager\ServiceManager
//In other words i now can access the SM from within my service.
$service2 = $this->getServiceLocator()->get('myService2');
$sm2 = $service2->getServiceManager();
//$sm2 becomes NULL
//The service isn't aware of the SM and can't access it.
}
}
You should continue to use the "invokables" section if you'd like to utilize the ServiceManagerAwareInterface and the automatic injection of the Service Manager into your service.
Looking through /Zend/ServiceManager/ServiceManager.php, "services" are meant to be registered as already instantiated objects with the ServiceManager. When the service locator looks up in it's local cache of services during retrieval, it assumes that "services" are already fully set up and does not inject the sm or run any initializers.
"invokables", "factories", "abstract_factories" are created on the fly and injects the sm when the "initializers" are run on a newly created service instance (see function create($name)).
Forget about getServiceConfig() and use your module config instead. It's faster and cacheable:
module.config.php:
'service_manager' => array(
'invokables' => array(
'MyModule\Service\Service' => 'MyModule\Service\Service',
),
)
MyModule\Service\Service.php:
<?php
namespace MyModule\Service;
use \Zend\ServiceManager\ServiceLocatorInterface;
class Service
{
public function __invoke(ServiceLocatorInterface $sm)
{
// go bananas here :)
}
public functiom greet()
{
return 'Hello World';
}
}
anywhere inside zend2:
<?php
$service=$serviceManager->get('MyModule\Service\Service');
echo $service->greet();

Categories