Can we use class as an dependency injection instead of interface - php

I've used another class as Dependency Injection is it good to work around or I've messed up the OOP way.
Helper.php
class Helper {
public function getModulePermission($role_id, $module, $type) {
// my work code
}
}
DesignationController.php
use App\Helpers\Helper;
class DesignationController extends Controller {
protected $designation;
protected $helper;
/**
* #param DesignationContract $designation
* #param Helper $helper
*/
public function __construct(DesignationContract $designation, Helper $helper) {
$this->designation = $designation;
$this->helper = $helper;
}
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index(Request $request) {
$permission = $this->helper->getModulePermission($request->id, 'Designation', 'view');
if ($permission) {
return true;
} else {
return view('errors.forbidden');
}
}
So I've a class named Helper which can be accessed within each and every controller for checking permissions but I thought that I've messed up the OOP functionality over here. Is it good to work like it as or I need to create an Interface instead of class

Those are two different OOP concepts. the interface forces whoever class implement it to implement functions stated in the interface (called function signature). So for multiple classes implement the same interface, you will end up with multiple classes implement the same set of functions (wither it is the same function body or not).
The second concept is called, dependency injection or inversion of control in some cases. you inject a class either via class constructor or via setters and you call certain function provided by the injected class. Here you will have the same function called by multiple classes which is good for less modification by using common (injected) class, easier unit-testing (you can mock objects easily), more modular code (you can inject different class if you want different functionality).
So the current situation is good enough but it all depends in what you want to do which stated above.

I don't like the name, it speaks nothing to me or gives me an idea that this class can help me get the permissions of the module. Moreover, with a name like this, one can simply put another method, like lets say Helper::login($id) or you name it, which will instantly break the single responsibility principle (laravel controllers do that anyway).
The injection is relatively OK, perhaps a middleware class would be better place to do that.

Related

How do i create a mock object that uses an array of traits?

I am currently on PHPUnit v5.7.27
I would like to create a mock object that uses an array of traits. How would I go about this? I only see getMockForTrait as a way to create a mock object using a single trait. My issue is that the trait requires the existence of another trait at the class level.
Update: More context to the issue
Given:
trait GetSet {
public function __call(){ /* does some magic */
}
trait RepositoryAware {
public function getRepository(string $name)
{
/* makes use of the GetSetTrait*/
}
}
class Controller
{
use GetSet;
use RepositoryAware;
}
Given the limitations of PHP, I can not simply put a use GetSet on the RepositoryAware trait because other traits that the controller imports could also bring the GetSet trait. Furhtermore, the controller class itself could be using the behavior provided by the GetSet trait.
The current solution I have is to create a Dummy Class that imports both traits and mock that class instead:
class RepositoryAwareClass
{
use GetSet;
use RepositoryAware;
}
Like this I am able to properly test the behavior provided by the RepositoryAware trait while at the same time composing its requirement of the GetSet trait.
Mocking concept was built with the idea that you would be using dependency injection. I can certainly see why you may not want to use dependency injection with this multiple inheritance like model that php uses called "Traits". Mocking tools like the one built for phpunit was built to substitute instances of objects not classes/interfaces/traits themselves. PHP Traits are more like having a static dependency instead of a dependency on an instance of an object. However, even if you were using traits and assuming a trait was basically the same as a class, according to mocking best practices should test the trait as its own test instead of testing a trait through another class. If you want to mock the trait itself you may want to try to revisit your design as I do not believe it can be done. You can certainly mock a trait and test that trait but you cannot mock a trait and then inject it as a dependency on an object. Imagine that a class for example implements an interface, mocking a trait would be the same a mocking an interface that a class implements, its not possible. You can only mock an interface of an object that a class depends upon through setter or constructor based dependency injection. Another example would be to try and mock the class that the class under test inherits from. You can't do that either. Perhaps in the javascript world this type of thing could be useful and from some people's point of view desired, but I think if you want to use mocking you would need to stick with object dependency injection instead of static use of traits.
So what's the alternative? I think the following example would be how to use perhaps "traditional" OOP practices with mocking to achieve your goal of sharing functionality without using inheritance. The example also makes your dependencies more explicit. And for the record, I applaud you for NOT using inheritance.
<?php
interface GetterSetter {
public function __call();
}
interface RepositoryProvider {
public function getRepository(string $name);
}
class GetSet implements GetterSetter {
public function __call() {
/* does some magic */
}
}
class DefaultRepository implements RepositoryProvider, GetterSetter {
/**
* #var GetterSetter
*/
private $_getterSetter;
public function __construct(GetterSetter $getterSetter) {
$this->_getterSetter = $getterSetter;
}
public function getRepository(string $name) {
// makes use of the GetSetTrait
$this->__call();
}
public function __call() {
// makes use of the GetSetTrait
$this->_getterSetter->__call();
}
}
class Controller implements RepositoryProvider, GetterSetter {
/**
* #var RepositoryProvider
*/
private $repositoryProvider;
public function __construct() {
$this->repositoryProvider = new DefaultRepository(new GetSet());
}
public function getRepository(string $name) {
return $this->repositoryProvider->getRepository($name);
}
public function __call() {
$this->repositoryProvider->__call();
}
}
In general I feel like the PHP community took a wild left turn, trying to be more like javascript and I feel that traits can walk you into a corner. This is a very good example of such a corner. I would really avoid them, at least for now. In the long run I believe Generics would be the better solution to your problem of needing a generic GetSet piece of code but generics haven't been implemented in php yet :-(.

Laravel : Dependency injection vs Facades?

What, I had been doing previously was to inject only MY MODELS using the constructor and use Facades for the Laravel's provided classes i.e. Session, Auth, Validator etc, for example. Will it be a good idea if I inject each and every class (either mine or Laravel's) through construct and use it by $this->.. syntax or should I inject my own classes using constructor and use Facades for anything provided by Laravel?
To be more specific, here is what my controllers normally look like:
class MyController extends BaseController
{
public function __construct( User $user, Bookmark $bookmark ) {
$this->user = $user;
$this->bookmark = $bookmark
}
public function foobar ( ) {
$user_id = Input::get('bar');
...
Session::get('someInfo');
...
return Redirect::to('/');
}
...
}
Should I structure my methods like controller like following, instead?
class MyController extends BaseController
{
public function __construct( User $user, Bookmark $bookmark, Input $input, Session $session, Redirect $redirect ) {
$this->user = $user;
$this->bookmark = $bookmark
$this->input = $input;
$this->session = $session;
$this->redirect = $redirect;
}
public function foobar ( ) {
$user_id = $this->input->get('bar');
...
$this->session->get('someInfo');
...
return $this->redirect->to('/');
}
...
}
Laravel now supports the same Dependency-Injection functionality for route-related methods of classes (not just constructors), such as controllers and middleware.
You could prevent unnecessary injections by only injecting to methods where the dependency is unique, perhaps leaving more common dependencies in the constructor:
class MyController extends BaseController
{
public function __construct( Input $input, Session $session, Redirect $redirect ) {
$this->input = $input;
$this->session = $session;
$this->redirect = $redirect;
}
public function foobar ( User $user, Bookmark $bookmark ) {
$user_id = $this->input->get('bar');
...
$this->session->get('someInfo');
...
return $this->redirect->to('/');
}
...
}
Conclusion
As for whether you should do it this way, that's up to you, but consider to:
First, use Dependency-Injection vs Facade (which also enables IDE auto-completion).
Then, wherever dependency is unique (and not required by most routes), use per-method injection vs constructor.
Because making all unique dependencies appear in method definition is easier to unit-test (and seems cleaner to me).
It is elegant and useful to inject certain classes, such as Request. In my opinion they should be specified in controller methods where they are needed, as they are then logically connected to the method implementation. Awesome thus far.
I find two facades to be problemmatic - App and Log. Neither are logically connected to a controller or its actions. App and Log are not inputs in any context. As App and Log are utility classes they are relevant to services and repositories as well, and it gets downright nasty if you type hint them in controllers and then pass them on as constructor or method parameters to your support classes.
An additional issue is that App facade does not implement the Illuminate\Contracts\Auth\Guard interface that it proxies, so my IDE lights up with warnings as static analysis is not possible.
For the sake of consistency and overall separation of concerns I would therefore instantiate both App and Log within a constructor or method, depending on how widespread they are used in a class. To make my IDE happy I created the below class to give me a properly typed instance wherever I need it:
<?php namespace App\Components;
use Illuminate\Contracts\Auth\Guard;
use Psr\Log\LoggerInterface;
/**
* Get the underlying object instances of facades from the container.
*/
class AppGlobal
{
/**
* Returns the global logger instance.
*
* #return LoggerInterface
*/
public static function log()
{
return app('log');
}
/**
* Returns the global auth instance, which internally proxies a guard.
*
* #return Guard
*/
public static function auth()
{
return app('auth');
}
}
If you need an object wit properties - put it in as an injection (e.g Input, Session...), otherwise, if you don't store any data in the object and pretty happy using class, than go with facades (e.g Log::..., Redirect::...).
Laravel has replaced many of it's facade with helpers for example
use Auth;
and
Auth::user()
is now just
auth()->user()
this makes thing simpler and neater (also prevents mistakes)
I would suggest using the helpers where possible and if no helper exists, use the facade because it is easier to mock than an injected instance.

PHP - How should the controller communicate data with the model layer in a proper MVC pattern

I have been researching so many times, asking experts on stackoverflow for the best practice, but I still could not find the solution, I might have got told the correct answer, but I didn't get it.
I always wanted to create a 'proper' MVC pattern to work on my projects, I have been researching for example this http://www.phpro.org/tutorials/Model-View-Controller-MVC.html but I got told that this is awful design, and I should not use the registery pattern anymore.
So I looked at teresko's answer, even though it's very old, can be seen here How should a model be structured in MVC? and I got the idea there, to use a global factory, which will create other factories
The idea I got from there, is to have a big factory, called ServiceFactory which will create instances of other factories like ModelFactory which will create instances of classes that are serving the model layer, and a ViewFactory, which will serve the view (Pretty useless at the moment I think).
But got something like this:
namespace library\application;
use library\application\exceptions\ClassNotFoundException;
use library\application\exceptions\PackageNotFoundException;
class ServiceFactory {
private $mapper;
private $package;
private $services = array();
public function __construct(DataMapper $mapper) {
$this->mapper = $mapper;
}
/**
* Setting a default package
* #param $package string Package path
* #throws exceptions\PackageNotFoundException
*/
public function setDefaultPackage($package) {
if (is_dir('library' . $package)) {
$this->package = 'library' . $package;
return;
}
throw new PackageNotFoundException("The package: " . $package . " was not found.");
}
/**
* #param $name string Class name
* #param null $constructor IF the class needs constructor parameters, use it.
* #return Factory
* #throws exceptions\ClassNotFoundException
*/
public function create($name, $constructor = null) {
$path = $this->package . "\\" . $name;
if (file_exists($path)) {
if ($constructor) {
return new $path($constructor);
}
return new $path;
}
throw new ClassNotFoundException("The requested class was not found: " . $path);
}
/**
* #param $name string Class name
* #param $object object Object to register
*/
public function register($name, $object) {
$this->services[$name] = $object;
}
/**
* #param $name string Class name
* #return Factory
*/
public function get($name) {
if (isset($this->services[$name])) {
return $this->services[$name];
}
return null;
}
}
This is awesome actually, but in my opinion, OO-wise, it's totally wrong, because it's not object-oriented friendly, since the returning object of S ServiceFactory::create() is anonymous, well fine, It's no longer anonymous, because the purpose of the class is to create instances of factories, sure, just added the interface of the factories in return.
But now the next problem, when I want to use the factories to create objects, that should not have the same interface, will cause problems to my IDE, since it doesn't know what is the object I am going to return, it can be Foo, can be Car and one day it can be HelloWorld.
So I always will have to declare a variable with the object when using it in the controller:
/**
* #var $items Items
* #var $categories CategoryModel
*/
$items = parent::getModelFactory()->create('Items');
$items->setDb(parent::getDatabase());
$categories = parent::getModelFactory()->create('Categories');
$categories->setDb(parent::getDatabase());
Now in one of Teresko's answer(s), it says the following rule: A controller can not create instances of the Model layer
So I assume he means like $foo = new Foo(); $foo->method($db); in the controller, but why not? how should a controller actually communicate the model layer?
The main purpose of me creating that god factory class, is to prevent doing new Object() in the controller class, but since it's calling the factory, which creates the instance, it's still considered as I am creating an instance of a model layer in a controller (I think).
I also could cache objects, using ServiceFactory::register() method, but that doesn't change the situation.
So is the ServiceFactory and factories idea fine ? What is the correct way communcating between the controller and the model layer?
Not really, but there aren't any rules in how to implement MVC as long as you have M V C clearly defined and C acts as a coordinator for M and V.
A factory of factories is clearly over engineering, if you don't need it don't implement it. What you need to understand in order to be easy for you to apply MVC is that 1) MVC is part of the UI layer and 2) Model refers to the bits of other layers (like, for example, Business, Persistence or Application/Service) which are used by the UI.
The controller always communicates directly to the Model, but depending on the use case, the Model means that bits of layers mentioned above. In a 'normal' app, it usually is like this: the controller uses an application service (the MVC Model) to update the business model. The service should be injected in the controller constructor.
For querying purposes, the controller can use a "querying service" or a query only repository so that it won't contain persistence logic (like writing sql). It still the same approach like above, only this time, the Model represents Persistence bits.
So you see, the Mvc Model is actually a facade for other layers used by UI and you want the controller not to have direct access to the business layer for example, because the controller should really just coordinate what model to change and what view model to be rendered. In contrast, an application service will implement an application use case using business/persistence objects.
Everything is really about respecting Separation of Concerns and Single Responsibility Principle

PhpStorm autocompletion in traits

I have a trait that must always be mixed in to a subclass of \PHPUnit_Framework_TestCase. PhpStorm doesn't know this. Is there anything I can do to get PhpStorm to autocomplete and "typecheck" things like assertNull inside the trait?
<?php
trait MyTestUtils
{
public function foo()
{
$this->assertNu // autocomplete?
}
}
The best I could come up with so far is putting the following in each method:
/** #var \PHPUnit_Framework_TestCase|MyTestUtils $this */
But this is repetitive and doesn't understand protected memebers. Is there a better option?
Besides using the php docblock to document $this, the only other way I'm aware of, which also, arguably makes your trait more "safe" anyway, is to define abstract methods on the trait itself, e.g.:
trait F {
/**
* #return string[]
*/
abstract public function Foo();
/**
* #return self
*/
abstract public function Bar();
}
abstract class Bar {
use F;
/**
* #return bool|string[]
*/
public function Baz () {
if ($this->Bar()) {
return $this->Foo();
}
return false;
}
}
UPDATE: Since PhpStorm 2016.1.2 (build 145.1616) autocompletion in traits works out-of-the-box. It is smart enough to figure out what classes use the trait, and then provide the autocompletion. Link to the issue: https://youtrack.jetbrains.com/issue/WI-16368
Previously replied with:
You can use:
#method \PHPUnit_Framework_TestCase assertTrue($condition, $message = '')
...in docblock of the trait itself, but the downside is that you'd need to put #method for each method that you'd like to have autocomplete for, which is not too bad if you're using a sane number of method calls in your trait. Or, "document" only those methods that you're using most often.
I would argue that this is not a valid use-case for a PHP trait. Your trait, as written is not guaranteed to only be used on classes that extend \PHPUnit_Framework_TestCase. This introduces very tightly coupled code. The best practice of Traits is for them to be very loosely coupled and only be aware of their own contents.
I would instead recommend that you either:
create a subclass of \PHPUnit_Framework_TestCase that your test cases that need this functionality can extend
create custom assertion classes. These can many times be used for doing groups of custom assertions.
Both techniques are detailed here: http://phpunit.de/manual/4.1/en/extending-phpunit.html
These are the two recommended best practices for where to place helper methods such as these.

Constructor-Injection when extending a class

This question is not strictly related to Symfony 2, but as I use Symfony 2 components and will later likely use a Symfony\Component\DependencyInjection\Container as DI-Container, it might be relevant.
I am currently building a small library using components from Symfony 2, e.g. HttpFoundation, Validator, Yaml. My Domain Services are all extending a basic AbstractService providing nothing but Doctrine\ORM\EntityManager and Symfony\Component\Validator\Validator via Constructor-Injection like this:
abstract class AbstractService
{
protected $em;
protected $validator;
/**
* #param Doctrine\ORM\EntityManager $em
* #param Symfony\Component\Validator\Validator $validator
*/
public function __construct(EntityManager $em, Validator $validator)
{
$this->em = $em;
$this->validator = $validator;
}
}
A Service-class extending this AbstractService may now need to inject additonal components, like Symfony\Component\HttpFoundation\Session. As of I do it like this:
class MyService extends AbstractService
{
/**
* #var Symfony\Component\HttpFoundation\Session
*/
protected $session;
/**
* #param Symfony\Component\HttpFoundation\Session $session
* #param Doctrine\ORM\EntityManager $em
* #param Symfony\Component\Validator\Validator $validator
*/
public function __construct(Session $session, EntityManager $em, Validator $validator)
{
parent::__construct($em, $validator);
$this->session = $session;
}
}
Is there a more elegant way to solve this without having to reiterate the parent's constructor arguments, e.g. by using Setter-Injection for Session instead?
As I see it, when I use Setter-Injection for Session, I have to add checks before accessing it in my methods, whether it is already injected, which I want to avoid. On the other hand I don't want to "repeat" injecting the basic components shared by all services.
An alternative would be not to extend your Services from the abstract type. Change the abstract type to a real class and then inject it to your Services, e.g.
class MyService
…
public function __construct(ServiceHelper $serviceHelper)
{
$this->serviceHelper = $serviceHelper;
}
}
Yet another option would be to not pass the dependencies until they are needed, e.g.
class MyService
…
public function somethingRequiringEntityManager($entityManager)
{
// do something with EntityManager and members of MyService
}
}
Is there a more elegant way to solve this without having to reiterate the parent's constructor arguments, e.g. by using Setter-Injection for Session instead?
Well, by using setter-injection like you've mentioned. Apart from that I see two possible solutions to your immediate problem:
Make the parent constructor accept a Session object as well, but make it null by default. This to me is ugly, since the parent doesn't actually need the session object, and if you have other implementations, this will result in a long parameter list for the parent constructor, so this is actually not really an option.
Pass in a more abstract object. Be it a ParameterObject for that specific type of object, or just a simple Registry, this should work. Again; not preferable and as you're using dependency injection, you probably already know why.
I do have to ask though; where's the harm in using your current way? I don't actually see the downside. I'd just go ahead and carry on. If you discover you're using even more parameters in the constructor, think about what the service's intentions are and why it needs it, chances are that particular pieces of behaviour can be moved to the objects you're requesting instead.
Well you could use singleton for the Session class and access it's instance anywhere, but that might not be an option if you want to restrict it's usage.
But then again Session::getInstance()->getStuff seem's pretty much the same as $this->session->getStuff so to answer your question - I don't think there's much of a choice here and you approach seems fine.
Oh and like Gordon said: you shouldn't change the order of the arguments.
I went through the same problem while developing my Abstract Controller Bundle — when controllers are defined as services — and ended up using the setter injection in the base class.

Categories