Форум программистов, компьютерный форум, киберфорум
PHP: ООП
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.77/26: Рейтинг темы: голосов - 26, средняя оценка - 4.77
Заблокирован

Суть DI в чём?

05.06.2020, 12:25. Показов 5609. Ответов 43
Метки php (Все метки)

Студворк — интернет-сервис помощи студентам
index.php
PHP
1
2
<?php
require_once 'engine/bootstrap.php';
service.php
PHP
1
2
3
4
<?php
return [
    \engine\service\router\Provider::class
];
bootstrap.php
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
require_once dirname(__DIR__) . '/vendor/autoload.php';
 
use engine\Cms;
use engine\di\Di;
 
try {
    $di = new Di();
    $services = require_once 'config/service.php';
    foreach ($services as $service) {
        $provider = new $service($di);
        $provider->init();
    }
    $cms = new Cms($di);
    $cms->run();
} catch (Error $error) {
    echo $error->getMessage();
}
Теперь вопросы:

1. Зачем вся эта муть, почему нельзя сделать так:
index.php
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
// require_once dirname(__DIR__) . '/vendor/autoload.php'; // удалено - ЗАЧЕМ ЭТО ТУТ!!!???
 
use engine\Cms;
use engine\di\Di;
 
try {
    $di = new Di(); // внутри заполняем container
    $services = require_once 'config/service.php';
    foreach ($services as $service) {
        $provider = new $service($di); // СРАЗУ СОЗДАЁМ ОБЪЕКТ(Ы) И ПИХАЕМ В ТОЧКУ ДОСТУПА!!!???
        $provider->init();
    }
    $cms = new Cms($di);
    $cms->run();
} catch (Error $error) {
    echo $error->getMessage();
}
И всё.

2. Я правильно понимаю, что у меня в $di->container будет массив СРАЗУ ВСЕХ объектов приложения, то есть они СРАЗУ УЖЕ СОЗДАНЫ, зачем мне куча УЖЕ СОЗДАННЫХ экземпляров, а не создание по мере обращения? Или я что-то не понимаю - это же так называемый РЕЕСТР.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
05.06.2020, 12:25
Ответы с готовыми решениями:

В чем суть интерфейсов?
За день я в интернете начиталась столько всего про интерфейсы, что запуталась до нельзя!!! И так, звучит главный вопрос: в чем же суть...

В чем суть PHP?
Ребят, подскажите пожалуйста правильно ли я понял суть PHP. Вот лежит на сервере код определенный. Мы обращаемся по домену и этот код...

В чем суть Invalid Parameter
Invalid Parameter – yii\base\InvalidParamException Hash is invalid. Добавлено через 27 минут вот код куда ругается in...

43
165 / 150 / 58
Регистрация: 15.06.2013
Сообщений: 1,107
05.06.2020, 15:36
Не совсем понятно в чем отличие первого куска кода от второго.
Откуда можно знать что там находится в контейнере. Вообще, конечно, там должны быть не все экземпляры, а только те, которые ты запросил. Например:
PHP
1
2
3
class IndexController{
    public function index(SomeClass $class){}
}
Контейнер понимает что для работы этого экшена тебе нужен экземпляр класса SomeClass и создает его.
0
Заблокирован
05.06.2020, 15:47  [ТС]
взяли реестр обозвали di
Цитата Сообщение от MadHatter Посмотреть сообщение
Не совсем понятно в чем отличие первого куска кода от второго.
в том что выкинут нахер autoload какой-то с цепочкой инклудов чтобы до него добраться

Цитата Сообщение от MadHatter Посмотреть сообщение
Откуда можно знать что там находится в контейнере
PHP
1
2
3
4
foreach ($services as $service) {
        $provider = new $service($di); // СРАЗУ СОЗДАЁМ ОБЪЕКТ(Ы) И ПИХАЕМ В ТОЧКУ ДОСТУПА!!!???
        $provider->init();
    }
цикл крутит массив неймспейсов и создаёт какждому экземпляр и $di заполняет у себя свойство container

я нихера не понял, зачем мне $di->container с массивом экземпляров ВСЕХ классов?

что это за чудо взяли РЕЕСТР переименовали в DI?

так я и сто лет назад так умел прописать неймспейсы и магией обращаться по ключу к массиву УЖЕ СОЗДАННЫХ экземпляров, которые постоянно висят в любой области видимости у меня

и init() тут зачем объект инициализируется при создании по new ведь?
0
165 / 150 / 58
Регистрация: 15.06.2013
Сообщений: 1,107
05.06.2020, 15:54
Я вот что-то тоже в упор не вижу где там $di->container.
Я не знаю кто и какой реестр переименовал, но инъекция зависимостей всегда ей и была, если под di автор подразумевает ее.
По идее в атолоаде должно быть автоподключение классов.
0
Заблокирован
05.06.2020, 15:59  [ТС]
Цитата Сообщение от MadHatter Посмотреть сообщение
не вижу где там $di->container
$di попадает в каждый экземпляр, в $di (экземпляр класса Di) есть свойство container - массив, в него я так понимаю попадает экземпляр что-ли

я чёт не догоняю
0
165 / 150 / 58
Регистрация: 15.06.2013
Сообщений: 1,107
05.06.2020, 16:02
А что находится в \engine\service\router\Provider?
0
Заблокирован
05.06.2020, 16:05  [ТС]
MadHatter, как я суть задумки понял автора этого кода, что в цикле мы перебирать ДОЛЖНЫ ТОЛЬКО неймспейсы и создавать объект, только если в роуте есть его ключ, но я чёт не нахожу такую проверку, ну типа если в роуте ключ, то создаём объект, я вижу что он в цикле дубасит всем классам по экземпляру

это я на ютюбе попробовал изучить DI - там есть курс CMS на PHP

Добавлено через 2 минуты
Цитата Сообщение от MadHatter Посмотреть сообщение
А что находится в \engine\service\router\Provide r?
там сервис подключается по имени сервиса, и по init создающий его экземпляр

тогда не понимаю

PHP
1
2
$provider = new $service($di); // зачем создавать экземпляр
        $provider->init(); // если тут мы его инициализируем в провайдере
короче я в шоке
0
165 / 150 / 58
Регистрация: 15.06.2013
Сообщений: 1,107
05.06.2020, 16:08
Ну надо копаться и смотреть. Вообще инъекция зависимостей это очень просто и удобно. ТЫ просто указываешь экземпляр какого класса тебе нужен в данном методе и фреймворк создает его вместо тебя.
0
Заблокирован
05.06.2020, 16:12  [ТС]
MadHatter, не ну я то примерно понимаю как должно работать, но то, что я дал в примере я так понимаю это не совсем DI - мне лично это полностью напомнило реестр, там постоянно уже готовые экземпляры висят и магия к ним доступ даёт по ключу
0
165 / 150 / 58
Регистрация: 15.06.2013
Сообщений: 1,107
05.06.2020, 16:15
Это похоже на сервис провайдер. Ты указываешь классы которые должны выполниться при инициализации приложения. Например автоматически подтянуть курсы валют с сайта нацбанка или погоду из метеосервиса.
0
Заблокирован
06.06.2020, 18:04  [ТС]
MadHatter, короче - ЭТО РЕЕСТР, дичь ещё та, все объекты созданы которые в конфиге неймспейсов и постоянно хранятся в conteiner, вот я создал несколько сервисов

выхлоп
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
object(engine\di\Di)[3]
  private array 'container' => 
    array (size=3)
      'error' => 
        object(engine\core\error\ErrorHandler)[4]
          private string 'head' => *uninitialized*
          private string 'file' => *uninitialized*
          private int 'line' => *uninitialized*
      'router' => 
        object(engine\core\router\Router)[2]
          private array 'routes' => 
            array (size=2)
              ...
          private array 'route' => 
            array (size=2)
              ...
      'view' => 
        object(engine\core\view\View)[5]
вот я обратился

PHP
1
$this->view = $this->di->get('view');
выхлоп

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
object(engine\di\Di)[3]
  private array 'container' => 
    array (size=3)
      'error' => 
        object(engine\core\error\ErrorHandler)[4]
          private string 'head' => *uninitialized*
          private string 'file' => *uninitialized*
          private int 'line' => *uninitialized*
      'router' => 
        object(engine\core\router\Router)[2]
          private array 'routes' => 
            array (size=2)
              ...
          private array 'route' => 
            array (size=2)
              ...
      'view' => 
        object(engine\core\view\View)[5]
вот я не обращаюсь

PHP
1
// $this->view = $this->di->get('view');
выхлоп

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
object(engine\di\Di)[3]
  private array 'container' => 
    array (size=3)
      'error' => 
        object(engine\core\error\ErrorHandler)[4]
          private string 'head' => *uninitialized*
          private string 'file' => *uninitialized*
          private int 'line' => *uninitialized*
      'router' => 
        object(engine\core\router\Router)[2]
          private array 'routes' => 
            array (size=2)
              ...
          private array 'route' => 
            array (size=2)
              ...
      'view' => 
        object(engine\core\view\View)[5]
они постоянно объекты эти висят в контейнере ВСЕГДА, потому что их циклом по массиву неймспейсов инициализировали, млять, а если у меня 1000 классов будет?
0
 Аватар для sad67man
2600 / 1504 / 689
Регистрация: 23.08.2015
Сообщений: 3,804
06.06.2020, 19:57
Verolomstvo, Смысл DI в создании объектов по требованию, причем у объекта могут быть зависимости, подобно comroser или npm. К примеру

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Controller
{
    private $service;
    private $renderer;
 
    public function __construct(
        UserService $service,
        Renderer $renderer
    )
    {
        $this->service = $service;
        $this->renderer = $renderer;
    }
 
    public function actionCreate()
    {
        $createForm =  new UserCreateForm();
 
        if ($createForm->load($_POST) && $createForm->validate()) {
            try {
                $user = $this->service->create($createForm);
                $_SESSION['successMessage'] = 'Пользователь создан';
            } catch (DomainException $e) {
                $_SESSION['errorMessage'] = $e->getMessage();
            }
        }
 
        return $this->renderer->render('create', compact('createForm'));
    }
}
PHP
1
2
3
4
interface Renderer
{
    public function render($name, array $params = []): string;
}
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class UserService
{
    private $users;
    private $hasher;
 
    public function __construct(UserRepository $users, PasswordHasher $hasher)
    {
        $this->users = $users;
        $this->hasher = $hasher;
    }
 
    public function create(UserForm $form)
    {
        $user = User::create($form->login, $form->password);
 
        $this->users->save($user);
    }
 
    public function changePassword($id, UserChangePasswordForm $form)
    {
        $user = $this->users->getById($id);
        $user->changePassword(
            $this->hasher->hash($form->password)
        );
        $this->users->save($user);
    }
}
Контроллер требует интерфейс Рендерера и UserService, в свою очередь у UserService есть зависимости, он требует UserRepository, который требует PDO - подключение к Базе данных и неких Hasher.

В контейнере мы сопоставляем интерфейс, и создаем подключение к БД. Причем он устроен таким образом, что он сам автоматически парсит конструкторы и создает необходимые объекты.

PHP
1
2
3
4
5
6
7
8
9
$container = new DiContainer();
 
$container->set(Renderer::class, function() {
    return new PhpRenderer(dirname(__DIR__) . '/views');
});
 
$container->set(PDO::class, function() {
    return new PDO(...)
});
При этом, объекты создаются в единственном экземпляре, т.е. если 2 класса требуют подключение к БД (PDO), то они оба получат один и тот же объект подключение к БД - аналог sington. Только зависимости подключаются через конструктор в качестве композиции)

Остается только создать сам контроллер через контейнер зависимостей.

Добавлено через 15 минут
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class UserRepository
{
    private $pdo;
 
    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }
 
    public function getById($id)
    {
        return $this->pdo-> ...;
    }
}
Добавлено через 16 секунд
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class UserRepository
{
    private $pdo;
 
    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }
 
    public function getById($id)
    {
        return $this->pdo-> ...;
    }
}
1
Заблокирован
06.06.2020, 20:05  [ТС]
sad67man, не вижу я создания по требованию вижу цикл по массиву неймспейсов

для чего тогда массив-контейнер не для хранения ли кучи уже созданных объектов?

я по мере надобности как минимум двумя способами и так могу обратиться к объекту

получат один и тот же объект? а если я сам залогинен через сервис User и просматриваю профиль другого пользователя, какие мне данные отдаст сервис User, если объект уже создан ДЛЯ МЕНЯ?

короче куча вопросов и я уже понял что мне такая дичь не нужна, я такое проходил с реестром
0
 Аватар для sad67man
2600 / 1504 / 689
Регистрация: 23.08.2015
Сообщений: 3,804
06.06.2020, 20:10
Verolomstvo, Контейнер хранит ключ и значение - значение может быть как функция, которая создает класс, так и имя класса - факторки. Т.е. по сути конейнер изначально хранит просто массив имен классов. И по требованию их дергает, сохраняя объекты в приватном массиве - я вам кидал ссылку, но вы не удосужились посмотреть.

сервис UserService необходим только для выполнения операций, просматривание данных к нему не относится.
1
Заблокирован
06.06.2020, 20:11  [ТС]
sad67man, тут не имена классов, тут объекты

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
object(engine\di\Di)[3]
  private array 'container' => 
    array (size=3)
      'error' => 
        object(engine\core\error\ErrorHandler)[4]
          private string 'head' => *uninitialized*
          private string 'file' => *uninitialized*
          private int 'line' => *uninitialized*
      'router' => 
        object(engine\core\router\Router)[2]
          private array 'routes' => 
            array (size=2)
              ...
          private array 'route' => 
            array (size=2)
              ...
      'view' => 
        object(engine\core\view\View)[5]
0
 Аватар для sad67man
2600 / 1504 / 689
Регистрация: 23.08.2015
Сообщений: 3,804
06.06.2020, 20:17
Verolomstvo, Я не знаю, какую статью вы читали, или какое видео смотрели. Контейнер чисто теоретически может создавать весь набор объектов сразу. Но это слишком примитивный вариант. Есть и более продвинутые реализации, когда контейнер просто хранит массив названия классов и названия классов факторок, которые внитри содержат логику создания объектов. Но пока их не дернули они представляют собой лишь строки.

PHP
1
$contener->ser(Pdo::class, PDOFactory::class)
И т.д. Посмотрите видос, который я вам скинул, все вопросы отпадут.
1
Заблокирован
06.06.2020, 20:20  [ТС]
Цитата Сообщение от sad67man Посмотреть сообщение
UserService необходим только для выполнения операций, просматривание данных к нему не относится
операция просмотра профиля другого юзера

пришёл айдишник другого юзера нужно дёрнуть данные на другого юзера, находясь у себя в аккаунте И ОДНОВРЕМЕННО чтобы шаблон (хотя бы шаблон) с моими показателями не исказился данными противника

терзаю в бою другого юзера: мне себе и ему нужно сбивать хп, отнимать у него бабло при победах, писать ему количество его поражений, считать ему рейтинг в зависимости от побед-поражений, регенерировать ему хп, чтобы когда убил, то он не оставался недоступным для боёв и так далее и тому подобное - это будет делать один экземпляр сервиса сразу для меня и для него? А есть ещё групповые бои например 5 на 5

Добавлено через 1 минуту
sad67man, там нудные видосы мне не заходят они несколько раз смотрел я эти видосы давно знаю
0
 Аватар для sad67man
2600 / 1504 / 689
Регистрация: 23.08.2015
Сообщений: 3,804
06.06.2020, 20:25
Лучший ответ Сообщение было отмечено Verolomstvo как решение

Решение

Verolomstvo, Сущность User отвечает главным образом за регистрацию, вход, восстановление пароля и т.д. Для ваших вещей нужно создать отдельную сущность Player.
Когда вы выполняете операцию - вы дергаете операционный уровень, просто изменяете состояние системы. Для получения данных для вывода нужен отдельная служба.

Добавлено через 1 минуту
Цитата Сообщение от Verolomstvo Посмотреть сообщение
там нудные видосы мне не заходят они несколько раз смотрел я эти видосы давно знаю
Знаю) Можно посмотреть на 2ой скорости. Чисто для галочки. Если вы их смотрели, не было бы таких вопросов)
1
Заблокирован
06.06.2020, 20:35  [ТС]
Цитата Сообщение от sad67man Посмотреть сообщение
Сущность User отвечает главным образом за регистрацию, вход, восстановление пароля и т.д. Для ваших вещей нужно создать отдельную сущность Player.
вот - это ближе к сути, примерно так и делается
0
 Аватар для sad67man
2600 / 1504 / 689
Регистрация: 23.08.2015
Сообщений: 3,804
06.06.2020, 20:41
Verolomstvo, В DI контейнере не нужно описывать все возможные классы. Там описываются только интерфейсы, и те объекты, которые требуют настройки в качестве параметров в конструкторе. В остальном Контейнер сам парсит через Рефлексию конструкторы и пытается создать все необходимые объекты.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
06.06.2020, 20:41
Помогаю со студенческими работами здесь

В чём суть ошибки? Warning: Parameter 3 to showBlogSection() expected to be a reference, value given in on line 100
Здравствуйте. Не могу понять в чем суть ошибки Warning: Parameter 3 to showBlogSection() expected to be a reference, value given in on line...

В чём суть сборки?
Здравствуйте. Я верю, что тут действительно есть знатоки компьютерного железа и я обращаюсь к вам. Я сам как бы начинающий IT-шник и учусь...

В чем суть continue в if-else
код первый. прата глава 7 упражнение 3. оператор continue отсутствует, все прекрасно работает. счетчик вынесен в отдельный оператор ?: 1...

В чем суть операторов << и >>
Здравствуйте. Уважаемые Форумчане, нужна помощь. Имеется следующий код if ((PINB&amp;(1 &lt;&lt; PB0)) == 0) // Если на выводе...

Интерфейсы - в чем их суть
В чем суть интерфейсов объясните пожалуйста. Добавлено через 19 минут А если быть точнее, то какова их практическая полезность?...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru