Zend Framework 2 && ServiceLocator init libraires - php

I have problem or misunderstanding of zf2's serviceLocator. Which is the right way to get a library/class with serviceLocator, which need configuration in the __construct method.
For example:
class PhpVersion extends AbstractTest implements TestInterface
{
public function __construct($expectedVersion, $operator = '>=')
{
}
}
The problem is that, the ServiceLocator's get method requires only one variable - Libraries name, without any place for configuration or dependency
P.S. My solution is with making a factory, but I think there should be a smarter way.

you can create your own service locator by extending the zends service locator class and customizing the get method to accepts arguments and pass them on to the constructor of that object.

Related

Laravel DI with interfaces

I have made a repository pattern app, having a repo and interface:
class UserRepository extends EloquentRepository implements UserRepositoryInterface
{
public function __construct()
{
$this->model = new User();
}
...
}
The repository and interfaces as well as extended class and its interface is registered in service provider and is called on app boot.
The questions I have are:
Is there a need to watch out for the order of registering? For example, should EloquentRepository class be loaded before the
repo, or does Laravel handle that on its own?
In case I inject UserRepositoryInterface in a controller, is the constructor method called automatically even though I didn't really new-up a class?
How long does the DI injection "live"? If I inject it in a page controller which calls some other controller and needs the same dependency, does the constructor call twice then, and operate separately in each controller?
Is there a difference if I call it like App::make() instead of DI?
Is there a need to watch out for the order of registering? For example, should EloquentRepository class be loaded before the repo, or does Laravel handle that on its own?
I don't quite understand where you would load EloquentRepository as (from the code posted) it seems you're only extending it. Which shouldn't be a problem.
In case I inject UserRepositoryInterface in a controller, is the constructor method called automatically even though I didn't really new-up a class?
Yes. Most of Laravel's main classes (controllers included) are loaded with DI in mind and the dependencies will be resolved automatically.
That being said, since you are injecting an interface and an interface by default cannot be initialized as a class, since it has no implementation - you need to bind an implementation to the interface first in order to use it.
How long does the DI injection "live"? If I inject it in a page controller which calls some other controller and needs the same dependency, does the constructor call twice then, and operate separately in each controller?
My understanding is that a new instance of the class will be created when the next controller is initialized. Unless you bind a class as a singleton.
Is there a difference if I call it like App::make() instead of DI?
App::make(some::class) will automatically resolve the dependencies of class some.
For example:
namespace App;
use App\Dependancy;
class Test
{
protected $d;
public function __construct(Dependancy $d)
{
$this->d = $d;
}
}
If you call this in the controller: $a = new \App\Test() you will get an error that \App\Test constructor expects class Dependency as first parameter.
But if you initialize it like this: $a = \App::make(\App\Test::class) the Dependency will be automatically resolved.
try to make the repositories abstract in the controllers and inject these through constructor.
like this here:
public function __construct(EloquentRepository $repository)
{
$this->repository = $repository;
}
And in the AppServiceProvider you can inject repositories you will need.
public function boot()
{
// provides any Repository in SomeController
$this->app->when(SomeController::class)
->needs(EloquentRepository::class)
->give(function (Application $app) {
return $app->make(SomeRepositoryInterface::class)
});
}

Is it possible to inject a repository as a dependency in a laravel service file?

What I am trying to do -
1) Controller will depend on service for logic and stuff.
2) Service with depend on repository for database access.
3) Controller will get service as a dependency.
4) Service will get a repository as a dependency.
My service class is -
class AnimeService implements IAnimeService{
protected $animeRepository;
public function _construct(IAnimeRepository $_animeRepository) {
$this->animeRepository = $_animeRepository;
}
public function add(Anime $anime) {
return $this->animeRepository->add($anime);
}
}
problem is -
Call to a member function add() on null
which is expected - as the _construct is never being called.
By the way; from my AppServiceProvider
public function register()
{
$this->app->bind('\App\Services\Interfaces\IAnimeService', '\App\Services\Implementations\AnimeService');
$this->app->bind('\App\Repositories\Interfaces\IAnimeRepository', '\App\Repositories\Implementations\AnimeRepository');
}
My questions are -
1) What can I do in this situation to make my service work?
2) What is the best practice?
3) What other ways are there to achieve what I am trying to do?
Thank you.
The constructor should be named __construct and not _construct, with two underscores :)
See the php docs: http://php.net/manual/en/language.oop5.decon.php
And if you're injecting the AnimeService in a controller constructor, Laravel should resolve the dependencies automatically, so it should work with what you have here just by fixing the name of the constructor method :)

PHP Dependency Injector or Factory?

I'm using Zend Framework 1 and Pimple dependency injector. After watching some Google Guice presentations on YouTube, I'm not sure if I'm really using DI and not a simple factory. The way I'm making use of my Pimple injector is by asking it to give me an instance of some object based on a string key registered and associated with the object:
class SomeService extends AbstactService {
/** #var Pimple $injector Inherited from base class */
protected $injector;
public function save(array $data) {
$model = $this->injector["some-model"];
if (empty($data["id"])) {
$model->insert($data);
} else {
$model->update($data);
}
}
}
The member variable $injector is created and configured at bootstrap, and sent to my AbstractService class, so all concrete services inherit it.
So by the way that $injector is used here, even though it uses Pimple (a DI container), is this implementing DI pattern or something else (factory or maybe service locator) ?
Update
Some further info: I'm using Zend Framework (MVC) building a nutrition/exercise website.
I think what is confusing me is how to create some object inside a method, where that object is only needed for that method, and the method takes some run-time arguments. For example, the SomeService class gets instantiated by the container in my controller. Then I call SomeService::save() passing in $data. Where and how would $model be created? Suppose $model is only used in that particular method, so that it wouldn't make sense to make it a class member, how could that be injected by the container?

How does laravels IoC/Dependency Injector intsantiate to static instances?

So this is probably a rather simple question but I can't seems to find a very direct answer. I supposed to could keep reading the source until i figure it out but I was hoping to get a bit of understand of the process of doing so.
I understand IoC and Dependency injection, I am certainly not very experienced in either but I have a good understand of what they are trying to accomplish. So how does this Laravel instantiate to static instances? I know it uses PHP reflections but I'm still lost on the part of going from non-static to static methods. Also I know Laravel is not the only framework to implement such a design but its my preferred and most understood framework.
When you call a static method on a facade it is being handled by the magic __callStatic method on the Facade class. This method gets the underlying class that serves the facade and proxies the static call to it.
Let's look at an example facade:
<?php
class MyFacade extends Facade {
public function getFacadeAccessor() { return "MyFacade"; }
}
With this example when we make a call to the class in a static manner such as: MyFacade::doSomething() no static method exists on the class. The underlying Facade base class however contains a __callStatic method that will be called.
Facade Class Source Code
public static function __callStatic($method, $args)
{
$instance = static::resolveFacadeInstance(static::getFacadeAccessor());
switch (count($args))
{
case 0:
return $instance->$method();
// Snipped for brevity...
This method then looks up the underlying class to service the facade. If the getFacadeAccessor method on the facade returns a string then a matching entry in the application's IOC container is used (i.e. $app['MyFacade']). If we returned an object from the getFacadeAccessor method it would be used instead (i.e. public function getFacadeAccessor(){ return new MyClass(); }
Turns out that Laravel instantiate the classes under the hood! In this site, the guy makes you understanding a little more of the Laravel's core by using it to create a new facade. In the way, he explains how tit works!
It quite simple, actualy:
1 - You create a classe which extends from Laravel's Facade class with a single call like:
<?php namespace Name\Space;
use Illuminate\Support\Facades\Facade;
class MyClass extends Facade {
/**
* Get the registered name of the component.
*
* #return string
*/
protected static function getFacadeAccessor() { return 'myclass'; }
}
... that's make Laravel look for $app['myclass']. So, the ServiceProvider will bind the myclass to MyClass (according to Laravel's conventions).
2 - For that, of course, you'll have to create a Service Provider.
The Service Provider will be responsible for returning the namespace, in this case Name\Space, for the class(es) that you may want to 'turn into facades'.
3 - You'll have to register your Service Provider in the providers array in the app/config/app.php.
Now, if you look with more attention, you'll realise that what Laravel does is just import a namespace and understanding it as it was a class, as well. Under the hood, it will call a instance, but for user (programmer) it will looks like a static call.
I hope I had been clear about it! Look the link I gave to you up there and HAVE FUN! :D

ZF1 Doctrine2 Service Layer

I'm looking for a good example of how to correctly implement Service Layer with Zend Framework and Doctrine2
I've seen some implementations but all of them have access to the EM from the controller when instantiating the service, and I think that might be wrong or not?
Exmaple:
http://cobbweb.me/2010/11/integrate-doctrine-2-zend-framework-application/
Also I got to this project but not really sure how to implement it:
Thanks
Use a helper to act like a factory for the services:
You need to create an Action Helper and inject the EntityManager on it when you register the instance in the Front Controller.
This Action Helper receives as parameter in the direct() method the name of the service class that the factory should create.
Inside this method you should try to instantiate the service class requested, and return it (or throw an exception if the same is not found).
Let your service classes receive as parameter in the constructor the EntityManager and inject it during the construction on the factory.
The rest should already be clear to you. In your controller you only need to use something like:
SomeController extends Zend_Controller_Action {
//...
public function someAction ()
{
$myService = $this->_helper->service( 'MyService' );
$myService->doSomething();
}
}

Categories