I've been changing my Controllers and helper classes to use dependency injection, and it seems I've got my helper classes stuck in an infinite loop.
Below is my custom ServiceProvider and the two sample helper classes. As you can see, they inject each other, so they keep going back and forth.
What's the solution to this issue? What mistake do I seem to be making? What can I do so that I can run tests on helper classes like General and Person, while mocking the helper classes that are called from inside of them?
One way that I guess could work is in my ServiceProvider, do the following:
if (isset($appmade->General)) {
// inject the General app that's already instantiated
} else {
$abc = app::make('\Lib\MyOrg\General');
$appmade->General = $abc;
}
Is that the correct way?
// /app/providers/myorg/MyOrgServiceProvider.php
namespace MyOrg\ServiceProvider;
use Illuminate\Support\ServiceProvider;
class MyOrgServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('\Lib\MyOrg\General', function ($app) {
return new \Lib\MyOrg\General(
$app->make('\Lib\MyOrg\Person'),
$app->make('\App\Models\User')
);
});
$this->app->bind('\Lib\MyOrg\Person', function ($app) {
return new \Lib\MyOrg\Person(
$app->make('\Lib\MyOrg\General'),
$app->make('\App\Models\Device')
);
});
}
}
// /app/libraries/myorg/general.php
namespace Lib\MyOrg;
use App\Models\User;
use Lib\MyOrg\Person;
class General
{
protected $model;
protected $class;
public function __construct(Person $personclass, User $user)
{
}
}
// /app/libraries/myorg/person.php
namespace Lib\MyOrg;
use App\Models\Device;
use Lib\MyOrg\General;
class Person
{
protected $model;
protected $class;
public function __construct(General $generalclass, Device $device)
{
}
}
Your helper classes have a case of circular dependency which, when mixed with dependency injection, make them un-instantiable...and there's no good way to get them to work and be easily testable.
There are some hack-y ways to get this to work:
You could use setter injection, injecting the dependency in a
setter method when the helper is used, rather than in the constructor
when it is instantiated. This has many disadvantages, poor
testability being chief among them. (See
http://symfony.com/doc/current/components/dependency_injection/types.html)
In Laravel 5, you could use method injection, particularly if the
dependency is only pertinent to one or two methods. (See
http://mattstauffer.co/blog/laravel-5.0-method-injection)
You could do an existence check like you propose above, or something
with an event listener. But all of this is masking the fact that...
A circular dependency usually indicates that a design change is in order, and is best solved by reconsidering how your classes interact with each other.
If your Person and General classes depend fully on each other, then
it's possible they share a single responsibility and should be
combined into a single class.
If, however, they rely on a subset of each other's functionality,
then there's probably a separate class with its own responsibility
hiding in there somewhere, and then the best solution would be
extract the common functionality into a 3rd class. That way, rather
than having Class A rely on Class B and Class B rely on Class A, both
Classes A and B would instead rely on Class C. You can safely
instantiate them all, and they all remain easily testable.
How can you easily figure out what your new Class C should contain? A great rule of thumb comes from http://misko.hevery.com/2008/08/01/circular-dependency-in-constructors-and-dependency-injection/... "List all of the methods in your class A used by class B, and all the methods in your class B used by class A. The shorter of the two lists is your hidden Class C."
Related
Sorry if this is a duplicate question or a common design principle, I have searched around but was unable to find any answers to this question. I'm probably just searching with the wrong keywords.
I have been looking at a popular library Sabre/Event (https://sabre.io/event/) and in the code there is a simple class/inheritance model that I am trying to understand:
The class EventEmitter implements EventEmitterInterface and uses EventEmitterTrait (see below for code).
There is a comment in EventEmitterTrait above the class which says:
* Using the trait + interface allows you to add EventEmitter capabilities
* without having to change your base-class.
I am trying to understand why this comment says this, and why it allows adding capabilities without changing the base class, and how that is different from just putting the routines into EventEmitter itself.
Couldn't you just extend EventEmitter and add capabilities in the derived class?
Simplified code:
// EventEmitter.php
class EventEmitter implements EventEmitterInterface {
use EventEmitterTrait;
}
// EventEmitterInterface.php
interface EventEmitterInterface {
// ... declares several function prototypes
}
// EventEmitterTrait.php
trait EventEmitterTrait {
// ... implements the routines declared in EventEmitterInterface
}
You're basically asking two questions here.
What are interfaces and why are they useful?
What are traits and why are they useful?
To understand why interfaces are useful you have to know a little about inheritance and OOP in general. If you've ever heard the term spaghetti code before (it's when you tend to write imperative code that's so tangled together you can hardly make sense of it) then you should liken that to the term lasagna code for OOP (that's when you extend a class to so many layers that it becomes difficult to understand which layer is doing what).
1. Interfaces
Interfaces diffuse some of this confusion by allow a class to implement a common set of methods without having to restrict the hierarchy of that class. we do not derive interfaces from a base class. We merely implement them into a given class.
A very clear and obvious example of that in PHP is DateTimeInterface. It provides a common set of methods which both DateTime and DateTimeImmutable will implement. It does not, however, tell those classes what the implementation is. A class is an implementation. An interface is just methods of a class sans implementation. However, since both things implement the same interface it's easy to test any class that implements that interface, since you know they will always have the same methods. So I know that both DateTime and DateTimeImmutable will implement the method format, which will accept a String as input and return a String, regardless of which class is implementing it. I could even write my own implementation of DateTime that implements DateTimeInterface and it is guaranteed to have that method with that same signature.
So imagine I wrote a method that accepts a DateTime object, and the method expects to run the format method on that object. If it doesn't care which class, specifically, is given to it, then that method could simply typehint its prototype as DateTimeInterface instead. Now anyone is free to implement DateTimeInterface in their own class, without having to extend from some base class, and provide my method with an object that's guaranteed to work the same way.
So in relation to your EventEmitter example, you can add the same capabilities of a class (like DateTime) to any class that might not even extend from DateTime, but as long as we know it implements the same interface, we know for sure it has the same methods with the same signatures. This would mean the same thing for EventEmitter.
2. Traits
Traits, unlike interfaces, actually can provide an implementation. They are also a form of horizontal inheritance, unlike the vertical inheritance of extending classes. Because two completely different class that do not derive from the same base class can use the same Trait. This is possible, because in PHP traits are basically just compiler-assisted copy and paste. Imagine, you literally copied the code inside of a trait and just pasted it into each class that uses it right before compile time. You'd get the same result. You're just injecting code into unrelated classes.
This is useful, because sometimes you have a method or set of methods that prove reusable in two distinct classes even though the rest of those classes have nothing else in common.
For example, imagine you are writing a CMS, where there is a Document class and a User class. Neither of these two classes are related in any meaningful way. They do very different things and it makes no sense for one of them to extend the other. However, they both share a particular behavior in common: flag() method that indicates the object has been flagged by a user for purposes of violating the Terms of Service.
trait FlagContent {
public function flag(Int $userId, String $reason): bool {
$this->flagged = true;
$this->byUserId = $userId;
$this->flagReason = $reason;
return $this->updateDatabase();
}
}
Now consider that perhaps your CMS has other content that's subject to being flagged, like a Image class, or a Video class, or even a Comment class. These classes are all typically unrelated. It probably wouldn't make much sense just to have a specific class for flagging content, especially if the properties of the relevant objects have to be passed around to this class to update the database, for example. It also doesn't make sense for them to derive from a base class (they're all completely unrelated to each other). It also doesn't make sense to rewrite this same code in every class, since it would easier to change it in one place instead of many.
So what seems to be most sensible here is to use a Trait.
So again, in relation to your EventEmitter example, they're giving you some traits you can reuse in your implementing class to basically make it easier to reuse the code without having to extend from a base class (horizontal inheritance).
Per Sabre's Event Emitter's docs on "Integration into other objects":
To add Emitter capabilities to any class, you can simply extend it.
If you cannot extend, because the class is already part of an existing
class hierarchy you can use the supplied trait.
So in this case, the idea is if you're using your own objects that already are part of a class hierarchy, you may simply implement the interface + use the trait, instead of extending the Emitter class (which you won't be able to).
The Integration into other objects documentation says:
If you cannot extend, because the class is already part of an existing class hierarchy you can use the supplied trait".
I understand it's a workaround when you already have an OOP design you don't want to alter and you want to add event capabilities. For example:
Model -> AppModel -> Customer
PHP doesn't have multiple inheritance so Customer can extend AppModel or Emitter but not both. If you implement the interface in Customer the code is not reusable elsewhere; if you implement in e.g. AppModel it's available everywhere, which might not be desirable.
With traits, you can write custom event code and cherry-pick where you reuse it.
This is an interesting question and I will try to give my take on it. As you asked,
What is the purpose of using traits to define functions for an interface ?
Traits basically gives you the ability to create some reusable code or functionality which can then be used any where in your code base. Now as it stands, PHP doesn't support multiple inheritance therefore traits and interfaces are there to solve that issue. The question here is why traits though ?? Well imagine a scenario like below,
class User
{
public function hasRatings()
{
// some how we want users to have ratings
}
public function hasBeenFavorited()
{
// other users can follow
}
public function name(){}
public function friends(){}
// and a few other methods
}
Now lets say that we have a post class which has the same logic as user and that can be achieved by having hasRatings() and hasBeenFavorited() methods. Now, one way would be to simply inherit from User Class.
class Post extends User
{
// Now we have access to the mentioned methods but we have inherited
// methods and properties which is not really needed here
}
Therefore, to solve this issue we can use traits.
trait UserActions
{
public function hasRatings()
{
// some how we want users to have ratings
}
public function hasBeenFavorited()
{
// other users can follow
}
}
Having that bit of logic we can now just use it any where in the code where ever it is required.
class User
{
use UserActions;
}
class Post
{
use UserActions;
}
Now lets say we have a report class where we want to generate certain report on the basis of user actions.
class Report
{
protected $user;
public function __construct(User $user)
{
$this->user = $user
}
public function generate()
{
return $this->user->hasRatings();
}
}
Now, what happens if i want to generate report for Post. The only way to achieve that would be to new up another report class i.e. maybe PostReport.. Can you see where I am getting at. Surely there could be another way, where i dont have to repeat myself. Thats where, interfaces or contracts come to place. Keeping that in mind, lets redefine our reports class and make it to accept a contract rather than concrete class which will always ensure that we have access to UserActions.
interface UserActionable
{
public function hasRatings();
public function hasBeenFavorited();
}
class Report
{
protected $actionable;
public function __construct(UserActionable $actionable)
{
$this->actionable = $actionable;
}
public function generate()
{
return $this->actionable->hasRatings();
}
}
//lets make our post and user implement the contract so we can pass them
// to report
class User implements UserActionable
{
uses UserActions;
}
class Post implements UserActionable
{
uses UserActions;
}
// Great now we can switch between user and post during run time to generate
// reports without changing the code base
$userReport = (new Report(new User))->generate();
$postReport = (new Report(new Post))->generate();
So in nutshell, interfaces and traits helps us to achieve design based on SOLID principles, much decoupled code and better composition. Hope that helps
What it is the best way to implement a dependency injection, this way:
new App\Controllers\HomeController();
Class HomeController
use App\Views\HomeView;
class HomeController {
private $view;
public function __construct() {
$this->view = new HomeView();
or this way:
new App\Controllers\HomeController(new App\Views\HomeView());
Dependency injections is usually (if not always) done via a IoC (Inversion of control) - container. The container, or rather it's dependency injection logic takes care of creating the objects and through some magic fetches all the parameters expected to be added and creates them, also from the containers dependency injection logic.
What you are doing is rather just creating new objects. You could do that either way you wish, but personally I would probably pass the view through the constructor.
If you wish to read more about dependency injection and containers, id refer to the wiki entry about it.
You can also take a look at one of my naive implementations of a dependency container using php reflections here if you wish!
Samples you've provided reflect totally different approaches (I've left class naming same as you have):
// App/Controllers/HomeController.php
use App\Views\HomeView;
class HomeController {
private $view;
public function __construct() {
$this->view = new HomeView();
}
}
This is not dependency injection, you create the stuff your class depends on inside the class.
Compare to:
// App/Controllers/HomeController.php
use App\Views\HomeView;
class HomeController {
private $view;
public function __construct(HomeView $view) {
$this->view = $view;
}
}
This is actually dependecy injection: whatever your class needs is created outside of the class and passed to it via constructor (in this particular case).
Some tool (dependency injection container) may or may not be used to manage the dependencies depending on your case.
To get some more details please see the article https://martinfowler.com/articles/injection.html by Martin Fowler and search here on SO - the topic is extensively covered (What is dependency injection?, What is Dependency Injection?, When to use Dependency Injection).
So ive finally gotten round to playing with traits and they are very handy, the problem that i have been having is that i want to have some traits to add functionality to my data objects.
In of itself this is simple except that in doing so im using methods that are defined in my base data object
abstract class Base_Object {
protected function _addToUpdate($field, $value) {
...
}
...
}
trait Extended_Object {
public function doSomeStuff() {
...
$this->_addToUpdate($someVar, $someOtherVar);
}
...
}
class User extends Base_Object {
use Extended_Object;
...
}
My problem is then if someone else in my team decides to use the Extended_Object trait on an object that doesnt extend Base_Object. I had thought about putting a check in the _addToUpdate method but ideally i would like an error to be shown when creating the instance.
I have come up with a solution that works but makes me feel a bit dirty and is far from ideal
abstract class Base_Object {
protected function _addToUpdate($field, $value) {
...
}
...
}
trait Extended_Object {
abstract protected function _addToUpdate($field, $value);
public function doSomeStuff() {
...
$this->_addToUpdate($someVar, $someOtherVar);
}
...
}
class User extends Base_Object {
use Extended_Object;
...
}
By adding an abstract method to the Extended_Object i then can at least be sure that an error will be show if the method i need in Base_Object isnt present but i am not guaranteed that the method in question will actually do what i want it to do.
Ideally i would like to be able to run something like the code below when an object is instantiated using the Extended_Object trait
if (!($this instanceof Base_Object)) {
throw new Inheritance_Exception("Base_Object");
}
Im hoping that someone has found a way to do this or at least a better solution than mine.
Note: i know that i could do this with a constructor but that would only be viable when using a single trait if i decided at a later date to create anther few object extension traits its going to get very messy very quickly
Edit: i do realize that traits arnt really designed for what im trying to do but they do at least in part allow me to get around the problem of single inheritance and i know im not the only dev planning to use them in this way
Well (IMHO) the problem exists with the way you are using traits which is technically anti-pattern.
First, What are traits and why should I use them:
To quote from one of the comments in php.net
The best way to understand what traits are and how to use them is to
look at them for what they essentially are: language assisted copy
and paste.
If you can copy and paste the code from one class to another (and
we've all done this, even though we try not to because its code
duplication) then you have a candidate for a trait.
Now even that traits lets you use members of the class which is using them, that does not mean you should do that. back to SRP, this is a real violation.
PHP lets you do echo $_POST['XSS data'] but that does not mean you should do it. So, regardless to the way you want to strict your trait usage, what you are actually doing is that you are introducing the issue and you are trying to solve it
so to answer your question, simply redesign your code in order for you not to use class methods and members based on an assumption that each class which will use the trait should have these methods and members.
I think your solution with an abstract function is precisely what that facility is intended for. I agree with your gut feeling:
i am not guaranteed that the method in question will actually do what i want it to do
However, this is the same assumption you make whenever you use an interface: the only thing that is asserted is that a method exists with the correct signature (which in PHP amounts mostly to its name and number of parameters). There is no way to know that the function actually behaves in a particularly useful way when given those parameters.
In the case of a trait, an abstract method is effectively the same kind of contract as an interface: "in order to use this trait, you must provide these pre-requisites".
I would also note that common description of traits is "automated copy and paste", so it should generally be thought of as separate from object hierarchies. More technically, it represents "horizontal code reuse", not "multiple inheritance". For example, you can define a trait that allows a class to implement an interface, but to the outside code, it is the interface that is important, not the trait.
I am faced with a similar problem, however with multiple subclasses inheriting from the base class.
It would make sense at this point to put trait abstract declarations into some sort of include file and as a trait itself, e.g.:
abstract class Base_Object {
use BaseObjectTrait;
...
}
trait BaseObjectTrait {
protected function _addToUpdate($field, $value) {
...
}
}
trait BaseObjectTraitPrototypes {
abstract protected function _addToUpdate($field, $value);
}
trait Extended_Object {
use BaseObjectTraitPrototypes;
public function doSomeStuff() {
...
$this->_addToUpdate($someVar, $someOtherVar);
}
...
}
class User extends Base_Object {
use Extended_Object;
...
}
Can anyone think of a more elegant solution than this? I'm using the term 'prototype' very loosely here from a C programming sense. 'Header' files are likewise from a C programming context but still not ideal. Can anyone think of a more concise concept for the problem domain, something php-fig acceptable perhaps?
My problem is then if someone else in my team decides to use the Extended_Object trait on an object that doesnt extend Base_Object.
:
Ideally i would like to be able to run something like the code below when an object is instantiated using the Extended_Object trait
if (!($this instanceof Base_Object)) {
throw new Inheritance_Exception("Base_Object");
}
Maybe I'm missing something, but if this trait should only ever be applied to instances of Base_Object, then it sounds as if this "trait" should be a subclass of the Base_Object and not a trait at all?
The User class then extends this Extended_Object (a subclass), rather than useing the Extended_Object (a trait).
From: http://php.net/manual/en/language.oop5.traits.php
A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies.
I'm trying to get some service (e.g. session) from outside of controller.
Please, explain how to do this right-way.
There are many different ways, all having pros and cons.
First, every service is some kind of object, so you can always just create the object in question yourself. You may be forced to deal with many references, but it's possible. This undermines the idea of Dependency Injection, so it's not what you should do!
The second way is inject the service into your class:
class MyClass{
public function __construct($session){
// ...
}
}
class MyContainer extends Controller{
public function SomeKindOfAction(){
$myClass = new MyClass($this->get('session'));
}
}
This might be ok if you only use the class within your Controller. If you have more nested relations, like in MyClass, you create another class where you need the session, you might run into tight coupling (which is to avoid) as well as complexity issues.
The best way is to create your own service and injecting the things you need there. There are many documentations out there, so I'll just give a short example using MyClass above.
services.yml:
services:
my.myClass:
class: /Acme/DefaultBundle/MyStuff/MyClass
arguments: ["#session"]
Now your Class is as service (who would guess it's that easy!) and you can use it within your controller:
class MyContainer extends Controller{
public function SomeKindOfAction(){
$myClass = $this->get('my.myClass');
}
}
Now you don't have to think about constructor and how to get your objects, the DI-Container will do it for you. If you want to know more, read here.
I have an application in which a number of objects are all extending an abstract class which defines methods like create() edit() retrieve() and delete(). Since each of the child classes use the same logic for these functions, the abstract class defines that default behaviour, and in the few cases where it needs to be augmented, the child classes can override or use the hooks I've built in.
Now I'm having the situation where some of the child classes need to be made immutable, meaning that they shouldn't have edit() or delete() methods. This need sounds to me like a job for an interface named something like immutable which the immutable classes could implement. Problem is that interfaces don't stop methods from being called, they just enforce a method's existence. So this is obviously not going to work.
Making two parent classes, one for mutable objects and one for immutable ones is ugly and is probably asking for problems down the line which maintenance. I could have the immutable objects override the offending methods with an empty method that did nothing, but that also seems messy and like I'm not doing proper OOP at that point.
So what would you suggest as the best way to allow a large set of classes to all inherit a set of methods, but for some of them to not inherit all of the methods? (The application in question is written php, but general OOP techniques from any language can still be helpful).
create an immutable-base class as a child of the base class.
the immutable-base should implement final overrides of edit() and delete() which do nothing or throw an error.
Final, so that all immutable children are guaranteed not to be able to edit or delete
bonuses of this strategy
easily check if an object is immutable by testing for instanceof immutable-base
easily change objects from immutable and back again by modifing what it extends
Actually creating classes that have empty methods or throw errors is bad - such methods are confusing, they take up space and do nothing.
A better approach would be to make the immutable class the base class and make the mutable class extend it with adding methods for modification. This way each class has only those methods, that really belong there.
I like Java's approach to this. Throw an exception. Create an UnsupportedOperationException and for those implementations that shouldn't use a specific method throw one to let the user know they can't use this functionality for this implementation.
Another thought I wanted to throw out as a possible solution. Classes could implement an interface that looks like the following:
Interface Immutable {
const immutable = true;
}
and then the Base abstract class can write the delete() and edit() methods with
if (!$this->immutable) {
//do_stuff
}
This would also extend well to other classifications of class, like NonDeletable and NonEditable to allow for more fine grained behaviour.
Here is super short workaround, make your method final and start it with:
if(self::class!=static::class) return;#or throw an error
It will not prevent inheritance itself, but methods will not work in children classes (with error or without - is up to you).
As of PHP 5.4, you can use Traits.
For example, you could make a base class that only includes the methods that all child classes have:
class EntityManager {
public function create() {/*...*/}
public function retrieve() {/*...*/}
}
Then you could define a couple of traits:
trait EditTrait {
public function edit() {/*...*/}
}
trait DeleteTrait {
public function delete() {/*...*/}
}
You would then create an immutable child class like this:
class LogManager extends EntityManager {
...
}
And a mutable child class like this:
class ContactManager extends EntityManager {
use EditTrait;
use DeleteTrait;
...
}
Traits have some advantages over some of the other solutions here such as:
No duplication of code.
Single base class.
Methods that don't work or don't make sense, don't appear on classes that don't support them (especially important for docs and apis).