EzDevInfo.com

PHP-DI

The dependency injection container for humans PHP-DI - The Dependency Injection Container for humans php-di is a dependency injection container for php that intends to be practical and powerful

Getting started PHP-DI without any 3rd party framework

I am just now discovering dependency injection and I want to apply it to a medium sized project which I've been working on. I already have a classes folder which holds all the classes used in the system

/application/core/classes

I would like to know how I can configure PHP-DI to locate these classes according to how they are required.

Thanks in advance


Source: (StackOverflow)

PHP-DI Register Instance for ctor Injection

I'm using php-di and am using twig in my project. I'd like to register the instance of $twig with php-di so that its instance is injected into the ctor argument on objects where it's needed. I'd like to use php definitions and avoid phpdoc annotations, and have read this http://php-di.org/doc/php-definitions.html

Here's my basic example:

$builder = new ContainerBuilder();
$builder->addDefinitions(['Twig_Environment' => $twig]);
$container = $builder->buildDevContainer();

Then I have $twig as a ctor argument in some other classes. Is this even possible? To be clear, I don't want to have to create a definition for each object that uses $twig.

public function __construct(\Twig_Environment $twig)
{
    $twig->render('homepage.twig');
}

The error I'm getting indicates that php-di is trying to create a new instance of Twig_Environment instead of using the instance already created.


Source: (StackOverflow)

Advertisements

How can I override a DI container dependency with a specific instance?

Imagine we have a Request object and a Controller object. The Controller object is constructed with a Request object, like so:

abstract class Controller {

    public $request;

    public function __construct(Request $request)
    {
        $this->request = $request;
    }

}

As you can see, this is an abstract class, so in reality a subclass of Controller will be constructed. Let's imagine the code is something like this:

// Instantiate the request.
$request = new Request($params); 

// Instantiate the registration controller.
$controller = new RegistrationController($request);

Now let's say that we add a dependency to our RegistrationController, like so:

class RegistrationController extends Controller {

    private $user_repo;

    public function __construct(Request $request, UserRepo $user_repo)
    {
        parent::__construct($request);

        $this->user_repo = $user_repo;
    }

}

At this point, what I'd like to do is introduce a dependency injection container to automatically inject the dependencies via the constructor. For this, I've been using PHP-DI. Usually, this would go something like so:

// Instantiate the registration controller.
$controller = $container->get('RegistrationController');

This would then instantiate RegistrationController with an instance of Request and an instance of UserRepo. It'd know to construct with those objects thanks to reflection, but if I wanted I could also override this via a configuration file.

The problem is that the Request object takes a parameter which is dynamic. I need the Request object passed to RegistrationController to be a specific instance, one I've just created.

I essentially want to be able to say: "Give me an instance of this class with all of its dependencies injected, but for a particular parameter, pass in this specific instance".

I've looked to see if PHP-DI (and a hand-full of other DI containers) support this kind of "override" for specific parameters, but so far I can't find anything.

What I want to know is:

  • Is there a DI container out there that can do this?
  • Is there an alternative approach which would leave the classes clean (I don't want to use annotations or anything else that'll add the container I use as a dependency)?

Source: (StackOverflow)

Why to use Dependency Injection components in PHP frameworks

When I first saw dependency injection components like PHP-DI, Symfony2 DI, etc., I though, there is a way to automatically inject instance of any class to any just with one instantiation.

So 1. Create instance in root class like $foo = new Foo() 2. And then I can use this instance in any object (like global singleton) without passing reference to constructor or method of the class I want to call from.

But I found out, that basicly I can use Dependency Injection in 2 ways 1. Passing the reference of the instance to constructor 2. Creating container where all objects are located. This container could be injected to other classes, but "This is not recommended".

As both ways can be easily done in pure PHP, the first is clear, the second could be solved with static properties, so why to use PHP-DI or Symfony2 for this work?


Source: (StackOverflow)

PHP-DI annotation not working

I have installed php-di 4.4 in a new custom project using composer.Im runing a xampp localhost with php 5.6.3 but I set netbeans for php 5.4 on this project. Im new to php-di, I did use annotations in my android projects but cant seem to make it work here. The code is simple, im testing out the injection to see how it works, here is the code:

// composer autoload
require_once __DIR__ . '/vendor/autoload.php';

// injection entry point
$builder = new DI\ContainerBuilder();
$container = $builder->build();

class ClassA
{
    public function methodA()
    {
        echo 'methodA';
    }
}
class ClassB
{
    /**
     * @Inject
     * @var ClassA
     */
    public $param;

    public function methodB()
    {
        $this->param->methodA();
    }
}

$b = new ClassB();
$b->methodB();

this is the error that i get: Call to a member function methodA() on null in D:\Projects\profi\test.php on line 27

It's basic implementation I don't understand why it does not inject.

Thank you in advance.


Source: (StackOverflow)

PHP-DI is not working in integration with ZendFramework2

Could you please give a hint why PHP-DI integration with Zend Framework 2 is not working for me (reproduced with Apache/2.4.9 (Win64) PHP/5.5.12 and Apache/2.2.22 (Win32) PHP/5.3.13).

composer.json:

{
    "require": {
        "php": ">=5.3.3",
        "zendframework/zendframework": "2.3.5",
        "mnapoli/php-di": "4.4.6",
        "mnapoli/php-di-zf2": "0.3.0",
       ...
},
    ...

config\application.config.php:

<?php
return array(
    'modules' => array(
        'Morpho',
        'DI\ZendFramework2',
    ),
    'module_listener_options' => array(
        'module_paths' => array(
            './module',
            './vendor',
        ),
    ),
);
?>

module/Morpho/config.module.config.php:

<?php
return array(
    'service_manager' => array(
        'factories' => array(
            'DI\Container' => function() {
                $builder = new DI\ContainerBuilder();
                $builder->addDefinitionsFromFile("config/di.yml");
                return $builder->build();
            },
        ),
    ),
    'router' => array(
        ...
    ),
    'controllers' => array(
        ...
    ),
    'view_manager' => array(
        ...
    ),
);

config/di.yml:

Morpho\Service\PartOfSpeechService:
    class: Morpho\Service\PhpMorphyPartOfSpeechService

module/Morpho/src/Morpho/Controller/PartOfSpeechController:

class PartOfSpeechController extends AbstractRestfulController {
    ...
    /**
     * @Inject
     * @var PartOfSpeechService
     */
    public $partOfSpeechService;

    public function processPostData(Request $request) {
        $partsOfSpeech = $this->partOfSpeechService->getPartsOfSpeech("test", "en_EN");
        return new JsonModel($partsOfSpeech);
    }
}

When running this code under apache each time I get:

PHP Fatal error:  Uncaught exception 'Zend\ModuleManager\Exception\RuntimeException'
with message 'Module (DI\ZendFramework2) could not be initialized.' in \vendor\zendframework\zendframework\library\Zend\ModuleManager\ModuleManager.php:195
Stack trace:
0 \vendor\zendframework\zendframework\library\Zend\ModuleManager\ModuleManager.php(169): Zend\ModuleManager\ModuleManager->loadModuleByName(Object(Zend\ModuleManager\ModuleEvent))
1 \vendor\zendframework\zendframework\library\Zend\ModuleManager\ModuleManager.php(96): Zend\ModuleManager\ModuleManager->loadModule('DI\ZendFramewor...')
2 [internal function]: Zend\ModuleManager\ModuleManager->onLoadModules(Object(Zend\ModuleManager\ModuleEvent))
3 \vendor\zendframework\zendframework\library\Zend\EventManager\EventManager.php(468):
call_user_func(Array, Object(Zend\ModuleManager\ModuleEvent))
4 \vendor\zendframework\zendframework\library\Zend\EventManager\EventManager.php(207): Zend\EventM in \vendor\zendframework\zendframework\library\Zend\ModuleManager\ModuleManager.php on line 195

Any your thoughts would be really appreciated.


Source: (StackOverflow)

JMS DIExtraBundle / Annotations beyond Symfony Applications

I am currently developing a symfony application in which I want to have loose coupling of the business logic and the framework. I don't want to depend on the whole symfony framework and may be able exchange the framework later (and run my business logic outside of a bundle).

The Symfony DI Container is an independent component, which may be used without the whole symfony framework. So I basically can handle my dependencies with this component (in a yml file, via PHP, etc.).

Assume, I want to configure the dependencies with annotations using the JMSDiExtraBundle. Is there any possibility to use this bundle outside of an symfony application? If not, what may be the best option, to handle my dependencies? I would like to use annotations :)

  • Configure the Container with PHP, Yaml or anything else and work without annotations
  • Use another DI Container in combination with the Symfony one, which offers annotations (e.g. PHP-DI)
  • Do not build the applicatoin independently from symfony and don't ever exchange the framework.

Source: (StackOverflow)

How to set PHP-DI definition to PHPActiveRecord Connection?

I'm a beginner about Dependency Injection and I'm using the following tools into my PHP 5.5.9 (under Apache2 and MySql) project:

All my classes use to be autoloaded by composer.

I already got some insight about PHP-DI Definitions by reading it's docs and running it's examples related to autowiring , annotations and config and I've been put it to work with my own classes, but now I'm stuck about how to set vendor libraries such as PHPActiveRecord.

Usually to use PHPActiveRecord all you need is to define connections settings like this:

$cfg = ActiveRecord\Config::instance();
$cfg->set_model_directory('/path/to/your/model_directory');
$cfg->set_connections(
    ['development' => 'mysql://username:password@localhost/database_name']
);

Or this:

ActiveRecord\Config::initialize(function($cfg)
{
    $cfg->set_model_directory('/path/to/your/model_directory');
    $cfg->set_connections(['development' =>
    'mysql://username:password@localhost/database_name']);
});

Finally your models should extends ActiveRecord\Model and you're ready to go.

For now I'm trying to inject my ActiveRecord models into controllers by using annotations such as PHP-DI's documentation suggests:

<?php

    namespace Controller;

    use Model\User;

    class TestController
    {
        /**
        * @Inject
        * @var User
        */
        protected $user;

        public function index()
        {
            echo $this->user->retrieveStatus();
        }
    }

Here I got the error:

Fatal error: Uncaught exception 'ActiveRecord\DatabaseException' with message 'Empty connection string' in /home/ubuntu/workspace/vendor/php-activerecord/php-activerecord/lib/Connection.php:105 

Stack trace: 
#0 /home/ubuntu/workspace/vendor/php-activerecord/php-activerecord/lib/ConnectionManager.php(33): ActiveRecord\Connection::instance(NULL) 
#1 /home/ubuntu/workspace/vendor/php-activerecord/php-activerecord/lib/Table.php(117): ActiveRecord\ConnectionManager::get_connection(NULL) 
#2 /home/ubuntu/workspace/vendor/php-activerecord/php-activerecord/lib/Table.php(93): ActiveRecord\Table->reestablish_connection(false) 
#3 /home/ubuntu/workspace/vendor/php-activerecord/php-activerecord/lib/Table.php(74): ActiveRecord\Table->__construct('Model\User') 
#4 /home/ubuntu/workspace/vendor/php-activerecord/php-activerecord/lib/Model.php(749): ActiveRecord\Table::load('Model\User') 
#5 /home/ubuntu/workspace/vendor/php-activerecord/php-activerecord/lib/Model.php(262): ActiveRecord\Model::table() 
#6 [internal function]: ActiveRecord\Model- in /home/ubuntu/workspace/vendor/mnapoli/php-di/src/DI/Definition/Resolver/ClassDefinitionResolver.php on line 276

As it seems, no string connection provided to ActiveRecord.

I just believe that I need a proper File Configuration setting (DI\factory I think) to return a ActiveRecord\Config instance based on the connection definitions above.

Another point the bring me worries is that PHPActiveRecord have a considerable amount of Singletons and statics functions into it's API and as far as I know it's considered an anti-pattern due to kinda tight coupling issues and it seems no good to DI's management once in this cases there's no well defined "injection points" such as constructor and/or setter injections.

If you think I'm not clear enough about my problem, aske me for and I can provide more info.


Source: (StackOverflow)