承接 kaspi/di-container 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

kaspi/di-container

Composer 安装命令:

composer require kaspi/di-container

包简介

Dependency injection container with autowired

README 文档

README

Kaspi/di-container — это контейнер внедрения зависимостей для PHP >= 8.1 реализующий рекомендацию PSR-11.

Установка

composer require kaspi/di-container

Особенности

  • Autowire – контейнер автоматически создаёт и внедряет зависимости.
  • Zero configuration – если класс не имеет зависимостей или зависит только от других конкретных классов, контейнеру не нужно указывать, как разрешить этот класс.
  • Php-атрибуты для конфигурирования сервисов в контейнере.
  • Поддержка тегов (tags) для определений и сервисов в контейнере.
  • Компиляция контейнера – генерация настроенного контейнера в PHP-код оптимизированный специально для вашей конфигурации и ваших классов.

Быстрый старт

📂 Определения классов:

// src/Services/Envelope.php
namespace App\Services;

// Класс для создания сообщения
class Envelope {
    public function subject(string $subject): static {
        // ...
        return $this;
    }
    
    public function message(string $message): static {
        // ...
        return $this;
    }
}
// src/Services/Mail.php
namespace App\Services;

// Сервис отправки почты
class Mail {
    public function __construct(private Envelope $envelope) {}
    
    public function envelop(): Envelope {
        return $this->envelope;
    }
    
    public function send(): bool {
        // отправка сообщения 
    }
}
// src/Models/Post.php
namespace App\Models;

// Модель данных — пост в блоге.
class Post {
    public string $title;
    // ...
}
// src/Controllers/PostController.php
namespace App\Controllers;

use App\Services\Mail;
use App\Models\Post;

// Контроллер для обработки действия.
class  PostController {
    public function __construct(private Mail $mail) {}
    
    public function send(Post $post): bool {
        $this->mail->envelop()
            ->subject('Publication success')
            ->message('Post <'.$post->title.'> was published.');
        return $this->mail->send();
    }
}

👷‍♂️ Создание контейнера и разрешение зависимостей:

use App\Controllers\PostController;
use App\Models\Post;
use Kaspi\DiContainer\DiContainerBuilder;

// Создать контейнер.
$container = (new DiContainerBuilder())
    ->build();

// more code...

// получить класс PostController с внедренным сервисом Mail.
$postController = $container->get(PostController::class);
//Заполняем модель данными.
$post = new Post();
$post->title = 'Publication about DiContainer';
// Выполняем метод `PostController::post()`.
$postController->send($post);

Note

Контейнер "пытается" самостоятельно определить запрашиваемую зависимость - является ли это классом или callable типом.

DiContainer выполнит следующие действия для App\Controllers\PostController:

$post = new App\Controllers\PostController(
    new App\Services\Mail(
        new App\Services\Envelope()
    )
);

Tip

Реализация кода в примере

Другой вариант для примера выше можно использовать для получения результата метод контейнера call():

use App\Controllers\PostController;
use App\Models\Post;

$post = new Post();
$post->title = 'Publication about DiContainer';

// ...

// получить класс PostController с внедренным сервисом Mail и выполнить метод "send"
// с передачей именованного аргумента
$container->call(
    definition: [PostController::class, 'send'],
    post: $post
);

Tip

Больше информации о методе call()

Note

Примеры использования пакета kaspi/di-container в репозитории

Конфигурирование DiContainer

Для конфигурирования контейнера используется класс \Kaspi\DiContainer\DiContainerConfig который реализует интерфейс \Kaspi\DiContainer\Interfaces\DiContainerConfigInterface.

Нулевая конфигурация для внедрения зависимостей:

\Kaspi\DiContainer\Interfaces\DiContainerConfigInterface::isUseZeroConfigurationDefinition(): bool;

Не нужно указывать контейнеру, как разрешить конкретный PHP-класс если класс не имеет зависимостей, или зависит только от других конкретных классов, или зависит от ранее сконфигурированных классов (интерфейсов).

Использовать Php-атрибуты для конфигурирования:

\Kaspi\DiContainer\Interfaces\DiContainerConfigInterface::isUseAttribute(): bool;

Предоставляет возможность конфигурирования определений на базе PHP атрибутов.

Разрешать зависимость как синглтон:

\Kaspi\DiContainer\Interfaces\DiContainerConfigInterface::isSingletonServiceDefault(): bool;

Для определений в контейнере можно указать как разрешать сервис – возвращать всегда одни и тот же объект или создавать объект сервиса каждый раз при получении через метод контейнера get(). Для определений контейнера у которых неуказан способ получения через метод контейнера get() применяется значение по умолчанию из конфигурации.

Пример конфигурации:

use Kaspi\DiContainer\{DiContainerConfig, DiContainerBuilder};

$diConfig = new DiContainerConfig(
    useZeroConfigurationDefinition: false,
    useAttribute: false,
    isSingletonServiceDefault: true,
);

// передать настройки в построитель контейнера
$container = (new DiContainerBuilder(containerConfig: $diConfig))
    ->build();

Особенности получения некоторых классов и интерфейсов.

Некоторые интерфейсы или классы всегда возвращают текущий контейнер зависимостей. При разрешении зависимости для интерфейсов и классов:

  • Psr\Container\ContainerInterface::class
  • Kaspi\DiContainer\Interfaces\DiContainerInterface::class
  • Kaspi\DiContainer\DiContainer::class

будет получен текущий контейнер зависимостей.

use Kaspi\DiContainer\DiContainerBuilder;
use Psr\Container\ContainerInterface;

function testFunc(ContainerInterface $c) {
    return $c;
}

$container = (new DiContainerBuilder())->build();

var_dump($container->call('testFunc') instanceof DiContainer); // true
var_dump($container->call('testFunc') instanceof ContainerInterface); // true
use Kaspi\DiContainer\DiContainerBuilder;
use Psr\Container\ContainerInterface;

class TestClass {
    public function __construct(
        public ContainerInterface $container
    ) {}
}

$container = (new DiContainerBuilder())->build();

var_dump($container->get(TestClass::class)->container instanceof ContainerInterface); // true

🧰 Подробное описание конфигурирования и использования

Тесты

Запуск тестов без подсчёта покрытия кода

composer test

Запуск тестов с проверкой покрытия кода тестами

composer test-cover

Статический анализ кода

Для статического анализа используем пакет PHPStan.

composer stat

Code style

Для приведения кода к стандартам используем php-cs-fixer который объявлен в dev зависимости composer-а

composer fixer

Использование Docker образа с PHP 8.1, 8.2, 8.3, 8.4, 8.5

Указать образ с версией PHP можно в файле .env в ключе PHP_IMAGE. По умолчанию контейнер собирается с образом php:8.1-cli-alpine.

Собрать контейнер

docker-compose build

Установить зависимости php composer-а:

docker-compose run --rm php composer install

🔔 Если установлен make в системе:

make install

Тесты

Запуск тестов без отчёта о покрытии кода:

docker-compose run --rm php vendor/bin/phpunit --no-coverage

🔔 Если установлен make в системе:

make test

Прогнать тесты с отчётом о покрытии кода:

docker-compose run --rm php vendor/bin/phpunit

🔔 Если установлен make в системе:

make test-cover

⛑ pезультаты будут в папке .coverage-html

Статический анализ кода PHPStan

docker-compose run --rm php vendor/bin/phpstan

если установлен make в системе:

make stat

Запуск комплексной проверки

Если установлен make – запуск проверки code-style, stat analyzer, tests:

make all

Запуск тестов для всех поддерживаемых версий PHP через Docker образы.

Если установлен make – перед запуском тестов удаляется директория vendor и файл composer.lock, устанавливаются зависимости только потом выполняются тесты:

make test-supports-php

Другое

Можно работать в shell оболочке в docker контейнере:

docker-compose run --rm php sh

kaspi/di-container 适用场景与选型建议

kaspi/di-container 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 363 次下载、GitHub Stars 达 2, 最近一次更新时间为 2024 年 01 月 02 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「dependency injection」 「container」 「di」 「autowire」 「Autowiring」 「PSR-11」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 kaspi/di-container 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 kaspi/di-container 我们能提供哪些服务?
定制开发 / 二次开发

基于 kaspi/di-container 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 363
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 3
  • 点击次数: 33
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 2
  • Watchers: 2
  • Forks: 1
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2024-01-02