<?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>Leakon &#187; Web开发</title>
	<atom:link href="http://www.leakon.com/archives/category/webdevelop/feed" rel="self" type="application/rss+xml" />
	<link>http://www.leakon.com</link>
	<description>勤奋 - 创新 - 矢志不渝 - 锲而不舍</description>
	<lastBuildDate>Sat, 24 Jul 2010 14:50:31 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Raw POST Data PHP 获取 HTTP 原始 body 部分的数据</title>
		<link>http://www.leakon.com/archives/437</link>
		<comments>http://www.leakon.com/archives/437#comments</comments>
		<pubDate>Tue, 16 Jun 2009 04:59:48 +0000</pubDate>
		<dc:creator>leakon</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[POST]]></category>
		<category><![CDATA[Raw]]></category>

		<guid isPermaLink="false">http://www.leakon.com/?p=437</guid>
		<description><![CDATA[通常做网站开发时，POST 数据都是从页面 form 表单中提交到服务器，POST Data 都是 key_1=value_1&#38;key_2=value_2 这样的形式。这样的字符串，PHP 会自动解析到 $_POST 数组中。
有另外一种应用场景，在开发基于 HTTP 协议的接口时，客户端把一段 XML 文本直接作为 POST Data 提交到服务器，这时 $_POST 是空数组。大家可以试试，用 Curl 实现 POST 请求，BODY 字段直接写上一段文本。
通过 WireShark Network Analyzer 这样的软件抓包，可以看到 HTTP 的 Header 之后，有 0d 0a 0d 0a 共 4 个字符，也就是 \r\n\r\n，代表 2 个 Windows 平台的换行符。这是 HTTP Header 与 Body 之间的分割标志。在这之后，Body 的内容可以提交给服务器，但 $_POST 变量为空。
发现问题后立刻头大，这可怎麽办啊！！
在 Google 用 'php post [...]]]></description>
			<content:encoded><![CDATA[<p>通常做网站开发时，POST 数据都是从页面 form 表单中提交到服务器，POST Data 都是 key_1=value_1&amp;key_2=value_2 这样的形式。这样的字符串，PHP 会自动解析到 $_POST 数组中。</p>
<p>有另外一种应用场景，在开发基于 HTTP 协议的接口时，客户端把一段 XML 文本直接作为 POST Data 提交到服务器，这时 $_POST 是空数组。大家可以试试，用 Curl 实现 POST 请求，BODY 字段直接写上一段文本。</p>
<p>通过 WireShark Network Analyzer 这样的软件抓包，可以看到 HTTP 的 Header 之后，有 0d 0a 0d 0a 共 4 个字符，也就是 \r\n\r\n，代表 2 个 Windows 平台的换行符。这是 HTTP Header 与 Body 之间的分割标志。在这之后，Body 的内容可以提交给服务器，但 $_POST 变量为空。</p>
<p>发现问题后立刻头大，这可怎麽办啊！！</p>
<p>在 Google 用 'php post raw' 这个关键词搜了一下，立刻找到答案，原来解决方法是如此的简单：</p>
<p>$strRawData<span> </span>= file_get_contents("php://input");</p>
<p>php://input 是一个资源标识，用 file_get_contents 从这个资源中获取的内容，就是原始的 Raw POST Data。</p>
<p>记录一下，留作日后备查。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leakon.com/archives/437/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>FCKeditor 2.6 安装 配置 问题 图片上传</title>
		<link>http://www.leakon.com/archives/410</link>
		<comments>http://www.leakon.com/archives/410#comments</comments>
		<pubDate>Wed, 08 Apr 2009 17:55:49 +0000</pubDate>
		<dc:creator>leakon</dc:creator>
				<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Web开发]]></category>
		<category><![CDATA[FCKEditor]]></category>

		<guid isPermaLink="false">http://www.leakon.com/?p=410</guid>
		<description><![CDATA[今天给使用 Symfony 的项目装了 FCKeditor 编辑器，配了图片上传。
遇到一些问题，总结下。
安装时，为了简单，最好把解压的 fckeditor 文件夹放在 web/ 目录下。
在模板中加入编辑器很简单：
 $webDir = sfConfig::get('sf_web_dir'); // DocumentRoot 的服务端路径
$editorInclude = $webDir . "fckeditor/fckeditor.php";
require_once($editorInclude);
$oFCKeditor = new FCKeditor('detail') ; // form 表单字段名称是 detail
$oFCKeditor-&#62;BasePath = '/fckeditor/' ; // 客户端访问编辑器资源文件的路径
$oFCKeditor-&#62;Width = '100%'; // 宽
$oFCKeditor-&#62;Height = '100%'; // 高
$oFCKeditor-&#62;Value = $articleItem-&#62;detail; // $articleItem 是 ORM 对象，直接引用 detail 字段
$oFCKeditor-&#62;Config = array(
        'AutoDetectLanguage' =&#62; false, // 关闭浏览器语言自动检测
     [...]]]></description>
			<content:encoded><![CDATA[<p>今天给使用 Symfony 的项目装了 FCKeditor 编辑器，配了图片上传。</p>
<p>遇到一些问题，总结下。</p>
<p>安装时，为了简单，最好把解压的 fckeditor 文件夹放在 web/ 目录下。</p>
<p>在模板中加入编辑器很简单：</p>
<p><span> </span>$webDir<span> </span>= sfConfig::get('sf_web_dir'); // DocumentRoot 的服务端路径<br />
$editorInclude<span> </span>= $webDir . "fckeditor/fckeditor.php";<br />
require_once($editorInclude);</p>
<p>$oFCKeditor<span> </span>= new FCKeditor('detail') ; // form 表单字段名称是 detail<br />
$oFCKeditor-&gt;BasePath<span> </span>= '/fckeditor/' ; // 客户端访问编辑器资源文件的路径<br />
$oFCKeditor-&gt;Width<span> </span>= '100%'; // 宽<br />
$oFCKeditor-&gt;Height<span> </span>= '100%'; // 高<br />
$oFCKeditor-&gt;Value<span> </span>= $articleItem-&gt;detail; // $articleItem 是 ORM 对象，直接引用 detail 字段<br />
$oFCKeditor-&gt;Config<span> </span>= array(<br />
        'AutoDetectLanguage'<span> </span>=&gt; false, // 关闭浏览器语言自动检测<br />
        'DefaultLanguage'<span> </span>=&gt; 'zh-cn' // 设置简体中文<br />
);<br />
$oFCKeditor-&gt;Create() ;</p>
<p>设置完了，刷新页面，直接可用！很简单。</p>
<p>已经检查的问题，可以很好地处理 XSS 问题，在编辑器里填写 &lt;script&gt;alert(123)&lt;/script&gt; 这样的字符串，都会转义成纯字符，不会被浏览器解析为 HTML 代码。这在编辑器和最终页面都可以正常显示，需要注意的是输出的时候都要加 htmlspecialchars 转义，这是必须养成的习惯！</p>
<p>图片上传的问题。</p>
<p>默认是关闭的，修改 fckeditor/editor/filemanager/connectors/php/config.php 为：</p>
<p>$Config['Enabled'] = true;</p>
<p>$Config['UserFilesPath'] = '/uploads/'; // 这是 Symfony 自动生成的目录。</p>
<p>现在可以上传了，不过会遇到 2 个问题。</p>
<p>问题 1：点击“发送到服务器上”按钮，浏览器 alert 一个错误，显示“Error creating folder "redirect:/index.php" (Can't create redirect: directory)”。参考了“<a rel="bookmark" href="http://www.foolbirds.com/symfony-fckeditory-and-upload-image.html">在symfony中使用FCKeditor上传图片附件</a>” 这篇文章，得到了很好的解决。是 .htaccess 造成的。最简单的办法是在 uploads 目录下再放置一个 .htaccess，关闭 rewrite 即可，内容如下：</p>
<p>Options +FollowSymLinks +ExecCGI<br />
&lt;IfModule mod_rewrite.c&gt;<br />
  RewriteEngine Off<br />
&lt;/IfModule&gt;</p>
<p>问题 2：上传文件后修改文件名。fckeditor 默认是保留原有文件名。英文名的文件还勉强能用，如果是中文文件名就麻烦了。最好是统一按照自己的命名规则修改文件名。这时编辑 fckeditor/editor/filemanager/connectors/php/io.php，修改一个函数：</p>
<p>function SanitizeFileName( $sNewFileName ) {<br />
  $arr<span> </span>= explode('.', $sNewFileName);<br />
  $ext<span> </span>= array_pop($arr);<br />
  $filename<span> </span>= date('Ymd_His_') . rand(1000, 9999) . '.' . $ext;<br />
  return<span> </span>$filename;<br />
} </p>
<p>把原函数改名作为备份。这函数就是保留了扩展名，把主文件名按照日期编码。呃，为了更好地保存文件，其实还应该把扩展名统一大小写，我记得有一个 pathinfo 函数，返回值有一个 extension 字段就是扩展名。其实过程都差不多，您自选吧。</p>
<p>总的说来，fckeditor 给我的感觉是安装简单，功能强大，代码逻辑清晰，便于修改。</p>
<p>赞一个~~</p>
<p>另：推荐一个 Blog</p>
<p><a href="http://www.foolbirds.com/">4’s symfony blog</a></p>
<p>这兄弟很深入地了解 Symfony 框架，我已订阅了他的 RSS，每天学习中……</p>
<p>睡了，晚安……</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leakon.com/archives/410/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apache ReWrite QUERY_STRING 问号 ?</title>
		<link>http://www.leakon.com/archives/404</link>
		<comments>http://www.leakon.com/archives/404#comments</comments>
		<pubDate>Fri, 27 Mar 2009 22:10:03 +0000</pubDate>
		<dc:creator>leakon</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[Apache]]></category>

		<guid isPermaLink="false">http://www.leakon.com/?p=404</guid>
		<description><![CDATA[



看一条应用中简单的 rewrite 规则：
将请求：
http://www.leakon.com/soft/install?ver=2.0
rewrite 为：
http://www. leakon.com/my/soft/install.php
配置文件 httpd.conf 加上如下配置：

RewriteCond %{QUERY_STRING} ^ver\=([0-9]+\.[0-9]+)?$ [NC]
RewriteRule ^/soft/install$ http://www. leakon.com/my/soft/install.php?[L]

请注意配置中的两个问号。
请求时，从 QUERY_STRING 取得 url 的查询字符串，这里只获取了 ver 的值，而且限定是带浮点的数字，ver 之后的查询字符都被忽略。实际上是用到 ? 来终结。
官方文档解释为：
注意：查询字符串
Pattern 不会按照查询字符串进行匹配。为了达到这个目的，你必须使用一个带有 %{QUERY_STRING} 变量的 RewriteCond 指令。
当 然，你也可以在替换字符串中创建包含查询字符串的 url：在替换字符串中使用问号，以标明其后的部分应该被重新注入到QUERY_STRING中。
而要删除一个已有的请求串，则可以用问号来终结替换字符串。为了联合新旧查询字符串，请使用[QSA]标志。



]]></description>
			<content:encoded><![CDATA[<div class="entry-body">
<div>
<div class="item-body">
<div>
<p>看一条应用中简单的 rewrite 规则：<br />
将请求：<br />
http://www.leakon.com/soft/install?ver=2.0<br />
rewrite 为：<br />
http://www. leakon.com/my/soft/install.php</p>
<p>配置文件 httpd.conf 加上如下配置：</p>
<div>
<div><span style="color: #ff0000;">RewriteCond</span><span style="color: #ff0000;"> %</span><span style="color: #ff0000;">{</span><span style="color: #ff0000;">QUERY_STRING</span><span style="color: #ff0000;">}</span><span style="color: #ff0000;"> ^</span><span style="color: #ff0000;">ver</span><span style="color: #ff0000;">\=</span><span style="color: #ff0000;">([</span><span style="color: #ff0000;">0</span><span style="color: #ff0000;">-</span><span style="color: #ff0000;">9</span><span style="color: #ff0000;">]</span><span style="color: #ff0000;">+\.</span><span style="color: #ff0000;">[</span><span style="color: #ff0000;">0</span><span style="color: #ff0000;">-</span><span style="color: #ff0000;">9</span><span style="color: #ff0000;">]</span><span style="color: #ff0000;">+</span><span style="color: #ff0000;">)</span><span style="color: #ff0000;">?$ </span><span style="color: #ff0000;">[</span><span style="color: #ff0000;">NC</span><span style="color: #ff0000;">]</span><span style="color: #ff0000;"><br />
</span><span style="color: #ff0000;">RewriteRule</span><span style="color: #ff0000;"> ^/</span><span style="color: #ff0000;">soft</span><span style="color: #ff0000;">/</span><span style="color: #ff0000;">install</span><span style="color: #ff0000;">$ </span><span style="color: #ff0000;">http</span><span style="color: #ff0000;">:</span><span style="color: #ff0000;">//www. leakon.com/my/soft/install.php?[L]</span></div>
</div>
<p>请注意配置中的两个问号。</p>
<p>请求时，从 QUERY_STRING 取得 url 的查询字符串，这里只获取了 ver 的值，而且限定是带浮点的数字，ver 之后的查询字符都被忽略。实际上是用到 ? 来终结。</p>
<p>官方文档解释为：<br />
注意：查询字符串<br />
Pattern 不会按照查询字符串进行匹配。为了达到这个目的，你必须使用一个带有 %{QUERY_STRING} 变量的 RewriteCond 指令。</p>
<p>当 然，你也可以在替换字符串中创建包含查询字符串的 url：在替换字符串中使用问号，以标明其后的部分应该被重新注入到QUERY_STRING中。</p>
<p>而要删除一个已有的请求串，则可以用问号来终结替换字符串。为了联合新旧查询字符串，请使用[QSA]标志。</p></div>
</div>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.leakon.com/archives/404/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>链接 样式 定义 顺序 link visited hover active</title>
		<link>http://www.leakon.com/archives/370</link>
		<comments>http://www.leakon.com/archives/370#comments</comments>
		<pubDate>Tue, 10 Feb 2009 22:10:12 +0000</pubDate>
		<dc:creator>leakon</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[link]]></category>

		<guid isPermaLink="false">http://www.leakon.com/?p=370</guid>
		<description><![CDATA[这是我 3 年前遇到的问题了，当时解决过，后来记不太清楚，今天又复习了一遍。
给 A 标签定义样式，有四种状态：

link 没被点过的链接
visited 点过的
hover 鼠标悬停在链接上
active 鼠标点击按键后 至 松开按键前这段时间

当年不懂，在 IE 这个死浏览器上怎么都不能设置正确，后来百度搜了一下，意识到定义的顺序很关键，马上实践，果然灵验。
为了记这个顺序，我还给他起了个顺口溜呢，“路哈”。
v 字母可以看做是 u，那么发音就顺畅了：l - v - h - a。
读成 l - u - h - a，就是“路哈”的音。
仅供参考和回忆……
]]></description>
			<content:encoded><![CDATA[<p>这是我 3 年前遇到的问题了，当时解决过，后来记不太清楚，今天又复习了一遍。</p>
<p>给 A 标签定义样式，有四种状态：</p>
<ul>
<li>link 没被点过的链接</li>
<li>visited 点过的</li>
<li>hover 鼠标悬停在链接上</li>
<li>active 鼠标点击按键后 至 松开按键前这段时间</li>
</ul>
<p>当年不懂，在 IE 这个死浏览器上怎么都不能设置正确，后来百度搜了一下，意识到定义的顺序很关键，马上实践，果然灵验。</p>
<p>为了记这个顺序，我还给他起了个顺口溜呢，“路哈”。</p>
<p>v 字母可以看做是 u，那么发音就顺畅了：l - v - h - a。</p>
<p>读成 l - u - h - a，就是“路哈”的音。</p>
<p>仅供参考和回忆……</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leakon.com/archives/370/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Web 前端开发 Firefox 扩展</title>
		<link>http://www.leakon.com/archives/353</link>
		<comments>http://www.leakon.com/archives/353#comments</comments>
		<pubDate>Sat, 24 Jan 2009 14:45:09 +0000</pubDate>
		<dc:creator>leakon</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[Firefox]]></category>

		<guid isPermaLink="false">http://www.leakon.com/?p=353</guid>
		<description><![CDATA[我在搞 Web 前端开发时用 Firefox 浏览器，有几个必备的扩展，非常好用，今天整理一下，给大家分享，也给自己列个清单备忘。

Firebug 不用说了，必备
YSlow 网站性能优化建议
Web Developer 必备
Tamper Data 这个需要重点介绍，当你也要做服务端开发时，客户端和服务器交互的 http 头部和 body 到底是什么样，都能准确地列出来，这曾经帮我发现并解决过重要的问题，强烈推荐。
MeasureIt 可以测量 html 元素的尺寸
DNS Flusher 更改 hosts 时，不必关闭 Firefox 即可访问新生效的服务器
View Source Chart 查看浏览器生成的 DOM 树，虽然 Firebug 可以完成 DOM 树的浏览和更改，但这个扩展可以用不同的颜色缩进代码，更直观，不过可惜的是暂时不支持 Firefox 3.0 以上的版本
Rainbow for Firebug 0.7 Javascript 语法高亮，用于 Firebug 1.2
FireGestures 1.1.6 鼠标动作，这个不能算是开发工具，不过我习惯了向左滑动一下鼠标代表“后退”动作

其他的工具也有好多，大家去 https://addons.mozilla.org/en-US/firefox/ 挖掘吧~~
]]></description>
			<content:encoded><![CDATA[<p>我在搞 Web 前端开发时用 Firefox 浏览器，有几个必备的扩展，非常好用，今天整理一下，给大家分享，也给自己列个清单备忘。</p>
<ul>
<li><a title="Firebug" href="https://addons.mozilla.org/en-US/firefox/addon/1843">Firebug</a> 不用说了，必备</li>
<li><a title="YSlow" href="https://addons.mozilla.org/en-US/firefox/addon/5369">YSlow</a> 网站性能优化建议</li>
<li><a title="Web Developer" href="https://addons.mozilla.org/en-US/firefox/addon/60">Web Developer</a> 必备</li>
<li><a title="Tamper Data" href="https://addons.mozilla.org/en-US/firefox/addon/966">Tamper Data</a> 这个需要重点介绍，当你也要做服务端开发时，客户端和服务器交互的 http 头部和 body 到底是什么样，都能准确地列出来，这曾经帮我发现并解决过重要的问题，强烈推荐。</li>
<li><a title="MeasureIt" href="https://addons.mozilla.org/en-US/firefox/addon/539">MeasureIt</a> 可以测量 html 元素的尺寸</li>
<li><a title="DNS Flusher" href="https://addons.mozilla.org/en-US/firefox/addon/7408">DNS Flusher</a> 更改 hosts 时，不必关闭 Firefox 即可访问新生效的服务器</li>
<li><a title="View Source Chart" href="https://addons.mozilla.org/en-US/firefox/addon/655">View Source Chart</a> 查看浏览器生成的 DOM 树，虽然 Firebug 可以完成 DOM 树的浏览和更改，但这个扩展可以用不同的颜色缩进代码，更直观，不过可惜的是暂时不支持 Firefox 3.0 以上的版本</li>
<li><a title="Rainbow for Firebug 0.7" href="https://addons.mozilla.org/en-US/firefox/addon/7575">Rainbow for Firebug</a> 0.7 Javascript 语法高亮，用于 Firebug 1.2</li>
<li><a title="FireGestures 1.1.6" href="https://addons.mozilla.org/en-US/firefox/addon/6366">FireGestures 1.1.6</a> 鼠标动作，这个不能算是开发工具，不过我习惯了向左滑动一下鼠标代表“后退”动作</li>
</ul>
<p>其他的工具也有好多，大家去 <a title="Firefox Addons" href="https://addons.mozilla.org/en-US/firefox/">https://addons.mozilla.org/en-US/firefox/</a> 挖掘吧~~</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leakon.com/archives/353/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>http header Expires not modified 304</title>
		<link>http://www.leakon.com/archives/343</link>
		<comments>http://www.leakon.com/archives/343#comments</comments>
		<pubDate>Tue, 20 Jan 2009 04:55:12 +0000</pubDate>
		<dc:creator>leakon</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Cache]]></category>

		<guid isPermaLink="false">http://www.leakon.com/?p=343</guid>
		<description><![CDATA[困扰了我好久，看了 YSlow 的文档，也看了好多网站优化的书，按照书上的说法，加了 expires 和 cache-control 头，静态文件被缓存后，浏览器就不会再次发送请求了。
可是我看 apache 日志，仍然是有请求发到服务器，apache 发送 304 响应头。虽然起到了缓存的作用，但我希望是完全的客户端缓存，也就是说浏览器根本不会向服务器发请求询问。
今天又 google 了下，恍然大悟，原来是浏览器加载页面的策略不同：按刷新按钮与在地址栏输入网址按回车分别代表不同的动作。
地址栏输入，浏览器会优先使用缓存，如果图片文件缓存时设置了 expires ，那么在有效期内，浏览器不向服务端发任何请求，这样速度最快。
按刷新按钮，尽管本地有缓存，浏览器也会向服务器发一个询问请求，如果服务器端文件没有改变，则会返回一个 304 的相应头，告诉浏览器可以使用本地缓存，否则就返回新的文件。
这就解释了我之前遇到的问题。我配置了 Apache 后，每次按 F5 刷新页面，同时观察日志，总是有浏览器请求，总是返回 304 响应。
今天我又试了下，每次都在地址栏按回车，这回只有 html 的请求，图片都使用了本地的缓存。
土了一把……
ExpiresActive On
ExpiresDefault "access plus 1 month"
]]></description>
			<content:encoded><![CDATA[<p>困扰了我好久，看了 YSlow 的文档，也看了好多网站优化的书，按照书上的说法，加了 expires 和 cache-control 头，静态文件被缓存后，浏览器就不会再次发送请求了。</p>
<p>可是我看 apache 日志，仍然是有请求发到服务器，apache 发送 304 响应头。虽然起到了缓存的作用，但我希望是完全的客户端缓存，也就是说浏览器根本不会向服务器发请求询问。</p>
<p>今天又 google 了下，恍然大悟，原来是浏览器加载页面的策略不同：按刷新按钮与在地址栏输入网址按回车分别代表不同的动作。</p>
<p>地址栏输入，浏览器会优先使用缓存，如果图片文件缓存时设置了 expires ，那么在有效期内，浏览器不向服务端发任何请求，这样速度最快。</p>
<p>按刷新按钮，尽管本地有缓存，浏览器也会向服务器发一个询问请求，如果服务器端文件没有改变，则会返回一个 304 的相应头，告诉浏览器可以使用本地缓存，否则就返回新的文件。</p>
<p>这就解释了我之前遇到的问题。我配置了 Apache 后，每次按 F5 刷新页面，同时观察日志，总是有浏览器请求，总是返回 304 响应。</p>
<p>今天我又试了下，每次都在地址栏按回车，这回只有 html 的请求，图片都使用了本地的缓存。</p>
<p>土了一把……</p>
<p>ExpiresActive On</p>
<p>ExpiresDefault "access plus 1 month"</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leakon.com/archives/343/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SofavDB_Debug_PDO MySQL 执行时间 日志</title>
		<link>http://www.leakon.com/archives/340</link>
		<comments>http://www.leakon.com/archives/340#comments</comments>
		<pubDate>Thu, 08 Jan 2009 18:58:54 +0000</pubDate>
		<dc:creator>leakon</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web开发]]></category>
		<category><![CDATA[原创]]></category>
		<category><![CDATA[PDO]]></category>

		<guid isPermaLink="false">http://www.leakon.com/?p=340</guid>
		<description><![CDATA[这个类可以完全替代 PDO，如果你需要知道自己的程序跟 MySQL 交互花费多少时间，而你又有洁癖，不想把自己的代码搞得一团糟，那我强烈地建议你试试这个 SofavDB_Debug_PDO。
通常，创建一个 PDO 连接，都是 new PDO()。
在开发环境中，你只需要把上面那个语句替换成 new SofavDB_Debug_PDO() 即可。
然后，凡是通过 prepare 的 statement 执行的任何查询和修改的语句，执行时间都能记录下来。
最后，通过 SofavDB_Debug_PDO::getTimer() 就可以得到一个数组，极其方便……
当然，这个类的执行效率会有一些小小的下降，不适合用于生产环境。
源码请见 GoogleCode：
http://leakon.googlecode.com/svn/trunk/leakon/php/sofav_db/SofavDB_Debug_PDO.php
]]></description>
			<content:encoded><![CDATA[<p>这个类可以完全替代 PDO，如果你需要知道自己的程序跟 MySQL 交互花费多少时间，而你又有洁癖，不想把自己的代码搞得一团糟，那我强烈地建议你试试这个 SofavDB_Debug_PDO。</p>
<p>通常，创建一个 PDO 连接，都是 new PDO()。</p>
<p>在开发环境中，你只需要把上面那个语句替换成 new SofavDB_Debug_PDO() 即可。</p>
<p>然后，凡是通过 prepare 的 statement 执行的任何查询和修改的语句，执行时间都能记录下来。</p>
<p>最后，通过 SofavDB_Debug_PDO::getTimer() 就可以得到一个数组，极其方便……</p>
<p>当然，这个类的执行效率会有一些小小的下降，不适合用于生产环境。</p>
<p>源码请见 GoogleCode：</p>
<p><a title="SofavDB Debug PDO" href="http://leakon.googlecode.com/svn/trunk/leakon/php/sofav_db/SofavDB_Debug_PDO.php">http://leakon.googlecode.com/svn/trunk/leakon/php/sofav_db/SofavDB_Debug_PDO.php</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.leakon.com/archives/340/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL 索引 优化 Using filesort</title>
		<link>http://www.leakon.com/archives/332</link>
		<comments>http://www.leakon.com/archives/332#comments</comments>
		<pubDate>Tue, 06 Jan 2009 16:07:53 +0000</pubDate>
		<dc:creator>leakon</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Web开发]]></category>
		<category><![CDATA[原创]]></category>

		<guid isPermaLink="false">http://www.leakon.com/?p=332</guid>
		<description><![CDATA[MySQL 数据库，MyISAM 类型的表 table_item，有 5、6 个字段，主键是 id。
user_id 和 item_id 两个字段都是单独的 INDEX 类型的索引。
问题是如何发现的？
今天搞程序，在自己的开发环境下，打开一个简单的页面都要好长时间，不知道问题出在哪里，只发现硬盘灯闪个不停。
观察 Windows 的任务管理器，看到 mysqld-nt.exe 这个进程的 "I/O 读取字节" 高达十几 G！！！
再次测试，发现每次刷新页面，这个进程要读取几十 M 的数据。
奇了怪了，查看 SQL 语句，还有表结构，字段都建了索引了呀。
后来 EXPLAIN 了一下，看到结果是 Using where; Using filesort。
explain SELECT * FROM table_item WHERE user_id = 2 ORDER BY item_id LIMIT 0, 5
翻了 MySQL 手册，仔细看下 filesort 的说明，知道了 Using filesort 是一种速度很慢的外部排序。
不过我不理解为什么会使用 filesort 排序，WHERE 和 ORDER BY 用到的字段都是有索引的呀。
赶紧 Google，找到几篇解释 Using filesort [...]]]></description>
			<content:encoded><![CDATA[<p>MySQL 数据库，MyISAM 类型的表 table_item，有 5、6 个字段，主键是 id。</p>
<p>user_id 和 item_id 两个字段都是单独的 INDEX 类型的索引。</p>
<p>问题是如何发现的？</p>
<p>今天搞程序，在自己的开发环境下，打开一个简单的页面都要好长时间，不知道问题出在哪里，只发现硬盘灯闪个不停。</p>
<p>观察 Windows 的任务管理器，看到 mysqld-nt.exe 这个进程的 "I/O 读取字节" 高达十几 G！！！</p>
<p>再次测试，发现每次刷新页面，这个进程要读取几十 M 的数据。</p>
<p>奇了怪了，查看 SQL 语句，还有表结构，字段都建了索引了呀。</p>
<p>后来 EXPLAIN 了一下，看到结果是 Using where; Using filesort。</p>
<p>explain SELECT * FROM table_item WHERE user_id = 2 ORDER BY item_id LIMIT 0, 5</p>
<p>翻了 MySQL 手册，仔细看下 filesort 的说明，知道了 Using filesort 是一种速度很慢的外部排序。</p>
<p>不过我不理解为什么会使用 filesort 排序，WHERE 和 ORDER BY 用到的字段都是有索引的呀。</p>
<p>赶紧 Google，找到几篇解释 Using filesort 的文章，得到的启示就是索引定义不当，MySQL 没有用到索引。</p>
<p>记得以前 Chenbin 给俺们培训过 MySQL 的优化，我还参加了两次，总感觉自己了解了如何优化 MySQL，没想到这么简单的语句我都没能优化。</p>
<p>现在想起来一些 MySQL 的特性了。</p>
<ol>
<li>一条 SQL 语句只能使用 1 个索引 (5.0-)，MySQL 根据表的状态，选择一个它认为最好的索引用于优化查询</li>
<li>联合索引，只能按从左到右的顺序依次使用</li>
</ol>
<p>这 2 点刚好可以解决我的问题。</p>
<p>user_id 和 item_id 是 2 个索引，我的语句中，MySQL 选择了 user_id，那么 item_id 的索引没有起到任何用处，所以，当我要排序的时候，由于记录数较多，内存中的排序 buffer 满了，只能 Using filesort 进行外部排序，因此每次查询要从磁盘读取几十 M 的数据，太慢了。</p>
<p>修改表结构，删除 user_id 和 item_id 的 INDEX 索引，建立一个名为 user_item 的联合 UNIQUE 索引，顺序是先 user_id 后 item_id，再 EXPLAIN，这回只有 Using where 了。</p>
<p>再刷新页面，观察任务管理器，mysqld-nt.exe 只读取了 2K 的数据，页面咔的一下就出来了……</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leakon.com/archives/332/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Javascript 字符串 数字 浏览器 性能差别</title>
		<link>http://www.leakon.com/archives/230</link>
		<comments>http://www.leakon.com/archives/230#comments</comments>
		<pubDate>Thu, 30 Oct 2008 03:29:42 +0000</pubDate>
		<dc:creator>leakon</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[原创]]></category>
		<category><![CDATA[默认分类]]></category>
		<category><![CDATA[Chrome]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.leakon.com/?p=230</guid>
		<description><![CDATA[我在做一个 Javascript 版的公历农历转换程序，功能完成后，需要对性能做优化。计算算法是在网上找的，原作者对历法的转换很精通，但对程序性能没有仔细考虑，当计算量大的时候，会给用户的浏览器造成很大压力，给用户的感觉就好像浏览器假死一样。
我花了2天时间在性能优化上，并在不同的浏览器下做对比测试，发现一个比较重要的差别，IE、Firefox 和 Chrome 之间的区别很大。
通常，生成一个月的日历，最多需要计算42天（可参考Google Calendar，每行代表一周7天，最多可能有6行）。
性能测试的时候，我让程序连续计算3年，共36个月，1000多天。
总的运行时间是：
IE7: 2.828 s
Safari3: 1.016 s
Firefox3: 0.885 s 
Opera9: 0.765 s
Chrome: 0.281 s
这下终于见识了 Chrome 采用的 Javascript V8 引擎的强大实力！ 
以上统计结果都是测试3次取结果平均值。
程序运行到这个时间量级，已经是我优化过了的，最开始的程序，完成2年的计算，也就是上述运算量的三分之二，Firefox3用了8秒左右，Chrome很棒，用了2秒，而IE，30秒过后，浏览器直接问我是否要强制停止脚本运行，实际上我还从来没有在IE上成功执行过！
关于浏览器性能的差别，你可以用IE和Chrome打开淘宝的同一个比较复杂的页面，感受一下拖拉机与飞机的区别。
上面是浏览器的差别，下面我再给一些 Javascript 程序上的差别。
我的农历转换算法，有一个关键函数，需要多次调用，这个正是性能的瓶颈所在。
观察了调用方式和次数，这个函数运行了33000多次，而总共参数的变化只有1000次左右，如果加入缓存，可以减少97%的运算量！！！
我采用hash表的方式对每个输入的key做缓存，由于函数的参数是年月日，共3个，所以需要把这3个参数拼接成一个key。
最开始，我用字符串拼接，y m d 之间用 "_" 下划线连接起来，但仅仅是一个这样的字符串操作，程序运行时间就从0.8秒增加到1.1秒，增加了将近40%的时间！！
这是不能接受的，这将使我的缓存优化方式变得毫无意义。
农历算法的大部分关键代码，都是数字上的计算，代码很多，但好像没有产生性能瓶颈，这给了我启发。
我改用数字索引，把 y m d 用加法和乘法算出类似于 20081026 这样的整数，这样运行时间从0.789 s增加到0.853 s，只有不到10%的增加。
我的缓存，只能把运行时间降低20%到30%，所以用整数索引，可以达到优化的目的。
http://leakon.googlecode.com/svn/trunk/leakon/javascript/wannianli/nice/
很愿意与大家一起分享，一起分析，一起应用~~
原创文章，请尊重我对互联网的贡献，谢谢！
]]></description>
			<content:encoded><![CDATA[<p>我在做一个 Javascript 版的公历农历转换程序，功能完成后，需要对性能做优化。计算算法是在网上找的，原作者对历法的转换很精通，但对程序性能没有仔细考虑，当计算量大的时候，会给用户的浏览器造成很大压力，给用户的感觉就好像浏览器假死一样。</p>
<p>我花了2天时间在性能优化上，并在不同的浏览器下做对比测试，发现一个比较重要的差别，IE、Firefox 和 Chrome 之间的区别很大。</p>
<p>通常，生成一个月的日历，最多需要计算42天（可参考Google Calendar，每行代表一周7天，最多可能有6行）。</p>
<p>性能测试的时候，我让程序连续计算3年，共36个月，1000多天。</p>
<p>总的运行时间是：</p>
<p>IE7: 2.828 s<br />
Safari3: 1.016 s<br />
Firefox3: 0.885 s <br />
Opera9: 0.765 s<br />
Chrome: 0.281 s</p>
<p>这下终于见识了 Chrome 采用的 Javascript V8 引擎的强大实力！ </p>
<p>以上统计结果都是测试3次取结果平均值。</p>
<p>程序运行到这个时间量级，已经是我优化过了的，最开始的程序，完成2年的计算，也就是上述运算量的三分之二，Firefox3用了8秒左右，Chrome很棒，用了2秒，而IE，30秒过后，浏览器直接问我是否要强制停止脚本运行，实际上我还从来没有在IE上成功执行过！</p>
<p>关于浏览器性能的差别，你可以用IE和Chrome打开淘宝的同一个比较复杂的页面，感受一下拖拉机与飞机的区别。</p>
<p>上面是浏览器的差别，下面我再给一些 Javascript 程序上的差别。</p>
<p>我的农历转换算法，有一个关键函数，需要多次调用，这个正是性能的瓶颈所在。</p>
<p>观察了调用方式和次数，这个函数运行了33000多次，而总共参数的变化只有1000次左右，如果加入缓存，可以减少97%的运算量！！！</p>
<p>我采用hash表的方式对每个输入的key做缓存，由于函数的参数是年月日，共3个，所以需要把这3个参数拼接成一个key。</p>
<p>最开始，我用字符串拼接，y m d 之间用 "_" 下划线连接起来，但仅仅是一个这样的字符串操作，程序运行时间就从0.8秒增加到1.1秒，增加了将近40%的时间！！</p>
<p>这是不能接受的，这将使我的缓存优化方式变得毫无意义。</p>
<p>农历算法的大部分关键代码，都是数字上的计算，代码很多，但好像没有产生性能瓶颈，这给了我启发。</p>
<p>我改用数字索引，把 y m d 用加法和乘法算出类似于 20081026 这样的整数，这样运行时间从0.789 s增加到0.853 s，只有不到10%的增加。</p>
<p>我的缓存，只能把运行时间降低20%到30%，所以用整数索引，可以达到优化的目的。</p>
<p><a title="Calendar" href="http://leakon.googlecode.com/svn/trunk/leakon/javascript/wannianli/nice/" target="_blank">http://leakon.googlecode.com/svn/trunk/leakon/javascript/wannianli/nice/</a></p>
<p>很愿意与大家一起分享，一起分析，一起应用~~</p>
<p>原创文章，请尊重我对互联网的贡献，谢谢！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leakon.com/archives/230/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>关注 Sphinx, Ratproxy</title>
		<link>http://www.leakon.com/archives/162</link>
		<comments>http://www.leakon.com/archives/162#comments</comments>
		<pubDate>Mon, 21 Jul 2008 14:01:06 +0000</pubDate>
		<dc:creator>leakon</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[MyConcerned]]></category>

		<guid isPermaLink="false">http://www.leakon.com/?p=162</guid>
		<description><![CDATA[今天听到 2 个新名词，看看都挺感兴趣的，不过工作太忙，没时间仔细看，记下来，回家看~~
一句话概括：

Sphinx 是一个基于 SQL 的全文检索引擎，可以结合 MySQL, PostgreSQL 做全文搜索，它可以提供比数据库本身更专业的搜索功能，使得应用程序更容易实现专业化的全文检索。


Ratproxy: Google 的 XSS 检测工具

http://www.sphinxsearch.com/
http://www.dbanotes.net/security/ratproxy_google_xss.html
上个图图吧，挺 PP 的：

]]></description>
			<content:encoded><![CDATA[<p>今天听到 2 个新名词，看看都挺感兴趣的，不过工作太忙，没时间仔细看，记下来，回家看~~</p>
<p>一句话概括：</p>
<ul>
<li>Sphinx 是一个基于 SQL 的全文检索引擎，可以结合 MySQL, PostgreSQL 做全文搜索，它可以提供比数据库本身更专业的搜索功能，使得应用程序更容易实现专业化的全文检索。</li>
</ul>
<ul>
<li>Ratproxy: Google 的 XSS 检测工具</li>
</ul>
<p><a title="http://www.sphinxsearch.com/" href="http://www.sphinxsearch.com/" target="_blank">http://www.sphinxsearch.com/</a></p>
<p><a title="http://www.dbanotes.net/security/ratproxy_google_xss.html" href="http://www.dbanotes.net/security/ratproxy_google_xss.html" target="_blank">http://www.dbanotes.net/security/ratproxy_google_xss.html</a></p>
<p>上个图图吧，挺 PP 的：</p>
<p><a href="http://www.leakon.com/wp-content/uploads/2008/07/google_ratproxy.png"><img class="alignnone size-medium wp-image-163" title="google ratproxy" src="http://www.leakon.com/wp-content/uploads/2008/07/google_ratproxy-300x180.png" alt="" width="300" height="180" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.leakon.com/archives/162/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
