假设您正在构建一个将成为打包产品的Web应用程序,用户希望能够扩展和自定义该应用程序。
它附带了一个核心库,其中包含包含类的PHP文件:
/library/
/library/frontend.class.php
/library/filesystem.class.php
/library/backend.class.php
现在,假设您要保留用户无法修补的干净核心。但是,如果需要,您希望用户能够自定义每个螺母和螺栓。
我目前的想法是创建一个自动加载机制,当实例化类时,首先加载核心包括:
/library/frontend.class.php
然后,它切换到user
目录并查看是否存在相同名称的包含:
/user/library/frontend.class.php
如果存在,也包括它。
显然,用户include必须包含一个类定义,扩展了核心中的定义。
现在我的问题是,我将如何实例化这样一个类?毕竟,我总能确定有一个定义:
class frontend_core
但我无法确定是否有
class frontend_user extends frontend_core
但是,无论是否有类的自定义扩展,我都希望能够依赖并实例化一个类名。
有一种聪明的方式,想法或模式如何实现这一目标?
当然,我可以编写一个简单的工厂辅助函数,首先查找user
类,然后查找core
类并返回一个初始化对象,但我真的希望将其保留为尽可能干净简单,因为正如我所说,它将成为一个包装产品。
我正在寻找一种使用尽可能少的代码的智能技巧或模式,并尽可能少地引入新功能。
答案 0 :(得分:3)
为什么不遵循Propel使用的方法?您生成基类并且已经提供了一个空的User类(扩展基类),您的用户可以在其中放置其覆盖/特定的实现细节,并且在您的代码中始终引用User类。所以基本上你只需使用你所描述的逻辑的逆。
如果上述说明不明确,请查看http://propel.phpdb.org/trac/wiki/Users/Documentation/1.4/QuickStart#a6.UsingtheGeneratedSQLandOMFiles并为小型数据库生成代码。基类位于om文件夹中,(默认为空)用户类位于根文件夹中。
答案 1 :(得分:0)
我会在核心中实现钩子,因此用户不必破解核心,但仍然能够使用钩子扩展核心
答案 2 :(得分:0)
我认为当你想使用继承时,使用单个文件名会更复杂。基本上class user_frontend extends core_frontend
必须知道在哪里找到这两个类。两者都必须包括在内。
如果你只想做new Frontend
,你可以使用PHP5.3的class_alias
将Frontend指向要使用的主类。低于5.3。您可以使用ServiceFinder,它知道如何将服务名称映射到类,然后使用$service->get('frontend')
获取前端或使用Dependency Injection framework。
编辑 我之前删除了之前提供的Loader代码,因为它确实遇到了这个问题。
答案 3 :(得分:0)
我将继续使用核心类的构造函数来确定要加载的用户类,然后在核心类中实现工厂方法以生成用户类的实例。通过使用户类的构造函数受到保护,并让用户类扩展核心类,您可以确保其他地方的代码无法实例化用户类。
下进行。
答案 4 :(得分:0)
你可以有一个加载器类来决定实例的哪个类:
Loader::instance()->load('Frontend')