<?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>Soul Of Free Loop &#187; PHP</title>
	<atom:link href="https://zohead.com/archives/category/technology/phps/feed/" rel="self" type="application/rss+xml" />
	<link>https://zohead.com</link>
	<description>Uranus Zhou&#039;s Blog</description>
	<lastBuildDate>Sat, 19 Jul 2025 15:42:46 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.8</generator>
	<item>
		<title>PHP 7找回MySQL扩展解决WordPress问题</title>
		<link>https://zohead.com/archives/php7-mysql/</link>
		<comments>https://zohead.com/archives/php7-mysql/#comments</comments>
		<pubDate>Tue, 21 Feb 2017 14:38:03 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[扩展]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1360</guid>
		<description><![CDATA[PHP 7 使用 MySQL 的问题 最近将 VPS 上的博客程序都迁移到 Bluemix 容器上之后，运行起来倒还算稳定，前两天手贱将 Bluemix 系统上的 LNMP 环境更新到了 1.3 版本，顺带地把 PHP 也更新到 7.0.7 版本了，不过更新完成之后访问博客就碰到了 WordPress 报错： 这才想起来 PHP 7 已经完全移除了 MySQL 扩展支持，通过 phpinfo 也能看到老的 mysql_ 系列的函数都不能使用了，一般建议使用新的 PHP mysqli 或者 pdo 扩展进行替换。 我的博客程序使用的还是 WordPress 3.6 版本，自然不支持 PHP 7， [&#8230;]]]></description>
				<content:encoded><![CDATA[<h2 id="php7-mysql-problem">PHP 7 使用 MySQL 的问题</h2>
<p>最近将 VPS 上的博客程序都<a href="https://zohead.com/archives/vps-anti-spider/">迁移</a>到 Bluemix 容器上之后，运行起来倒还算稳定，前两天手贱将 Bluemix 系统上的 <a href="https://lnmp.org/">LNMP</a> 环境更新到了 1.3 版本，顺带地把 PHP 也更新到 7.0.7 版本了，不过更新完成之后访问博客就碰到了 WordPress 报错：</p>
<pre class="brush: plain; title: ; notranslate">
您的 PHP 似乎没有安装运行 WordPress 所必需的 MySQL 扩展。
</pre>
<p>这才想起来 PHP 7 已经完全移除了 MySQL 扩展支持，通过 phpinfo 也能看到老的 <code>mysql_</code> 系列的函数都不能使用了，一般建议使用新的 PHP mysqli 或者 pdo 扩展进行替换。</p>
<p>我的博客程序使用的还是 WordPress 3.6 版本，自然不支持 PHP 7，如果直接升级 WordPress 的话又要考虑一堆 WordPress 插件的兼容性问题，于是像我这么懒的人就考虑如何把 PHP 7 的 MySQL 扩展找回来了。</p>
<h2 id="php7-mysql-ext">找回 PHP 7 的 MySQL 扩展</h2>
<p>由于 PHP 7 只是在发布前将对 MySQL 扩展的支持移除掉了，这样我们就可以检出遗留版本的支持 MySQL 扩展的 PHP 7 代码自行编译安装了，不过需要注意的就是 MySQL 扩展可是完全没有后续更新的了。</p>
<p>我们可以首先看看 LNMP 环境里 PHP 7 自带的扩展：</p>
<pre class="brush: bash; title: ; notranslate">
root@instance-007a20ff:/home/lnmp1.3/src/php-7.0.7/ext# ls
bcmath      date      ext_skel_win32.php  gmp        json      mysqlnd  pcre          pdo_odbc    pspell      simplexml  sqlite3   tokenizer  xsl
bz2         dba       fileinfo            hash       ldap      oci8     pdo           pdo_pgsql   readline    skeleton   standard  wddx       zip
calendar    dom       filter              iconv      libxml    odbc     pdo_dblib     pdo_sqlite  recode      snmp       sysvmsg   xml        zlib
com_dotnet  enchant   ftp                 imap       mbstring  opcache  pdo_firebird  pgsql       reflection  soap       sysvsem   xmlreader
ctype       exif      gd                  interbase  mcrypt    openssl  pdo_mysql     phar        session     sockets    sysvshm   xmlrpc
curl        ext_skel  gettext             intl       mysqli    pcntl    pdo_oci       posix       shmop       spl        tidy      xmlwriter
</pre>
<p>MySQL 扩展确实已经被移除了，我们可以直接在 <code>ext</code> 目录下检出老的 PHP MySQL 扩展代码：</p>
<pre class="brush: bash; title: ; notranslate">
root@instance-007a20ff:/home/lnmp1.3/src/php-7.0.7/ext# git clone https://github.com/php/pecl-database-mysql mysql --recursive
Cloning into 'mysql'...
remote: Counting objects: 145, done.
remote: Total 145 (delta 0), reused 0 (delta 0), pack-reused 145
Receiving objects: 100% (145/145), 88.41 KiB | 0 bytes/s, done.
Resolving deltas: 100% (65/65), done.
Checking connectivity... done.
</pre>
<p>使用 <code>phpize</code> 准备编译：</p>
<pre class="brush: bash; title: ; notranslate">
root@instance-007a20ff:/home/lnmp1.3/src/php-7.0.7/ext# cd mysql
root@instance-007a20ff:/home/lnmp1.3/src/php-7.0.7/ext/mysql# ls
config.m4  config.w32  CREDITS  LICENSE  mysql.mak  mysql_mysqlnd.h  package.xml  php_mysql.c  php_mysql.h  php_mysql_structs.h  README.md  tests
root@instance-007a20ff:/home/lnmp1.3/src/php-7.0.7/ext/mysql# /usr/local/php/bin/phpize
Configuring for:
PHP Api Version:         20151012
Zend Module Api No:      20151012
Zend Extension Api No:   320151012
root@instance-007a20ff:/home/lnmp1.3/src/php-7.0.7/ext/mysql# ./configure --with-php-config=/usr/local/php/bin/php-config
</pre>
<p>运行 <code>make</code> 编译之后 <code>make install</code> 确认 MySQL 扩展安装是否正确：</p>
<pre class="brush: bash; title: ; notranslate">
root@instance-007a20ff:/home/lnmp1.3/src/php-7.0.7/ext/mysql# make &amp;&amp; make install
root@instance-007a20ff:~# ls /usr/local/php/lib/php/extensions/no-debug-non-zts-20151012/
fileinfo.so  mysql.so  opcache.a  opcache.so
</pre>
<p>最后修改 <code>php.ini</code> 配置文件，增加一行：</p>
<pre class="brush: plain; title: ; notranslate">
extension = &quot;mysql.so&quot;
</pre>
<p>重新启动 LNMP 程序就能在 phpinfo 里看到 MySQL 扩展了：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442872/phpinfo-mysql.png" alt="PHP 7 下的 MySQL 扩展" title="PHP 7 下的 MySQL 扩展"></p>
<p>此时再访问 WordPress 博客就没有问题了，PHP 7 的问题初步搞定。另外网上也有人是直接把老的 MySQL 扩展静态编译进 PHP 7 程序中，这样用起来也还算比较方便的。当然后面我肯定还是要找机会直接升级 WordPress 了，毕竟 PHP 7 带着有各种漏洞的 WordPress 3.6 实在有点浪费哈，最后祝大家玩的开心。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/php7-mysql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>简单PHP实现Pocket抓取知乎专栏文章</title>
		<link>https://zohead.com/archives/php-zhihu-pocket/</link>
		<comments>https://zohead.com/archives/php-zhihu-pocket/#comments</comments>
		<pubDate>Mon, 31 Oct 2016 16:03:50 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Pocket]]></category>
		<category><![CDATA[专栏]]></category>
		<category><![CDATA[知乎]]></category>
		<category><![CDATA[阅读]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1293</guid>
		<description><![CDATA[Pocket 抓取知乎专栏的问题 Pocket 是我平时用的比较多的 稍后阅读 类网络服务，其收集抓取网上文章正文的效果比较好，去除页面广告等无关内容还算给力，支持标记和搜索，同步速度也还可以，免费会员限制也挺少，所以看到一些来不及马上阅读消化的文章我都会先加到 Pocket 队列里，有空时再去查看归档。 只是由于目前抓取网页正文原理的限制，Pocket 对现在越来越多的 AJAX 动态网页基本上都支持的不太好，比较典型的就是知乎专栏文章了。知乎专栏之前曾经是支持 Pocket 直接抓取的，改为 AJAX 加载数据之后，发送文章到 Pocket 之后就是这种效果： Pocket 正常抓取的文章 [&#8230;]]]></description>
				<content:encoded><![CDATA[<h2 id="pocket-抓取知乎专栏的问题">Pocket 抓取知乎专栏的问题</h2>
<p><a href="https://getpocket.com/">Pocket</a> 是我平时用的比较多的 稍后阅读 类网络服务，其收集抓取网上文章正文的效果比较好，去除页面广告等无关内容还算给力，支持标记和搜索，同步速度也还可以，免费会员限制也挺少，所以看到一些来不及马上阅读消化的文章我都会先加到 Pocket 队列里，有空时再去查看归档。</p>
<p>只是由于目前抓取网页正文原理的限制，Pocket 对现在越来越多的 AJAX 动态网页基本上都支持的不太好，比较典型的就是知乎专栏文章了。知乎专栏之前曾经是支持 Pocket 直接抓取的，改为 AJAX 加载数据之后，发送文章到 Pocket 之后就是这种效果：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442877/pocket-zhihu-zl.png" alt="Pocket 抓取知乎专栏效果" title="Pocket 抓取知乎专栏效果"></p>
<p>Pocket 正常抓取的文章应该能显示摘要文字或者文章中的图片，知乎专栏文章则是空白的，而且点击文章条目也是直接跳转到知乎专栏链接，并没有显示 Pocket 抓取优化的效果。</p>
<h2 id="问题分析">问题分析</h2>
<p>稍微看看知乎专栏网页代码可以发现，如果在浏览器中访问类似这样的专栏文章链接：</p>
<p><a href="https://zhuanlan.zhihu.com/p/21542817">https://zhuanlan.zhihu.com/p/21542817</a></p>
<p>实际会加载下面的文章内容数据 API 链接，知乎专栏页面加载完数据之后才会显示：</p>
<p><a href="https://zhuanlan.zhihu.com/api/posts/21542817">https://zhuanlan.zhihu.com/api/posts/21542817</a></p>
<p>这种动态加载方式显然 Pocket 是不支持的，不过也好办，我们自己用 PHP 或者 Node.js 等实现一个简单的程序读取专栏文章内容并输出，然后放到 VPS 或者其它虚拟主机上运行，后面访问我自己的网址并发送到 Pocket 应该就可以使 Pocket 正确抓取了。另外这种方式比较好的一面就是输出内容里没有任何其它知乎相关的网页代码，只有专栏文章内容，更易于 Pocket 抓取处理。</p>
<h2 id="php-程序-pocket-抓取效果">PHP 程序 Pocket 抓取效果</h2>
<p>这个 PHP 程序实在没有什么技术含量，我就直接写一个简单的 PHP 文件接受传入专栏页面 ID 的 <code>page</code> 参数然后输出文章内容即可：</p>
<pre class="brush: php; title: zhihu.php; notranslate">
&lt;?php
if (!isset($_GET[&quot;page&quot;])) {
	echo &quot;need page id.&quot;;
	exit;
}

$PAGE_ID = $_GET[&quot;page&quot;];
$P_HEADERS = getallheaders();

if (array_key_exists(&quot;Referer&quot;, $P_HEADERS) || (isset($_GET[&quot;redirect&quot;]) &amp;&amp; $_GET[&quot;redirect&quot;] == '1')) {
	header(&quot;Location: https://zhuanlan.zhihu.com/p/&quot; . $PAGE_ID);
	exit;
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta name=&quot;referrer&quot; content=&quot;never&quot;/&gt;
&lt;meta http-equiv=&quot;content-type&quot; content=&quot;text/html; charset=UTF-8&quot;/&gt;
&lt;?php
$PAGE_DATA = file_get_contents(&quot;https://zhuanlan.zhihu.com/api/posts/&quot; . $PAGE_ID);
$PAGE_OBJ = json_decode($PAGE_DATA);
echo '&lt;title&gt;' . $PAGE_OBJ-&gt;{&quot;title&quot;} . '&lt;/title&gt;';
?&gt;
&lt;link rel=&quot;shortcut icon&quot; href=&quot;https://static.zhihu.com/static/favicon.ico&quot; type=&quot;image/x-icon&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;
&lt;?php
echo $PAGE_OBJ-&gt;{&quot;title&quot;};
?&gt;
&lt;/h1&gt;
&lt;div&gt;
&lt;?php
echo $PAGE_OBJ-&gt;{&quot;content&quot;};
?&gt;
&lt;div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>上面的程序只是简单做了下判断，如果请求头中包含 Referer 信息（例如从 Pocket 网站跳转等）或者请求地址中 <code>redirect</code> 参数值为 <code>1</code> 就会直接跳转到知乎专栏页面，默认则输出专栏文章内容。另外程序中使用了 <code>getallheaders</code> 函数得到 HTTP 请求头信息，默认只支持 Apache，如果你要在 nginx 等服务器上使用则稍微修改下即可。</p>
<p> 另外程序中还将 <code>referrer</code> 值指定为 <code>never</code> 防止页面引用知乎图片等资源时触发知乎的防盗链机制。</p>
<p>把上面的 PHP 程序放到虚拟主机上，访问类似下面的链接（单纯演示用，需要翻墙哦）：</p>
<p><a href="http://devio.us/~nocwat/zhihu-grub.php?page=21542817">http://devio.us/~nocwat/zhihu-grub.php?page=21542817</a></p>
<p>正确显示文章内容后，将上面的链接发送到 Pocket 稍等片刻就能在 Pocket 队列里看到抓取的专栏文章了。</p>
<blockquote>
<p><strong>提示</strong></p>
<p>由于知乎专栏中的图片做了防盗链策略，直接访问上面的链接可能会出现文章中的图片不能正确显示的问题，不过没关系，Pocket 会自动为我们抓取保存文章中的图片的。</p>
</blockquote>
<p>最后来看看我的 Pocket 队列里的显示效果：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442877/pocket-php-zhihu.png" alt="Pocket 通过 PHP 抓取知乎专栏" title="Pocket 通过 PHP 抓取知乎专栏"></p>
<p>而且点击文章条目进入也能看到 Pocket 优化过的文章内容，在 Pocket 中点击 <strong>查看原始文档</strong> 也能自动跳转到知乎的专栏文章页面，这样再也不用担心专栏作者删除文章之后就没办法查看咯。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/php-zhihu-pocket/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>整合Wikitten和MDwiki搭建个人知识库</title>
		<link>https://zohead.com/archives/wikitten-mdwiki/</link>
		<comments>https://zohead.com/archives/wikitten-mdwiki/#comments</comments>
		<pubDate>Wed, 16 Mar 2016 08:43:49 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[学习感悟]]></category>
		<category><![CDATA[Evernote]]></category>
		<category><![CDATA[Front Matter]]></category>
		<category><![CDATA[Markdown]]></category>
		<category><![CDATA[MDwiki]]></category>
		<category><![CDATA[Wiki]]></category>
		<category><![CDATA[Wikitten]]></category>
		<category><![CDATA[知识管理]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1193</guid>
		<description><![CDATA[我的知识库管理现状 一段时间以来我都算是 Pocket 和 Evernote 的忠实用户，Pocket 用于采集网上看到的想要稍后预读的文章，遇到比较好的内容觉得该记录下来的就记录在 Evernote 里，这样 Evernote 基本被我用来做个人知识库了，平常比较零散的个人信息之类的则记录到 Google Keep 中。 最近在 Android 手机上碰到几次比较奇怪的 Evernote 数据库错误之后还是觉得 Evernote 虽然有相对还算好用的离线、同步、搜索等功能，但也有一些问题： 众所周知的编辑功能确实比较烂，不支持 Markdown，对于表格等稍微复杂点的内容那编辑效果简直惨不忍 [&#8230;]]]></description>
				<content:encoded><![CDATA[<h2 id="我的知识库管理现状">我的知识库管理现状</h2>
<p>一段时间以来我都算是 <a href="https://getpocket.com/">Pocket</a> 和 <a href="https://www.evernote.com/">Evernote</a> 的忠实用户，Pocket 用于采集网上看到的想要稍后预读的文章，遇到比较好的内容觉得该记录下来的就记录在 Evernote 里，这样 Evernote 基本被我用来做个人知识库了，平常比较零散的个人信息之类的则记录到 <a href="https://keep.google.com/">Google Keep</a> 中。</p>
<p>最近在 Android 手机上碰到几次比较奇怪的 Evernote 数据库错误之后还是觉得 Evernote 虽然有相对还算好用的离线、同步、搜索等功能，但也有一些问题：</p>
<ul>
<li>众所周知的编辑功能确实比较烂，不支持 Markdown，对于表格等稍微复杂点的内容那编辑效果简直惨不忍睹；</li>
<li>只有笔记本组和笔记本这两层结构对于我来说始终还是觉得不够；</li>
<li>客户端里所有笔记数据都放在 SQLite 数据库文件感觉稳定性一般。</li>
</ul>
<p>再加上最近 Evernote 这头大象给人的前景似乎一直不太好，所以我就想找到一个相对比较简单优雅的个人知识库系统，最好是能直接支持 Markdown 格式，不需要复杂的搭建步骤，能方便的在我的 VPS 和本地跑起来，当然 Evernote 我暂时还是不会弃用的。</p>
<h2 id="mdwiki-和-wikitten-对比">MDwiki 和 Wikitten 对比</h2>
<p>我找了几个比较流行的 Wiki 系统，开始就跳过了 MediaWiki 这种看起来略复杂的系统，也简单看了看很多网友推荐的 DokuWiki，甚至还有 TiddlyWiki 这种直接单文件的 Wiki 方式，初步考虑后想用 MDwiki 这个基于 Markdown 而且超级简单的纯静态 Wiki 系统。</p>
<p>MDwiki 相对于其它 Wiki 系统的最大好处是其单纯使用浏览器就可以解析 Markdown 文档，部署可算是超级简单了，VPS 上只要有 Web 服务器就可以访问（纯静态不需要 PHP 支持），甚至在 PC 本地也可以直接打开（虽然 IE11 和 Chrome 浏览器上已经不支持请求本地文件了）。</p>
<p>按照 <a href="http://www.mdwiki.info/">MDwiki</a> 官网的介绍生成一个 Wiki 主页还是非常简单的，网上的说明也比较多这里就不介绍了，如果知识库内容比较少用 MDwiki 还是很方便的，但我想稍微增加一些内容时就发现了 MDwiki 一些明显的不足：</p>
<ul>
<li>导航菜单只支持两层，这个是 MDwiki 使用的 Bootstrap 的限制，而且如果有很多层目录，每个目录下又有不少 Markdown 文档，直接全部放在导航菜单里那体验也是比较糟糕的；</li>
<li>由于纯静态的限制，如果在某个目录下增加了 Markdown 文档，那就需要同步修改导航菜单，或者在其它页面里加上指向新文档的链接，这样如果需要动态修改更新实在有点麻烦；</li>
<li>同样由于纯静态的限制，基本没有办法实现搜索功能，如果后续知识库文章较多那还需要同步下来对文件夹进行搜索；</li>
<li>MDwiki 只有一个主 html 文件，切换文章是用 AJAX 异步加载 Markdown 文档然后解析显示的，这样就意味着 MDwiki 对于搜索引擎来说是非常不友好的，基本没有实际可用内容。</li>
</ul>
<p>因此我还是想实现既能兼顾 MDwiki 直接使用 Markdown 的方便之处又能解决上面列出的问题，最后还是找到了 <a href="http://wikitten.vizuina.com/">Wikitten</a> 这个用 PHP 实现的 Wiki 系统。</p>
<p>Wikitten 与 MDwiki 不同之处在于 Markdown 文档是由 PHP 程序解析并直接转换为 HTML 返回给浏览器的，而且配置好知识库目录之后访问就可以显示完整的目录树（有修改更新时也不用手工修改其它 Markdown 文件了），也有比较简单的搜索功能，可以直接把源代码文件以比较漂亮的形式显示出来。</p>
<p>我部署的 Wikitten 系统运行效果图如下：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442965/wikitten-ui.png" alt="Wikitten 界面" title="Wikitten 界面"></p>
<p>综合考虑之后我准备对 Wikitten 和 MDwiki 做出少量修改，以实现在我的 VPS 服务器上主要还是用 Wikitten 来动态展示，需要在本地直接查看修改时也可以用上 MDwiki，这样就能兼顾两者的优点了。</p>
<h2 id="mdwiki-的修改">MDwiki 的修改</h2>
<p>对 MDwiki 的修改主要考虑到要能方便的找到目录树的 Markdown 文档，修改如下：</p>
<ol>
<li>把 Markdown 文档放到单独的目录中，我是直接改成放到和 <code>mdwiki.html</code> 主文件相同路径的 <code>library</code> 目录，这与 Wikitten 的默认知识库目录是一致的，这样 Wikitten 和 MDwiki 就可以共用 Markdown 文档了；</li>
<li>
<p>支持识别 Markdown 文件开头添加的 <a href="http://jekyllrb.com/docs/frontmatter/">YAML front matter</a> 数据，front matter 可以用来表示 Markdown 文档的标题、作者、标签等信息；</p>
<blockquote>
<p><strong>提示</strong></p>
<p>MDwiki 新增加的 font matter 支持需要修改 <code>config.json</code> 配置文件增加 <code>"parseHeader": true</code> 进行开启。</p>
</blockquote>
<p>Wikitten 是直接支持 YAML front matter 的并能动态生成到 HTML 数据中的，常见的 front matter 数据格式是这样的：</p>
<pre class="brush: plain; title: ; notranslate">
---
&quot;title&quot;: &quot;Wiki site&quot;,
&quot;tags&quot;: [&quot;tag1&quot;, &quot;tag2&quot;, &quot;tag3&quot;],
&quot;author&quot;: &quot;xxx&quot;
---
</pre>
<blockquote>
<p><strong>注意</strong></p>
<p>上面的格式中开头和结束是 3 个横线，而且开头以及结束的横线和中间的实际 front matter（也就是 meta data）内容之间只有一个回车哦；下面修改后的格式也是类似的。</p>
</blockquote>
<p>不过上面这种格式很多 Markdown 编辑器却是不支持的显示有问题，这里我改成了和 MDwiki 暂未发布的开发版本中一致的形式：</p>
<pre class="brush: plain; title: ; notranslate">
```
&quot;title&quot;: &quot;Wiki site&quot;,
&quot;tags&quot;: [&quot;tag1&quot;, &quot;tag2&quot;, &quot;tag3&quot;],
&quot;author&quot;: &quot;xxx&quot;
```
</pre>
</li>
<li>
<p>我写了一个自动生成 Markdown 知识库目录下面所有子目录索引文件 <code>index.md</code> 的 shell 脚本 <strong><code>generate-index.sh</code></strong> 给 MDwiki 使用，使用起来也很简单：</p>
<pre class="brush: bash; title: ; notranslate">
(trusty)zzm@localhost:~/wiki$ ./generate-index.sh library
Generate index file: library/生活/index.md
Generate index file: library/阅读/index.md
Generate index file: library/技术/网络/index.md
Generate index file: library/技术/硬件/USB/index.md
Generate index file: library/技术/硬件/PCI-E/index.md
Generate index file: library/技术/硬件/index.md
Generate index file: library/技术/存储/index.md
Generate index file: library/技术/index.md
Generate index file: library/技术/音视频/index.md
Generate index file: library/技术/Linux/内存管理/index.md
Generate index file: library/技术/Linux/文件系统/index.md
Generate index file: library/技术/Linux/开发工具/index.md
Generate index file: library/技术/Linux/index.md
Generate index file: library/技术/Android/index.md
Generate index file: library/技术/Docker/index.md
</pre>
<p><strong><code>generate-index.sh</code></strong> 脚本会查找输入的 Markdown 知识库目录并判断是否需要生成子目录下的索引文件（如果用户自己单独写了 <code>index.md</code> 文档就不会直接覆盖）；</p>
<p>编写者在创建新的 Markdown 文档或者删除更新时，只需要再运行 <strong><code>generate-index.sh</code></strong> 脚本就可以自动更新知识库中所有目录的索引。</p>
<p>我修改的 <strong><code>generate-index.sh</code></strong> 自动生成脚本下载地址在这里（也可以从文章最后的版本库里检出）： <br />
<a href="http://mdwiki.zohead.com/generate-index.sh">http://mdwiki.zohead.com/generate-index.sh</a></p>
</li>
</ol>
<p>这样修改之后 MDwiki 里就可以通过指向目录的索引文件以间接实现目录树功能（只是需要像 Windows 资源管理器那样一层层往下），同时这种方式生成的每个子目录的 <code>index.md</code> 索引文件也可以给 Wikitten 使用（Wikitten 自带目录树功能基本很少会用到索引文件）。</p>
<p>MDwiki 下访问目录的效果（使用脚本自动生成的索引文件）：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442839/mdwiki-dirindex.png" alt="MDwiki 目录索引" title="MDwiki 目录索引"></p>
<h2 id="wikitten-的修改">Wikitten 的修改</h2>
<p>由于 Wikitten 的基本功能都算可以用了，故我对 Wikitten 只有一些小改动：</p>
<ol>
<li>同时兼容上面说明的 Markdown 文件开头的两种 YAML front matter 形式，可以实现和 MDwiki 下面基本相同的效果；</li>
<li>浏览具体目录页时 Wikitten 原有处理是直接提示用户从左边目录树中选择，这里我稍微修改为自动判断该目录下是否有 <code>index.md</code> 文件，存在则直接解释显示 Markdown 文档；</li>
<li>修正上面的 <strong><code>generate-index.sh</code></strong> 脚本生成的目录索引 Markdown 表格的显示效果。</li>
</ol>
<h2 id="同时部署-wikitten-和-mdwiki">同时部署 Wikitten 和 MDwiki</h2>
<h3 id="部署-wikitten">部署 Wikitten</h3>
<p>Wikitten 部署参照其官网的说明一般没什么问题，只是 Wikitten 需要至少 PHP 5.3 版本，为此我还专门对 VPS 上 LNMP 套件里的 PHP 进行了升级，同时 Wikitten 也需要开启 PHP 的 fileinfo 模块。</p>
<p>Wikitten 需要 Web 服务器支持 rewrite，其版本库中自带了 Apache 适用的 <code>.htaccess</code> 文件，这里贴下适用于 nginx 的我的 Wiki 主域名 <code>wiki.zohead.com</code> 的 vhost 配置给大家一个参考：</p>
<pre class="brush: plain; title: ; notranslate">
server
{
	listen 80;

	server_name wiki.zohead.com;
	index index.html index.htm index.php default.html default.htm default.php;
	root /home/wwwroot/wiki.zohead.com;

	location ~* ^/static/(css|js|img|fonts)/.+.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt|swf|pdf|txt|bmp|eot|svg|ttf|woff|woff2)$ {
		access_log off;
		expires max;
	}
	location / {
		rewrite ^(.*)$ /index.php last;
	}
	location ~ /index.php$ {
		try_files $uri =404;
		fastcgi_pass  unix:/tmp/php-cgi.sock;
		include fastcgi.conf;
	}
}
</pre>
<p>其实也是比较简单的，参考 Wikitten 自带的 <code>.htaccess</code> 就可以修改过来，主要是下面的 rewrite 规则配置正确就可以了。</p>
<h3 id="部署-mdwiki">部署 MDwiki</h3>
<p>这里为了和上面的 Wiki 主域名 <code>wiki.zohead.com</code> 区分，我为 MDwiki 站点单独搞了个 Wiki 备用域名 <code>mdwiki.zohead.com</code>，这个的配置就非常简单了，只要最基本的 vhost 配置就可以了：</p>
<pre class="brush: plain; title: ; notranslate">
server
{
	listen 80;

	server_name mdwiki.zohead.com;
	index index.html index.htm default.html default.htm;
	root /home/wwwroot/wiki.zohead.com;
}
</pre>
<p>可以看到这个 MDwiki 备用域名的主目录和上面的 Wikitten 是一样的，只是刚好把 <code>index.html</code> 给 MDwiki 使用，<code>index.php</code> 给 Wikitten 使用。</p>
<h2 id="综述">综述</h2>
<p>说了这么多，下面是我的初步 Wiki 知识库演示效果了。这样修改之后对于我来说最大的好处是当发现哪个用的不爽时可以无缝切换，毕竟现在这两个系统的目录结构和数据是完全共用的，哈哈。</p>
<p>Wikitten 动态主站请访问：</p>
<p><a href="http://wiki.zohead.com/">http://wiki.zohead.com/</a></p>
<p>备用 MDwiki 纯静态站点请访问：</p>
<p><a href="http://mdwiki.zohead.com/">http://mdwiki.zohead.com/</a></p>
<p>整个 Markdown 知识库目录我是使用 BitTorrent Sync 进行本机和 VPS 之间的同步，另外我把整合和修改过的 Wikitten 和 MDwiki 基础代码放到了一起，并在 GitHub 上建立了一个版本库：</p>
<p><a href="https://github.com/zohead/wikitten-and-mdwiki">https://github.com/zohead/wikitten-and-mdwiki</a></p>
<p>大家有兴趣的话可以检出这个版本库自行修改部署哦，项目主页上也有一些介绍说明，如果你不需要同时支持 Wikitten 和 MDwiki 的话也可以自己取舍的，毕竟这个版本库里 MDwiki 的代码只有根目录下的 <code>index.html</code> 这一个文件。</p>
<p>Wikitten 的配置文件为根目录下的 <code>config.php</code>，MDwiki 的配置文件为根目录下的 <code>config.json</code>，还是比较一致的哈。</p>
<p>如果你只想要 Wikitten 系统的话那删除 <code>index.html</code>、<code>config.json</code> 文件即可，如果你只需要 MDwiki 那也只用保留 <code>index.html</code>、<code>config.json</code> 和 <code>generate-index.sh</code> 这几个文件。</p>
<p>最后本文及对应版本库中有任何问题欢迎提出指正哦，祝大家玩的开心 ^_^。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/wikitten-mdwiki/feed/</wfw:commentRss>
		<slash:comments>52</slash:comments>
		</item>
		<item>
		<title>搭建自己的全文RSS系统</title>
		<link>https://zohead.com/archives/full-text-rss/</link>
		<comments>https://zohead.com/archives/full-text-rss/#comments</comments>
		<pubDate>Thu, 13 Aug 2015 13:06:43 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[工具]]></category>
		<category><![CDATA[fivefilters]]></category>
		<category><![CDATA[fulltextrssfeed]]></category>
		<category><![CDATA[RSS]]></category>
		<category><![CDATA[全文]]></category>

		<guid isPermaLink="false">http://zohead.com/?p=1028</guid>
		<description><![CDATA[最近在使用 feedly 阅读器查看之前订阅的一些文章发现有些博客网站的 RSS 输出已经改成只输出摘要信息而不输出全文的形式了，这样对于 RSS 阅读器来说可是很不方便的，我订阅的几个 RSS 源中像 虎嗅网、某个 51CTO 博客、Phoronix 这几个 RSS 源都已经不输出全文了。 之前我是使用 fulltextrssfeed.com 这个网站来辅助生成全文 RSS 输出的，但现在发现 fulltextrssfeed.com 对于我实际要用的几个 RSS 源没有什么作用了，经常不能输出有效的信息。 最后在网上找到 fivefilters.org 也提供了类似的服务，在其网站上输入原始 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>最近在使用 feedly 阅读器查看之前订阅的一些文章发现有些博客网站的 RSS 输出已经改成只输出摘要信息而不输出全文的形式了，这样对于 RSS 阅读器来说可是很不方便的，我订阅的几个 RSS 源中像 虎嗅网、某个 51CTO 博客、Phoronix 这几个 RSS 源都已经不输出全文了。</p>
<p>之前我是使用 <a href="http://fulltextrssfeed.com/" target="_blank">fulltextrssfeed.com</a> 这个网站来辅助生成全文 RSS 输出的，但现在发现 fulltextrssfeed.com 对于我实际要用的几个 RSS 源没有什么作用了，经常不能输出有效的信息。</p>
<p>最后在网上找到 <a href="http://fivefilters.org/content-only/" target="_blank">fivefilters.org</a> 也提供了类似的服务，在其网站上输入原始的 RSS 源地址就可以输出全文 RSS 内容，看起来确实是比较好用，但这个网站默认只输出 3 条最近的文章的限制确实还是有点坑。不过好在 fivefilters.org 把他们的全文 RSS 程序开源了，用户可以使用这个程序自己搭建一个全文 RSS 输出系统，虽然他们最新版本的全文 RSS 程序是需要购买的，但是老版本的程序是可以免费下载使用的（只是不对老版本提供技术支持）。</p>
<p>按照 fivefilters.org 网站的说明，找一个支持 PHP 的普通主机就可以使用了，首先访问其项目主页并检出最新的 full-text-rss 的源代码：</p>
<p><a href="https://bitbucket.org/fivefilters/full-text-rss" target="_blank">https://bitbucket.org/fivefilters/full-text-rss</a></p>
<p>解压缩放到 PHP 空间目录里，把目录中的 config.php 拷贝为 custom_config.php，然后就可以修改 custom_config.php 配置文件：</p>
<pre class="brush: php; title: custom_config.php; notranslate">
$options-&gt;max_entries = 10;
$options-&gt;caching = true;
$options-&gt;key_required = true;
$options-&gt;api_keys[1] = 'secret-key-1';
</pre>
<p>上面列出了几个常用的配置项，max_entries 表示最多输出多少篇文章，caching 最好改为 true 这样可以启用缓存防止每次请求时都需要重新产生 RSS 输出，另外 key_required 和 api_keys 也可以启用，这样就可以为 RSS 全文输出系统增加密码验证功能，防止被其它用户使用（如果你是壕而且主机毫无压力的话大可以不设置密码并共享给其他人使用哦 ^_^）。</p>
<p>修改完成之后通过浏览器访问 full-text-rss 目录就会出现全文 RSS 的界面了：</p>
<div style="width: 697px" class="wp-caption alignnone"><a href="http://res.cloudinary.com/digwht2y0/image/upload/v1737371061/full-text-rss.png" target="_blank"><img alt="全文RSS输出配置" src="http://res.cloudinary.com/digwht2y0/image/upload/v1737371061/full-text-rss.png" width="687" height="556" /></a><p class="wp-caption-text">全文RSS输出配置</p></div>
<p>输入原始 RSS 源的地址（这里以虎嗅为例），输入密码（就是 Access Key 了）并选择最大输出文章数，点击 Create Feed 按钮之后一切正常的话就会出现全文 RSS 输出了，此时显示的地址就可以给 feedly 等各种 RSS 阅读器使用咯。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/full-text-rss/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>解决WordPress Batcache插件无法工作的问题</title>
		<link>https://zohead.com/archives/fix-wordpress-batcache/</link>
		<comments>https://zohead.com/archives/fix-wordpress-batcache/#comments</comments>
		<pubDate>Sat, 16 Nov 2013 16:26:26 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[BAE]]></category>
		<category><![CDATA[Batcache]]></category>
		<category><![CDATA[cookie]]></category>
		<category><![CDATA[插件]]></category>

		<guid isPermaLink="false">http://zohead.com/?p=631</guid>
		<description><![CDATA[本文同步自（最佳显示效果请点击）：https://zohead.com/archives/fix-wordpress-batcache/ 前几天看到 AlexYang 同学写的一篇非常好的关于在百度 BAE 云平台上启用 WordPress 博客缓存全页面加速的文章，由于 BAE 云平台不支持本地文件读写，WP Super Cache 之类的 WordPress 本地缓存插件无法正常工作（也不支持 NFS 目录作为缓存目录哦），文章中使用基于 BAE cache 空间的 memcache 接口，并通过 Batcache 这个 WordPress 插件实现全页面加速，据说缓存加速效果非常明显。  [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>本文同步自（最佳显示效果请点击）：<a href="https://zohead.com/archives/fix-wordpress-batcache/" target="_blank">https://zohead.com/archives/fix-wordpress-batcache/</a></p>
<p>前几天看到 AlexYang 同学写的一篇非常好的关于在百度 BAE 云平台上启用 WordPress 博客缓存全页面加速的文章，由于 BAE 云平台不支持本地文件读写，WP Super Cache 之类的 WordPress 本地缓存插件无法正常工作（也不支持 NFS 目录作为缓存目录哦），文章中使用基于 BAE cache 空间的 memcache 接口，并通过 Batcache 这个 WordPress 插件实现全页面加速，据说缓存加速效果非常明显。</p>
<p>介绍缓存加速的文章请参考 [<a href="http://www.alexyang.me/2013/07/08/%E5%88%A9%E7%94%A8%E7%99%BE%E5%BA%A6%E4%BA%91%E7%BC%93%E5%AD%98%E5%8A%A0%E9%80%9Fbae-wordpress%E4%B9%8B%E7%BB%88%E6%9E%81%E5%8A%A0%E9%80%9F.html" target="_blank">这里</a>]，Batcache WordPress 插件可以点击 [<a href="http://wordpress.org/plugins/batcache/" target="_blank">这里</a>] 下载。</p>
<p>我按照上面文章中的介绍在 wp-content 目录中增加了 BAE 版本的 object-cache.php 文件和 Batcache 插件的 advanced-cache.php 文件，但在测试中发现始终没有看到作者所介绍的效果：首次访问站点之后缓存到内存，后续访问都会从缓存中读取，无需多余的数据库请求，网页 head 信息中始终没有 cache 的调试输出。</p>
<p>在参考 AlexYang 的文章做了多遍的检查之后，觉得一切条件都符合的，还无法正常缓存，只能看看 Batcache 的代码了。在 Batcache 代码中增加一堆调试信息，经过坑爹的调试过程（BAE 的应用日志查询功能简直是弱的让人无力吐槽的），终于发现真正原因：</p>
<p>Batcache 在判断页面请求时会检查当前请求所使用的 cookie，插件觉得某些情况下页面必须刷新，就忽略当前缓存的内容，例如：用户在文章下发表评论，这种情况下必须忽略之前的缓存，否则用户评论之后将无法看到自己评论的内容；还有一种情况就是管理员登录到后台了，这种情况下也必须禁用缓存，否则管理员对博客做的修改操作也将无法正常看到。</p>
<p>正是考虑到类似上面的情况，Batcache 在检测到一些 cookie 值时会禁用缓存，advanced-cache.php 中的判断代码如下：</p>
<p><pre class="brush: php; title: ; notranslate">
// Never batcache when cookies indicate a cache-exempt visitor.
if ( is_array( $_COOKIE) &amp;&amp; ! empty( $_COOKIE ) )
	foreach ( array_keys( $_COOKIE ) as $batcache-&gt;cookie )
		if ( $batcache-&gt;cookie != 'wordpress_test_cookie' &amp;&amp; 
			( substr( $batcache-&gt;cookie, 0, 2 ) == 'wp' || substr( $batcache-&gt;cookie, 0, 9 ) == 'wordpress' || substr( $batcache-&gt;cookie, 0, 14 ) == 'comment_author' ) )
			return;
</pre>
</p>
<p>这就表示 Batcache 发现如果请求中的 cookie 是以 wp、wordpress 或者 comment_author 开头时就禁用缓存，这样后台管理、用户评论等功能才能正常工作。</p>
<p>而通过对我访问博客时的数据进行抓包显示，由于我安装了 WordPress Mobile Pack 这个插件，访问博客时会向浏览器发送切换浏览类型的 wpmp_switcher cookie，这就刚好在 Batcache 插件的过滤范围内，当然就导致 Batcache 全页面缓存始终无法起作用。知道原因了就好办，将 wp-content 目录下的 advanced-cache.php 的判断 cookie 处改为：</p>
<p><pre class="brush: php; title: ; notranslate">
// Never batcache when cookies indicate a cache-exempt visitor.
if ( is_array( $_COOKIE) &amp;&amp; ! empty( $_COOKIE ) )
	foreach ( array_keys( $_COOKIE ) as $batcache-&gt;cookie )
		if ( $batcache-&gt;cookie != 'wordpress_test_cookie' &amp;&amp; $batcache-&gt;cookie != 'wpmp_switcher' &amp;&amp; substr( $batcache-&gt;cookie, 0, 12 ) != 'wp-settings-' &amp;&amp; 
			( substr( $batcache-&gt;cookie, 0, 2 ) == 'wp' || substr( $batcache-&gt;cookie, 0, 9 ) == 'wordpress' || substr( $batcache-&gt;cookie, 0, 14 ) == 'comment_author' ) )
			return;
</pre>
</p>
<p>刷新页面就可以看到缓存起作用了，不得不说启用内存缓存之后，页面访问速度还是有不少提升了。</p>
<p>备注：上面的修改代码中另外还增加了 wp-settings- 开头的 cookie 项，因为测试时发现有时还会有这个 cookie 导致缓存不起作用。</p>
<p>网上有不少的网友说装了 Batcache 插件之后缓存没用，可以参考这个思路看看到底是什么 cookie 之类的条件不满足导致的。本文章为个人修改经验，如果有任何问题欢迎提出指正，玩的开心 ^_^</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/fix-wordpress-batcache/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WordPress友言近期评论Widget更新（v1.1）</title>
		<link>https://zohead.com/archives/wordpress-uyan-recent-comment-widget-v1-1/</link>
		<comments>https://zohead.com/archives/wordpress-uyan-recent-comment-widget-v1-1/#comments</comments>
		<pubDate>Sat, 12 May 2012 11:38:27 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[友言]]></category>
		<category><![CDATA[小工具]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[评论]]></category>

		<guid isPermaLink="false">http://zohead.com/?p=152</guid>
		<description><![CDATA[本文同步自（如浏览不正常请点击跳转）：https://zohead.com/archives/wordpress-uyan-recent-comment-widget-v1-1 前两天写了一个友言近期评论的 WordPress Widget，初步测试还能用，但多次进行刷新，会出现不能正常登录之类的问题（Failed to authentication with uyan.cc、Invalid comments data from uyan.cc 之类的报错），而且原来每次都需要登录友言的后台管理严重影响速度，我也比较怕怕这样不断发请求会导致友言把我的脚本和博客给封掉，嘿嘿。 由于友言没有公开  [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>本文同步自（如浏览不正常请点击跳转）：<a href="https://zohead.com/archives/wordpress-uyan-recent-comment-widget-v1-1" target="_blank">https://zohead.com/archives/wordpress-uyan-recent-comment-widget-v1-1</a></p>
<p>前两天写了一个友言近期评论的 WordPress Widget，初步测试还能用，但多次进行刷新，会出现不能正常登录之类的问题（Failed to authentication with uyan.cc、Invalid comments data from uyan.cc 之类的报错），而且原来每次都需要登录友言的后台管理严重影响速度，我也比较怕怕这样不断发请求会导致友言把我的脚本和博客给封掉，嘿嘿。</p>
<p>由于友言没有公开 API 给我等码农来调用，因此今天又花了点时间做了一些改进，弄了个 1.1 版本，原介绍文章在这：</p>
<p><a href="https://zohead.com/archives/wordpress-uyan-recent-comment-widget/" target="_blank">https://zohead.com/archives/wordpress-uyan-recent-comment-widget/</a></p>
<p><strong><span style="color: #ff0000;">1.1版本更新说明：</span></strong></p>
<p><em>1、登录友言后台管理，得到近期评论等地方增加错误处理，如果服务端返回的 JSON 数据不对则报错</em><br />
<em> 2、减少 PHP 本身的 error message 输出</em><br />
<em> 3、将得到近期评论的功能分离为一个函数单独调用</em><br />
<em> 4、登录成功之后保存得到的 cookies 到同目录下的 uyan_cookie.php 文件中方便下次直接使用，而无需再重复登录，如果 cookie 过期下次获取评论时失败则再重新登录</em><br />
<em> 5、发查询近期评论请求时增加友言本身的管理地址作为 referer</em></p>
<p>此次增加了一个 uyan_cookie.php 文件用于保存 cookie，从下面的链接下载解压缩之后，请将此文件也上传到同一目录中（不上传的话 PHP 可能会报 require_once 出错），此文件默认为空，详细代码就不贴了，直接在下面下载查看吧。友言 的登录邮箱、密码、域名之类的修改请参考原始的介绍文章了。</p>
<p>这个是 1.1 版本的下载地址：</p>
<p><a href="http://miseal.googlecode.com/files/uyan_comments_v1.1.zip" target="_blank">http://miseal.googlecode.com/files/uyan_comments_v1.1.zip</a></p>
<p>当前的通过临时文件保存 cookie 方式应该还有改进空间，有任何问题欢迎指正咯 ^_^</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/wordpress-uyan-recent-comment-widget-v1-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP实现WordPress友言近期评论Widget</title>
		<link>https://zohead.com/archives/wordpress-uyan-recent-comment-widget/</link>
		<comments>https://zohead.com/archives/wordpress-uyan-recent-comment-widget/#comments</comments>
		<pubDate>Fri, 11 May 2012 16:16:35 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[post-to-host]]></category>
		<category><![CDATA[友言]]></category>
		<category><![CDATA[小工具]]></category>
		<category><![CDATA[社交网络]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[评论]]></category>

		<guid isPermaLink="false">http://zohead.com/?p=120</guid>
		<description><![CDATA[本文同步自（如浏览不正常请点击跳转）：https://zohead.com/archives/wordpress-uyan-recent-comment-widget/ 现在有很多人都使用 WordPress 来搭建自己的博客系统，其中有一些是像我这样使用 友言 这个社交评论插件来替代系统原始的评论框的，友言 评论框插件对一些主流的社交网站支持比较好，很是推荐，友言官网： http://uyan.cc/ 之前我写过一个修改 友言 插件实现完美与 WordPress Mobile Pack 插件配合实现移动版博客的文章，在这里仅供参考： https://zohead.com/archives/m [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>本文同步自（如浏览不正常请点击跳转）：<a href="https://zohead.com/archives/wordpress-uyan-recent-comment-widget/" target="_blank">https://zohead.com/archives/wordpress-uyan-recent-comment-widget/</a></p>
<p>现在有很多人都使用 WordPress 来搭建自己的博客系统，其中有一些是像我这样使用 友言 这个社交评论插件来替代系统原始的评论框的，友言 评论框插件对一些主流的社交网站支持比较好，很是推荐，友言官网：</p>
<p><a href="http://uyan.cc/" target="_blank">http://uyan.cc/</a></p>
<p>之前我写过一个修改 友言 插件实现完美与 WordPress Mobile Pack 插件配合实现移动版博客的文章，在这里仅供参考：</p>
<p><a href="https://zohead.com/archives/modify-plugin-wordpress-mobile-pack/" target="_blank">https://zohead.com/archives/modify-plugin-wordpress-mobile-pack/</a></p>
<p>但现在发现还是有一点不足，由于使用了友言评论框替代 WordPress 本身的，导致 WordPress 的 ”近期评论“ Widget（小工具）显示不了，因此小折腾一个晚上，靠着还依稀记得的 PHP 编程经历，写了一个简单的显示 友言 近期评论的 WordPress Widget，先看效果图（本博客右侧就有 ^_^）：</p>
<p><a href="http://zohead.com/wp-content/uploads/wordpress-uyan-recent-comment-widget.png" target="_blank"><img src="http://zohead.com/wp-content/uploads/wordpress-uyan-recent-comment-widget.png" alt="友言近期评论Widget效果图" width="228" height="152" /></a></p>
<p><span style="color: #f00;"><strong>原理及代码：<br />
</strong></span></p>
<p>实现原理比较简单，先用工具分析 友言 评论的后台登录和评论显示之类的 HTTP 包信息，然后用 PHP 的 fsockopen 来自己发送 GET、POST 请求实现在 WordPress 上列举显示已经存在的友言评论（<span style="color: #006400;">备注：默认只显示已经经过审核的评论</span>）。</p>
<p>由于中间有几步 GET 和 POST 请求，就找了个现成的 <strong>post-to-host</strong> 这个很小的 PHP 脚本来发 GET 和 POST 请求，下载地址：</p>
<p><a href="http://code.google.com/p/post-to-host/" target="_blank">http://code.google.com/p/post-to-host/</a></p>
<p>下面是主程序 <span style="color: #006400;"><strong>uyan_comments.php</strong></span> 的代码：</p>
<pre class="brush: php; highlight: [3,4,5,6,8,13,36,40,72]; title: uyan_comments.php; notranslate">
&lt;?php
// global site information
$email = &quot;xxxx login email xxxx&quot;;
$password = &quot;xxxx encrypted password xxxx&quot;;
$domain = &quot;xxxx domain name xxxx&quot;;
$maxcomments = 10;

require_once(&quot;post_to_host.php&quot;);

header(&quot;Content-Type:text/html; charset=utf-8&quot;);

// Login to uyan.cc
$url = &quot;http://uyan.cc/index.php/youyan_login/userAutoLoginCrossDomain?email=&quot; . $email . &quot;&amp;loginPassword=&quot; . $password . &quot;&amp;rem=1&amp;domain=&quot; . $domain;

$ret_str = post_to_host($url, array(), array(), &quot;&quot;, $ret_head, 0);
$ret_str = trim($ret_str, &quot;()&quot;);

if ($ret_str == null || $ret_str == 'noData' || $ret_str == '&quot;noData&quot;') {
	echo(&quot;Failed to authentication with uyan.cc&quot;);
	return;
}

$ret_json = json_decode($ret_str, true);

// check response JSON data
if (!array_key_exists('uid', $ret_json) || !array_key_exists('uname', $ret_json)) {
	echo(&quot;Invalid data from uyan.cc&quot;);
	return;
}

// delete unneeded 'auth' cookie key
$arr_cookie = get_cookies_from_heads($ret_head);
unset($arr_cookie['auth']);

// need this to set uid and uname
$url = &quot;http://uyan.cc/setting?uid=&quot; . $ret_json['uid'] . &quot;&amp;domain=&quot; . $domain . &quot;&amp;uname=&quot; . $ret_json['uname'];
$ret_str = post_to_host($url, array(), $arr_cookie, &quot;&quot;, $ret_head, 0);

// get comment
$url = &quot;http://uyan.cc/youyan_admin/getMoreCommentsByDomain/0&quot;;
$get_comment_params = array('currentMore' =&gt; '0', 'normalCommentToogle' =&gt; '1', 'readyCommentToogle' =&gt; '0', 'trashCommentToogle' =&gt; '0', 'delCommentToogle' =&gt; '0');

$ret_str = post_to_host($url, $get_comment_params, $arr_cookie, &quot;&quot;, $ret_head);

$comment_json = json_decode($ret_str, true);
$nr_comments = 0;

echo(&quot;&lt;ul&gt;&quot;);

foreach ($comment_json as $comment) {
	$display_name = &quot;&quot;;
	$display_title = &quot;&quot;;

	if ($maxcomments &gt;= 0 &amp;&amp; $nr_comments &gt;= $maxcomments) break;

	// must with valid URL and page title
	if (!array_key_exists('page_url', $comment) || !array_key_exists('page_title', $comment) || strlen($comment['page_url']) &lt;= 0 || strlen($comment['page_title']) &lt;= 0)
		continue;

	// must with a valid display name
	if (array_key_exists('comment_author', $comment) &amp;&amp; strlen($comment['comment_author']) &gt; 0)
		$display_name = $comment['comment_author'];
	else if (array_key_exists('show_name', $comment) &amp;&amp; strlen($comment['show_name']) &gt; 0)
		$display_name = $comment['show_name'];
	else
		continue;

	$display_title = $comment['page_title'];
	$pos = strpos($display_title, ' | ');
	if ($pos &gt;= 0) $display_title = substr($display_title, 0, $pos);

	echo('&lt;li&gt;' . $display_name . '&amp;nbsp;&lt;strong&gt;&lt;font color=&quot;#0000FF&quot;&gt;&amp;gt;&amp;gt;&lt;/font&gt;&lt;/strong&gt;&amp;nbsp;&lt;a href=&quot;' . $comment['page_url'] . '&quot;&gt;' . $display_title . '&lt;/a&gt;&lt;/li&gt;');

	$nr_comments++;
}

echo(&quot;&lt;/ul&gt;&quot;);
?&gt;
</pre>
<p>代码本身比较简单，有些 PHP 基础就可以看懂了，把 <span style="color: #006400;"><strong>uyan_comments.php</strong></span> 文件最上面的 <span style="color: #006400;"><strong>$email</strong></span>、<span style="color: #006400;"><strong>$password</strong></span>、<span style="color: #006400;"><strong>$domain</strong></span>、<span style="color: #006400;"><strong>$maxcomments</strong></span> 改为实际的 友言 后台管理的登录邮箱、密码、你的域名、显示的最多评论数（备注：默认为10条，如果改为小于0的值则不限制显示的评论条数），就可以使用了。你应该已经发现这个 <span style="color: #006400;"><strong>uyan_comments.php</strong></span> 其实和 WordPress 没太大关系，完全也可以直接单独使用。</p>
<p>需要注意的是为了避免使用明文密码而可能导致的问题（安全第一 ^_^），上面的 <span style="color: #006400;"><strong>$password</strong></span> 是 友言 后台管理时实际用到的加密过的密码。这个加密过的密码可以通过 Firefox 的 Live HTTP headers 插件之类的抓取 HTTP 协议头的插件或工具来得到。</p>
<p><span style="color: #f00;"><strong>得到友言的加密登录密码：</strong></span></p>
<p>下面以 Firefox 的 Live HTTP headers 插件为例说明如何得到 友言 的实际加密的密码，打开 Live HTTP headers，该插件会自动开始抓取，然后用正确的邮箱和密码登录 友言 的后台管理，停止 Live HTTP headers 的抓取，在输出里就能找到地址为如下格式的 GET 请求，请求参数中就有加密的密码：</p>
<p><strong>http://uyan.cc/index.php/youyan_login/userAutoLoginCrossDomain?callback=jsonpxxxxxxx&amp;email=xxxxx@xxxxx.com&amp;loginPassword=<span style="color: #b22222;">xxxxxxxxxxxxxxxxx</span>&amp;rem=1&amp;domain=xxx.com<br />
</strong></p>
<p>其中的 <span style="color: #006400;"><strong>email</strong></span> 段就是登录邮箱，<span style="color: #006400;"><strong>loginPassword</strong></span> 段即为加密的密码，保存下该密码，修改 <span style="color: #006400;"><strong>uyan_comments.php</strong></span> 文件中的 <span style="color: #006400;"><strong>$email</strong></span> 和 <span style="color: #006400;"><strong>$password</strong></span> 值。</p>
<p>Live HTTP headers 的抓取截图如下所示（后面的未显示完整）：</p>
<p><a href="http://zohead.com/wp-content/uploads/uyan-login-http-headers.png" target="_blank"><img src="http://zohead.com/wp-content/uploads/uyan-login-http-headers.png" alt="友言后台管理的登录HTTP包" width="588" height="478" /></a></p>
<p><span style="color: #f00;"><strong>如何加入 WordPress Widget 列表中：</strong></span></p>
<p>你如果有真正实现一个 WordPress Widget 的心思，可以用本代码加上 WordPress 的 register_widget 之类的接口来实现。无奈我是一个超级懒人，懒人就有懒人的办法，下面介绍的就是懒人的办法，哈哈。</p>
<p>首先下载本文最下面下载链接中的 <span style="color: #006400;"><strong>post_to_host.php</strong></span> 和 <span style="color: #006400;"><strong>uyan_comments.php</strong></span>，将 <span style="color: #006400;"><strong>uyan_comments.php</strong></span> 中对应的 登录邮箱、密码、域名 改掉（参考上面），将这两个文件上传到 WordPress 根目录中（位置也可以自己修改），然后给 WordPress 安装 <strong>PHP Code Widget</strong> 插件，这是一个通用 Widget，添加之后，可以自行添加 文本、HTML、PHP 代码等，比较方便，插件地址：</p>
<p><a href="http://wordpress.org/extend/plugins/php-code-widget/" target="_blank">http://wordpress.org/extend/plugins/php-code-widget/</a></p>
<p>安装之后，在 WordPress 管理后台的 外观 - 小工具 里就能看到名为 “PHP Code”  的小工具，将其托至右侧的 “第一小工具区域”，输入自定义的标题，然后加入以下代码保存即可（如果上传的位置不在 WordPress 根目录那请自行修改）：</p>
<pre class="brush: php; highlight: [2]; title: 小工具的PHP代码; notranslate">
&lt;?php
include_once(&quot;uyan_comments.php&quot;);
?&gt;
</pre>
<p>重新访问 WordPress，如果上面的 登录邮箱、密码、域名 设定都正确的话，应该就可以出现类似上面效果图的评论列表。</p>
<p><span style="color: #f00;"><strong>不足和改进：</strong></span></p>
<p>1、uyan_comments.php 每次访问时都需要登录 友言 管理后台，请求评论列表，因此速度会有些影响，这个有空再改进了。</p>
<p>2、由于需要在 Web服务器中使用 PHP 的 fsockopen 来发 GET、POST 请求得到评论列表，因此可能对 WordPress 博客的访问速度造成一些影响，如果 PHP 空间在国内还可以，像我这样空间在国外的就稍微悲剧点了，所以建议安装 WP Super Cache WordPress 之类的插件来实现更好的缓存加速，将影响尽量降低。</p>
<p><span style="color: #f00;"><strong>下载地址（115网盘）：</strong></span></p>
<p><a href="http://115.com/file/beezjk3b" target="_blank">http://115.com/file/beezjk3b</a></p>
<p>写博客好累，准备休息，HOHO，本文件为个人作品，有任何问题欢迎指正。 ^_^</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/wordpress-uyan-recent-comment-widget/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
