《关于依赖注入在php框架中的应用》由会员分享,可在线阅读,更多相关《关于依赖注入在php框架中的应用(35页珍藏版)》请在金锄头文库上搜索。
1、关于依赖注入在 PHP 框架中的应用现在的 PHP 应用包含了很多对象。有的对象能帮你发送电子邮件,另一个可以帮你把数据持久化到数据库中。在你的应用中,你可能会创建一个管理产品库存的对象,或者是一个处理第三方 API 数据的对象。这篇文章中,我们的关注这件事情:应用做了很多事情,它组织了很多对象来处理每一个任务。在 PHP 的 Symfony 2 框架中,有一个特殊的对象,帮助你实例化、组织和获取应用中的那一系列的对象。它叫 Service Container(服务容器),可以让你标准化和集中化地创建应用中对象。容器让生活简化,它速度很快,包含的架构思想促进代码的重用和解耦。所有 Symfon
2、y 2 的核心的类都使用容器,容器为框架的速度和可扩展性做了最大的贡献。先来了解下什么是 Service。简单的说,一个 Service 就是任何的可以完成某类“全局”任务的 PHP 对象。一个 Service 是一个 PHP 对象的通用性的术语,这个对象能执行特定的任务,通常被“全局” 地使用,比如一个数据库连接的对象,或者一个能发送电子邮件的对象。如果拥有很多松耦合的 Service,我们就说这个应用遵循了 SOA(面向服务的架构)。创建一个 Service 很简单,你只要为那份能完成特定任务的代码写个类,就 OK 了。一般来说,PHP 对象如果要成为 Service,必须要在应用中被全局
3、的使用。比如一个 Mailer Service 被全局的用于发送电子邮件,但是由 Mailer 发送的邮件内容对象(每次的内容都不同)就不是 Service。既然 Service 这么容易创建,那有啥了不起的呢?如果你开始考虑将应用中的每个功能都分离开来,你就能开始感受 Service 的好处了。因为每个 Service 只做一个工作,你在任何地方都可以轻松地获得并使用它们的功能。每个 Service 也能更容易的被测试和配置,因为在应用中它们是互相分离的。将你的应用组织成一系列独立的 Service 的类,也是面向对象编程的最佳实践之一。这种技能在任何开发语言中都是好程序员的标志。什么是 S
4、ervice Container。Service Container 也叫 Dependency Injection Container(依赖注入容器),就是一个简单的 PHP 对象,管理着 Service 们的实例化。假设你有个发送电子邮件的 PHP 类。如果不用 Service Container,在你需要它时,都必须手工地创建对象。这也算简单。但是,如果你不想重复地去配置它,就可以把它作为 Service。当你需要创建一个 Service,它依赖了 Service Container 中一个或几个其他的 Service 们时,你才会意识到容器的强大。假设你的一个新的 Service,依赖
5、了发送电子邮件的 Service。只要在新的 Service 配置中将发送电子邮件的 Service 设为参数即可,如果你的这个 Service 后来做了改动,需要再依赖一个 Service,只需要改下配置,增加参数即可。对应到依赖注入模式,其实 Service Container 就是注入器;Service A 依赖 Service B,前者是依赖者,后者是被依赖者;被依赖者的接口一般就是依赖的定义。这次设计模式解决的是整个框架的架构问题,解决了:功能间的松耦合、框架的扩展性,运行效率也高。其实还是蛮羡慕学 Java 的同学,很早就接触一些好的设计和应用,比如:Spring 框架。当然现在
6、PHP 的新的框架层出不穷,也借鉴各种好的思想。面包和牛奶已经有了,可以吃了。看 Laravel 的 IoC 容器文档只是介绍实例,但是没有说原理,之前用 MVC 框架都没有在意这个概念,无意中在 phalcon 的文档中看到这个详细的介绍,感觉豁然开朗,复制粘贴过来,主要是好久没有写东西了,现在确实很懒变得!首先,我们假设,我们要开发一个组件命名为 SomeComponent。这个组件中现在将要注入一个数据库连接。在这个例子中,数据库连接在 component 中被创建,这种方法是不切实际的,这样做的话,我们将不能改变数据库连接参数及数据库类型等一些参数。php view plaincopy
7、1. localhost, 15. username = root, 16. password = secret, 17. dbname = invo 18. ); 19. 20. / . 21. 22. 23. 24. 25. $some = new SomeComponent(); 26. $some-someDbTask(); 为了解决上面所说的问题,我们需要在使用前创建一个外部连接,并注入到容器中。就目前而言,这看起来是一个很好的解决方案:php view plaincopy1. _connection = $connection; 14. 15. 16. public functio
8、n someDbTask() 17. 18. $connection = $this-_connection; 19. 20. / . 21. 22. 23. 24. 25. $some = new SomeComponent(); 26. 27. /Create the connection 28. $connection = new Connection(array( 29. host = localhost, 30. username = root, 31. password = secret, 32. dbname = invo 33. ); 34. 35. /Inject the c
9、onnection in the component 36. $some-setConnection($connection); 37. 38. $some-someDbTask(); 现在我们来考虑一个问题,我们在应用程序中的不同地方使用此组件,将多次创建数据库连接。使用一种类似全局注册表的方式,从这获得一个数据库连接实例,而不是使用一次就创建一次。php view plaincopy1. localhost, 13. username = root, 14. password = secret, 15. dbname = invo 16. ); 17. 18. 19. 20. 21. cl
10、ass SomeComponent 22. 23. 24. protected $_connection; 25. 26. /* 27. * Sets the connection externally 28. */ 29. public function setConnection($connection) 30. $this-_connection = $connection; 31. 32. 33. public function someDbTask() 34. 35. $connection = $this-_connection; 36. 37. / . 38. 39. 40. 4
11、1. 42. $some = new SomeComponent(); 43. 44. /Pass the connection defined in the registry 45. $some-setConnection(Registry:getConnection(); 46. 47. $some-someDbTask(); 现在,让我们来想像一下,我们必须在组件中实现两个方法,首先需要创建一个新的数据库连接,第二个总是获得一个共享连接:php view plaincopy1. localhost, 15. username = root, 16. password = secret,
12、17. dbname = invo 18. ); 19. 20. 21. /* 22. * Creates a connection only once and returns it 23. */ 24. public static function getSharedConnection() 25. 26. if (self:$_connection=null) 27. $connection = self:_createConnection(); 28. self:$_connection = $connection; 29. 30. return self:$_connection; 3
13、1. 32. 33. /* 34. * Always returns a new connection 35. */ 36. public static function getNewConnection() 37. 38. return self:_createConnection(); 39. 40. 41. 42. 43. class SomeComponent 44. 45. 46. protected $_connection; 47. 48. /* 49. * Sets the connection externally 50. */ 51. public function setConnection($connection) 52. $this-_connection = $connection; 53. 54. 55. /* 56. * This method always needs the shared connection 57. */ 58. public function someDbTask() 59. 60. $connection = $this-_connection; 61. 62. / . 63. 64. 65. /* 66. * This method always needs a new connection 67