在 PHP 项目中,存在哪些模式来存储、访问和组织辅助对象? [英] In a PHP project, what patterns exist to store, access and organize helper objects?

查看:17
本文介绍了在 PHP 项目中,存在哪些模式来存储、访问和组织辅助对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在基于 PHP 的面向对象的项目中,您如何组织和管理帮助对象,例如数据库引擎、用户通知、错误处理等?

How do you organize and manage your helper objects like the database engine, user notification, error handling and so on in a PHP based, object oriented project?

假设我有一个大型 PHP CMS.CMS 分为不同的类.几个例子:

Say I have a large PHP CMS. The CMS is organized in various classes. A few examples:

  • 数据库对象
  • 用户管理
  • 用于创建/修改/删除项目的 API
  • 用于向最终用户显示消息的消息传递对象
  • 一个带你到正确页面的上下文处理程序
  • 显示按钮的导航栏类
  • 一个日志对象
  • 可能,自定义错误处理

我正在处理一个永恒的问题,即如何最好地让需要它的系统的每个部分都可以访问这些对象.

I am dealing with the eternal question, how to best make these objects accessible to each part of the system that needs it.

多年前,我的第一个方法是拥有一个 $application global,其中包含这些类的初始化实例.

my first apporach, many years ago was to have a $application global that contained initialized instances of these classes.

global $application;
$application->messageHandler->addMessage("Item successfully inserted");

然后我改用单例模式和工厂函数:

I then changed over to the Singleton pattern and a factory function:

$mh =&factory("messageHandler");
$mh->addMessage("Item successfully inserted");

但我对此也不满意.单元测试和封装对我来说越来越重要,在我的理解中,全局/单例背后的逻辑破坏了 OOP 的基本思想.

but I'm not happy with that either. Unit tests and encapsulation become more and more important to me, and in my understanding the logic behind globals/singletons destroys the basic idea of OOP.

然后当然有可能给每个对象提供一些指向它需要的辅助对象的指针,这可能是最干净、节省资源和测试友好的方式,但我对长期的可维护性有疑问跑.

Then there is of course the possibility of giving each object a number of pointers to the helper objects it needs, probably the very cleanest, resource-saving and testing-friendly way but I have doubts about the maintainability of this in the long run.

我研究过的大多数 PHP 框架要么使用单例模式,要么使用访问初始化对象的函数.两种方法都很好,但正如我所说,我对两者都不满意.

Most PHP frameworks I have looked into use either the singleton pattern, or functions that access the initialized objects. Both fine approaches, but as I said I'm happy with neither.

我想拓宽视野,了解这里存在哪些常见模式.我正在寻找从长期现实世界角度讨论这个问题的示例、其他想法和资源.

I would like to broaden my horizon on what common patterns exist here. I am looking for examples, additional ideas and pointers towards resources that discuss this from a long-term, real-world perspective.

此外,我有兴趣了解针对该问题的专业、小众或普通的方法.

Also, I'm interested to hear about specialized, niche or plain weird approaches to the issue.

推荐答案

我会避免 Flavius 建议的单例方法.避免这种方法的原因有很多.它违反了良好的 OOP 原则.谷歌测试博客上有一些关于单身人士以及如何避免它的好文章:

I would avoid the Singleton approach suggested by Flavius. There are numerous reasons to avoid this approach. It violates good OOP principles. The google testing blog has some good articles on the Singleton and how to avoid it:

http:///googletesting.blogspot.com/2008/08/by-miko-hevery-so-you-join-new-project.htmlhttp://googletesting.blogspot.com/2008/05/tott-using-dependancy-injection-to.htmlhttp://googletesting.blogspot.com/2008/08/where-have-all-singletons-gone.html

  1. 服务提供商

  1. a service provider

http://java.sun.com/blueprints/corej2eepatterns/Patterns/ServiceLocator.html

依赖注入

http://en.wikipedia.org/wiki/Dependency_injection

和一个php解释:

http://components.symfony-project.org/dependency-injection/trunk/book/01-Dependency-Injection

这是一篇关于这些替代方案的好文章:

This is a good article about these alternatives:

http://martinfowler.com/articles/injection.html

您可以手动提供所需的对象(依赖项)($application = new Application(new MessageHandler()).但您也可以使用 DI 框架(维基百科页面提供了指向 PHP DI 框架的链接).

You can provide the needed objects (dependencies) manually ($application = new Application(new MessageHandler()). But you can also use a DI framework (the wikipedia page provides links to PHP DI frameworks).

重要的是你只传递你实际使用的东西(调用一个动作),而不是你简单地传递给其他对象,因为他们需要它.这是鲍勃叔叔"(罗伯特·马丁)最近发表的一篇文章,讨论了 手动 DI 与使用框架.

Important is that you only pass in what you actually use (call an action on), NOT what you simply pass to other objects because they need it. Here's a recent post from 'uncle Bob' (Robert Martin) discussing manual DI vs using framework.

关于 Flavius 解决方案的更多想法.我不希望这篇文章成为反帖,但我认为了解为什么依赖注入至少对我来说比全局更好.

Some more thoughts on Flavius's solution. I don't want this post to be an anti-post but I think it's important to see why dependency injection is, at least for me, better than globals.

即使它不是真实的"单身 实施,我仍然认为 Flavius 弄错了.全局状态不好.请注意,此类解决方案也使用 难以测试静态方法.

Even though it is not a 'true' Singleton implementation, I still think Flavius got it wrong. Global state is bad. Note that such solutions also use difficult to test static methods.

我知道很多人都这样做了,批准了它并使用了它.但是阅读 Misko Heverys 的博客文章(一个 google 可测试性专家),重新阅读并慢慢消化他所说的确实改变了我对设计的看法.

I know a lot of people do it, approve it and use it. But reading Misko Heverys blog articles (a google testability expert), rereading it and slowly digesting what he says did alter the way I see design a lot.

如果您希望能够测试您的应用程序,您需要采用不同的方法来设计您的应用程序.当你进行测试优先编程时,你会遇到这样的问题:接下来我想在这段代码中实现日志记录;让我们先编写一个记录基本消息的测试,然后提出一个测试,强制您编写和使用无法替换的全局记录器.

If you want to be able to test you application, you'll need to adopt a different approach to designing your application. When you do test-first programming, you'll have difficulty with things like this: 'next I want to implement logging in this piece of code; let's write a test first that logs a basic message' and then come up with a test that forces you to write and use a global logger that can't be replaced.

我仍然挣扎 我从那个博客上得到的所有信息,实施起来并不总是那么容易,我有很多问题.但是在我掌握了 Misko Hevery 所说的内容之后,我无法回到我之前所做的事情(是的,全局状态和单身人士(大 S)):-)

I am still struggling with all the information I got from that blog, and it's not always easy to implement, and I have many questions. But there's no way I can go back to what I did before (yes, global state and Singletons (big S)) after I grasped what Misko Hevery was saying :-)

这篇关于在 PHP 项目中,存在哪些模式来存储、访问和组织辅助对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆