Skip to content

Instantly share code, notes, and snippets.

@mizegit
Created March 25, 2025 16:09
Show Gist options
  • Select an option

  • Save mizegit/848bfe40024021c75e0d38feb5be8dc6 to your computer and use it in GitHub Desktop.

Select an option

Save mizegit/848bfe40024021c75e0d38feb5be8dc6 to your computer and use it in GitHub Desktop.
laravel框架技术关键解析 代码
<?php
interface Visit
{
public function go();
}
class Train implements Visit
{
public function go()
{
echo "go to tibet by train";
}
}
class Container
{
protected $bindings = [];
public function bind($abstract, $concrete = null, $shared = false)
{
if (! $concrete instanceof Closure) {
$concrete = $this->getClosure($abstract, $concrete);
}
$this->bindings[$abstract] = compact('concrete', 'shared');
}
protected function getClosure($abstract, $concrete)
{
return function($c) use ($abstract, $concrete) {
$method = ($abstract == $concrete) ? 'build' : 'make';
return $c->$method($concrete);
};
}
public function make($abstract)
{
$concrete = $this->getConcrete($abstract);
if ($this->isBuildable($concrete, $abstract)) {
$object = $this->build($concrete);
} else {
$object = $this->make($concrete);
}
return $object;
}
protected function isBuildable($concrete, $abstract)
{
return $concrete === $abstract || $concrete instanceof Closure;
}
protected function getConcrete($abstract)
{
if (! isset($this->bindings[$abstract])) {
return $abstract;
}
return $concrete = $this->bindings[$abstract]['concrete'];
}
public function build($concrete)
{
if ($concrete instanceof Closure){
return $concrete($this);
}
$reflector = new ReflectionClass($concrete);
if (! $reflector->isInstantiable()) {
echo "Target [$concrete] is not instantiable.";
}
$constructor = $reflector->getConstructor();
if (is_null($constructor)) {
return new $concrete;
}
$dependencies = $constructor->getParameters();
$instances = $this->getDependencies($dependencies);
return $reflector->newInstanceArgs($instances);
}
protected function getDependencies($parameters)
{
$dependencies = [];
foreach ($parameters as $parameter)
{
$dependency = $parameter->getClass();
if (is_null($dependency)) {
$dependencies[] = NULL;
} else {
$dependencies[] = $this->resolveClass($parameter);
}
}
return (array) $dependencies;
}
protected function resolveClass(ReflectionParameter $parameter)
{
return $this->make($parameter->getClass()->name);
}
}
class Traveller
{
protected $trafficTool;
public function __construct(Visit $trafficTool)
{
$this->trafficTool = $trafficTool;
}
public function visitTibet()
{
$this->trafficTool->go();
}
}
// 实例化 IoC 容器
$app = new Container();
// 完成容器的填充
$app->bind("Visit", "Train");
$app->bind("traveller", "Traveller");
// 通过容器实现依赖注入,完成类的实例化
$tra = $app->make("traveller");
$tra->visitTibet();
@mizegit
Copy link
Copy Markdown
Author

mizegit commented Mar 25, 2025

deepseek重写了一下,有点意思

<?php

// 确保所有需要的类和接口都在这里定义或者已正确加载

interface Visit
{
    public function go();
}

class Train implements Visit
{
    public function go()
    {
        echo "乘坐火车前往目的地。\n";
    }
}

class Container
{
    protected $bindings = [];

    /**
     * 绑定一个抽象类型到具体的实现
     *
     * @param string $abstract 抽象类型名称(通常是接口或基类)
     * @param string|Closure $concrete 具体的实现类或闭包
     * @param bool $shared 是否为单例
     */
    public function bind($abstract, $concrete = null, $shared = false)
    {
        if (is_null($concrete)) {
            $concrete = $abstract;
        }

        // 如果绑定的是一个类名而不是闭包,则创建一个默认的闭包来实例化该类
        if (! $concrete instanceof Closure) {
            $concrete = $this->getClosure($abstract, $concrete);
        }

        $this->bindings[$abstract] = compact('concrete', 'shared');
    }

    /**
     * 默认生成实例的回调函数
     *
     * @param string $abstract 抽象类型名称
     * @param string $concrete 具体的实现类名
     * @return Closure
     */
    protected function getClosure($abstract, $concrete)
    {
        return function ($c) use ($abstract, $concrete) {
            // 检查绑定是否为自身,如果是则使用传入的容器方法来解析
            return $c->make($concrete);
        };
    }

    /**
     * 创建一个具体类型的实例
     *
     * @param string $abstract 抽象类型名称
     * @return mixed 具体类型的实例
     * @throws Exception 如果无法解析类
     */
    public function make($abstract)
    {
        $concrete = $this->getConcrete($abstract);

        // 判断是否可以构建
        if ($this->isBuildable($concrete, $abstract)) {
            $object = $this->build($concrete);
        } else {
            $object = $this->make($concrete);
        }

        return $object;
    }

    /**
     * 判断是否可以构建该类型
     *
     * @param string|Closure $concrete 具体的实现类或闭包
     * @param string $abstract 抽象类型名称
     * @return bool
     */
    protected function isBuildable($concrete, $abstract)
    {
        return $concrete === $abstract || $concrete instanceof Closure;
    }

    /**
     * 获取绑定的具体实现
     *
     * @param string $abstract 抽象类型名称
     * @return string|Closure 具体的实现类或闭包
     */
    protected function getConcrete($abstract)
    {
        // 如果没有找到绑定关系,则默认使用抽象类型本身
        if (!isset($this->bindings[$abstract])) {
            return $abstract;
        }

        return $this->bindings[$abstract]['concrete'];
    }

    /**
     * 构建实例
     *
     * @param string|Closure $concrete 具体的实现类或闭包
     * @return mixed 实例化的对象
     * @throws Exception 如果无法实例化类
     */
    public function build($concrete)
    {
        if ($concrete instanceof Closure) {
            return $concrete($this);
        }

        $reflector = new ReflectionClass($concrete);

        // 检查类是否可实例化
        if (!$reflector->isInstantiable()) {
            throw new Exception("Target [$concrete] is not instantiable.");
        }

        $constructor = $reflector->getConstructor();

        // 如果没有构造函数,则直接实例化
        if (is_null($constructor)) {
            return new $concrete;
        }

        // 获取构造函数的参数
        $dependencies = $constructor->getParameters();
        $instances = $this->getDependencies($dependencies);

        // 使用解析的依赖项创建实例
        return $reflector->newInstanceArgs($instances);
    }

    /**
     * 解析构造函数的依赖项
     *
     * @param ReflectionParameter[] $parameters 构造函数的参数列表
     * @return array 解析后的依赖项实例
     * @throws Exception 如果无法解析某个依赖项
     */
    protected function getDependencies($parameters)
    {
        $dependencies = [];

        foreach ($parameters as $parameter) {
            // 获取参数的类名
            $dependency = $parameter->getClass();

            if (is_null($dependency)) {
                // 如果参数没有类型提示,尝试从容器中获取默认值或抛出异常
                // 这里选择抛出异常,您可以根据需要调整
                throw new Exception("Cannot resolve class dependency for parameter '{$parameter->getName()}' in {$parameter->getDeclaringClass()->getName()}::{$parameter->getName()}().");
            }

            // 递归解析依赖项
            $dependencies[] = $this->make($dependency->name);
        }

        return $dependencies;
    }
}

// 定义 Traveller 类,依赖于 Visit 接口
class Traveller
{
    protected $trafficTool;

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

    public function visitTibet()
    {
        $this->trafficTool->go();
    }
}

// 实例化 IoC 容器
$app = new Container();

// 绑定 Visit 接口到 Train 类
$app->bind("Visit", Train::class);

// 绑定 Traveller 类到自身,并设置为单例(可选)
$app->bind("traveller", Traveller::class);

// 通过容器实现依赖注入,完成类的实例化
try {
    $tra = $app->make("traveller");
    $tra->visitTibet();
} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment