怎么从0到1开发一个PHP框架-3?

写在前面

本人开发的框架在2021年年初开发完成,后面没有再做过任何维护和修改。是仅供大家参考交流的学习项目,请勿使用在生产环境,也勿用作商业用途。

框架地址: github.com/yijiebaiyi/...

实现容器依赖注入

首先我们先了解概念。框架中的容器指的是什么?什么是依赖注入?

容器 (当前所指)是一个用于管理和存储应用程序中各种对象的工具。它允许你注册、创建和解析对象,以及管理它们之间的依赖关系。当前框架中的容器通常使用关联数组来存储对象和服务。

依赖注入是一种设计模式,它允许你将一个对象的依赖关系传递给它,而不是在对象内部直接创建或管理依赖关系。 这可以使代码更加可测试、可维护和可扩展,因为它将对象的依赖性解耦,并使它们更容易替换和修改。 依赖注入通常通过构造函数注入、方法注入或属性注入来实现。 在当前框架中,依赖注入和容器一起使用,容器负责实例化和解析对象,并自动注入它们的依赖关系。

那么如何实现呢?通过php的反射,来获取类的相关信息来解决依赖。

我们从容器中拿一个服务对象,如果没有拿到,则需要创建。创建的时候通过下面几步我们来解决依赖。

  1. 根据类名获取目标类(实际是反射类)
PHP 复制代码
$reflection = new \ReflectionClass($className)
  1. 进一步获取目标类的构造方法(实际是构造方法类)
PHP 复制代码
$reflection->getConstructor()
  1. 获取构造方法所需参数类(是一个数组)
PHP 复制代码
$constructorParameters = $constructor->getParameters()
  1. 循环所需参数,如果参数没有默认值,则是一个服务对象,我们继续从容器中获取,直到解决所有的依赖。
PHP 复制代码
foreach ($constructorParameters as $param) {
    if (version_compare(PHP_VERSION, '5.6.0', '>=') && $param->isVariadic()) {
        break;
    } elseif ($param->isDefaultValueAvailable()) {
        $dependencies[] = $param->getDefaultValue();
    } else {
        $c = $param->getClass();
        $dependencies[] = $this->get($c->getName(), $this->_params[$c->getName()] ?? []);
    }
}

注:请避免出现循环嵌套,否则会出现未知问题

创建的完整代码:

PHP 复制代码
    public function build(string $className, array $params = []): ?object
    {
        if (isset($this->_reflections[$className])) {
            $reflection = $this->_reflections[$className];
        } else {
            try {
                $reflection = new \ReflectionClass($className);
            } catch (ReflectionException $exception) {
                throw new Exception("Failed to reflect class " . $className . ", error: " . $exception->getMessage());
            }
            $this->_reflections[$className] = $reflection;
        }

        if (!$reflection->isInstantiable()) {
            throw new Exception("Is not instantiable:" . $reflection->name);
        }

        $dependencies = [];
        $constructor = $reflection->getConstructor();
        if ($constructor !== null) {
            $constructorParameters = $constructor->getParameters();
            foreach ($constructorParameters as $param) {
                if (version_compare(PHP_VERSION, '5.6.0', '>=') && $param->isVariadic()) {
                    break;
                } elseif ($param->isDefaultValueAvailable()) {
                    $dependencies[] = $param->getDefaultValue();
                } else {
                    $c = $param->getClass();
                    $dependencies[] = $this->get($c->getName(), $this->_params[$c->getName()] ?? []);
                }
            }
        }

        $this->_dependencies[$className] = Arr::arrayMergeBase($dependencies, $params);
        $object = $reflection->newInstanceArgs($this->_dependencies[$className]);
        $this->_objects[$className] = $object;
        return $object;
    }
}

解决完依赖,我们就把改服务存入容器中。

业务层调用:

PHP 复制代码
    $container = new Container();
    $container->set("app\service\Group", [123]);
    $container->set("app\service\User");
    $container->set("app\service\UserList");
    $group = $container->get("app\service\Group");
    $userList = $container->get("app\service\UserList");
    $group->getA();
    $userList->getUserList();

Group.php:

PHP 复制代码
<?php
namespace app\service;

class Group
{
    public static $a = 0;

    function __construct($a =1)
    {
        static::$a = $a;
    }

    public function getA()
    {
        echo self::$a;
    }
}

User.php:

PHP 复制代码
<?php
namespace app\service;

class User
{
    public function __construct(Group $group)
    {

    }

    function user()
    {

    }
}

UserList.php:

PHP 复制代码
<?php
namespace app\service;

class UserList
{
    public function __construct(User $user)
    {

    }

    public function getUserList()
    {
        echo "this is the user-list";
    }
}

尾声

至此,这款简易的php框架的实现过程就介绍完了。更多详细的内容请异步:

github.com/yijiebaiyi/...

这里有详细的代码示例和完整的实现过程。

相关推荐
REDcker9 小时前
Linux信号机制详解 POSIX语义与内核要点 sigaction与备用栈实践
linux·运维·php
REDcker11 小时前
浏览器端Web程序性能分析与优化实战 DevTools指标与工程清单
开发语言·前端·javascript·vue·ecmascript·php·js
云云只是个程序马喽13 小时前
AI漫剧创作系统开发定制指南
人工智能·小程序·php
niucloud-admin1 天前
PHP V6 单商户常见问题——云编译报错处理
php
xxjj998a1 天前
Laravel 1.x:PHP框架的原始魅力
android·php·laravel
xxjj998a1 天前
Laravel 5.x版本核心特性全解析
php·laravel
魔极客1 天前
第十二节:龙晰 AnolisOS-23.4-x86_64.qcow2 虚拟机的网络配置方式及 ssh 连接
网络·ssh·php
dog2502 天前
圆锥曲线和二次曲线
开发语言·网络·人工智能·算法·php
千寻girling2 天前
五一劳动节快乐 [特殊字符][特殊字符][特殊字符]
java·c++·git·python·学习·github·php
xxjj998a2 天前
Laravel3.x:奠定现代PHP框架的重要里程碑
android·开发语言·php