前四章建立了一个基本的内容插件。但是内容插件实际是什么,如何写一个真正声明周期的内容插件。这章将讨论内容插件的通用用法和可用事件。
引言
Joomla是个CMS系统,所有的都是content。内容插件可以做很多事,文章要被创建在存进数据库前可以进行修改,文章在数据库中被调用,在展示前也可以修改。甚至可以修改文章的编辑框。
当我们讨论Joomla的内容时,首先想到的是文章。但是,内容包括更多的东西:weblinks,contacts还有来自第三方扩展的内容(K2,ZOO等)。Joomla本身致力于将内容插件用于各种插件,首先是文章插件。对于第三方扩展,有点复杂,会在文章的末尾讨论。
插件事件
下面是Joomla核心的事件,以字母顺序
- onContentAfterDelete
- onContentAfterDisplay
- onContentAfterSave
- onContentAfterTitle
- onContentBeforeDelete
- onContentBeforeDisplay
- onContentBeforeSave
- onContentChangeState
- onContentPrepareon
- onContentPrepareForm
事件什么时间发生
写插件时最重要的是知道事件什么时候发生。不幸的是,没有一个硬性标准如何找到事件如何生成。有些事件在前端,有些在后端。组件代码决定事件是怎么用的。com_component
提供了很多这种事件如何做,但其他组件不一定这么做。
Joomla希望所有的扩展以相同的方式工作,这叫做Unified Content Model。
遍历代码。最好的查询一个组件如何抛出一个特定事件的方法是看代码。
代码会使用JDispatcher
类(通过$dispatcher = JEventDispatcher::getInstance();
来获得)来触发特定的事件,细节会在第11章讨论。另一个方法是查找事件的名称。第13章会给更多得提示如果搜索事件。
来看一下com_content如何抛出事件。搜素关键词trigger
可以收到很多。content组件中事件都在viem.html.php文件中
// Process the content plugins.
JPluginHelper::importPlugin('content');
$dispatcher->trigger('onContentPrepare', array ('com_content.article', &$item, &$item->params, $offset));
$item->event = new stdClass;
$results = $dispatcher->trigger('onContentAfterTitle', array('com_content.article', &$item, &$item->params, $offset));
$item->event->afterDisplayTitle = trim(implode("\n", $results));
$results = $dispatcher->trigger('onContentBeforeDisplay', array('com_content.article', &$item, &$item->params, $offset));
$item->event->beforeDisplayContent = trim(implode("\n", $results));
$results = $dispatcher->trigger('onContentAfterDisplay', array('com_content.article', &$item, &$item->params, $offset));
$item->event->afterDisplayContent = trim(implode("\n", $results));
把4个事件放到了一起,显然这是个坏例子。
模板覆写能够阻止事件起作用
onContentPrepare
总是能起作用,$item
对象被修改了。但是,后面三个方法只是添加额外的属性到$item
对象,需要模板文件(tmpl/default.php
)来显示这些额外的属性。
在模板文件中,$item
对象引用为$this->item
,在运行onContentAfterDisplay
事件后,多了个属性event->afterDisplayTitle:
<?php echo $this->item->event->afterDisplayTitle; ?>
基于Jmodeladmin
的后台组件
开发后台组件要基于MVC模式。Joomla1.5版本以后,加入了很多新子类,可以自动完成很多事情。比如,mode扩展自JModelAdmin
,自动化各种批处理方法,自动应用ACL规则,自动存储数据。
FOF事件。Joomla3.2之后,Framework-on-Framework(FoF)库(作者Nikolas
Dionysopoulos )加入到核心代码。FoF,是Joomla框架的扩展。可以快速的开发一个MVC组件,用一点代码,实现很多功能。通过提供一系列的父类,通过继承他们能够实现很多功能。比如,model父类FOFModel包含很多model功能,不用重新写CRUD(增删改查)方法。
其中就包括事件处理。比如,FOFModel::delete()
方法自动触发onBeforeDelete()
和onAfterDelete()
事件。换句话说,任何基于FoF的组件,自动支持内容事件,而不需要任何额外的代码。这就是为什么FoF被称作**Rapid Application
Development (RAD)**框架。它能够快速的建立任何Joomla应用,因为各种FoF类的通用类做了大量工作。
插件参数都包含什么?
onContentPrepare($context, &$row, &$params, $page = 0)
第一个参数$context
,表示这个事件是由哪个Joomla应用触发的。比如,当处理文章表单时,context会被设为com_content.form
。检查这个变量十分必要,它决定你的这个插件是否应用对了应用。
第二个参数,经常取名为$row
或者$item
,包含要处理的内容。经常,这个对象就是一篇文章。也可是能目录等。大部分时候,是从通过$db->loadObject()
或者$db->loadObjectList()
方法从数据库读取的数据。一个简单的查看这个对象属性的方法是去看数据库。有的情况,不如content对象,有个getProperties()
方法(继承自JObject
)。一般情况一个对象有title
,alias
和text
。虽然这些字段并非必须。比如,#__content
表,就没有text
字段。而是有introtext
和fulltext
。
第三个参数,$params
包含content的参数,是一个JRegistry
对象,有个get()
方法。可以通过下面的代码看看参数包含那些内容,
public function onContentBeforeDisplay(
$context, &$row, &$params, $page = 0
) {
echo ′<pre>′;
echo __FILE__ . ′ [′ . __LINE__ . ′] ′;
print_r($params->toArray());
echo ′</pre>′;
}
**JRegistry::toArray()**方法返回一个清洁的数组,包含所有的参数字段。如果一个参数包含show_title字段,可以如下使用这个参数:
$show_title = $params->get(′show_title′);