热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入解析PHP容器概念:理解依赖注入容器的基础与应用(第一篇)

本文作为探讨PHP依赖注入容器系列文章的开篇,将首先通过具体示例详细阐述依赖注入的基本概念及其重要性,为后续深入解析容器的实现奠定基础。

本文是PHP依赖注入容器的实现这个系列的第一章。

今天,先不谈容器(container),首先用一些具体的例子来介绍依赖注入的概念,证明依赖注入这种模式可以解决哪些问题,同时能给开发人员带来哪些好处。

如果你已经知道了依赖注入的概念,你可以跳过这篇文章。

依赖注入可能是我所知道的最简单设计模式之一,很多情况下可能你无意识中已经使用了依赖注入。不过它也是最难解释的一个。我认为有一部分原因是由于大多数介绍依赖注入的例子缺乏实际意义,让人难理解。因为PHP主要用于Web开发,那就先来看一个简单的web开发实例。

HTTP本身是一个无状态的连接协议,为了支持客户在发起WEB请求时应用程序能存储用户信息,我们就需要通过一种技术来实现存储状态交互。理所当然最简单的是使用COOKIE,更好的方式是PHP内置的Session机制。$_SESSION['language'] = 'fr';

上面代码将用户语言存储在了名为language的Session变量中,因此在该用户随后的请求中,可以通过全局数组$_SESSION来获取language:$user_language = $_SESSION['language'];

依赖注入主要用于面向对像开发,现在让我们假设我们有一个SessionStorage类,该类封装了PHP Session机制:class SessionStorage

{

function __construct($COOKIEName = 'PHP_SESS_ID')

{

session_name($COOKIEName);

session_start();

}

function set($key, $value)

{

$_SESSION[$key] = $value;

}

function get($key)

{

return $_SESSION[$key];

}

// ...

}

同时还有一个User类提供了更高级的封装:class User

{

protected $storage;

function __construct()

{

$this->storage = new SessionStorage();

}

function setLanguage($language)

{

$this->storage->set('language', $language);

}

function getLanguage()

{

return $this->storage->get('language');

}

// ...

}

代码很简单,同样使用User类也很简单:$user = new User();

$user->setLanguage('fr');

$user_language = $user->getLanguage();

一切都很美好,除非你的程序需要更好的扩展性。假设现在你想要更改保存session_id的COOKIE键值,以下有一些可供选择的方法:

User类中创建SessionStorage实例时,在SessionStorage构造方法中使用字符串’SESSION_ID’硬编码:class User

{

function __construct()

{

$this->storage = new SessionStorage('SESSION_ID');

}

// ...

}

在User类外部设置一个常量(名为STORAGE_SESSION_NAME)class User

{

function __construct()

{

$this->storage = new SessionStorage(STORAGE_SESSION_NAME);

}

// ...

}

define('STORAGE_SESSION_NAME', 'SESSION_ID');

通过User类构造函数中的参数传递Session nameclass User

{

function __construct($sessionName)

{

$this->storage = new SessionStorage($sessionName);

}

// ...

}

$user = new User('SESSION_ID');

还是通过User类构造函数中的参数传递Session name,不过这次参数采用数组的方式class User

{

function __construct($storageOptions)

{

$this->storage = new SessionStorage($storageOptions['session_name']);

}

// ...

}

$user = new User(array('session_name' => 'SESSION_ID'));

上面的方式都很糟糕。

在user类中硬编码设置session name的做法没有真正解决问题,如果以后你还需要更改保存session_id的COOKIE键值,你不得不再一次修改user类(User类不应该关心COOKIE键值)。

使用常量的方式同样很糟,造成User类依赖于一个常量设置。

通过User类构造函数的参数或数组来传递session name相对来说好一些,不过也不完美,这样做干扰了User类构造函数的参数,因为如何存储Session并不是User类需要关心的,User类不应该和它们扯上关联。

另外,还有一个问题不太好解决:我们如何改变SessionStorage类。这种应用场景很多,比如你要用一个Session模拟类来做测试,或者你要将Session存储在数据库或者内存中。目前这种实现方式,在不改变User类的情况下,很难做到这点。

现在,让我们来使用依赖注入。回忆一下,之前我们是在User类内部创建SessionStorage对像的,现在我们修改一下,让SessionStorage对像通过User类的构造函数传递进去。class User

{

function __construct($storage)

{

$this->storage = $storage;

}

// ...

}

这就是依赖注入最经典的案例,没有之一。现在使用User类有一些小小的改变,首先你需要创建SessionStorage对像。$storage = new SessionStorage('SESSION_ID');

$user = new User($storage);

现在,配置session存储对像很简单了,同样如果改变session存储对像也很简单,所有这一切并不需要去更新User类,降低了业务类之间的耦合。

Pico Container 的网站上是这样描述依赖注入:

依赖注入是通过类的构造函数、方法、或者直接写入的方式,将所依赖的组件传递给类的方式。

所以依赖注入并不只限于通过构造函数注入。下面来看看几种注入方式:

构造函数注入class User

{

function __construct($storage)

{

$this->storage = $storage;

}

// ...

}

setter方法注入class User

{

function setSessionStorage($storage)

{

$this->storage = $storage;

}

// ...

}

属性直接注入class User

{

public $sessionStorage;

}

$user->sessionStorage = $storage;

根据经验,一般通过构造函数注入的是强依赖关系的组件,setter方式用来注入可选的依赖组件。

现在,大多数流行的PHP框架都采用了依赖注入的模式实现业务组件间的高内聚低耦合。// symfony: 构造函数注入的例子

$dispatcher = new sfEventDispatcher();

$storage = new sfMySQLSessionStorage(array('database' => 'session', 'db_table' => 'session'));

$user = new sfUser($dispatcher, $storage, array('default_culture' => 'en'));

// Zend Framework: setter方式注入的例子

$transport = new Zend_Mail_Transport_Smtp('smtp.gmail.com', array(

'auth' => 'login',

'username' => 'foo',

'password' => 'bar',

'ssl' => 'ssl',

'port' => 465,

));

$mailer = new Zend_Mail();

$mailer->setDefaultTransport($transport);

以上就是理解PHP依赖注入容器系列(一) 什么是的内容,更多相关内容请关注PHP中文网(www.php.cn)!

本文原创发布php中文网,转载请注明出处,感谢您的尊重!



推荐阅读
  • 本项目在Java Maven框架下,利用POI库实现了Excel数据的高效导入与导出功能。通过优化数据处理流程,提升了数据操作的性能和稳定性。项目已发布至GitHub,当前最新版本为0.0.5。该项目不仅适用于小型应用,也可扩展用于大型企业级系统,提供了灵活的数据管理解决方案。GitHub地址:https://github.com/83945105/holygrail,Maven坐标:`com.github.83945105:holygrail:0.0.5`。 ... [详细]
  • 在尝试对从复杂 XSD 生成的类进行序列化时,遇到了 `NullReferenceException` 错误。尽管已经花费了数小时进行调试和搜索相关资料,但仍然无法找到问题的根源。希望社区能够提供一些指导和建议,帮助解决这一难题。 ... [详细]
  • Java集合框架特性详解与开发实践笔记
    Java集合框架特性详解与开发实践笔记 ... [详细]
  • 【并发编程】全面解析 Java 内存模型,一篇文章带你彻底掌握
    本文深入解析了 Java 内存模型(JMM),从基础概念到高级特性进行全面讲解,帮助读者彻底掌握 JMM 的核心原理和应用技巧。通过详细分析内存可见性、原子性和有序性等问题,结合实际代码示例,使开发者能够更好地理解和优化多线程并发程序。 ... [详细]
  • 如何在Spark数据排序过程中有效避免内存溢出(OOM)问题
    本文深入探讨了在使用Spark进行数据排序时如何有效预防内存溢出(OOM)问题。通过具体的代码示例,详细阐述了优化策略和技术手段,为读者在实际工作中遇到类似问题提供了宝贵的参考和指导。 ... [详细]
  • 本文详细探讨了Java集合框架的使用方法及其性能特点。首先,通过关系图展示了集合接口之间的层次结构,如`Collection`接口作为对象集合的基础,其下分为`List`、`Set`和`Queue`等子接口。其中,`List`接口支持按插入顺序保存元素且允许重复,而`Set`接口则确保元素唯一性。此外,文章还深入分析了不同集合类在实际应用中的性能表现,为开发者选择合适的集合类型提供了参考依据。 ... [详细]
  • 本题库精选了Java核心知识点的练习题,旨在帮助学习者巩固和检验对Java理论基础的掌握。其中,选择题部分涵盖了访问控制权限等关键概念,例如,Java语言中仅允许子类或同一包内的类访问的访问权限为protected。此外,题库还包括其他重要知识点,如异常处理、多线程、集合框架等,全面覆盖Java编程的核心内容。 ... [详细]
  • 掌握PHP框架开发与应用的核心知识点:构建高效PHP框架所需的技术与能力综述
    掌握PHP框架开发与应用的核心知识点对于构建高效PHP框架至关重要。本文综述了开发PHP框架所需的关键技术和能力,包括但不限于对PHP语言的深入理解、设计模式的应用、数据库操作、安全性措施以及性能优化等方面。对于初学者而言,熟悉主流框架如Laravel、Symfony等的实际应用场景,有助于更好地理解和掌握自定义框架开发的精髓。 ... [详细]
  • Spring框架入门指南:专为新手打造的详细学习笔记
    Spring框架是Java Web开发中广泛应用的轻量级应用框架,以其卓越的功能和出色的性能赢得了广大开发者的青睐。本文为初学者提供了详尽的学习指南,涵盖基础概念、核心组件及实际应用案例,帮助新手快速掌握Spring框架的核心技术与实践技巧。 ... [详细]
  • 本课程详细介绍了如何使用Python Flask框架从零开始构建鱼书应用,涵盖高级编程技巧和实战项目。通过视频教学,学员将学习到Flask的高效用法,包括数据库事务处理和书籍交易模型的实现。特别感谢AI资源网提供的课程下载支持。 ... [详细]
  • 本文将介绍一种扩展的ASP.NET MVC三层架构框架,并通过使用StructureMap实现依赖注入,以降低代码间的耦合度。该方法不仅能够提高代码的可维护性和可测试性,还能增强系统的灵活性和扩展性。通过具体实践案例,详细阐述了如何在实际开发中有效应用这一技术。 ... [详细]
  • Spring注解开发指南:@Resource与@Component详解 ... [详细]
  • 本课程详细解析了Spring AOP的核心概念及其增强机制,涵盖前置增强、后置增强和环绕增强等类型。通过具体示例,深入探讨了如何在实际开发中有效运用这些增强技术,以提升代码的模块化和可维护性。此外,还介绍了Spring AOP在异常处理和性能监控等场景中的应用,帮助开发者更好地理解和掌握这一强大工具。 ... [详细]
  • MySQL日志分析在应急响应中的应用与优化策略
    在应急响应中,MySQL日志分析对于检测和应对数据库攻击具有重要意义。常见的攻击手段包括弱口令、SQL注入、权限提升和备份数据窃取。通过对MySQL日志的深入分析,不仅可以及时发现潜在的攻击行为,还能详细还原攻击过程并追踪攻击源头。此外,优化日志记录和分析策略,能够提高安全响应效率,增强系统的整体安全性。 ... [详细]
  • 深入解析MyBatis的高级映射技术
    在前一章节中,我们探讨了MyBatis的基本对象映射方法,其中对象属性与数据库表字段之间实现了直接的一对一映射。然而,在实际开发中,这种简单的映射方式往往难以满足复杂业务需求。本文将深入分析MyBatis的高级映射技术,介绍如何通过配置和注解实现更为灵活的对象与数据库表之间的映射关系,包括嵌套结果、联合查询和动态SQL等高级功能,以提高开发效率和代码可维护性。 ... [详细]
author-avatar
手机用户2502892503
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有