Zend Framework 2 - How to give declare folder path in terms of "use" and "namespace" - zend-framework2

I am facing problem while creating adapter object in controller file named Listcontroller.My code is
namespace Blog\Controller;
use Blog\Service\PostServiceInterface;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\Db\Sql\Sql;
use Zend\Db\Adapter\Adapter;
class ListController extends AbstractActionController
{
/**
* #var \Blog\Service\PostServiceInterface
*/
protected $postService;
public function __construct(PostServiceInterface $postService)
{
$this->postService = $postService;
}
public function indexAction()
{
$adapter = new Zend\Db\Adapter\Adapter($configArray);
print_r($adapter);
//code ....
}
}
here it is serching to find Zend\Db\Adapter\Adapter inside Blog\Controller.
Error is -> Fatal error: Class 'Blog\Controller\Zend\Db\Adapter\Adapter' not found. Can anybody tell me please how can i move two folder back from above path. so that i can get proper object??

You don't need the fully qualified class name (FQCN) when instantiating a new Adapter since you declare that class path via use statement:
use Zend\Db\Adapter\Adapter;
Change this block
public function indexAction()
{
$adapter = new Zend\Db\Adapter\Adapter($configArray);
print_r($adapter);
}
to
public function indexAction()
{
$adapter = new Adapter($configArray);
print_r($adapter);
}
It should work.
Anyway, new \Zend\Db\Adapter\Adapter($configArray) also works (notice the first backslash) but its longer, harder to type and less readable than first example.
You may also want to read namespace aliasing/importing section of the documentation.

Related

How to get the instance of an injected dependency, by its type using Umbraco.Core.Composing (Umbraco 8)

I need to find a way to get an instance of DataProcessingEngine without calling it's constractor.
I am trying to find a way to do so using the registered DataProcessingEngine in composition object (please see the following code). But I could not find a way to do so.
Anyone have a suggestion? Thanks in advance.
public class Composer : IUserComposer
{
public void Compose(Composition composition)
{
composition.Register<IDataProcessingEngine, DataProcessingEngine>(Lifetime.Singleton);
//DataProcessingEngine dataProcessing = compostion.Resolve<IDataProcessingEngine>()??//no resolve function exists in Umbraco.Core.Composing
SaveImagesThread(dataProcessingEngine);
}
public Task SaveImagesThread(IDataProcessingEngine dataProcessingEngine)//TODO - decide async
{
string dataTimerTime = WebConfig.SaveProductsDataTimer;
double time = GetTimeForTimer(dataTimerTime);
if (time > 0)
{
var aTimer = new System.Timers.Timer(time);
aTimer.Elapsed += new ElapsedEventHandler(dataProcessingEngine.SaveImages);
aTimer.Start();
}
return default;
}
}
For all of you who are looking for a way to call a function (that's defined in another class in your code, an Engine or ...) from the composer(where the app starts) and want to avoid calling this function's class' constractor. I've found another way to do so:
public class QueuePollingHandler
{
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
public class SubscribeToQueuePollingHandlerComponentComposer :
ComponentComposer<SubscribeToQueuePollingHandler>
{ }
public class SubscribeToQueuePollingHandler : IComponent
{
private readonly IDataProcessingEngine _dataProcessingEngine;
public SubscribeToQueuePollingHandler(IDataProcessingEngine
dataProcessingEngine)
{
_dataProcessingEngine = dataProcessingEngine;
SaveImagesThread(_dataProcessingEngine);
}
public void SaveImagesThread(IDataProcessingEngine
dataProcessingEngine)
{
....
}
}
And the logic explenation: You create a class (SubscribeToQueuePollingHandlerComponentComposer from the example) and define its base class to be ComponentComposer<Class_that_inherits_IComponent>.
And when you start the application you could see that it gets to the registered class' constractor (SubscribeToQueuePollingHandler constructor).
That's the way that I found to be able to call a function right when the application starts without needing to call its class constractor and actualy use dependency injection.

Typo3 Call to a member function on null

I have seen similar problems on Stackoverflow but none of those answers has worked for me (including clearing cache, clearing PHP opcode cache systems, de-activating and re-activating the extension). Hopefully someone can point me in the right direction.
I am running a scheduled command for an extension. At some point my command will need to call the method test() from the MyController class.
I have tried to create a reference to the class via an inheritance call AND by ALL injection methods but no matter which way I try it I always get the same issue...:
Call to a member function test() on null
Most recently I used the injection method that is not recommended, but it simplifies my example below so I'll use it for now. (VendorName and ExtensionName are obvs dummy names):
* #var \VendorName\ExtensionName\Controller\MyController
* #inject
*/
protected $mc;
public function myCommand()
{
return $this->mc->test(); //should return true
}
...and inside MyController
public function test()
{
return true;
}
The issue isn't the injection call on the command Class, but some automatically generated code on the MyController Class. It seems Extension Builder can cause the error by incorrectly creating the #inject line in the wrong place. Here is the code it created automatically:
/**
* #var \VendorName\ExtensionKey\Domain\Repository\ExampleRepository
* #inject
*/
protected $importService = null;
/**
* #inject
*/
protected $exampleRepository = null;
...that second #inject call creates the error. It should be just:
/**
* #var \VendorName\ExtensionKey\Domain\Repository\ExampleRepository
* #inject
*/
protected $importService = null;
protected $exampleRepository = null;
Unfortunately the dubugging doesn't tell you which class is causing the issue so I naturally thought it was my own code.

Autofac get decorated QueryHandler by convention based on constructor parameter name?

We inject IQueryHandler<TQUery,TResult> into our MVC controllers. We globally register all of these in the container
We have written a decorator that can cache the results of IQueryHandler.
We want to sometimes get cached reults and other times not from the same handler.
Is it possible to conditionally get a decorated handler based on the name of the constructor parameter. e.g. inject IQueryHandler<UnemployedQuery, IEnumerable<People>> cachedPeopleHandler if we prefix constructor parameter name with cached we actually get it wrapped with decorator?
Just trying to use a more convention over configuration approach to simplify things.
Yes it's possible to do it. Below is a simple working example on how you can achieve it:
class Program
{
public interface IQueryHandler{}
private class QueryHandler : IQueryHandler
{
}
private class CacheQueryHandler : IQueryHandler
{
}
public interface IService
{
}
private class Service : IService
{
private readonly IQueryHandler _queryHandler;
private readonly IQueryHandler _cacheQueryHandler;
public Service(IQueryHandler queryHandler, IQueryHandler cacheQueryHandler)
{
_queryHandler = queryHandler;
_cacheQueryHandler = cacheQueryHandler;
}
public override string ToString()
{
return string.Format("_queryHandler is {0}; _cacheQueryHandler is {1}", _queryHandler,
_cacheQueryHandler);
}
}
static void Main(string[] args)
{
var builder = new ContainerBuilder();
// Register the dependency
builder.RegisterType<QueryHandler>().As<IQueryHandler>();
// Register the decorator of the dependency
builder.RegisterType<CacheQueryHandler>().Keyed<IQueryHandler>("cache");
// Register the service implementation
builder.RegisterType<Service>().AsSelf();
// Register the interface of the service
builder.Register(c =>
{
var ctor = typeof (Service).GetConstructors()[0];
var parameters =
ctor.GetParameters()
.Where(p => p.Name.StartsWith("cache"))
.Select(p => new NamedParameter(p.Name, c.ResolveKeyed("cache", p.ParameterType)));
return c.Resolve<Service>(parameters);
}).As<IService>();
using (var container = builder.Build())
{
var service = container.Resolve<IService>();
Console.WriteLine(service.ToString());
Console.ReadKey();
}
}
}
Update:
Basically you need to:
1. Think up a general convention. Prefix "cache" of ctor parameter name in your case.
2. Register your dependencies as usual.
3. Register your decorators, so they don't overwrite your original dependencies and you can easily resolve them basing on your convention. e.g. Keyed, Named, via Attribute, etc.
4. Register you actual implementation of class that uses decorators
5. Register your interface that describes the class via lambda expression that has all magic inside.
Note: I provided just a simple and working example. It's on you to make it nice, easy to use and fast e.g. make it as an extension, generic, cache reflection results etc. It's not difficult anyway.
Thanks.

ZF2: How to attach listener on the event in the Module class?

I want to set a basePath to be the same for every component of my Mvc for a given request. I mean when I call these methods I want to get the same result, lets say '/spam/ham/':
echo $this->headLink()->prependStylesheet($this->basePath() . '/styles.css') // $this->basePath() has to be '/spam/ham/'
$this->getServiceLocator()
->get('viewhelpermanager')
->get('headLink')
->rependStylesheet($this->getRequest()->getBasePath() . '/styles.css') // $this->setRequest()->getBasePath() has to be /spam/ham/
How to set the basePath for the first case I have found already, here's my question. By the way, the original manual doesn't have any info I received from the answer.
And now the second one - the basePath has to be set in the Request:
$this->getRequest()->getBasePath()
Here I found some answer that in fact doesn't work at all http://zend-framework-community.634137.n4.nabble.com/Setting-the-base-url-in-ZF2-MVC-td3946284.html. As said here StaticEventManager is deprecated so I changed it with SharedEventManager :
// In my Application\Module.php
namespace Application;
use Zend\EventManager\SharedEventManager
class Module {
public function init() {
$events = new SharedEventManager();
$events->attach('bootstrap', 'bootstrap', array($this, 'registerBasePath'));
}
public function registerBasePath($e) {
$modules = $e->getParam('modules');
$config = $modules->getMergedConfig();
$app = $e->getParam('application');
$request = $app->getRequest();
$request->setBasePath($config->base_path);
}
}
}
And in my modules/Application/configs/module.config.php I add:
'base_path' => '/spam/ham/'
But it desn't work. The problems are:
1) The run never comes to the registerBasePath function. But it has to. I've attached an event with the listener in the init function.
2) When I change SharedEventManager for just EventManager it happens to come to the registerBasePath function but an exeption is thrown:
Fatal error: Call to undefined method Zend\EventManager\EventManager::getParam()
What do I do wrong? Why the run of the program doesn't come to the registerBasePath function? If this is the only way to set the basePath globally then how to do it right?
I know the documentation is lacking of these kinds of things. But you are right in the way to approach this:
Be early (so at bootstrap)
Grab the request from the application
Set the base path in the request
The docs are lacking this information and the post you refer to is quite old. The fastest and easiest way to do this is using the onBootstrap() method:
namespace MyModule;
class Module
{
public function onBootstrap($e)
{
$app = $e->getApplication();
$app->getRequest()->setBasePath('/foo/bar');
}
}
If you want to grab the base path from your config, you can load the service manager there:
namespace MyModule;
class Module
{
public function onBootstrap($e)
{
$app = $e->getApplication();
$sm = $app->getServiceManager();
$config = $sm->get('config');
$path = $config->base_path;
$app->getRequest()->setBasePath($path);
}
}

code run before every actions in a module ZF2?

I want to write some code to run before every actions in my module. I have tried hooking onto onBootstrap() but the code run on the other modules too.
Any suggestions for me?
There are two ways to do this.
One way is to create a serice and call it in every controllers dispatch method
Use onDispatch method in controller.
class IndexController extends AbstractActionController {
/**
*
* #param \Zend\Mvc\MvcEvent $e
* #return type
*/
public function onDispatch(MvcEvent $e) {
//Call your service here
return parent::onDispatch($e);
}
public function indexAction() {
return new ViewModel();
}
}
don't forget to include following library on top of your code
use Zend\Mvc\MvcEvent;
Second method is to do this via Module.php using event on dispatch
namespace Application;
use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
class Module {
public function onBootstrap(MvcEvent $e) {
$sharedEvents = $e->getApplication()->getEventManager()->getSharedManager();
$sharedEvents->attach(__NAMESPACE__, 'dispatch', array($this, 'addViewVariables'), 201);
}
public function addViewVariables(Event $e) {
//your code goes here
}
// rest of the Module methods goes here...
//...
//...
}
How to create simple service using ZF2
reference2
reference3

Resources