<?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>超群.com的博客 &#187; PHP</title>
	<atom:link href="http://www.fuchaoqun.com/category/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.fuchaoqun.com</link>
	<description></description>
	<lastBuildDate>Thu, 22 Jul 2010 23:31:23 +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>Mediawiki扩展编写实战</title>
		<link>http://www.fuchaoqun.com/2010/07/mediawiki-extension/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=mediawiki-extension</link>
		<comments>http://www.fuchaoqun.com/2010/07/mediawiki-extension/#comments</comments>
		<pubDate>Thu, 22 Jul 2010 11:25:50 +0000</pubDate>
		<dc:creator>超群.com</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[mediawiki]]></category>

		<guid isPermaLink="false">http://www.fuchaoqun.com/?p=381</guid>
		<description><![CDATA[Wikipedia大家都很熟悉，而Mediawiki则是Wikipedia背后的功臣，整个Wikipedia都构建在mediawiki之上，mediawiki的稳定性和高效性值得信赖，同时Mediawiki非常易于扩展，可以通过Extension的方式添加非常多的功能，而且Mediawiki的Extension社区也非常活跃，大家可以到Mediawiki Extension目录下去下载自己需要的扩展程序。 上周末，帮朋友写了一些Mediawiki的扩展，立即被Mediawiki的强大扩展性折服，主要实现的功能有：增加Google Analytics统计、自定义标题、增加Google Adsense广告之类，写Mediawiki的扩展，最好的参考是Mediawiki扩展手册：http://www.mediawiki.org/wiki/Manual:Extensions。 Mediawiki的扩展主要有Tag Extension、Parser Functions、Hooks、Special Pages、Skins、Magic Words，对应的中文是：标签扩展（自定义wiki标签，比如xxxx）、解析扩展（和标签类似，不过呈现方式稍有不通，为{{#foo : bar}}）、钩子、特殊页面、皮肤、魔术关键字，我这里演示的是Parser Functions和Hooks，其他的差不多类似。 一、增加Google Analytics统计和Google Adsense广告 原理很简单，我们在页面显示之前，把Google Analytics和Google Adsense的代码append到要显示的内容即可，代码： &#60;?php /** * 安全设置，防止恶意调用 */ if &#40;!defined&#40;'MEDIAWIKI'&#41;&#41; &#123; die&#40; 'This file is a MediaWiki extension, it is not a valid entry point' &#41;; &#125; &#160; /** * 扩展的基本信息 */ $wgExtensionCredits&#91;'other'&#93;&#91;&#93; = array&#40; 'path' =&#62; __FILE__, 'name' [...]]]></description>
			<content:encoded><![CDATA[<p>Wikipedia大家都很熟悉，而<a href="http://www.mediawiki.org/" target="_blank">Mediawiki</a>则是Wikipedia背后的功臣，整个Wikipedia都构建在mediawiki之上，mediawiki的稳定性和高效性值得信赖，同时Mediawiki非常易于扩展，可以通过Extension的方式添加非常多的功能，而且Mediawiki的Extension社区也非常活跃，大家可以到<a href="http://www.mediawiki.org/wiki/Category:Extensions" target="_blank">Mediawiki Extension</a>目录下去下载自己需要的扩展程序。</p>
<p>上周末，帮朋友写了一些Mediawiki的扩展，立即被Mediawiki的强大扩展性折服，主要实现的功能有：增加Google Analytics统计、自定义标题、增加Google Adsense广告之类，写Mediawiki的扩展，最好的参考是Mediawiki扩展手册：<a href="http://www.mediawiki.org/wiki/Manual:Extensions" target="_blank">http://www.mediawiki.org/wiki/Manual:Extensions</a>。</p>
<p>Mediawiki的扩展主要有Tag Extension、Parser Functions、Hooks、Special Pages、Skins、Magic Words，对应的中文是：标签扩展（自定义wiki标签，比如<foo>xxxx</foo>）、解析扩展（和标签类似，不过呈现方式稍有不通，为{{#foo : bar}}）、钩子、特殊页面、皮肤、魔术关键字，我这里演示的是Parser Functions和Hooks，其他的差不多类似。</p>
<p>一、增加Google Analytics统计和Google Adsense广告</p>
<p>原理很简单，我们在页面显示之前，把Google Analytics和Google Adsense的代码append到要显示的内容即可，代码：</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #009933; font-style: italic;">/**
 * 安全设置，防止恶意调用
 */</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">defined</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MEDIAWIKI'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'This file is a MediaWiki extension, it is not a valid entry point'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 扩展的基本信息
 */</span>
<span style="color: #000088;">$wgExtensionCredits</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'other'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
	<span style="color: #0000ff;">'path'</span>           <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #339933;">,</span>
	<span style="color: #0000ff;">'name'</span>           <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'插件名称'</span><span style="color: #339933;">,</span>
	<span style="color: #0000ff;">'version'</span>        <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'1.0'</span><span style="color: #339933;">,</span>
	<span style="color: #0000ff;">'author'</span>         <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'作者'</span><span style="color: #339933;">,</span>
	<span style="color: #0000ff;">'descriptionmsg'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'简要说明'</span><span style="color: #339933;">,</span>
	<span style="color: #0000ff;">'url'</span>            <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'作者地址'</span><span style="color: #339933;">,</span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 注册一个钩子，在页面显示之前，处理页面显示内容
 * 
 * 全部钩子列表：http://www.mediawiki.org/wiki/Manual:Hooks
 * 
 */</span>
<span style="color: #000088;">$wgHooks</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'BeforePageDisplay'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'dzBeforePageDisplay'</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">function</span> dzBeforePageDisplay<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span><span style="color: #000088;">$out</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$skin</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #009933; font-style: italic;">/**
     * 在LocalSettings.php定义$wgDangZhiAppendHtml
     * 把要添加的Google Analytics和Google Adsense代码放里面
     */</span>
    <span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$wgDangZhiAppendHtml</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// 页面添加HTML</span>
    <span style="color: #000088;">$out</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addHTML</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$wgDangZhiAppendHtml</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// 记得返回true，收工</span>
    <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>短短几行代码，完成添加Google Analytics统计和Google Adsense广告代码，当然，你还可以添加任意你想添加到网页最后的代码，可以查看<a href="http://www.dangzhi.com" target="_blank">示例网站</a>的源代码，Google Analytics的代码布在每个页面上。</p>
<p>二、自定义文章标题</p>
<p>自定义文章标题对搜索引擎来说非常重要，Mediawiki默认的标题只能和内容条目一样，缺乏灵活性，这里的原理是增加一个{{#title: 标题内容}}的标签，在页面显示之前替换成网页标题，<a href="http://www.dangzhi.com" target="_blank">示例网站</a>的首页就自定了HTML标题。</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 还是第一示例中的显示前处理函数，这里是部分内容
 */</span>
<span style="color: #000000; font-weight: bold;">function</span> dzBeforePageDisplay<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span><span style="color: #000088;">$out</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$skin</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// 如果页面中存在{{#title: 标题内容}}，那么指定文章标题</span>
    <span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/\{\{#title: ?(.*)\}\}/U'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$out</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">mBodytext</span><span style="color: #339933;">,</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$out</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">mBodytext</span> <span style="color: #339933;">=</span> <span style="color: #990000;">str_replace</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span> <span style="color: #000088;">$out</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">mBodytext</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$out</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">mHTMLtitle</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>三、文章在新窗口打开</p>
<p>Mediawiki是外国人做的东西，国外少有默认新窗口打开链接的习惯，国人的习惯可不是这样，让Mediawiki默认新窗口打开的做法非常的简单。</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * 还记得这个函数吧
 */</span>
<span style="color: #000000; font-weight: bold;">function</span> dzBeforePageDisplay<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span><span style="color: #000088;">$out</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$skin</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// 新窗口打开链接</span>
    <span style="color: #000088;">$p</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/(&lt;a href=\&quot;\/index.php\?title=.+\&quot;)/U'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'/(&lt;a href=\&quot;\/wiki\/.+\&quot;)/U'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$r</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'$1 target=&quot;_blank&quot;'</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$out</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">mBodytext</span> <span style="color: #339933;">=</span> <span style="color: #990000;">preg_replace</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$p</span><span style="color: #339933;">,</span> <span style="color: #000088;">$r</span><span style="color: #339933;">,</span> <span style="color: #000088;">$out</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">mBodytext</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>在页面输出之前，给需要的a标签加个target=&#8221;_blank&#8221;的属性即可。</p>
<p>四、解析HTML标签</p>
<p>Mediawiki为了安全考虑，不允许在内容中使用非安全HTML标签，我们可以使用一种加密HTML的方法来达到安全性和易用性的平衡。在内容中增加{{#html: 加密码 | html内容}}，其中加密码是系统密钥和html内容的md5值，如果符合则显示。</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * 初始化Parser Functions
 */</span>
<span style="color: #000088;">$wgHooks</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'ParserFirstCallInit'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'dzParserSetup'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$wgHooks</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'LanguageGetMagic'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'dzMagicSetup'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 设置解析函数
 */</span>
<span style="color: #000000; font-weight: bold;">function</span> dzParserSetup<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span><span style="color: #000088;">$parser</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$parser</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setFunctionHook</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'html'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'dzParseHtml'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">// 可以设置多个，$parser-&gt;setFunctionHook('foo', 'dzParseFoo');</span>
	<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 初始化Parser关键字
 */</span>
<span style="color: #000000; font-weight: bold;">function</span> dzMagicSetup<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span><span style="color: #000088;">$magicWords</span><span style="color: #339933;">,</span> <span style="color: #000088;">$langCode</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$magicWords</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'html'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'html'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">// 可以设置多个，$magicWords['foo'] = array(0, 'foo');</span>
    <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 解析HTML
 */</span>
<span style="color: #000000; font-weight: bold;">function</span> dzParseHtml<span style="color: #009900;">&#40;</span><span style="color: #000088;">$parser</span><span style="color: #339933;">,</span> <span style="color: #000088;">$param1</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span> <span style="color: #000088;">$param2</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// 在LocalSettings.php定义HTML加密密钥</span>
    <span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$wgHtmlSalt</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$key</span> <span style="color: #339933;">=</span> <span style="color: #990000;">md5</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$wgHtmlSalt</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$param2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$key</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$param1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$param2</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'noparse'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'isHTML'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">'bad html'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Mediawiki的扩展写起来还是相当容易，文中提到的效果可以在<a href="http://www.dangzhi.com" target="_blank">这里体验</a>，老外写的东西对Extension都很重视，wordpress也是这样，不似国内的某些项目，稍做修改都得hack代码，hack的坏处是升级的时候容易悲剧。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fuchaoqun.com/2010/07/mediawiki-extension/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ColaPHP 0.8beta发布</title>
		<link>http://www.fuchaoqun.com/2010/07/colaphp-0-8-beta/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=colaphp-0-8-beta</link>
		<comments>http://www.fuchaoqun.com/2010/07/colaphp-0-8-beta/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 16:31:52 +0000</pubDate>
		<dc:creator>超群.com</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[ColaPHP]]></category>

		<guid isPermaLink="false">http://www.fuchaoqun.com/?p=378</guid>
		<description><![CDATA[代号：Mini，bugfix版本，改善框架易用性，代码重构。 下载ColaPHP 0.8beta，阅读ColaPHP文档，访问ColaPHP项目。 ColaPHP 0.8beta已经很稳定，可以在生产环境使用。]]></description>
			<content:encoded><![CDATA[<p>代号：Mini，bugfix版本，改善框架易用性，代码重构。</p>
<p><a href="http://colaphp.googlecode.com/files/ColaPHP-0.8-beta.zip" target="_blank">下载ColaPHP 0.8beta</a>，阅读<a href="http://code.google.com/p/colaphp/w/list" target="_blank">ColaPHP文档</a>，访问<a href="http://code.google.com/p/colaphp/" target="_blank">ColaPHP项目</a>。</p>
<p>ColaPHP 0.8beta已经很稳定，可以在生产环境使用。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fuchaoqun.com/2010/07/colaphp-0-8-beta/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PHP导出MySQL数据到Excel文件</title>
		<link>http://www.fuchaoqun.com/2010/05/php-export-mysql-excel/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=php-export-mysql-excel</link>
		<comments>http://www.fuchaoqun.com/2010/05/php-export-mysql-excel/#comments</comments>
		<pubDate>Wed, 12 May 2010 01:37:07 +0000</pubDate>
		<dc:creator>超群.com</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[excel]]></category>

		<guid isPermaLink="false">http://www.fuchaoqun.com/?p=352</guid>
		<description><![CDATA[经常会碰到需要从数据库中导出数据到Excel文件，用一些开源的类库，比如PHPExcel，确实比较容易实现，但对大量数据的支持很不好，很容易到达PHP内存使用上限。这里的方法是利用fputcsv写CSV文件的方法，直接向浏览器输出Excel文件。 &#60;?php // 输出Excel文件头，可把user.csv换成你要的文件名 header&#40;'Content-Type: application/vnd.ms-excel'&#41;; header&#40;'Content-Disposition: attachment;filename=&#34;user.csv&#34;'&#41;; header&#40;'Cache-Control: max-age=0'&#41;; &#160; // 从数据库中获取数据，为了节省内存，不要把数据一次性读到内存，从句柄中一行一行读即可 $sql = 'select * from tbl where ……'; $stmt = $db-&#62;query&#40;$sql&#41;; &#160; // 打开PHP文件句柄，php://output 表示直接输出到浏览器 $fp = fopen&#40;'php://output', 'a'&#41;; &#160; // 输出Excel列名信息 $head = array&#40;'姓名', '性别', '年龄', 'Email', '电话', '……'&#41;; foreach &#40;$head as $i =&#62; $v&#41; &#123; // CSV的Excel支持GBK编码，一定要转换，否则乱码 $head&#91;$i&#93; = iconv&#40;'utf-8', [...]]]></description>
			<content:encoded><![CDATA[<p>经常会碰到需要从数据库中导出数据到Excel文件，用一些开源的类库，比如<a href="http://phpexcel.codeplex.com/" target="_blank">PHPExcel</a>，确实比较容易实现，但对大量数据的支持很不好，很容易到达PHP内存使用上限。这里的方法是利用fputcsv写CSV文件的方法，直接向浏览器输出Excel文件。</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #666666; font-style: italic;">// 输出Excel文件头，可把user.csv换成你要的文件名</span>
<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Content-Type: application/vnd.ms-excel'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Content-Disposition: attachment;filename=&quot;user.csv&quot;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Cache-Control: max-age=0'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// 从数据库中获取数据，为了节省内存，不要把数据一次性读到内存，从句柄中一行一行读即可</span>
<span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'select * from tbl where ……'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$stmt</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// 打开PHP文件句柄，php://output 表示直接输出到浏览器</span>
<span style="color: #000088;">$fp</span> <span style="color: #339933;">=</span> <span style="color: #990000;">fopen</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'php://output'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'a'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// 输出Excel列名信息</span>
<span style="color: #000088;">$head</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'姓名'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'性别'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'年龄'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Email'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'电话'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'……'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$head</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$v</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// CSV的Excel支持GBK编码，一定要转换，否则乱码</span>
    <span style="color: #000088;">$head</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">iconv</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'utf-8'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'gbk'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$v</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// 将数据通过fputcsv写到文件句柄</span>
<span style="color: #990000;">fputcsv</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fp</span><span style="color: #339933;">,</span> <span style="color: #000088;">$head</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// 计数器</span>
<span style="color: #000088;">$cnt</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// 每隔$limit行，刷新一下输出buffer，不要太大，也不要太小</span>
<span style="color: #000088;">$limit</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">100000</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// 逐行取出数据，不浪费内存</span>
<span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$row</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$stmt</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fetch</span><span style="color: #009900;">&#40;</span>Zend_Db<span style="color: #339933;">::</span><span style="color: #004000;">FETCH_NUM</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000088;">$cnt</span> <span style="color: #339933;">++;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$limit</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$cnt</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #666666; font-style: italic;">//刷新一下输出buffer，防止由于数据过多造成问题</span>
        <span style="color: #990000;">ob_flush</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #990000;">flush</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$cnt</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$row</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$v</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$row</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">iconv</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'utf-8'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'gbk'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$v</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #990000;">fputcsv</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fp</span><span style="color: #339933;">,</span> <span style="color: #000088;">$row</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>简单易用，非常节省内存，不依赖第三方类库。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fuchaoqun.com/2010/05/php-export-mysql-excel/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ColaPHP 0.7beta发布</title>
		<link>http://www.fuchaoqun.com/2010/04/colaphp-0-7beta/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=colaphp-0-7beta</link>
		<comments>http://www.fuchaoqun.com/2010/04/colaphp-0-7beta/#comments</comments>
		<pubDate>Sat, 03 Apr 2010 06:36:47 +0000</pubDate>
		<dc:creator>超群.com</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.fuchaoqun.com/?p=341</guid>
		<description><![CDATA[ColaPHP的2010.3月度发布计划版本，稍微晚了几天，代号Recode，和0.6beta相比,框架结构有比较大的变化，主要修改如下： 精简框架核心，除FrontController、Router、MVC外，其他功能组件化 Cola_Db、Cola_Cache、Cola_Log、Cola_Yaml已组件化成Cola_Com_Db、Cola_Com_Cache、Cola_Com_Log、Cola_Com_Yaml Controller中可直接使用$this-&#62;com-&#62;db($config)之类的接口来调用组件 少量代码重构以及bug fix 下载ColaPHP 0.7beta，阅读ColaPHP文档，访问ColaPHP项目。 由于0.7beta做框架架构上变化有点大，不建议立即采用，生产环境中建议使用稳定的0.6beta，下一个版本0.8beta开发代号：Mini，主要对架构、代码做进一步重构优化。]]></description>
			<content:encoded><![CDATA[<p>ColaPHP的2010.3月度发布计划版本，稍微晚了几天，代号Recode，和0.6beta相比,框架结构有比较大的变化，主要修改如下：</p>
<ul>
<li>精简框架核心，除FrontController、Router、MVC外，其他功能组件化</li>
<li>Cola_Db、Cola_Cache、Cola_Log、Cola_Yaml已组件化成Cola_Com_Db、Cola_Com_Cache、Cola_Com_Log、Cola_Com_Yaml</li>
<li>Controller中可直接使用$this-&gt;com-&gt;db($config)之类的接口来调用组件</li>
<li>少量代码重构以及bug fix</li>
</ul>
<p><a href="http://colaphp.googlecode.com/files/ColaPHP-0.7-beta.zip" target="_blank">下载ColaPHP 0.7beta</a>，阅读<a href="http://code.google.com/p/colaphp/w/list" target="_blank">ColaPHP文档</a>，访问<a href="http://code.google.com/p/colaphp/" target="_blank">ColaPHP项目</a>。</p>
<p>由于0.7beta做框架架构上变化有点大，不建议立即采用，生产环境中建议使用稳定的0.6beta，下一个版本0.8beta开发代号：Mini，主要对架构、代码做进一步重构优化。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fuchaoqun.com/2010/04/colaphp-0-7beta/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ColaPHP 0.6beta发布</title>
		<link>http://www.fuchaoqun.com/2010/02/colaphp-0-6-beta/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=colaphp-0-6-beta</link>
		<comments>http://www.fuchaoqun.com/2010/02/colaphp-0-6-beta/#comments</comments>
		<pubDate>Sat, 27 Feb 2010 17:39:33 +0000</pubDate>
		<dc:creator>超群.com</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[ColaPHP]]></category>

		<guid isPermaLink="false">http://www.fuchaoqun.com/?p=330</guid>
		<description><![CDATA[ColaPHP月度发布计划版本，代号：Easy，和0.5beta相比变化不大，主要修改如下： 增加Yaml处理，底层调用symfony yaml包处理 增加自定义异常类，后续准备将框架中的异常细分（好处是将来可以对异常做针对性处理） 少量代码重构以及bug fix 下载ColaPHP 0.6beta，阅读ColaPHP文档，访问ColaPHP项目。 下一个版本0.7beta开发代号：Recode，主要对代码做进一步重构优化。]]></description>
			<content:encoded><![CDATA[<p>ColaPHP月度发布计划版本，代号：Easy，和0.5beta相比变化不大，主要修改如下：</p>
<ul>
<li>增加Yaml处理，底层调用symfony yaml包处理</li>
<li> 增加自定义异常类，后续准备将框架中的异常细分（好处是将来可以对异常做针对性处理）</li>
<li> 少量代码重构以及bug fix</li>
</ul>
<p><a href="http://colaphp.googlecode.com/files/ColaPHP-0.6-beta.zip" target="_blank">下载ColaPHP 0.6beta</a>，阅读<a href="http://code.google.com/p/colaphp/w/list" target="_blank">ColaPHP文档</a>，访问<a href="http://code.google.com/p/colaphp/" target="_blank">ColaPHP项目</a>。</p>
<p>下一个版本0.7beta开发代号：Recode，主要对代码做进一步重构优化。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fuchaoqun.com/2010/02/colaphp-0-6-beta/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>ColaPHP-0.4-alpha发布</title>
		<link>http://www.fuchaoqun.com/2009/12/colaphp-0-4-alpha/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=colaphp-0-4-alpha</link>
		<comments>http://www.fuchaoqun.com/2009/12/colaphp-0-4-alpha/#comments</comments>
		<pubDate>Wed, 23 Dec 2009 13:46:59 +0000</pubDate>
		<dc:creator>超群.com</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[ColaPHP]]></category>
		<category><![CDATA[PHP Framework]]></category>

		<guid isPermaLink="false">http://www.fuchaoqun.com/?p=279</guid>
		<description><![CDATA[ColaPHP月度发布计划，基本上每月发一个release，相比较0.3alpha，比较大的修改如下： 增加了动态路由模式，可不用定义URL规则 增加对MySQL Master-Slave支持，可以由单数据库无缝迁移到主从模式 去除框架中Smarty模板的绑定，可以在Controller中自行调用Smarty模板 Helper中增加了性能测试模块Benchmark.php 增加对MongoDB的简单绑定Mongo.php 性能进一步提升 大量的代码重构以及bug fix 访问ColaPHP官方网站，下载0.4alpha，不过建议随时跟进我们的svn://colaphp.googlecode.com/svn/trunk/，ColaPHP一直在活跃开发。 ColaPHP 0.4alpha已完成预期目标，所有的函数都控制在20行以内。下一个版本0.5alpha版本开发代号：Practice，ColaPHP已经在一些实际项目中使用，0.5alpha将得到更多的实践优化 招募PHP极客加入ColaPHP，联系fuchaoqun#gmail.com。]]></description>
			<content:encoded><![CDATA[<p>ColaPHP月度发布计划，基本上每月发一个release，相比较0.3alpha，比较大的修改如下：</p>
<ul>
<li>增加了动态路由模式，可不用定义URL规则</li>
<li>增加对MySQL Master-Slave支持，可以由单数据库无缝迁移到主从模式</li>
<li>去除框架中Smarty模板的绑定，可以在Controller中自行调用Smarty模板</li>
<li>Helper中增加了性能测试模块Benchmark.php</li>
<li>增加对MongoDB的简单绑定Mongo.php</li>
<li>性能进一步提升</li>
<li>大量的代码重构以及bug fix </li>
</ul>
<p>访问<a href="http://code.google.com/p/colaphp/" target="_blank">ColaPHP</a>官方网站，下载<a href="http://colaphp.googlecode.com/files/ColaPHP-0.4-alpha.zip" target="_blank">0.4alpha</a>，不过建议随时跟进我们的svn://colaphp.googlecode.com/svn/trunk/，ColaPHP一直在活跃开发。</p>
<p>ColaPHP 0.4alpha已完成预期目标，所有的函数都控制在20行以内。下一个版本0.5alpha版本开发代号：Practice，ColaPHP已经在一些实际项目中使用，0.5alpha将得到更多的实践优化</p>
<p>招募PHP极客加入ColaPHP，联系fuchaoqun#gmail.com。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fuchaoqun.com/2009/12/colaphp-0-4-alpha/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ColaPHP-0.3-alpha发布</title>
		<link>http://www.fuchaoqun.com/2009/11/colaphp-03-alpha/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=colaphp-03-alpha</link>
		<comments>http://www.fuchaoqun.com/2009/11/colaphp-03-alpha/#comments</comments>
		<pubDate>Sat, 07 Nov 2009 05:08:29 +0000</pubDate>
		<dc:creator>超群.com</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[ColaPHP]]></category>

		<guid isPermaLink="false">http://www.fuchaoqun.com/?p=255</guid>
		<description><![CDATA[开发工作很久以前就基本完成了，一直没来得及整理，今天发布0.3alpha，相比较0.2alpha，比较大的修改如下： Helper中增加了验证码模块Captcha.php、HTTP访问模块Http.php、数据校验模块Validate.php 修订DB模块中result($sql)函数，如果$sql是select语句则返回结果集，如果是insert语句则返回最后插入ID，如果是update或者delete语句，则返回受影响行数（有可能为0行），其他语句则返回query句柄 完善框架的易用性：增加了统一配置文件；可以指定models、views、controllers目录；支持默认模版名称 大量的代码重构以及bug fix 下载0.3alpha，不过建议随时跟进我们的SVN://colaphp.googlecode.com/svn/trunk/，ColaPHP一直在活跃开发。 0.4alpha版本开发代号：20 lines，目标是把所有的函数都控制在20行以内以及代码的持续重构。 继续招募PHP极客加入Cola，联系fuchaoqun#gmail.com。]]></description>
			<content:encoded><![CDATA[<p>开发工作很久以前就基本完成了，一直没来得及整理，今天发布0.3alpha，相比较0.2alpha，比较大的修改如下： </p>
<ul>
<li>Helper中增加了验证码模块Captcha.php、HTTP访问模块Http.php、数据校验模块Validate.php</li>
<li>修订DB模块中result($sql)函数，如果$sql是select语句则返回结果集，如果是insert语句则返回最后插入ID，如果是update或者delete语句，则返回受影响行数（有可能为0行），其他语句则返回query句柄</li>
<li>完善框架的易用性：增加了统一配置文件；可以指定models、views、controllers目录；支持默认模版名称 </li>
<li>大量的代码重构以及bug fix </li>
</ul>
<p><a href="http://colaphp.googlecode.com/files/ColaPHP-0.3-alpha.zip" target="_blank">下载0.3alpha</a>，不过建议随时跟进我们的SVN://colaphp.googlecode.com/svn/trunk/，ColaPHP一直在活跃开发。</p>
<p>0.4alpha版本开发代号：20 lines，目标是把所有的函数都控制在20行以内以及代码的持续重构。 </p>
<p>继续招募PHP极客加入Cola，联系fuchaoqun#gmail.com。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fuchaoqun.com/2009/11/colaphp-03-alpha/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP处理Etag、lastModified和Expires</title>
		<link>http://www.fuchaoqun.com/2009/09/php_etag_lastmodified_expires/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=php_etag_lastmodified_expires</link>
		<comments>http://www.fuchaoqun.com/2009/09/php_etag_lastmodified_expires/#comments</comments>
		<pubDate>Sat, 05 Sep 2009 13:40:12 +0000</pubDate>
		<dc:creator>超群.com</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Etag]]></category>
		<category><![CDATA[Expires]]></category>
		<category><![CDATA[lastModified]]></category>

		<guid isPermaLink="false">http://www.fuchaoqun.com/?p=237</guid>
		<description><![CDATA[之前看到robbin基于资源的HTTP Cache的实现介绍，想到这是一个很有意思的功能，原理很简单，但很多人都会忽略，于是乎打算集成到ColaPHP框架中来，让浏览器缓存动态内容，对于一些由动态脚本生成、更新不频繁但又会被用户重复访问的页面内容，还是很有意义的。 如果在服务器端设置了Etag、lastModified和Expires之后，下次再访问同一资源的时候，一个典型的HTTP头是这样的： Host            127.0.0.1 User-Agent        Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 QQDownload/1.7 Accept            text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language        zh-cn,zh;q=0.5 Accept-Encoding        gzip,deflate Accept-Charset        GB2312,utf-8;q=0.7,*;q=0.7 Keep-Alive        300 Connection        keep-alive If-Modified-Since    Sat, 05 Sep 2009 12:44:56 GMT If-None-Match        foobar Cache-Control        max-age=0 关于lastModified、Etag和Expires的工作原理，可以参看http://longrujun.name/index.php/2009/03/04/etag%E5%92%8Cexpires/，简单来说： lastModified：设定一个最后修改时间，浏览器下次访问的时候，发送一个&#8221;If-Modified-Sinc&#8221;的头信息，如果内容在这个时间之后没有更新，服务器直接返回一个304 Not [...]]]></description>
			<content:encoded><![CDATA[<p>之前看到robbin<a href="http://robbin.javaeye.com/blog/462476" target="_blank">基于资源的HTTP Cache的实现介绍</a>，想到这是一个很有意思的功能，原理很简单，但很多人都会忽略，于是乎打算集成到<a href="http://code.google.com/p/colaphp/" target="_blank">ColaPHP</a>框架中来，让浏览器缓存动态内容，对于一些由动态脚本生成、更新不频繁但又会被用户重复访问的页面内容，还是很有意义的。</p>
<p>如果在服务器端设置了Etag、lastModified和Expires之后，下次再访问同一资源的时候，一个典型的HTTP头是这样的：</p>
<pre>Host            127.0.0.1
User-Agent        Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 QQDownload/1.7
Accept            text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language        zh-cn,zh;q=0.5
Accept-Encoding        gzip,deflate
Accept-Charset        GB2312,utf-8;q=0.7,*;q=0.7
Keep-Alive        300
Connection        keep-alive
If-Modified-Since    Sat, 05 Sep 2009 12:44:56 GMT
If-None-Match        foobar
Cache-Control        max-age=0</pre>
<p>关于lastModified、Etag和Expires的工作原理，可以参看<a href="http://longrujun.name/index.php/2009/03/04/etag%E5%92%8Cexpires/" target="_blank">http://longrujun.name/index.php/2009/03/04/etag%E5%92%8Cexpires/</a>，简单来说：</p>
<p><strong>lastModified</strong>：设定一个最后修改时间，浏览器下次访问的时候，发送一个&#8221;If-Modified-Sinc&#8221;的头信息，如果内容在这个时间之后没有更新，服务器直接返回一个304 Not Modified而不传输详细内容，可以节省带宽。</p>
<p><strong>Etag</strong>：设定一个标记，浏览器下次访问时，发送一个&#8221;If-None-Match&#8221;的头信息，如果服务器内容还是这个标记没变，也直接返回一个304 Not Modified而不传输详细内容，同样可以节省带宽。</p>
<p><strong>Expires</strong>：设定一个过期时间，如果当前请求在这个过期时间之类，则<strong>不发送HTTP请求</strong>，不仅可以节约服务器带宽，还可以<strong>减少服务器HTTP请求数</strong>。</p>
<p>主要通过header函数来发送，比较简单，直接上代码：</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> etag<span style="color: #009900;">&#40;</span><span style="color: #000088;">$etag</span><span style="color: #339933;">,</span> <span style="color: #000088;">$notModifiedExit</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$notModifiedExit</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_IF_NONE_MATCH'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$etag</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_IF_NONE_MATCH'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">statusCode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'304'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #990000;">exit</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Etag: '</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$etag</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> lastModified<span style="color: #009900;">&#40;</span><span style="color: #000088;">$modifiedTime</span><span style="color: #339933;">,</span> <span style="color: #000088;">$notModifiedExit</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$modifiedTime</span> <span style="color: #339933;">=</span> <span style="color: #990000;">date</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'D, d M Y H:i:s'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$modifiedTime</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">' GMT'</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$notModifiedExit</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_IF_MODIFIED_SINCE'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$modifiedTime</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_IF_MODIFIED_SINCE'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">statusCode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'304'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #990000;">exit</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Last-Modified: <span style="color: #006699; font-weight: bold;">$modifiedTime</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> expires<span style="color: #009900;">&#40;</span><span style="color: #000088;">$seconds</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1800</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$time</span> <span style="color: #339933;">=</span> <span style="color: #990000;">date</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'D, d M Y H:i:s'</span><span style="color: #339933;">,</span> <span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #000088;">$seconds</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">' GMT'</span><span style="color: #339933;">;</span>
    <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Expires: <span style="color: #006699; font-weight: bold;">$time</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>如果你是用<a href="http://code.google.com/p/colaphp/" target="_blank">ColaPHP</a>，可以直接在controller里面写上：</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// 设定最后修改时间，通常是数据库中内容修改时间</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">helper</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">response</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lastModified</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1252154696</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// 设定内容标记，自己可以按照一定的规则来生成，当然也可以用内容最后修改的时间戳</span>
 <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">helper</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">response</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">etag</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'foobar'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// 设定失效时间</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">response</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">expires</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>PS：ColaPHP近期发0.3alpha，主要改进Model和DB设计，加入了一下小功能（比如验证码），以及bugfix。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fuchaoqun.com/2009/09/php_etag_lastmodified_expires/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ColaPHP-0.1-alpha发布</title>
		<link>http://www.fuchaoqun.com/2009/06/colaphp-01-alpha/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=colaphp-01-alpha</link>
		<comments>http://www.fuchaoqun.com/2009/06/colaphp-01-alpha/#comments</comments>
		<pubDate>Fri, 19 Jun 2009 11:25:43 +0000</pubDate>
		<dc:creator>超群.com</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[ColaPHP]]></category>
		<category><![CDATA[framework]]></category>

		<guid isPermaLink="false">http://www.fuchaoqun.com/?p=227</guid>
		<description><![CDATA[非常简陋的一个PHP框架，只是把架子搭起来了，地址：http://code.google.com/p/colaphp/ 现在PHP框架已经很多了，为什么还要去&#8221;重复的发明轮子&#8221;？ 你和我一样不想重新学习一门&#8221;框架语言&#8221; 你和我一样希望规范的MVC开发 你和我一样希望一个高性能的框架 你和我一样不希望改变已有的PHP开发方式 现在，ColaPHP还很不成熟，暂且当做一个&#8221;玩具&#8221;试试，有兴趣的可以阅读一下代码，品味好的代码和指出坏味道的代码都是一个好的过程。 文档方面现在还很不全，我希望只用一个Tutorial就能讲明白，以后也不会有别的新的文档（文档越多，表明系统越复杂，学习成本也越高），当然，Tutorial会是一个持续完善的过程。 ColaPHP是写给PHP程序员的一个框架，信奉KISS的同学可以试试。]]></description>
			<content:encoded><![CDATA[<p>非常简陋的一个PHP框架，只是把架子搭起来了，地址：<a href="http://code.google.com/p/colaphp/" target="_blank">http://code.google.com/p/colaphp/</a></p>
<p>现在PHP框架已经很多了，为什么还要去&#8221;重复的发明轮子&#8221;？</p>
<ul>
<li>你和我一样不想重新学习一门&#8221;框架语言&#8221;</li>
<li>你和我一样希望规范的MVC开发</li>
<li>你和我一样希望一个高性能的框架</li>
<li>你和我一样不希望改变已有的PHP开发方式</li>
</ul>
<p>现在，ColaPHP还很不成熟，暂且当做一个&#8221;玩具&#8221;试试，有兴趣的可以阅读一下代码，品味好的代码和指出坏味道的代码都是一个好的过程。</p>
<p>文档方面现在还很不全，我希望只用一个<a href="http://code.google.com/p/colaphp/wiki/Tutorial_ZH_CN" target="_blank">Tutorial</a>就能讲明白，以后也不会有别的新的文档（文档越多，表明系统越复杂，学习成本也越高），当然，Tutorial会是一个持续完善的过程。</p>
<p>ColaPHP是写给PHP程序员的一个框架，信奉KISS的同学可以<a href="http://colaphp.googlecode.com/files/ColaPHP-0.1-alpha.zip" target="_blank">试试</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fuchaoqun.com/2009/06/colaphp-01-alpha/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PHP SESSION解惑</title>
		<link>http://www.fuchaoqun.com/2009/02/php-session-confuse/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=php-session-confuse</link>
		<comments>http://www.fuchaoqun.com/2009/02/php-session-confuse/#comments</comments>
		<pubDate>Fri, 27 Feb 2009 18:38:14 +0000</pubDate>
		<dc:creator>超群.com</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[session]]></category>

		<guid isPermaLink="false">http://chaoqun.17348.com/?p=171</guid>
		<description><![CDATA[一、PHP SESSION原理 我们知道，session是在服务器端保持用户会话数据的一种方法，对应的cookie是在客户端保持用户数据。HTTP协议是一种无状态协议，服务器响应完之后就失去了与浏览器的联系，最早，Netscape将cookie引入浏览器，使得数据可以客户端跨页面交换，那么服务器是如何记住众多用户的会话数据呢？ 首先要将客户端和服务器端建立一一联系，每个客户端都得有一个唯一标识，这样服务器才能识别出来。建议唯一标识的方法有两种：cookie或者通过GET方式指定。默认配置的PHP使用session的时会建立一个名叫&#8221;PHPSESSID&#8221;的cookie（可以通过php.ini修改session.name值指定），如果客户端禁用cookie,你也可以指定通过GET方式把session id传到服务器（修改php.ini中session.use_trans_sid等参数）。 我们查看服务器端session.save_path目录会发现很多类似sess_vv9lpgf0nmkurgvkba1vbvj915这样的文件，这个其实就是session id &#8220;vv9lpgf0nmkurgvkba1vbvj915&#8243;对应的数据。 真相就在这里，服务器将session id传递到服务器，服务器根据session id找到对应的文件，读取的时候对文件内容进行反序列化就得到session的值，保存的时候先序列化再写入。 事实就是这样，所以如果服务器不支持session或者你想自定义session，完全可以DIY，通过PHP的uniqid生成永不重复的session id，然后找个地方存储session的内容即可，你也可以学flickr把session存储在MySQL数据库中。 二、使用session之前为什么必须先执行session_start()？ 了解的原理之后，所谓的session其实就是客户端一个session id服务器端一个session file，新建session之前执行session_start()是告诉服务器要种一个cookie以及准备好session文件，要不然你的session内容怎么存；读取session之前执行session_start()是告诉服务器，赶紧根据session id把session文件反序列化。 只有一个session函数可以在session_start()之前执行，session_nam()：读取或指定session名称（比如默认的就是&#8221;PHPSESSID&#8221;），这个当然要在session_start之前执行。 三、session影响系统性能 session在大访问量网站上确实影响系统性能，影响性能的原因之一由文件系统设计造成，在同一个目录下超过10000个文件时，文件的定位将非常耗时，PHP支持session目录hash，我们可以通过修改php.ini中session.save_path = &#8220;2;/path/to/session/dir&#8221;，那么session将存储在两级子目录中（修订：参见david回复），不过好像PHP session不支持创建目录，你需要事先把那么些目录创建好 。 还有一个问题就是小文件的效率问题，一般我们的session数据都不会太大（1～2K），如果有大量这样1～2K的文件在磁盘上，IO效率肯定会很差，PHP手册上建议使用Reiserfs文件系统，不过Reiserfs的前景堪忧，Reiserfs的作者把媳妇给杀了，SuSE也抛弃了Reiserfs。 其实还有很多中存储session的方式，可以通过php -i&#124;grep &#8220;Registered save handlers&#8221;查看，比如Registered save handlers =&#62; files user sqlite eaccelerator可以通过文件、用户、sqlite、eaccelerator来存，如果服务器装了memcached，还有会mmcache的选项。当然还有很多，比如MySQL、PostgreSQL等等。都是不错的选择。 四、session的同步 我们前端可能有很多台服务器，用户在A服务器上登录了，种下了session信息，然后访问网站的某些页面没准跳到B服务器上去了，如果这个时候B服务器上没有session信息又没有做特殊处理，可能就会出问题了。 session同步有很多种，如果你是存储在memcached或者MySQL中，那就很容易了，指定到同样的位置即可，如果是文件形式的，你可以用NFS统一存储。 还有一种方式是通过加密的cookie来实现，用户在A服务器上登录成功，在用户的浏览器上种上一个加密的cookie，当用户访问B服务器时，检查有无session，如果有当然没问题，如果没有，就去检验cookie是否有效，cookie有效的话就在B服务器上重建session。这种方法其实很有用，如果网站有很多个子频道，服务器也不在一个机房，session没办法同步又想做统一登录那就太有用了。 当然还有一种方法就是在负载均衡那一层保持会话，把访问者帮定在某个服务器上，他的所有访问都在那个服务器上就不需要session同步了，这些都是运维层面的东西。 就说这么多吧，根据自己的应用来选择使用session，不要因为大家都说session影响系统性能就畏首畏尾，知道问题，解决问题才是关键，惹不起躲得起不适合这里。]]></description>
			<content:encoded><![CDATA[<p>一、PHP SESSION原理</p>
<p>我们知道，session是在服务器端保持用户会话数据的一种方法，对应的cookie是在客户端保持用户数据。HTTP协议是一种无状态协议，服务器响应完之后就失去了与浏览器的联系，最早，Netscape将cookie引入浏览器，使得数据可以客户端跨页面交换，那么服务器是如何记住众多用户的会话数据呢？</p>
<p>首先要将客户端和服务器端建立一一联系，每个客户端都得有一个唯一标识，这样服务器才能识别出来。建议唯一标识的方法有两种：cookie或者通过GET方式指定。默认配置的PHP使用session的时会建立一个名叫&#8221;PHPSESSID&#8221;的cookie（可以通过php.ini修改session.name值指定），如果客户端禁用cookie,你也可以指定通过GET方式把session id传到服务器（修改php.ini中session.use_trans_sid等参数）。</p>
<p>我们查看服务器端session.save_path目录会发现很多类似sess_vv9lpgf0nmkurgvkba1vbvj915这样的文件，这个其实就是session id &#8220;vv9lpgf0nmkurgvkba1vbvj915&#8243;对应的数据。</p>
<p>真相就在这里，服务器将session id传递到服务器，服务器根据session id找到对应的文件，读取的时候对文件内容进行反序列化就得到session的值，保存的时候先序列化再写入。</p>
<p>事实就是这样，所以如果服务器不支持session或者你想自定义session，完全可以DIY，通过PHP的uniqid生成永不重复的session id，然后找个地方存储session的内容即可，你也可以学flickr把session存储在MySQL数据库中。</p>
<p>二、使用session之前为什么必须先执行session_start()？</p>
<p>了解的原理之后，所谓的session其实就是客户端一个session id服务器端一个session file，新建session之前执行session_start()是告诉服务器要种一个cookie以及准备好session文件，要不然你的session内容怎么存；读取session之前执行session_start()是告诉服务器，赶紧根据session id把session文件反序列化。</p>
<p>只有一个session函数可以在session_start()之前执行，session_nam()：读取或指定session名称（比如默认的就是&#8221;PHPSESSID&#8221;），这个当然要在session_start之前执行。</p>
<p>三、session影响系统性能</p>
<p>session在大访问量网站上确实影响系统性能，影响性能的原因之一由文件系统设计造成，在同一个目录下超过10000个文件时，文件的定位将非常耗时，PHP支持session目录hash，我们可以通过修改php.ini中session.save_path = &#8220;2;/path/to/session/dir&#8221;，那么session将存储在两级子目录中（修订：参见david回复），不过好像PHP session不支持创建目录，你需要事先把那么些目录创建好 。</p>
<p>还有一个问题就是小文件的效率问题，一般我们的session数据都不会太大（1～2K），如果有大量这样1～2K的文件在磁盘上，IO效率肯定会很差，PHP手册上建议使用<a href="http://zh.wikipedia.org/wiki/ReiserFS" target="_blank">Reiserfs</a>文件系统，不过Reiserfs的前景堪忧，Reiserfs的作者把媳妇给杀了，SuSE也抛弃了Reiserfs。</p>
<p>其实还有很多中存储session的方式，可以通过php -i|grep &#8220;Registered save handlers&#8221;查看，比如Registered save handlers =&gt; files user sqlite eaccelerator可以通过文件、用户、sqlite、eaccelerator来存，如果服务器装了memcached，还有会mmcache的选项。当然还有很多，比如MySQL、PostgreSQL等等。都是不错的选择。</p>
<p>四、session的同步</p>
<p>我们前端可能有很多台服务器，用户在A服务器上登录了，种下了session信息，然后访问网站的某些页面没准跳到B服务器上去了，如果这个时候B服务器上没有session信息又没有做特殊处理，可能就会出问题了。</p>
<p>session同步有很多种，如果你是存储在memcached或者MySQL中，那就很容易了，指定到同样的位置即可，如果是文件形式的，你可以用<a href="http://nio.infor96.com/sharing-php-session-data-between-servers" target="_blank">NFS统一存储</a>。</p>
<p>还有一种方式是通过加密的cookie来实现，用户在A服务器上登录成功，在用户的浏览器上种上一个加密的cookie，当用户访问B服务器时，检查有无session，如果有当然没问题，如果没有，就去检验cookie是否有效，cookie有效的话就在B服务器上重建session。这种方法其实很有用，如果网站有很多个子频道，服务器也不在一个机房，session没办法同步又想做统一登录那就太有用了。</p>
<p>当然还有一种方法就是在负载均衡那一层保持会话，把访问者帮定在某个服务器上，他的所有访问都在那个服务器上就不需要session同步了，这些都是运维层面的东西。</p>
<p>就说这么多吧，根据自己的应用来选择使用session，不要因为大家都说session影响系统性能就畏首畏尾，知道问题，解决问题才是关键，惹不起躲得起不适合这里。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fuchaoqun.com/2009/02/php-session-confuse/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->