M
M
Miku Hatsune2015-12-11 15:44:40
PHP
Miku Hatsune, 2015-12-11 15:44:40

Am I using PHP-DI correctly?

DI itself - php-di.org
It seems that I understood the essence of the pattern, but did not understand how to apply it ...
For example, here is the code (Simplified and put together for an example):

<?php
require_once '../vendor/autoload.php';

use DI\ContainerBuilder;

$di = ContainerBuilder::buildDevContainer();

$di->set('db', new class {
  public function getRow ()
  {
    return [
      'name'   => 'MyName',
      'family' => 'MyFamily',
      'age'    => '17'
    ];
  }
});

abstract class BaseController
{
  protected $di;

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

  abstract function indexAction ();
}

class Controller extends BaseController
{
  public function indexAction ()
  {
    $row = $this->di->get('db')->getRow();

    // Пример всё таки, не прикручивать же для него шаблонизатор
    echo 'Name: ',$row['name'],'<br> Family: ',$row['family'],'<br> Age: ',$row['age'];
  }
}

$controller = new Controller($di);
$controller->indexAction();

Is the overall approach correct? And yet, this confuses me:
$row = $this->di->get('db')->getRow();
I want something simpler like this:
$row = $this->db->getRow();
How to do it with PHP-DI? And is it even possible?

Answer the question

In order to leave comments, you need to log in

4 answer(s)
S
Sergey Protko, 2015-12-11
Protko @Fesor

no, you misunderstood the idea. Passing the entire container as a dependency is a violation of this very pattern and the principle of dependency inversion. This can only be done in the case of cyclic dependencies, or simply as an alternative to lazy initialization of services (although the alternative is so-so, and cyclic dependencies should be avoided).
1) we read about the principle of dependency inversion
2) we read about dependency injection
3) if you already use nameless classes, then they must implement some interface or extend from some class.
Instead of what you want it should be:

class Foo {
     private $db;

     public function __construct(Connection $connection) {
           $this->db = $connection;
     }

     public function makeFoo() {
          return $this->db->getRows(); // как вы и хотели
     }
}

// а это уже дергаем в конструкторе
$foo = $di->get(Foo::class);
$foo->makeFoo();

that is, in the controllers, we need to pull the service that will return the finished data to us.

O
OnYourLips, 2015-12-11
@OnYourLips

Not right.
Problem in line

$this->di = $di;

You don't have to demand ANYTHING from him. This is SL, not DI.
Look at Pimple and examples from there.
How to do it with PHP-DI? And is it even possible?
Can. Get the object in the constructor.

X
xfg, 2015-12-11
@xfg

Not right. Inject dependencies, not a container. You are breaking the Law of Demeter . There will be the same problems with the classic approach to unit testing, as if you did not inject anything at all and instantiated all dependencies right in the class.

D
dmitriy, 2015-12-11
@dmitriylanets

Falcon successfully uses this approach docs.phalconphp.ru/ru/latest/reference/di.html

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question