PHP:创建可扩展的 CMS 系统

客户给了我一项新任务,主要是为演员/歌手等创建一个 CMS,客户将向他们出售.

I have been given a new task from the client which is basically creating a CMS for actors/singers and the like that client will be selling out to them.

它基本上是一个软件包,开箱即用,与 WordPress 非常相似,您只需将其交给购买它的人,当然这不会成为一个博客平台.它将允许开发人员:

It will basically be a package and would work out-of-box pretty much similar to WordPress, you just hand over to whoever buys it but of course this is not going to be a blogging platform. It will allow developers to:

  • 添加插件/小部件
  • 添加模板/主题

我认为 观察者模式 可能有用,但我不太确定.你们可以建议在以下方面创建这种灵活/可扩展的 CMS:

I thought the Observer Pattern may be useful but I am not that sure about it. What you guys could suggest to create such flexible/extensible CMS in terms of:

  • 能够添加插件(例如 WordPress)
  • 能够添加主题/模板(例如 WordPress)
  • 设计模式
  • 任何其他事情

推荐答案

Observer 很好,但您将不得不考虑超越基本模式.规范的观察者/主题模式只将主题对象发送给观察者,没有别的,甚至没有为什么通知它.

Observer's fine, but you're going to have to consider going beyond the basic pattern. The canonical Observer/Subject pattern only sends the Subject object to the Observer, nothing else, not even why it's being notified.

最初,解决方案似乎还包括向观察者发出通知的原因,但随后您可能最终会通知不关心某些通知的观察者.更好的解决方案可能是要求观察者还要求提供他们希望收到的通知列表.

Initially, the solution might seem like also including the reason for the notification to the Observer, but then you might end up notifying Observers that don't care about certain notifications. A better solution might be requiring Observers to also ask for a list of notifications they'd like to receive.

但这也带来了一个问题.为了让观察者真正将自己附加到主题,它们必须被实例化.每一次.即使他们永远不需要.那是愚蠢的.

But that also presents a problem. In order for the Observers to actually attach themselves to Subjects, they have to be instantiated. Every single time. Even if they'd never be needed. That's silly.

因此,我们很快就达到了插件的规范 PHP 实现之一:hooks".Hooks 使用与 Observer/Subject 相同的概念,但在一个非常重要的方面实现不同:实际的 Observers 不是为了观察 Subjects 而实例化的.相反,Subjects 向某种中央存储库发送通知.该存储库配置了所有已安装和激活插件(观察者)的列表,并包含每个插件想要接收的所有事件的列表.每个插件仅在事件发生时通知,通常通过静态方法而不是通过创建插件实例并通知它.call_user_func_array 和一个好的自动加载器使这变得非常简单.

So, we've quickly reached one of the canonical PHP implementations of plugins: "hooks". Hooks use the same concept as Observer/Subject, but the implementation is different in a very important way: the actual Observers aren't instantiated in order to Observe Subjects. Instead, Subjects send a notification to some variety of central repository. This repository is configured with a list of all installed and activated plugins (Observers), and contains a list of all of the events that each plugin wants to receive. Each plugin and notified only when the event takes place, often through a static method rather than by creating an instance of the plugin and notifying it. call_user_func_array and a good autoloader makes this incredibly trivial.

因此,您可以为所有插件创建一个简单的接口来实现.您需要的方法包括但不限于:

You can therefore create a simple Interface for all plugins to implement. Methods that you'll need include but are not limited to:

  • 用于获取有关插件数据的内容,例如名称、作者、官方网站、版本等.人类可使用的信息.
  • 返回插件想要订阅的事件的方法.
  • 一种安装方法,用于插件为了安装自身而需要做的事情,例如操作数据库.
  • 卸载方法也可能很方便.
  • 将接收事件通知并返回所需数据的(可能是静态的)方法.

根据您采用插件概念的程度,您最终可能会得到具有用户可配置选项的插件.您可能需要考虑到这一点.沿着这条路走下去的是疯狂和配置系统.

Depending on how far you take the plugin concept, you could end up with plugins that have user configurable options. You might need to take that into account. Down that road lies madness and configuration systems.

为了使插件有效,您需要到处放置钩子,并经常与最终用户合作,在需要的地方添加新的钩子.

In order to make plugins effective, you're going to need to place hooks everywhere, and frequently work with end-users to add new hooks where they are needed.

小部件可以很容易地以类似的方式工作,就像在页面呈现之前调用的插件一样.

Widgets can easily work in a similar way, as plugins that get called prior to page rendering.

主题/模板,天哪.您可能有两大选择.

Themes/templates, oh my. You probably have two big options.

  1. Smarty 或类似的模板引擎.或者您自己的非 PHP 模板引擎.
  2. PHP 模板.

此决定将由您的最终用户决定.Smarty 的限制令人难以置信,但如果您想确保模板中只运行经过批准的代码,它可能是一个可行的选择.此外,允许直接在应用程序本身中编辑 Smarty 模板并不是不安全的.

This decision will be driven by your end users. Smarty is incredibly limiting, but if you want to make sure that only approved code runs in a template, it might be a viable option. Furthermore, it's not unsafe to allow editing of Smarty templates right in the application itself.

另一方面,Wordpress 模板运行良好的原因之一是它们是纯 PHP 的.他们可以调用 Wordpress API 中公开的任何方法,甚至可以执行自己有趣的逻辑.如果您希望您的最终用户具有技术头脑,或者至少具有技术能力,那么 PHP 模板就是您的最佳选择.另一方面,如果恶意用户进入管理位,允许在应用程序中编辑 PHP 模板可能会打开一个巨大的潜在安全漏洞.您可能想限制对文件系统的编辑.

On the other hand, one of the reason Wordpress templates work so well is that they're pure PHP. They can call any method exposed in the Wordpress API, and even do their own interesting logic. If you expect your end users to be technically minded, or at least technically competent, then PHP templates are the way to go. On the other hand, allowing editing of PHP templates within the application can open up a huge potential security hole if a malicious user gets into the admin bits. You probably want to restrict editing to the filesystem.

虽然这涵盖了 HTML 创建,但您还应该考虑 CSS.您的最终用户能否直接操作 CSS?他们愿意吗?如果您的默认模板包含足够多的语义类,那么如果他们知道自己在做什么,他们可能会毫不费力地进行大量样式设置.另一方面,您的最终用户可能不知道 CSS 是什么,所以他们可能想要,哦,比如说,颜色选择器和预先构建的配色方案,以及配色方案选择器,以及其他类似令人讨厌的东西来构建.现在最好考虑一下那些恐怖事件.

While this covers HTML creation, you should also take CSS into consideration. Will your end-users be able to manipulate CSS directly? Will they want to? If your default templates include enough semantic classes, they can probably do a great deal of styling with not a lot of effort, if they know what they're doing. On the other hand, your end-users might not know what CSS is, so they might want, oh, say, color pickers and pre-built color schemes, and a color scheme chooser, and other such annoying things to build. It's probably best to think about those horrors now.

杂项.

如果没有草稿和发布状态的概念,任何 CMS 都是不完整的.除了先编码之外,我在这里没有给你任何建议.如果您的客户或最终用户想要任何类型的历史存档、管理审批机制或任何其他使草稿/发布的内容不只是简单状态字段的内容,您需要很快知道.(我被这个深深地咬住了.我们围绕一个简单的已发布/未发布的模型设计了整个系统,并在我们意识到它不起作用时通过规范构建和相关原型代码获得了大约 9/10我们必须做一些更远、更复杂的事情才能真正满足客户的要求.重建粗略的计划是我们迄今为止遇到的最大的一次浪费时间.)

No CMS would be complete without the concept of drafts and publish states. I don't have any advice for you here, other than code this first. If your customer or the end-users want any sort of historical archiving, managerial approval mechanism, or anything else that makes draft/published anything but a simple state field, you need to know very soon. (I've been bitten horribly by this one. We'd designed the entire system around a simple published/not-published model, and got about 9/10ths through spec building and related prototype code when we realized it wouldn't work and we'd have to do something far, far more complex to actually meet customer requirements. Rebuilding the rough plan was the single largest time-sink we encountered so far.)

你会使用 ORM 吗?如果没有,请确保使用适当的数据库接口库.PDO,或者来自 PEAR 的东西,或者 Zend_Db.您不可避免地会有一个客户坚持代码在 Oracle 或 MSSQL 上运行.或 SQLite.很高兴告诉他们可以做到(需要付出一些努力).插件作者也会感谢您的理智.不要自己动手.

Will you use an ORM? If not, be sure to use a proper database interface library. PDO, or maybe something from PEAR, or maybe Zend_Db. You'll inevitably have a customer that will insist that the code runs on Oracle or MSSQL. Or SQLite. It'll be nice to tell them it can be done (with some effort). Plugin authors will thank you for the sanity as well. Don't roll your own.

(再说一次,对于您的代表级别,我希望您已经熟悉我所说的几乎所有内容.啊,我做的事情是在思考自己的编码问题时分散自己的注意力......)

(Then again, with your rep level, I expect that you're already familiar with pretty much everything I've said. Ah, the things I do to distract myself while thinking about my own set of coding problems...)

相关文章