iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > PHP编程 >一文理解和实现现代PHP框架里的IOC容器
  • 187
分享到

一文理解和实现现代PHP框架里的IOC容器

php 2023-05-14 19:05:50 187人浏览 八月长安
摘要

本篇文章给大家带来了关于PHP的相关知识,其中主要介绍了关于ioc容器的相关内容,ioC的全称是:Inversion Of Control,反转控制,下面一起来看一下,希望对大家有帮助。容器是什么?相信很多人听说过依赖注入,依赖注入实现的基

本篇文章给大家带来了关于PHP的相关知识,其中主要介绍了关于ioc容器的相关内容,ioC的全称是:Inversion Of Control,反转控制,下面一起来看一下,希望对大家有帮助。

一文理解和实现现代PHP框架里的IOC容器

容器是什么?

相信很多人听说过依赖注入,依赖注入实现的基础条件离不开容器,容器就是用来管理类依赖和注入的,负责服务的管理和解耦组件,最简单的理解我们可以把容器理解成一个超级大、专门存对象的数组

35.png

如图所示调用者通过容器的标示获取到对象实例,图里可以看出来,可以通过 ::class 的方式来获取也可以直接通过对象标示获取实例对象。

IOC是什么?

大家可能都听说过IOC容器,IOC的全称是:(Inversion Of Control,反转控制)。

我们来理解一下什么是反转控制,在我们传统编码中我们在类与类之间的依赖通常是我们通过编码的方式new出来对象再传递的,而使用控制反转我们可以把对象的控制权交给容器或者框架去实现。目的是为了让我们不需要硬编码去创建对象,看图1可以知道,容器里面存放着很多对象,当我们要使用的时候可以直接去用。而容器里面的对象不需要我们在代码中编码创建。在需要某个类对象的时候会去容器里面获取对象,如果对象不存在则会自动创建。这就是省略了我们在代码里面去创建对象的过程,由容器去帮我们实现这个创建的过程,这就叫反转控制。一句话总结IOC:把创建对象的控制权转移给容器实现类的实例化。

例如:没有使用IOC的情况下,我们想要创建类

<?php
class Sunny{
}
$sunny = new Sunny();

我们需要手动去new一个类,这种情况就是硬编码在代码里面去实现的。

而使用IOC容器的代码则可以这样写。

<?php
class Sunny{
}
$sunny = Container::getBean(Sunny::class);

在容器的内部去帮我们实现这个类,有同学看到这里可能会有疑问,我使用 new Sunny 不是代码写得更短更简单吗?我们看完依赖注入再看一个例子。

依赖注入

现在知道了IOC是什么,那么一个新的问题出来了,我们在创建类的时候有些类的构造方法会需要我们传递参数怎么办?通过IOC的学习我们知道了IOC容器会帮我们解决这个对象实例创建的问题,那么在容器里面创建对象的时候发现类有其他依赖则会进行依赖查找,容器寻找需要对象的过程,称为DL(Dependency Lookup, 依赖查找)。而把需要的依赖注入到代码片段中这个称为DI(Dependency Injection,依赖注入)。

例如IOC里面说到的 new Sunny 这个例子。如果在类与类之间有多重依赖。

<?php
class Computer{
    public function run(){
        echo "编程中....\n";
    }
}
class Sunny{
    private $computer;
    public function __construct(Computer $computer){
        $this->computer = $computer;
    }
    public function program(){
        $this->computer->run();
    }
}
$sunny = new Sunny(new Computer());
$sunny->program();

这里可以看到 Sunny 这个类想要编程依赖类 Computer 这个类,而如果使用IOC容器实现依赖注入的话,代码就简单了。

<?php
class Computer{
    public function run(){
        echo "编程中....\n";
    }
}
class Sunny{
    private $computer;
    public function __construct(Computer $computer){
        $this->computer = $computer;
    }
    public function program(){
        $this->computer->run();
    }
}
$sunny = Container::getBean(Sunny::class);
$sunny->program();

一句话总结:解决创建类实例当中对其他类的依赖,动态的向某个对象提供它所需要的其他对象。

依赖倒置

依赖倒置解决的问题是松耦各个模块之间的重度依赖,上层模块不应该依赖底层模块,它们都应该依赖于抽象。通常简单的理解依赖倒置就是面向接口或者面向抽象来进行编程。我们通过下面的例子来看看面向接口编程。

class Cache{
    public function set($key,$value){
        $Redis = new CFile();
        $redis->set($key,$value);
    }
}
class CFile{
    public function set($key,$value){
        echo "file:{$key}->{$value}\n";
    }
}
$cache = new Cache();
$cache->set("name","sunny");

上面的这段代码看似没有什么大问题,但是如果有一天把文件缓存改成Redis缓存呢?

class Cache{
    public function set($key,$value){
        $redis = new CRedis();
        $redis->set($key,$value);
    }
}
class CRedis{
    public function set($key,$value){
        echo "redis:{$key}->{$value}\n";
    }
}
$cache = new Cache();
$cache->set("name","sunny");

通过这段代码可以看出来当一个缓存使用的驱动改变了的时候,Cache的代码也必须作出相应的改变,因为代码写死在调用者身上了,耦合度变得高了。再对代码进行改造一样,让程序员面向interface编程,让代码变得更通用,更规范。

interface ICache{
    public function set($key,$value);
}
class CRedis implements ICache {
    public function set($key,$value)
{
        echo "redis:{$key}->{$value}\n";
    }
}
class CFile implements ICache{
    public function set($key,$value)
{
        echo "file:{$key}->{$value}\n";
    }
}
class Cache{
    private $drive;
    public function __construct(ICache $drive)
{
        $this->drive = $drive;
    }
    public function set($key,$value){
        $this->drive->set($key,$value);
    }
}
$cache = new Cache(new CFile());
$cache->set("name","sunny");

很多人看到这段代码的时候想着,那我在构造方法直接把要的对象传进去不就好了吗?为什么还要定义一个interface呢?其实定义interface是为了规范代码,不管你使用哪个驱动,只要实现了我这个interface的都可以用,没有interface开发者在开发驱动的时候就会不知道这个驱动里面该有什么方法。当我们使用interface之后大家只要面向接口编程,Cache完全不管类是怎么实现的,Cache只是根据interface的方法进行操作。

一句话总结:依赖倒置实现松耦合

实战:根据容器原理实现容器

<?php
class Container
{
    // 当前容器对象
    private static $instance;
    // 存放在容器里面到实例
    protected $instances = [];
    private function __construct()
{
    }
    public static function getInstance()
{
        if (!self::$instance) {
            self::$instance = new static();
        }
        return self::$instance;
    }
    
    public function get($key)
{
        if (isset($this->instances[$key])) {
            return $this->instances[$key];
        }
    }
    
    public function bind($key, $concrete = null)
{
        if ($concrete instanceof Closure) {
            $this->instances[$key] = $concrete;
        } elseif (is_object($concrete)) {
            $this->instances[$key] = $concrete;
        }
        return $this;
    }
}
class Sunny
{
    public function getName()
{
        echo time() . "\n";
    }
}
$app = Container::getInstance();
$sunny = $app->bind(Sunny::class,new Sunny());
$sunny = $app->get(Sunny::class);
$sunny->getName();

实战:实现依赖注入

Container.php
<?php
class Container
{
    // 当前容器对象
    private static $instance;
    // 存放在容器里面到实例
    protected $instances = [];
    private function __construct()
{
    }
    public static function getInstance()
{
        if (!self::$instance) {
            self::$instance = new static();
        }
        return self::$instance;
    }
    
    public function get($key)
{
        if (isset($this->instances[$key])) {
            return $this->instances[$key];
        }
        return $this->make($key);
    }
    
    public function bind($key, $concrete = null)
{
        if ($concrete instanceof Closure) {
            $this->instances[$key] = $concrete;
        } elseif (is_object($concrete)) {
            $this->instances[$key] = $concrete;
        } else {
            $this->make($key, $concrete);
        }
        return $this;
    }
    
    public function make($abstract, $atgs = null)
{
        if (isset($this->instances[$abstract])) {
            return $this->instances[$abstract];
        }
        $object = $this->invokeClass($abstract);
        $this->instances[$abstract] = $object;
        return $object;
    }
    
    public function invokeClass($abstract)
{
        $reflectionClass = new \ReflectionClass($abstract);
        // 获取构造方法
        $construct = $reflectionClass->getConstructor();
        // 获取参数得到实例
        $params = $construct ? $this->parserParams($construct) : [];
        $object = $reflectionClass->newInstanceArgs($params);
        return $object;
    }
    
    public function parserParams(ReflectionMethod $reflect)
{
        $args = [];
        $params = $reflect->getParameters();
        if (!$params) {
            return $args;
        }
        if (count($params) > 0) {
            foreach ($params as $param) {
                $class = $param->getClass();
                if ($class) {
                    $args[] = $this->make($class->getName());
                    continue;
                }
                // 获取变量的名称
                $name = $param->getName();
                // 默认值
                $def = null;
                // 如果有默认值,从默认值获取类型
                if ($param->isOptional()) {
                    $def = $param->getDefaultValue();
                }
                $args[] = $_REQUEST[$name] ?? $def;
            }
        }
        return $args;
    }
}
Test.php
<?php
class Test
{
    public $name;
    private $test1;
    public function __construct(Test1 $test1)
{
        $this->test1 = $test1;
        $this->name = $this->test1->getName();
    }
}
Test1.php
<?php
class Test1
{
    public function getName(){
        return "test1返回的名字";
    }
}
Sunny.php
<?php
require_once "./Container.php";
require_once "./Test.php";
require_once "./Test1.php";
class Sunny
{
    private $test;
    public function __construct(Test $test)
{
        $this->test = $test;
    }
    public function getName()
{
        echo "获取test里面的name:{$this->test->name}\n";
    }
}
$app = Container::getInstance();
$sunny = $app->get(Sunny::class);
$sunny->getName();

以上就是一文理解和实现现代PHP框架里的IOC容器的详细内容,更多请关注编程网其它相关文章!

--结束END--

本文标题: 一文理解和实现现代PHP框架里的IOC容器

本文链接: https://www.lsjlt.com/news/203486.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 一文理解和实现现代PHP框架里的IOC容器
    本篇文章给大家带来了关于PHP的相关知识,其中主要介绍了关于IOC容器的相关内容,IOC的全称是:Inversion Of Control,反转控制,下面一起来看一下,希望对大家有帮助。容器是什么?相信很多人听说过依赖注入,依赖注入实现的基...
    99+
    2023-05-14
    php
  • 现代PHP框架里的IOC容器怎么实现
    这篇文章主要讲解了“现代PHP框架里的IOC容器怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“现代PHP框架里的IOC容器怎么实现”吧!容器是什么?相信很多人听说过依赖注入,依赖注入...
    99+
    2023-07-04
  • 一文了解自定义MVC框架实现
    目录一、让中央控制器动态加载存储子控制器二、参数传递封装优化三、对于方法执行结果转发重定向优化四、框架配置可变一、让中央控制器动态加载存储子控制器 上期回顾,我们说明了自定义MVC工...
    99+
    2024-04-02
  • PHP容器技术能否实现Spring框架的实时数据处理?
    随着大数据时代的到来,实时数据处理成为了越来越多企业和开发者的需求,而Spring框架则是Java语言中最为流行的框架之一,它在实时数据处理方面有着得天独厚的优势。那么,PHP容器技术是否能够实现Spring框架的实时数据处理呢?本文将从...
    99+
    2023-09-12
    容器 实时 spring
  • PHP 重定向:如何在容器化的框架中实现?
    在现代的 Web 开发中,重定向是一个非常常见的功能,它允许我们将用户重定向到一个新的 URL,以便实现各种功能,比如登录、注册、购买等。在 PHP 中,重定向可以通过 header 函数来实现,但是在容器化的框架中,如何实现重定向呢?本...
    99+
    2023-09-17
    重定向 容器 框架
  • PHP框架和Linux环境:如何实现最佳兼容性?
    在今天的互联网时代,PHP已经成为了最流行的服务器端编程语言之一。而PHP框架的出现,更是让PHP的应用范围更加广泛。在使用PHP框架的同时,与之兼容的Linux环境也是至关重要的。本文将会探讨如何实现PHP框架和Linux环境的最佳兼容性...
    99+
    2023-11-11
    框架 linux linux
  • React前端框架实现原理的理解
    目录vdomdsl 的编译渲染 vdom组件状态管理react 架构的演变fiber 架构总结vdom react 和 vue 都是基于 vdom 的前端框架,我们先聊下 vdom:...
    99+
    2024-04-02
  • 一文带你解密Python迭代器的实现原理
    目录可迭代对象与迭代器迭代器的创建迭代器的底层结构元素迭代的具体过程小结可迭代对象与迭代器 Python 一切皆对象,类型对象定义了哪些操作,决定了实例对象拥有哪些行为。 比如类型对...
    99+
    2022-12-14
    Python迭代器原理 Python迭代器
  • Java 容器和 NPM 框架:你需要了解的一切。
    Java 容器和 NPM 框架:你需要了解的一切 在现代软件开发中,容器和框架是必不可少的工具。它们可以帮助开发人员更快地编写、测试和部署应用程序,提高生产力和可靠性。本文将介绍两种流行的工具:Java 容器和 NPM 框架。 Java 容...
    99+
    2023-07-08
    容器 npm 框架
  • spring IOC容器的Bean管理XML自动装配怎么实现
    这篇文章主要讲解了“spring IOC容器的Bean管理XML自动装配怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“spring IOC容器的Bean管理XML...
    99+
    2023-06-30
  • PHP 重定向与容器框架:实现最佳实践的关键要素。
    PHP 重定向与容器框架:实现最佳实践的关键要素 在现代 Web 应用中,重定向是非常常见的一种操作,它可以将用户从一个 URL 地址重定向到另一个 URL 地址,以实现页面跳转、表单提交、登录验证等功能。而在 PHP 中,重定向的实现可以...
    99+
    2023-09-17
    重定向 容器 框架
  • 一文了解Java动态代理的原理及实现
    代理是指:某些场景下对象会找一个代理对象,来辅助自己完成一些工作,如明星的经纪人、买房的人找房产中介等。 代理主要是对对象的行为额外做一些辅助操作。  如何创建代理对象: ...
    99+
    2024-04-02
  • C# CM框架实现多页面管理的实例代码
    概述 之前我分享过一个wpf的项目实践,主页面左侧是个listbox,每次选择改变后呈现对应的页面,界面图如下 要实现这样一个功能,我之前是采用传统方式实现的,本节我采用CM框架下...
    99+
    2024-04-02
  • 容器化框架的重定向:使用 PHP 实现的最佳实践是什么?
    随着云计算的快速发展,容器化技术已经成为了云计算领域中的一项重要技术。而容器化技术中的重定向功能更是一个不可或缺的部分。在本文中,我们将讨论使用 PHP 实现容器化框架的重定向的最佳实践。 什么是容器化框架的重定向? 容器化框架的重定向是...
    99+
    2023-09-17
    重定向 容器 框架
  • GO语言中的缓存管理:容器框架的实现原理是什么?
    随着网络技术的不断发展,数据量的不断增加,对数据的快速响应成为了当今互联网应用的重要问题。在这个背景下,缓存技术作为一种优化手段越来越受到开发者的关注。而GO语言因为其高效性、简洁性和可扩展性,成为了越来越多开发者选择的语言。那么,在GO...
    99+
    2023-07-24
    容器 框架 缓存
  • GolangGin框架实现文件下载功能的示例代码
    目录Layui框架实现文件上传Gin框架获取前端上传的文件Gin框架的文件下载Layui框架实现文件上传 基本的思路就是随便创建一个元素,然后使用layui的upload组件对创建的...
    99+
    2024-04-02
  • PHP容器技术的新进展:如何实现Spring框架的实时数据传输?
    随着互联网的快速发展,各种技术不断涌现。PHP作为一种流行的编程语言,一直以来在Web应用程序开发中扮演着重要的角色。而PHP容器技术则是近年来备受关注的技术之一,它可以轻松地将PHP应用程序打包成容器,实现快速部署和移植。本文将介绍PH...
    99+
    2023-09-12
    容器 实时 spring
  • 一文了解Seata的实现原理
    目录一、背景二、分布式事务规范2.1、分布式事务相关概念2.2、分布式事务实现规范2.2.1、XA2.2.2、柔性事务的最终一致性三、Seata 架构3.1、系统组成3.2、工作模式...
    99+
    2024-04-02
  • Go和Laravel:完美结合的文件框架实现方式?
    在现代软件开发中,文件操作是一个非常常见的需求。从简单的读写文件到复杂的文件操作,我们都需要一个可靠的文件框架来处理这些任务。在本文中,我们将探讨如何使用Go和Laravel这两个流行的编程语言和框架来构建一个完美的文件框架。 为什么使用...
    99+
    2023-06-25
    laravel 文件 框架
  • PHP在Linux下如何实现Laravel框架的并发处理?
    Laravel是一个流行的PHP框架,它提供了许多便利的功能和工具,使得开发Web应用变得更加容易和高效。然而,在处理大量请求时,Laravel框架可能会遇到性能瓶颈。为了解决这个问题,我们需要实现并发处理。 在Linux下,我们可以使用...
    99+
    2023-07-08
    linux laravel 并发
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作