<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>睡到25点 &#187; hook</title>
	<atom:link href="http://www.voidman.com/tag/hook/feed" rel="self" type="application/rss+xml" />
	<link>http://www.voidman.com</link>
	<description>个人博客，记录与分享，仅此而已。</description>
	<lastBuildDate>Fri, 30 Jul 2010 09:54:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>WordPress 的 Hook 机制在 Discuz 二次开发中的应用</title>
		<link>http://www.voidman.com/2009/05/using-wordpress-plugin-api-hack-discuz.html</link>
		<comments>http://www.voidman.com/2009/05/using-wordpress-plugin-api-hack-discuz.html#comments</comments>
		<pubDate>Fri, 01 May 2009 16:41:30 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[discuz]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[hook]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.voidman.com/?p=285</guid>
		<description><![CDATA[最近工作需要对 Discuz 做二次开发，本着最小化改动方便以后升级的原则，我引入了 WordPress 的 Hook 机制（即 Plugin API）来降低二次开发代码与 Discuz 原生代码的耦合度。 WordPress 内部提供了许多 Hook（钩子），以便插件可以将相应的 action 或 filter 挂接上去接管或改进 WordPress 的默认处理来达到自己期望的目的，在处理完毕后将控制权重新交给 WordPress。而我们所要做的就是将这种机制移植到 Discuz 中，所幸的是，WordPress 的 Hook 机制并没有过多地依赖于它的其它核心程序，所以基本不需要做多少修改就可以拿来使用。 基本步骤 在 Discuz 安装目录新建一个文件夹，命名为extra，复制 WordPress 的wp-includes/plugin.php文件到此文件夹。为了符合 Discuz 名命名规范，将文件重命名为plugin.func.php 为了避免潜在的函数命名冲突，可以将plugin.func.php文件里的函数名称都加上前缀，例如do_action()修改成dz_do_action()；另外 plugin_basename(), register_activation_hook(), register_deactivation_hook(), register_uninstall_hook() 等函数可以删除。 在extra文件夹新建一个php文件，命名为hooks.inc.php，这里放置绝大部分 filter 和 action，将它们放在该文件中的一个最大的好处是方便集中维护。 载入相关文件。打开include/common.inc.php文件，找到 require_once DISCUZ_ROOT.'./config.inc.php'; 在该行代码下面添加 require_once DISCUZ_ROOT.'./extra/plugin.func.php'; require_once DISCUZ_ROOT.'./extra/hooks.inc.php'; 至此，基本的 Hook 机制已经建立 [...]]]></description>
			<content:encoded><![CDATA[<p>最近工作需要对 Discuz 做二次开发，本着最小化改动方便以后升级的原则，我引入了 WordPress 的 Hook 机制（即 Plugin API）来降低二次开发代码与 Discuz 原生代码的耦合度。</p>
<p>WordPress 内部提供了许多 Hook（钩子），以便插件可以将相应的 action 或 filter 挂接上去接管或改进 WordPress 的默认处理来达到自己期望的目的，在处理完毕后将控制权重新交给 WordPress。而我们所要做的就是将这种机制移植到 Discuz 中，所幸的是，WordPress 的 Hook 机制并没有过多地依赖于它的其它核心程序，所以基本不需要做多少修改就可以拿来使用。<br />
<span id="more-285"></span><br />
<strong>基本步骤</strong></p>
<ol>
<li>在 Discuz 安装目录新建一个文件夹，命名为<code>extra</code>，复制 WordPress 的<code>wp-includes/plugin.php</code>文件到此文件夹。为了符合 Discuz 名命名规范，将文件重命名为<code>plugin.func.php</code></li>
<li>为了避免潜在的函数命名冲突，可以将<code>plugin.func.php</code>文件里的函数名称都加上前缀，例如<code>do_action()</code>修改成<code>dz_do_action()</code>；另外 <code>plugin_basename()</code>, <code>register_activation_hook()</code>, <code>register_deactivation_hook()</code>, <code>register_uninstall_hook()</code> 等函数可以删除。</li>
<li>在<code>extra</code>文件夹新建一个php文件，命名为<code>hooks.inc.php</code>，这里放置绝大部分 filter 和 action，将它们放在该文件中的一个最大的好处是方便集中维护。</li>
<li>载入相关文件。打开<code>include/common.inc.php</code>文件，找到

<div class="wp_syntax"><pre class="php"><span style="color: blue;">require_once</span> DISCUZ_ROOT.<span style="color: #ff00ff;">'./config.inc.php'</span>;</pre></div>

<p>在该行代码下面添加</p>

<div class="wp_syntax"><pre class="php"><span style="color: blue;">require_once</span> DISCUZ_ROOT.<span style="color: #ff00ff;">'./extra/plugin.func.php'</span>;
<span style="color: blue;">require_once</span> DISCUZ_ROOT.<span style="color: #ff00ff;">'./extra/hooks.inc.php'</span>;</pre></div>

<p>至此，基本的 Hook 机制已经建立
</li>
</ol>
<p><strong>实际应用示例</strong></p>
<p>接下来我们就可以开始添加自己的代码了。举个例子，Discuz 中<code>$discuz_auth_key</code>是这样定义的：</p>

<div class="wp_syntax"><pre class="php"><span style="color: #008080;">$discuz_auth_key</span> = <span style="color: #ff0000;">md5</span><span style="color: #800000;">&#40;</span><span style="color: #008080;">$_DCACHE</span><span style="color: #800000;">&#91;</span><span style="color: #ff00ff;">'settings'</span><span style="color: #800000;">&#93;</span><span style="color: #800000;">&#91;</span><span style="color: #ff00ff;">'authkey'</span><span style="color: #800000;">&#93;</span>.<span style="color: #008080;">$_SERVER</span><span style="color: #800000;">&#91;</span><span style="color: #ff00ff;">'HTTP_USER_AGENT'</span><span style="color: #800000;">&#93;</span><span style="color: #800000;">&#41;</span>;</pre></div>

<p>如果想将<code>$discuz_auth_key</code>的定义修改为<code>md5(authkey+user_agent+ip)</code>这样的形式，我们可以通过 filter 来实现。在<code>$discuz_auth_key</code>的定义代码下一行添加：</p>

<div class="wp_syntax"><pre class="php"><span style="color: #008000; font-style: italic;">// 生成一个名为 discuz_auth_key 的钩子</span>
<span style="color: #008080;">$discuz_auth_key</span> = dz_apply_filters<span style="color: #800000;">&#40;</span><span style="color: #ff00ff;">'discuz_auth_key'</span>, <span style="color: #008080;">$discuz_auth_key</span>, <span style="color: #008080;">$_DCACHE</span><span style="color: #800000;">&#91;</span><span style="color: #ff00ff;">'settings'</span><span style="color: #800000;">&#93;</span><span style="color: #800000;">&#91;</span><span style="color: #ff00ff;">'authkey'</span><span style="color: #800000;">&#93;</span>, <span style="color: #008080;">$_SERVER</span><span style="color: #800000;">&#91;</span><span style="color: #ff00ff;">'HTTP_USER_AGENT'</span><span style="color: #800000;">&#93;</span>, <span style="color: #008080;">$onlineip</span><span style="color: #800000;">&#41;</span>;</pre></div>

<p>然后打开<code>hooks.inc.php</code>文件，添加以下代码</p>

<div class="wp_syntax"><pre class="php"><span style="color: #008000; font-style: italic;">// 为了方便维护，所有 filter 类 hook 都以 filter_ 为前缀</span>
<span style="color: blue;">function</span> filter_discuz_auth_key<span style="color: #800000;">&#40;</span><span style="color: #008080;">$discuz_auth_key</span>, <span style="color: #008080;">$authkey</span>, <span style="color: #008080;">$ua</span>, <span style="color: #008080;">$ip</span><span style="color: #800000;">&#41;</span> <span style="color: #800000;">&#123;</span>
  <span style="color: #008000; font-style: italic;">// 符合自己设定的条件时才重新定义 authkey</span>
  <span style="color: #008000; font-style: italic;">// 否则返回 Discuz 定义的 discuz_auth_key 原值</span>
  <span style="color: blue;">if</span> <span style="color: #800000;">&#40;</span><span style="color: #008080;">$authkey</span> &amp;&amp; <span style="color: #008080;">$ua</span> &amp;&amp; <span style="color: #008080;">$ip</span><span style="color: #800000;">&#41;</span> <span style="color: #800000;">&#123;</span>
    <span style="color: #008080;">$discuz_auth_key</span> = <span style="color: #ff0000;">md5</span><span style="color: #800000;">&#40;</span><span style="color: #008080;">$authkey</span> . <span style="color: #008080;">$ua</span> . <span style="color: #008080;">$ip</span><span style="color: #800000;">&#41;</span>;
  <span style="color: #800000;">&#125;</span>
  <span style="color: blue;">return</span> <span style="color: #008080;">$discuz_auth_key</span>;
<span style="color: #800000;">&#125;</span>
&nbsp;
<span style="color: #008000; font-style: italic;">// 将 filter 函数 filter_discuz_auth_key 挂接到 discuz_auth_key 钩子上</span>
<span style="color: #008000; font-style: italic;">// 第三个参数的值 10 代表执行优先级，因为一个钩子上可以挂接多个callback函数</span>
<span style="color: #008000; font-style: italic;">// 第四个参数的值 4 代表允许 filter_discuz_auth_key 函数接收的参数个数</span>
add_filter<span style="color: #800000;">&#40;</span><span style="color: #ff00ff;">'discuz_auth_key'</span>, <span style="color: #ff00ff;">'filter_discuz_auth_key'</span>, <span style="color: #800080;">10</span>, <span style="color: #800080;">4</span><span style="color: #800000;">&#41;</span>;</pre></div>

<p>这样便达到我们所要的效果了。当然有些情况下还是无法避免了二次开发代码与原代码的夹杂在一起，不过由于有了 Hook 机制，这种情形已经可以大大减少了。</p>
<p><strong>相关阅读</strong><br />
<a href="http://codex.wordpress.org/Plugin_API">WordPress Plugin API</a></p>
<h4>Related Posts</h4><ul class="related_post"><li><a href="http://www.voidman.com/2009/11/media-temple-hacked.html" title="Media Temple Hacked">Media Temple Hacked</a></li><li><a href="http://www.voidman.com/2009/05/mogilefs-for-discuz.html" title="在 Discuz 中应用 MogileFS 分布式文件存储系统">在 Discuz 中应用 MogileFS 分布式文件存储系统</a></li><li><a href="http://www.voidman.com/2009/04/at-reply-mail-notification-1-release.html" title="At Reply Mail Notification 1.0 Release">At Reply Mail Notification 1.0 Release</a></li><li><a href="http://www.voidman.com/2009/03/lbs-to-wordpress.html" title="LBS 转 WordPress 不完全记录">LBS 转 WordPress 不完全记录</a></li><li><a href="http://www.voidman.com/2009/01/wordpress-is-using-a-bad-way-to-detect-duplicate-comment.html" title="Wordpress 糟糕的重复评论检测方式">Wordpress 糟糕的重复评论检测方式</a></li><li><a href="http://www.voidman.com/2009/01/at-reply-mail-notification-test.html" title="At Reply Mail Notification 测试贴">At Reply Mail Notification 测试贴</a></li><li><a href="http://www.voidman.com/2008/11/automatically-delete-post-revisions.html" title="让 Wordpress 自动删除 Post Revisions">让 Wordpress 自动删除 Post Revisions</a></li><li><a href="http://www.voidman.com/2008/11/google-xml-sitemaps-ignore-the-specified-categories.html" title="让 Google Sitemaps Generator 可以忽略指定的日志分类">让 Google Sitemaps Generator 可以忽略指定的日志分类</a></li><li><a href="http://www.voidman.com/2008/11/the-better-solution-for-static-paged-post.html" title="Wordpress 分页文章静态化的更优解决方案">Wordpress 分页文章静态化的更优解决方案</a></li><li><a href="http://www.voidman.com/2008/07/upgraded-to-wordpress-v26.html" title="升级到 WordPress 2.6">升级到 WordPress 2.6</a></li></ul><hr /><a href="http://www.voidman.com">Voidman.com</a> | Link: <a href="http://www.voidman.com/2009/05/using-wordpress-plugin-api-hack-discuz.html">http://www.voidman.com/2009/05/using-wordpress-plugin-api-hack-discuz.html</a><br /><img alt="linezing" width="1" height="1" src="http://img.tongji.linezing.com/288120/tongji.gif" />]]></content:encoded>
			<wfw:commentRss>http://www.voidman.com/2009/05/using-wordpress-plugin-api-hack-discuz.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
