<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet href="/templates/default/atom.css" type="text/css" ?>

<feed 
   xmlns="http://www.w3.org/2005/Atom"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:admin="http://webns.net/mvcb/"
   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
   xmlns:wfw="http://wellformedweb.org/CommentAPI/">
    <link href="http://blog.nulltao.net/feeds/atom.xml" rel="self" title="nullTao | 净空无道 | Blog" type="application/atom+xml" />
    <link href="http://blog.nulltao.net/"                        rel="alternate"    title="nullTao | 净空无道 | Blog" type="text/html" />
    <link href="http://blog.nulltao.net/rss.php?version=2.0"     rel="alternate"    title="nullTao | 净空无道 | Blog" type="application/rss+xml" />
    <title type="html">nullTao | 净空无道 | Blog</title>
    <subtitle type="html">如果死真的是种解脱，那么愿死者有他的天堂，愿生者有他的寄托。但愿在宇宙的深处真有一处天堂，有一天当我们在经历生死契阔之后，还有一个地方在等待着我们的——重逢。</subtitle>
    <icon>http://blog.nulltao.net/templates/default/img/s9y_banner_small.png</icon>
    <id>http://blog.nulltao.net/</id>
    <updated>2008-09-07T03:00:06Z</updated>
    <generator uri="http://www.s9y.org/" version="1.3">Serendipity 1.3 - http://www.s9y.org/</generator>
    <dc:language>en</dc:language>
    <admin:errorReportsTo rdf:resource="mailto:nulltao@gmail.com" />

    <entry>
        <link href="http://blog.nulltao.net/archives/99-unknown.html" rel="alternate" title="看图说话：耿氏凉面" />
        <author>
            <name>Wei Geng</name>
            <email>nulltao@gmail.com</email>        </author>
    
        <published>2008-09-05T16:30:10Z</published>
        <updated>2008-09-07T03:00:06Z</updated>
        <wfw:comment>http://blog.nulltao.net/wfwcomment.php?cid=99</wfw:comment>
    
        <slash:comments>2</slash:comments>
        <wfw:commentRss>http://blog.nulltao.net/rss.php?version=atom1.0&amp;type=comments&amp;cid=99</wfw:commentRss>
    
            <category scheme="http://blog.nulltao.net/categories/3-TrashcaN" label="TrashcaN" term="TrashcaN" />
    
        <id>http://blog.nulltao.net/archives/99-guid.html</id>
        <title type="html">看图说话：耿氏凉面</title>
        <content type="xhtml" xml:base="http://blog.nulltao.net/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <p>今日晚饭：炸酱凉面，做法简单，口味独特，实乃耿氏厨艺精髓之体现。</p>
<p><a href="http://blog.nulltao.net/uploads/images/2008/P1060534.JPG" target="_blank"><img src="http://blog.nulltao.net/uploads/images/2008/P1060534.thumb.JPG" /></a></p>
<p>五花肉糜、四川甜面酱、香菇丁、葱花熬得如此炸酱，可惜南京找不到六必居的干黄酱买，口味大打折扣……虽然还是那么好吃。想起来小时候帮厨的时候用水去化那个像便便一样的美味的干黄酱的情景了。</p>
<p>配上黄瓜丝，清脆可口，不过偷懒，没有自己手擀面，市场上买得机制手工面，聊胜于无。</p>
<p>右上角是<a onclick="javascript: pageTracker._trackPageview('/extlink/iliuchen.blogspot.com');"  href="http://iliuchen.blogspot.com" target="_blank">室友</a>赞助的干瘪小葱（买了块一个星期了）拌老豆腐，撒花～～～～～</p>
<p>顺便翻出来上个星期的芝麻酱凉面配剁椒木耳：</p>
<p><a href="http://blog.nulltao.net/uploads/images/2008/P1060530.JPG" target="_blank"><img src="http://blog.nulltao.net/uploads/images/2008/P1060530.thumb.JPG" /></a><br />开拌前的：调好的芝麻酱一小碗，陈醋蒜泥一小碗，过水凉面一晚，黄瓜丝半根。</p>
<p><a href="http://blog.nulltao.net/uploads/images/2008/P1060533.JPG" target="_blank"><img src="http://blog.nulltao.net/uploads/images/2008/P1060533.thumb.JPG" /></a><br />拌好的样子，不过芝麻酱的颜色很浅，看得不是很清楚。</p>
<p><a href="http://blog.nulltao.net/uploads/images/2008/P1060531.JPG" target="_blank"><img src="http://blog.nulltao.net/uploads/images/2008/P1060531.thumb.JPG" /></a><br />剁椒木耳，木耳香脆，陈醋微酸，配上剁椒蒜泥，简单美味。</p> 
            </div>
        </content>
        <dc:subject>food</dc:subject>
<dc:subject>trashcan</dc:subject>

    </entry>
    <entry>
        <link href="http://blog.nulltao.net/archives/98-Google.html" rel="alternate" title="看图说话：Google 大爱" />
        <author>
            <name>Wei Geng</name>
            <email>nulltao@gmail.com</email>        </author>
    
        <published>2008-09-05T16:19:13Z</published>
        <updated>2008-09-06T10:52:27Z</updated>
        <wfw:comment>http://blog.nulltao.net/wfwcomment.php?cid=98</wfw:comment>
    
        <slash:comments>1</slash:comments>
        <wfw:commentRss>http://blog.nulltao.net/rss.php?version=atom1.0&amp;type=comments&amp;cid=98</wfw:commentRss>
    
            <category scheme="http://blog.nulltao.net/categories/3-TrashcaN" label="TrashcaN" term="TrashcaN" />
    
        <id>http://blog.nulltao.net/archives/98-guid.html</id>
        <title type="html">看图说话：Google 大爱</title>
        <content type="xhtml" xml:base="http://blog.nulltao.net/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <p>近三天 Google 颇为奇怪，RSS Reader 速度爆慢不说，还经常动不动就自己转向 Chrome 的一个介绍幻灯片的网站，难道 Google 知道偶不会这么快就用他的 Chrome，就用这种方式强迫我？</p>
<p>问了其他的几个用 RSS Reader 的朋友，都木有这种问题，怪哉。</p>
<p><a href="http://blog.nulltao.net/uploads/images/2008/greader1.png" target="_blank"><img src="http://blog.nulltao.net/uploads/images/2008/greader1.thumb.png" /></a><br />RSS Reader 自动跳转……仔细看地址栏、Tab 标签标题和状态栏……</p>
<p><a href="http://blog.nulltao.net/uploads/images/2008/greader2.png" target="_blank"><img src="http://blog.nulltao.net/uploads/images/2008/greader2.thumb.png" /></a><br />跳转后的 Slides，真丑……</p> 
            </div>
        </content>
        <dc:subject>google</dc:subject>
<dc:subject>trashcan</dc:subject>

    </entry>
    <entry>
        <link href="http://blog.nulltao.net/archives/97-unknown.html" rel="alternate" title="一个 # 不够，那么就多来几个吧" />
        <author>
            <name>Wei Geng</name>
            <email>nulltao@gmail.com</email>        </author>
    
        <published>2008-09-03T07:15:11Z</published>
        <updated>2008-09-03T17:26:44Z</updated>
        <wfw:comment>http://blog.nulltao.net/wfwcomment.php?cid=97</wfw:comment>
    
        <slash:comments>3</slash:comments>
        <wfw:commentRss>http://blog.nulltao.net/rss.php?version=atom1.0&amp;type=comments&amp;cid=97</wfw:commentRss>
    
            <category scheme="http://blog.nulltao.net/categories/2-TechniquE" label="TechniquE" term="TechniquE" />
    
        <id>http://blog.nulltao.net/archives/97-guid.html</id>
        <title type="html">一个 # 不够，那么就多来几个吧</title>
        <content type="xhtml" xml:base="http://blog.nulltao.net/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <p>网页中经常要做的一件事情就是让一个链接来执行一个 JavaScript 脚本，例如：<code>&lt; href="#" onClick="some_js_here();"&gt;Some text&lt;/a&gt;</code>，不过这样的副作用是因为有 <code>href="#"</code>。所以导致点击完后页面会滚动到最上面。</p>
<p>以前用的几种解决方案：</p><ul>
<li>不写 href，这样会导致很多浏览器不会把 a 标签按照你预期的方式渲染；</li>
<li>在href 里面直接写 JavaScript 脚本，这样不完全符合 W3C 的规范。</li>
</ul>
<p>其实要解决这个问题，不让浏览器把页面滚动到最上面，很简单，<code>href=""</code> 里面 多写几个 # 就行了，我一般用 6 个比较保险，这个方法适用于 IE5、IE6、IE7、FF2、FF3。虽然不知道为什么但是很好用。猜测是因为 # 表示进行页内书签的跳转，但是多个 # 浏览器就不知道什么意思了，干脆罢工好了，哈哈。</p> 
            </div>
        </content>
        <dc:subject>html</dc:subject>
<dc:subject>technique</dc:subject>
<dc:subject>tip</dc:subject>

    </entry>
    <entry>
        <link href="http://blog.nulltao.net/archives/96-unknown.html" rel="alternate" title="加入了原创博客联盟" />
        <author>
            <name>Wei Geng</name>
            <email>nulltao@gmail.com</email>        </author>
    
        <published>2008-08-28T10:40:33Z</published>
        <updated>2008-08-30T20:26:41Z</updated>
        <wfw:comment>http://blog.nulltao.net/wfwcomment.php?cid=96</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://blog.nulltao.net/rss.php?version=atom1.0&amp;type=comments&amp;cid=96</wfw:commentRss>
    
            <category scheme="http://blog.nulltao.net/categories/3-TrashcaN" label="TrashcaN" term="TrashcaN" />
    
        <id>http://blog.nulltao.net/archives/96-guid.html</id>
        <title type="html">加入了原创博客联盟</title>
        <content type="xhtml" xml:base="http://blog.nulltao.net/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <p><a onclick="javascript: pageTracker._trackPageview('/extlink/oblogger.org/');"  href="http://oblogger.org/" target="_blank"><img src="http://oblogger.org/img/8831w.png" border="0" /></a></p> 
            </div>
        </content>
        <dc:subject>oblogger</dc:subject>
<dc:subject>trashcan</dc:subject>

    </entry>
    <entry>
        <link href="http://blog.nulltao.net/archives/95-KMLGeoRSS-GeoJSON.html" rel="alternate" title="地图聚合的数据格式前三名：KML、GeoRSS 和 GeoJSON" />
        <author>
            <name>Wei Geng</name>
            <email>nulltao@gmail.com</email>        </author>
    
        <published>2008-08-28T10:34:37Z</published>
        <updated>2008-08-28T10:34:37Z</updated>
        <wfw:comment>http://blog.nulltao.net/wfwcomment.php?cid=95</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://blog.nulltao.net/rss.php?version=atom1.0&amp;type=comments&amp;cid=95</wfw:commentRss>
    
            <category scheme="http://blog.nulltao.net/categories/4-TranslatioN" label="TranslatioN" term="TranslatioN" />
    
        <id>http://blog.nulltao.net/archives/95-guid.html</id>
        <title type="html">地图聚合的数据格式前三名：KML、GeoRSS 和 GeoJSON</title>
        <content type="xhtml" xml:base="http://blog.nulltao.net/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <p>原文地址：<a onclick="javascript: pageTracker._trackPageview('/extlink/blog.programmableweb.com/2008/08/27/3-top-data-formats-for-map-mashups-kml-georss-and-geojson/');"  href="http://blog.programmableweb.com/2008/08/27/3-top-data-formats-for-map-mashups-kml-georss-and-geojson/" target="_blank">3 Top Data Formats for Map Mashups: KML, GeoRSS and GeoJSON</a>。</p>
<hr />

<p><a onclick="javascript: pageTracker._trackPageview('/extlink/www.programmableweb.com/mapping');"  title="ProgrammableWeb" href="http://www.programmableweb.com/mapping"><img src="http://www.programmableweb.com/images/apis/at22.png" alt=""></a> 随着地图聚合给最终用户提供的一系列更广泛的工具和应用程序，它在完善程度和功能性两方面逐渐走向成熟。 因此，我们需要一些预定义好的方法在传统的地理空间数据和新一代的<a onclick="javascript: pageTracker._trackPageview('/extlink/www.programmableweb.com/mapping');"  href="http://www.programmableweb.com/mapping">地图聚合</a>之间交换、发布这些地理空间数据，并且使用一种对 web 友好的方式使用这些数据。</p>
<p>为了满足这种需求，出现了一些新的地理空间数据格式，这能够让更大范围的用户和开发者来聚合地理相关的信息。 下面是当前可供从事地理信息聚合的开发者使用的三种主要数据格式的一个概括：</p>
<h3><a onclick="javascript: pageTracker._trackPageview('/extlink/code.google.com/apis/kml/');"  href="http://code.google.com/apis/kml/">KML</a></h3>
<p>你知道 <a onclick="javascript: pageTracker._trackPageview('/extlink/earth.google.com');"  href="http://earth.google.com">Google 地球</a>的前身，那个流行的名为 Keyhole 的三维地球浏览器吗？ 如果你知道，那么这个基于 XML 的，Google 地球自己的文件格式被叫做 <a onclick="javascript: pageTracker._trackPageview('/extlink/code.google.com/apis/kml/');"  href="http://code.google.com/apis/kml/">KML</a>，意为 Keyhole 标记语言，就不值得惊讶了。 在地理空间相关的网站上，KML 无处不在，KML 支持从类似 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.programmableweb.com/api/google-maps');"  href="http://www.programmableweb.com/api/google-maps">Google 地图</a>、微软的<a onclick="javascript: pageTracker._trackPageview('/extlink/www.programmableweb.com/api/microsoft-virtual-earth');"  href="http://www.programmableweb.com/api/microsoft-virtual-earth">虚拟地球</a>这样商业化的地图 API 和 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.programmableweb.com/api/openlayers');"  href="http://www.programmableweb.com/api/openlayers">OpenLayers</a> 这样开源的地图 API 中导入、导出数据。 今年早些时候，Google 把 KML 作为一种开放标准发布，并且被开放地理空间联盟 (OGC) 采用。 你可以研读<a onclick="javascript: pageTracker._trackPageview('/extlink/code.google.com/apis/kml/documentation/kmlreference.html');"  href="http://code.google.com/apis/kml/documentation/kmlreference.html">最新的 KML 规范</a> (当前是 2.2 版) 或者学习如何让 KML 与 <a onclick="javascript: pageTracker._trackPageview('/extlink/code.google.com/apis/maps/documentation/reference.html#GGeoXml');"  href="http://code.google.com/apis/maps/documentation/reference.html#GGeoXml">Google 地图 API</a>、<a onclick="javascript: pageTracker._trackPageview('/extlink/blogs.msdn.com/keithkin/archive/2007/11/20/virtual-earth-api-adding-kml-or-georss-layers-to-the-map.aspx');"  href="http://blogs.msdn.com/keithkin/archive/2007/11/20/virtual-earth-api-adding-kml-or-georss-layers-to-the-map.aspx">虚拟地球</a>或者 <a onclick="javascript: pageTracker._trackPageview('/extlink/dev.openlayers.org/releases/OpenLayers-2.6/doc/apidocs/files/OpenLayers/Format/KML-js.html');"  href="http://dev.openlayers.org/releases/OpenLayers-2.6/doc/apidocs/files/OpenLayers/Format/KML-js.html">OpenLayers</a> 集成。</p>
<h3><a onclick="javascript: pageTracker._trackPageview('/extlink/georss.org/');"  href="http://georss.org/">GeoRSS</a></h3>
<p><a onclick="javascript: pageTracker._trackPageview('/extlink/georss.org/');"  href="http://georss.org/">GeoRSS</a> 提供了一种在 RSS (或者 Atom) 种子里通过特定的编码来包含地理参考信息的方法。GeoRSS 站点上说：</p>
<blockquote>
<p>RSS 和 Atom 作为一种发布、共享信息的方法，正在逐渐流行起来， 因此，使用互操作的方式描述位置信息，来让程序能够请求、聚合、共享、地图化地理标记过的种子变得益发重要。</p>
</blockquote>
<p>嵌入 <a class="bodytag" target="_blank" href="http://blog.nulltao.net/articles/tag/GeoRSS"><em>GeoRSS</em></a> 非常简单，仅仅在每个条目中增加一个类似 <code>&lt;georss:point&gt;45.256 -71.92&lt;/georss:point&gt; 这样的元素就行了，这里使用的是<a onclick="javascript: pageTracker._trackPageview('/extlink/georss.org/simple');"  href="http://georss.org/simple">简易GeoRSS</a> 格式， 如果要需要复杂完整的编码格式，可以选择支持更多的特性的 <a onclick="javascript: pageTracker._trackPageview('/extlink/georss.org/gml');"  href="http://georss.org/gml">GeoRSS-GML</a> 格式。这两种 GeoRSS 格式都支持基本的地理特征 (点、线、边框和多边形)。 和 KML 一样，商业化的地图 API 和开源地图 API 都支持 GeoRSS，并且主要作为导入数据的格式使用。 GeoRSS 许诺对整合内容的会有更好的支持。</code></p>
<h3><a onclick="javascript: pageTracker._trackPageview('/extlink/geojson.org');"  href="http://geojson.org">GeoJSON</a></h3>
<p><a onclick="javascript: pageTracker._trackPageview('/extlink/geojson.org');"  href="http://geojson.org">GeoJSON</a> 是基于 JavaScript 对象表示法 (JSON)的一种新的数据格式，用来对大量的地理特征进行编码，支持的地理特征有点、线、多边形、多多边形和地理信息集合。</p>
<p><code>{ "type": "Point", "coordinates": [43.542, -118.454] }</code></p>
<p><a class="bodytag" target="_blank" href="http://blog.nulltao.net/articles/tag/GeoJSON"><em>GeoJSON</em></a> 可以被 JavaScript 简单、快速的解析，而且 GeoJSON 还提供了一个可以很容易的进行交换的轻量级数据格式。 自从 GeoJSON 正式发表 1.0 版后，GeoJSON 的魅力逐渐增加，得到了包括 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.programmableweb.com/api/fire-eagle');"  href="http://www.programmableweb.com/api/fire-eagle">FireEagle</a> 和 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.programmableweb.com/api/openlayers');"  href="http://www.programmableweb.com/api/openlayers">OpenLayers</a> 在内的一些流行的 API 的支持 (但是不确定将来是否能够得到类似 Google 地图或者虚拟地球这样的商业 API 的支持)。</p>
<p>注意 <a class="bodytag" target="_blank" href="http://blog.nulltao.net/articles/tag/GeoRSS"><em>GeoRSS</em></a> 和 <a class="bodytag" target="_blank" href="http://blog.nulltao.net/articles/tag/GeoJSON"><em>GeoJSON</em></a> 都采用创作共用授权协议授权。</p>
<p>我们饶有兴趣的看着这些格式如何发展，而且很想知道类似 <a class="bodytag" target="_blank" href="http://blog.nulltao.net/articles/tag/GeoRSS"><em>GeoRSS</em></a> 和 <a class="bodytag" target="_blank" href="http://blog.nulltao.net/articles/tag/GeoJSON"><em>GeoJSON</em></a> 这样的格式能否得到<a onclick="javascript: pageTracker._trackPageview('/extlink/www.programmableweb.com/apis/directory/1?apicat=Mapping');"  href="http://www.programmableweb.com/apis/directory/1?apicat=Mapping">地图 API</a> 和地图聚合开发者的采用。</p> 
            </div>
        </content>
        <dc:subject>geojson</dc:subject>
<dc:subject>georss</dc:subject>
<dc:subject>kml</dc:subject>
<dc:subject>map</dc:subject>
<dc:subject>mashup</dc:subject>
<dc:subject>translation</dc:subject>

    </entry>
    <entry>
        <link href="http://blog.nulltao.net/archives/94-propel-convert-xml-schema-null.html" rel="alternate" title="解决 propel-convert-xml-schema 把 null 默认值处理为字符串的问题" />
        <author>
            <name>Wei Geng</name>
            <email>nulltao@gmail.com</email>        </author>
    
        <published>2008-08-21T03:32:56Z</published>
        <updated>2008-08-21T03:32:56Z</updated>
        <wfw:comment>http://blog.nulltao.net/wfwcomment.php?cid=94</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://blog.nulltao.net/rss.php?version=atom1.0&amp;type=comments&amp;cid=94</wfw:commentRss>
    
            <category scheme="http://blog.nulltao.net/categories/2-TechniquE" label="TechniquE" term="TechniquE" />
    
        <id>http://blog.nulltao.net/archives/94-guid.html</id>
        <title type="html">解决 propel-convert-xml-schema 把 null 默认值处理为字符串的问题</title>
        <content type="xhtml" xml:base="http://blog.nulltao.net/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <p>通过 propel-convert-xml-schema 把 xml schema 转化成 PHP 代码的时候，如果一个字符型字段不能为空且没有明确输入默认值，例如：</p>
<div class="xml" style="text-align: left"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;column</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;username&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;VARCHAR&quot;</span> <span style="color: #000066;">size</span>=<span style="color: #ff0000;">&quot;128&quot;</span> <span style="color: #000066;">required</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">default</span>=<span style="color: #ff0000;">&quot;&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span></div></li></ol></div>
<p>生成的 PHP 代码中该字段的默认值是 'null' 而不是 null，导致页面输入框的默认值不是空值，而是一个字符串的 null，很恼火。因为要么在页面中每个字段都对 'null' 做特殊处理，要么修改生成的 PHP 类文件，但是一旦重新执行 propel-convert-xml-schema 就会重新覆盖。</p>
<p>解决办法：修改 <code>propel-generator/classes/propel/phing/PropelCreoleTransformTask.php</code> 文件（对于 Symfony 来说，就是 <code>symfony/vendor/propel-generator/classes/propel/phing/PropelCreoleTransformTask.php</code>）。应用如下 patch：</p>
<div class="diff" style="text-align: left"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #440088;"><span style="">507</span>,510c507</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #991111;">&lt; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; //$node-&gt;setAttribute<span style="">&#40;</span>&quot;default&quot;, iconv<span style="">&#40;</span>$this-&gt;dbEncoding, 'utf<span style="">-8</span>', $defValue<span style="">&#41;</span><span style="">&#41;</span>;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #991111;">&lt; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; if<span style="">&#40;</span>!empty<span style="">&#40;</span>$defValue<span style="">&#41;</span><span style="">&#41;</span> <span style="">&#123;</span></span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #991111;">&lt; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; $node-&gt;setAttribute<span style="">&#40;</span>&quot;default&quot;, iconv<span style="">&#40;</span>$this-&gt;dbEncoding, 'utf<span style="">-8</span>', $defValue<span style="">&#41;</span><span style="">&#41;</span>;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #991111;">&lt; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; <span style="">&#125;</span></span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #888822;">---</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #00b000;">&gt; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; $node-&gt;setAttribute<span style="">&#40;</span>&quot;default&quot;, iconv<span style="">&#40;</span>$this-&gt;dbEncoding, 'utf<span style="">-8</span>', $defValue<span style="">&#41;</span><span style="">&#41;</span>;</span></span></div></li></ol></div>
<p>参见：<a onclick="javascript: pageTracker._trackPageview('/extlink/trac.symfony-project.org/ticket/2045');"  href="http://trac.symfony-project.org/ticket/2045" target="_blank">#2045 (propel-convert-xml-schema generate null text as default values) - symfony - Trac</a>。</p>
<p>下载：<a href="http://blog.nulltao.net/uploads/images/2008/PropelCreoleTransformTask.7z">PropelCreoleTransformTask.7z</a>。</p> 
            </div>
        </content>
        <dc:subject>bug</dc:subject>
<dc:subject>php</dc:subject>
<dc:subject>propel</dc:subject>
<dc:subject>symfony</dc:subject>
<dc:subject>technique</dc:subject>

    </entry>
    <entry>
        <link href="http://blog.nulltao.net/archives/93-Symfony-StructuresDataGridsfSmartViewPropel.html" rel="alternate" title="在 Symfony 中结合使用 Structures/DataGrid、sfSmartView、Propel" />
        <author>
            <name>Wei Geng</name>
            <email>nulltao@gmail.com</email>        </author>
    
        <published>2008-08-17T16:15:50Z</published>
        <updated>2008-08-17T16:15:50Z</updated>
        <wfw:comment>http://blog.nulltao.net/wfwcomment.php?cid=93</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://blog.nulltao.net/rss.php?version=atom1.0&amp;type=comments&amp;cid=93</wfw:commentRss>
    
            <category scheme="http://blog.nulltao.net/categories/2-TechniquE" label="TechniquE" term="TechniquE" />
    
        <id>http://blog.nulltao.net/archives/93-guid.html</id>
        <title type="html">在 Symfony 中结合使用 Structures/DataGrid、sfSmartView、Propel</title>
        <content type="xhtml" xml:base="http://blog.nulltao.net/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <p>今天需要在 <code>symfony</code> 中使用 datagrid 型控件对一个分页+排序的表格进行展示。但是 <code>sfDataGrid</code> 写得实在是太糟糕了，没有找到其他的比较好的 plugin。</p>
<p><code>PEAR</code> 中的 <code>Structures/DataGrid</code> 倒是不错。但是两个问题：无法和现在偶使用的 <code>sfSmartyView</code> 直接结合，因为在 <code>$datagrid->fill($smarty);</code> 的时候，<code>symfony</code> 还没有生成 view instance，除非直接获取生成的 HTML_TABLE 或者类似的结果，这样不利于 MVC 的分离和对具体样式的控制；二是现有的 <code>datasource</code> 无法和 <code>symfony</code> 使用的 <code>propel</code> 直接结合，如果采用检索全部结果再传递给 <code>Structures/DataGrid</code> 进行分页处理，那么效率非常低下。</p>
<p>于是自己写一个 <code>datasource</code>，并且使用了一点技巧解决和 <code>sfSmartyView</code> 结合的问题。</p>
<p><code>Structures_DataGrid_DataSource_Propel</code> 类的定义：</p>
<div class="php" style="text-align: left"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #000000; font-weight: bold;">class</span> Structures_DataGrid_DataSource_Propel <span style="color: #000000; font-weight: bold;">extends</span> Structures_DataGrid_DataSource <span style="color: #66cc66;">&#123;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; protected <span style="color: #0000ff;">$criteria</span> = <span style="color: #000000; font-weight: bold;">null</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; protected <span style="color: #0000ff;">$con</span> = <span style="color: #000000; font-weight: bold;">null</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; protected <span style="color: #0000ff;">$object</span> = <span style="color: #000000; font-weight: bold;">null</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; </div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$object</span>, <span style="color: #0000ff;">$criteria</span>, <span style="color: #0000ff;">$con</span> = <span style="color: #000000; font-weight: bold;">null</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; parent::<span style="color: #006600;">Structures_DataGrid_DataSource</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">object</span> = <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #0000ff;">$object</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">criteria</span> = <span style="color: #0000ff;">$criteria</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">con</span> = <span style="color: #0000ff;">$con</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #66cc66;">&#125;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; </div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #000000; font-weight: bold;">function</span> <a onclick="javascript: pageTracker._trackPageview('/extlink/www.php.net/count');"  href="http://www.php.net/count"><span style="color: #000066;">count</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #808080; font-style: italic;">//TODO: this is not a good way, due to MySQL Bug #21787</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">criteria</span>-&gt;<span style="color: #006600;">setLimit</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">criteria</span>-&gt;<span style="color: #006600;">setOffset</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #0000ff;">$result</span> = <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">object</span>-&gt;<span style="color: #006600;">doCount</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">criteria</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">$result</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #66cc66;">&#125;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; </div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #000000; font-weight: bold;">function</span> <a onclick="javascript: pageTracker._trackPageview('/extlink/www.php.net/sort');"  href="http://www.php.net/sort"><span style="color: #000066;">sort</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$sortSpec</span>, <span style="color: #0000ff;">$sortDir</span> = <span style="color: #ff0000;">'ASC'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #b1b100;">switch</span> <span style="color: #66cc66;">&#40;</span><a onclick="javascript: pageTracker._trackPageview('/extlink/www.php.net/strtolower');"  href="http://www.php.net/strtolower"><span style="color: #000066;">strtolower</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$sortDir</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; &#160; <span style="color: #b1b100;">case</span> <span style="color: #ff0000;">'asc'</span> :</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; &#160; &#160; <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">criteria</span>-&gt;<span style="color: #006600;">addAscendingOrderByColumn</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$sortSpec</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; &#160; &#160; <span style="color: #b1b100;">break</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; &#160; <span style="color: #b1b100;">case</span> <span style="color: #ff0000;">'desc'</span> :</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; &#160; &#160; <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">criteria</span>-&gt;<span style="color: #006600;">addDescendingOrderByColumn</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$sortSpec</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; &#160; &#160; <span style="color: #b1b100;">break</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; &#160; <span style="color: #000000; font-weight: bold;">default</span> :</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; &#160; &#160; <span style="color: #b1b100;">return</span> PEAR::<span style="color: #006600;">raiseError</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;Sorting dir must be ASC or DESC!&quot;</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #66cc66;">&#125;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">true</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #66cc66;">&#125;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; </div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #000000; font-weight: bold;">function</span> fetch<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$offset</span> = <span style="color: #cc66cc;">0</span>, <span style="color: #0000ff;">$len</span> = <span style="color: #000000; font-weight: bold;">null</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #0000ff;">$c</span> = <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">criteria</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #0000ff;">$c</span>-&gt;<span style="color: #006600;">setOffset</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$offset</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span>! <a onclick="javascript: pageTracker._trackPageview('/extlink/www.php.net/is_null');"  href="http://www.php.net/is_null"><span style="color: #000066;">is_null</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$len</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; &#160; <span style="color: #0000ff;">$c</span>-&gt;<span style="color: #006600;">setLimit</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$len</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #66cc66;">&#125;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #0000ff;">$objects</span> = <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">object</span>-&gt;<span style="color: #006600;">doSelect</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$c</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #0000ff;">$result</span> = <a onclick="javascript: pageTracker._trackPageview('/extlink/www.php.net/array');"  href="http://www.php.net/array"><span style="color: #000066;">array</span></a> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #b1b100;">foreach</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$objects</span> <span style="color: #b1b100;">as</span> <span style="color: #0000ff;">$object</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; &#160; <span style="color: #0000ff;">$result</span><span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #0000ff;">$object</span>-&gt;<span style="color: #006600;">toArray</span><span style="color: #66cc66;">&#40;</span>BasePeer::<span style="color: #006600;">TYPE_COLNAME</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #66cc66;">&#125;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">$result</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #66cc66;">&#125;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span></div></li></ol></div>
<p><code>action</code> 中的代码段：</p>
<div class="php" style="text-align: left"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> execute<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #808080; font-style: italic;">// get data source</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #0000ff;">$c</span> = <span style="color: #000000; font-weight: bold;">new</span> Criteria<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #0000ff;">$datasource</span> = <span style="color: #000000; font-weight: bold;">new</span> Structures_DataGrid_DataSource_Propel<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'SysUiaAccountPeer'</span>, <span style="color: #0000ff;">$c</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #808080; font-style: italic;">// setup datagrid</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #0000ff;">$datagrid</span> = &amp; <span style="color: #000000; font-weight: bold;">new</span> Structures_DataGrid<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #0000ff;">$datagrid</span>-&gt;<span style="color: #006600;">bindDataSource</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$datasource</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #0000ff;">$datagrid</span>-&gt;<span style="color: #006600;">setDefaultSort</span><span style="color: #66cc66;">&#40;</span><a onclick="javascript: pageTracker._trackPageview('/extlink/www.php.net/array');"  href="http://www.php.net/array"><span style="color: #000066;">array</span></a> <span style="color: #66cc66;">&#40;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; SysUiaAccountPeer::<span style="color: #006600;">USERNAME</span>=&gt;<span style="color: #ff0000;">&quot;DESC&quot;</span> </div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #0000ff;">$datagrid</span>-&gt;<span style="color: #006600;">addColumn</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Structures_DataGrid_Column<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'用户名'</span>, SysUiaAccountPeer::<span style="color: #006600;">USERNAME</span>, SysUiaAccountPeer::<span style="color: #006600;">USERNAME</span>, <a onclick="javascript: pageTracker._trackPageview('/extlink/www.php.net/array');"  href="http://www.php.net/array"><span style="color: #000066;">array</span></a> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #ff0000;">'&amp;nbsp;'</span>, <span style="color: #ff0000;">''</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #808080; font-style: italic;">// add more columns here</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; </div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #808080; font-style: italic;">// use a tip to get output using smarty</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #0000ff;">$smarty</span> = <span style="color: #0000ff;">$datagrid</span>-&gt;<span style="color: #006600;">setRenderer</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'smarty'</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #808080; font-style: italic;">// set pager params</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #0000ff;">$pager</span> = <span style="color: #0000ff;">$smarty</span>-&gt;<span style="color: #006600;">smartyGetPaging</span><span style="color: #66cc66;">&#40;</span><a onclick="javascript: pageTracker._trackPageview('/extlink/www.php.net/array');"  href="http://www.php.net/array"><span style="color: #000066;">array</span></a> <span style="color: #66cc66;">&#40;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #ff0000;">'prevImg'</span>=&gt;<span style="color: #ff0000;">&quot;上一页&quot;</span>, <span style="color: #ff0000;">'nextImg'</span>=&gt;<span style="color: #ff0000;">&quot;下一页&quot;</span>, <span style="color: #ff0000;">'separator'</span>=&gt;<span style="color: #ff0000;">&quot;|&quot;</span>, <span style="color: #ff0000;">'delta'</span>=&gt;<span style="color: #ff0000;">&quot;5&quot;</span>, <span style="color: #ff0000;">'clearIfVoid'</span>=&gt;true, <span style="color: #ff0000;">'spacesBeforeSeparator'</span>=&gt;<span style="color: #ff0000;">&quot;1&quot;</span>, <span style="color: #ff0000;">'spacesAfterSeparator'</span>=&gt;<span style="color: #ff0000;">&quot;1&quot;</span>, <span style="color: #ff0000;">'firstPageText'</span>=&gt;<span style="color: #ff0000;">'第一页'</span>, <span style="color: #ff0000;">'lastPageText'</span>=&gt;<span style="color: #ff0000;">'最后页'</span> </div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #66cc66;">&#41;</span>, <span style="color: #0000ff;">$smarty</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">dg</span> = <span style="color: #0000ff;">$datagrid</span>-&gt;<span style="color: #006600;">getOutput</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">pager</span> = <span style="color: #0000ff;">$pager</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #b1b100;">return</span> sfView::<span style="color: #006600;">SUCCESS</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span></div></li></ol></div>
<p>模板中的处理：</p>
<div class="html4strict" style="text-align: left"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><a onclick="javascript: pageTracker._trackPageview('/extlink/december.com/html/4/element/table.html');"  href="http://december.com/html/4/element/table.html"><span style="color: #000000; font-weight: bold;">&lt;table&gt;</span></a></span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #009900;"><span style="color: #808080; font-style: italic;">&lt;!-- Build header --&gt;</span></span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #009900;"><a onclick="javascript: pageTracker._trackPageview('/extlink/december.com/html/4/element/tr.html');"  href="http://december.com/html/4/element/tr.html"><span style="color: #000000; font-weight: bold;">&lt;tr&gt;</span></a></span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; {section name=col loop=$dg.columnSet}</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #009900;"><a onclick="javascript: pageTracker._trackPageview('/extlink/december.com/html/4/element/th.html');"  href="http://december.com/html/4/element/th.html"><span style="color: #000000; font-weight: bold;">&lt;th</span></a><span style="color: #66cc66;">&#123;</span>$dg.columnSet<span style="color: #66cc66;">&#91;</span>col<span style="color: #66cc66;">&#93;</span>.attributes<span style="color: #66cc66;">&#125;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #009900;"><span style="color: #808080; font-style: italic;">&lt;!-- Check if the column is sortable --&gt;</span></span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; {if $dg.columnSet[col].link != &quot;&quot;} <span style="color: #009900;"><a onclick="javascript: pageTracker._trackPageview('/extlink/december.com/html/4/element/a.html');"  href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;{$dg.columnSet[col].link}&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>{$dg.columnSet[col].label}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #009900;"><span style="color: #808080; font-style: italic;">&lt;!-- Show the current ordering with an arrow --&gt;</span></span> {if</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; $dg.columnSet[col].name == $smarty.request.orderBy} {if</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; $smarty.request.direction == &quot;ASC&quot;}<span style="color: #ddbb00;">&amp;uarr;</span>{elseif</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; $smarty.request.direction == &quot;DESC&quot;}<span style="color: #ddbb00;">&amp;darr;</span>{/if} {/if} {else}</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; {$dg.columnSet[col].label} {/if}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/th&gt;</span></span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; {/section}</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/tr&gt;</span></span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #009900;"><span style="color: #808080; font-style: italic;">&lt;!-- Build body --&gt;</span></span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; {section name=row loop=$dg.recordSet}</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #009900;"><a onclick="javascript: pageTracker._trackPageview('/extlink/december.com/html/4/element/tr.html');"  href="http://december.com/html/4/element/tr.html"><span style="color: #000000; font-weight: bold;">&lt;tr</span></a> <span style="color: #66cc66;">&#123;</span>if $smarty.section.row.iteration is even<span style="color: #66cc66;">&#125;</span><span style="color: #000066;">bgcolor</span>=<span style="color: #ff0000;">&quot;#EEEEEE&quot;</span><span style="color: #66cc66;">&#123;</span>/if<span style="color: #66cc66;">&#125;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; {section name=col loop=$dg.recordSet[row]}</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #009900;"><a onclick="javascript: pageTracker._trackPageview('/extlink/december.com/html/4/element/td.html');"  href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">&lt;td</span></a><span style="color: #66cc66;">&#123;</span>$columnSet<span style="color: #66cc66;">&#91;</span>col<span style="color: #66cc66;">&#93;</span>.attributes<span style="color: #66cc66;">&#125;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>{$dg.recordSet[row][col]}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/td&gt;</span></span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; {/section}</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/tr&gt;</span></span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; {/section}</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #009900;"><a onclick="javascript: pageTracker._trackPageview('/extlink/december.com/html/4/element/tr.html');"  href="http://december.com/html/4/element/tr.html"><span style="color: #000000; font-weight: bold;">&lt;tr&gt;</span></a></span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #009900;"><a onclick="javascript: pageTracker._trackPageview('/extlink/december.com/html/4/element/td.html');"  href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">&lt;td</span></a> <span style="color: #000066;">colspan</span>=<span style="color: #ff0000;">&quot;...&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>{$pager}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/td&gt;</span></span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/tr&gt;</span></span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/table&gt;</span></span></div></li></ol></div> 
            </div>
        </content>
        <dc:subject>datagrid</dc:subject>
<dc:subject>symfony</dc:subject>
<dc:subject>technique</dc:subject>

    </entry>
    <entry>
        <link href="http://blog.nulltao.net/archives/92-MySQL-COUNT-LIMIT-BUG.html" rel="alternate" title="MySQL 对于 COUNT(*) 和 LIMIT 同时使用的 BUG  " />
        <author>
            <name>Wei Geng</name>
            <email>nulltao@gmail.com</email>        </author>
    
        <published>2008-08-17T15:53:05Z</published>
        <updated>2008-08-17T16:09:37Z</updated>
        <wfw:comment>http://blog.nulltao.net/wfwcomment.php?cid=92</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://blog.nulltao.net/rss.php?version=atom1.0&amp;type=comments&amp;cid=92</wfw:commentRss>
    
            <category scheme="http://blog.nulltao.net/categories/2-TechniquE" label="TechniquE" term="TechniquE" />
    
        <id>http://blog.nulltao.net/archives/92-guid.html</id>
        <title type="html">MySQL 对于 COUNT(*) 和 LIMIT 同时使用的 BUG  </title>
        <content type="xhtml" xml:base="http://blog.nulltao.net/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <p>对一个有 29 条记录的表进行如下操作：</p>
<ul>
<li><div class="sql" style="text-align: left"><span style="color: #993333; font-weight: bold;">SELECT</span> COUNT<span style="color: #66cc66;">&#40;</span> sys_uia_account.ID <span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">FROM</span> sys_uia_account</div>结果 29</li>
<li><div class="sql" style="text-align: left"><span style="color: #993333; font-weight: bold;">SELECT</span> COUNT<span style="color: #66cc66;">&#40;</span> sys_uia_account.ID <span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">FROM</span> sys_uia_account <span style="color: #993333; font-weight: bold;">LIMIT</span> <span style="color: #cc66cc;">10</span></div>结果 29</li>
<li><div class="sql" style="text-align: left"><span style="color: #993333; font-weight: bold;">SELECT</span> COUNT<span style="color: #66cc66;">&#40;</span> sys_uia_account.ID <span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">FROM</span> sys_uia_account <span style="color: #993333; font-weight: bold;">LIMIT</span> <span style="color: #cc66cc;">10</span> , <span style="color: #cc66cc;">10</span></div>没有结果</li>
</ul>
<p>看来以后使用 <code>COUNT(*)</code> 的时候不能同时使用 <code>LIMIT offset, row_count</code> 这种表达方式了。</p>
<p>PS：如果统计全表记录，使用下面的方法会更加快捷：</p>
<div class="sql" style="text-align: left"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #993333; font-weight: bold;">SELECT</span> SQL_CALC_FOUND_ROWS *</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #993333; font-weight: bold;">FROM</span> sys_uia_account;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #993333; font-weight: bold;">SELECT</span> FOUND_ROWS<span style="color: #66cc66;">&#40;</span> <span style="color: #66cc66;">&#41;</span> ;</div></li></ol></div>
<p>唯一需要注意的就是，这两个查询必须在一起进行，因为 <code>SQL_CALC_FOUND_ROWS</code> 不对结果进行任何缓存。</p> 
            </div>
        </content>
        <dc:subject>bug</dc:subject>
<dc:subject>mysql</dc:subject>
<dc:subject>technique</dc:subject>
<dc:subject>tip</dc:subject>

    </entry>
    <entry>
        <link href="http://blog.nulltao.net/archives/91-MySQL-GKB-UTF-8.html" rel="alternate" title="MySQL 中用 GKB 来让 UTF-8 字段中的中文按照拼音排序" />
        <author>
            <name>Wei Geng</name>
            <email>nulltao@gmail.com</email>        </author>
    
        <published>2008-08-16T07:39:24Z</published>
        <updated>2008-08-16T08:13:48Z</updated>
        <wfw:comment>http://blog.nulltao.net/wfwcomment.php?cid=91</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://blog.nulltao.net/rss.php?version=atom1.0&amp;type=comments&amp;cid=91</wfw:commentRss>
    
            <category scheme="http://blog.nulltao.net/categories/2-TechniquE" label="TechniquE" term="TechniquE" />
    
        <id>http://blog.nulltao.net/archives/91-guid.html</id>
        <title type="html">MySQL 中用 GKB 来让 UTF-8 字段中的中文按照拼音排序</title>
        <content type="xhtml" xml:base="http://blog.nulltao.net/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <p>UTF-8 中的中文不是按照拼音排序的，因此对于 使用 UTF-8 编码集的字段就无法按照拼音进行排序，最简单的解决方法就是转成 GBK 编码。</p>
<p>实例代码：<div class="sql" style="text-align: left"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"> <span style="color: #993333; font-weight: bold;">SELECT</span> *</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`test`</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> CONVERT<span style="color: #66cc66;">&#40;</span> <span style="color: #ff0000;">`test`</span>.<span style="color: #ff0000;">`name`</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; &#160; <span style="color: #993333; font-weight: bold;">USING</span> GBK <span style="color: #66cc66;">&#41;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #993333; font-weight: bold;">LIMIT</span> <span style="color: #cc66cc;">0</span> , <span style="color: #cc66cc;">30</span></div></li></ol></div></p>
<p>数据库表结构：<div class="sql" style="text-align: left"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #993333; font-weight: bold;">IF</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">EXISTS</span> <span style="color: #ff0000;">`test`</span> <span style="color: #66cc66;">&#40;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #ff0000;">`id`</span> int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span>,</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #ff0000;">`name`</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span> COLLATE utf8_bin <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span>,</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&#160; <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">&#41;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#41;</span> ENGINE=InnoDB &#160;<span style="color: #993333; font-weight: bold;">DEFAULT</span> CHARSET=utf8 COLLATE=utf8_bin <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span>=<span style="color: #cc66cc;">1</span> ;</div></li></ol></div></p>
<p>测试环境：Windows 2003 Standard Edition，MySQL 5.1.22-rc-community。</p>
<p>对于偶正在使用的 Symfony 框架，因为使用了 propel 做 ORM，比较难直接操作SQL，除非使用 RAW SQL，而且使用 RAW SQL会导致很多高级特性无法使用，解决方式：<div class="php" style="text-align: left"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #0000ff;">$criteria</span>-&gt;<span style="color: #006600;">addAscendingOrderByColumn</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'CONVERT('</span> . TestPeer::<span style="color: #006600;">NAME</span> . <span style="color: #ff0000;">' USING GBK)'</span><span style="color: #66cc66;">&#41;</span>;</div></li></ol></div></p>
 
            </div>
        </content>
        <dc:subject>mysql</dc:subject>
<dc:subject>php</dc:subject>
<dc:subject>sort</dc:subject>
<dc:subject>technique</dc:subject>
<dc:subject>utf-8</dc:subject>

    </entry>
    <entry>
        <link href="http://blog.nulltao.net/archives/90-unknown.html" rel="alternate" title="胡言乱语之奥运会" />
        <author>
            <name>Wei Geng</name>
            <email>nulltao@gmail.com</email>        </author>
    
        <published>2008-08-08T05:07:49Z</published>
        <updated>2008-08-08T05:17:14Z</updated>
        <wfw:comment>http://blog.nulltao.net/wfwcomment.php?cid=90</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://blog.nulltao.net/rss.php?version=atom1.0&amp;type=comments&amp;cid=90</wfw:commentRss>
    
            <category scheme="http://blog.nulltao.net/categories/3-TrashcaN" label="TrashcaN" term="TrashcaN" />
    
        <id>http://blog.nulltao.net/archives/90-guid.html</id>
        <title type="html">胡言乱语之奥运会</title>
        <content type="xhtml" xml:base="http://blog.nulltao.net/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <ul>
<li>在偶看来，奥运会就是一群没有大脑的国人庆祝自己纳的税被浪费掉还欢呼鼓掌发自肺腑的庆祝的脑残盛会。</li>
<li>本来说不看开幕式的，不过想想还是看看吧。看看张艺谋这次是怎么糟蹋中国文化的。</li>
</ul> 
            </div>
        </content>
        <dc:subject>olympic</dc:subject>
<dc:subject>trashcan</dc:subject>

    </entry>
    <entry>
        <link href="http://blog.nulltao.net/archives/89-Firefox3-Flash.html" rel="alternate" title="让 Firefox3 支持 Flash" />
        <author>
            <name>Wei Geng</name>
            <email>nulltao@gmail.com</email>        </author>
    
        <published>2008-06-18T03:49:37Z</published>
        <updated>2008-06-19T01:53:56Z</updated>
        <wfw:comment>http://blog.nulltao.net/wfwcomment.php?cid=89</wfw:comment>
    
        <slash:comments>2</slash:comments>
        <wfw:commentRss>http://blog.nulltao.net/rss.php?version=atom1.0&amp;type=comments&amp;cid=89</wfw:commentRss>
    
            <category scheme="http://blog.nulltao.net/categories/2-TechniquE" label="TechniquE" term="TechniquE" />
    
        <id>http://blog.nulltao.net/archives/89-guid.html</id>
        <title type="html">让 Firefox3 支持 Flash</title>
        <content type="xhtml" xml:base="http://blog.nulltao.net/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <p>Firefox3 在 beta 和 RC 阶段对 Flash 支持的不好是臭名昭著，用 Google 随便搜索 Firefox3+Flash 看看结果就知道了。</p>
<p>Beata 和 RC 不支持吧。还能说是 bug，今天正式版发布，居然还是不支持，这就说不过去啦。用 Firefox 内嵌的 addons 管理机制安装 Flash 从来就木有成功过。</p>
<p>最后用如下方法才安装成功：</p>
<ol>
<li>下载 <a onclick="javascript: pageTracker._trackPageview('/extlink/fpdownload.macromedia.com/get/flashplayer/current/uninstall_flash_player.exe');"  href="http://fpdownload.macromedia.com/get/flashplayer/current/uninstall_flash_player.exe" target="_blank">Adobe 官方的 FLash 卸载程序</a>；</li>
<li>下载 <a onclick="javascript: pageTracker._trackPageview('/extlink/fpdownload.macromedia.com/get/flashplayer/current/install_flash_player.exe');"  href="http://fpdownload.macromedia.com/get/flashplayer/current/install_flash_player.exe" target="_blank">Adobe 官方的 Flash 安装程序</a>；</li>
<li>关闭 Firefox；</li>
<li>运行卸载程序，再运行安装程序；</li>
<li>如果有必须要，则<a onclick="javascript: pageTracker._trackPageview('/extlink/support.mozilla.com/en-US/kb/Troubleshooting+plugins#Re_initializing_the_plugins_database');"  href="http://support.mozilla.com/en-US/kb/Troubleshooting+plugins#Re_initializing_the_plugins_database" target="_blank">重建 Firefox 插件数据库</a>。</li>
</ol>
<p>最后一步不是必需的，至少偶就木有用到。</p>
<p>现在终于能够看到满屏的 Flash 了……下一步，安装 flashblock 插件屏幕它们～hiahia～～</p>
<p>参考：<a onclick="javascript: pageTracker._trackPageview('/extlink/support.mozilla.com/tiki-view_forum_thread.php?forumId=1&amp;comments_parentId=10088');"  href="http://support.mozilla.com/tiki-view_forum_thread.php?forumId=1&comments_parentId=10088" target="_blank">FIrefox 3 and Flash pluggins </a>。</p> 
            </div>
        </content>
        <dc:subject>firefox</dc:subject>
<dc:subject>flash</dc:subject>
<dc:subject>technique</dc:subject>
<dc:subject>tip</dc:subject>

    </entry>
    <entry>
        <link href="http://blog.nulltao.net/archives/88-Google-Gears.html" rel="alternate" title="做好准备迎接新的平台大战。Google Gears 直指微软领地" />
        <author>
            <name>Wei Geng</name>
            <email>nulltao@gmail.com</email>        </author>
    
        <published>2008-06-16T03:06:36Z</published>
        <updated>2008-06-18T08:12:36Z</updated>
        <wfw:comment>http://blog.nulltao.net/wfwcomment.php?cid=88</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://blog.nulltao.net/rss.php?version=atom1.0&amp;type=comments&amp;cid=88</wfw:commentRss>
    
            <category scheme="http://blog.nulltao.net/categories/4-TranslatioN" label="TranslatioN" term="TranslatioN" />
    
        <id>http://blog.nulltao.net/archives/88-guid.html</id>
        <title type="html">做好准备迎接新的平台大战。Google Gears 直指微软领地</title>
        <content type="xhtml" xml:base="http://blog.nulltao.net/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <p>原文：<a onclick="javascript: pageTracker._trackPageview('/extlink/www.techcrunch.com/2008/06/13/google-drives-towards-microsoft-and-adobe-with-gears/');"  target="_blank" href="http://www.techcrunch.com/2008/06/13/google-drives-towards-microsoft-and-adobe-with-gears/">Get Ready For A New Platform War. Google Gears Drives Straight At Microsoft’s Profits.</a>。</p>
	<hr />
	<p><img width="244" height="158" border="0" src="http://www.techcrunch.com/wp-content/nextgenweb2.jpg" alt="lame_logo" style="border-width: 0px; float: left;"/> </p>
	<p><a onclick="javascript: pageTracker._trackPageview('/extlink/crunchbase.com/company/google');"  href="http://crunchbase.com/company/google" target="_blank">Google</a> 在去年五月发布了 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.crunchbase.com/product/google-gears');"  href="http://www.crunchbase.com/product/google-gears" target="_blank">Gears</a>，之后的一年里 Gears 被认为是一个小众产品，只会有很少开发者和用户用它来开发能够离线访问的 web 程序。兴许你还能回想起当年的争论：在到处都有网络连接的情况下，究竟谁需要离线访问功能，而且还没有足够的程序支持，等等。不到一年的时间，就在几周前，Google 亮出了他的王牌：<a onclick="javascript: pageTracker._trackPageview('/extlink/www.techcrunch.com/2008/05/28/myspace-shows-facebook-how-its-done-google-gears-to-power-messaging/');"  href="http://www.techcrunch.com/2008/05/28/myspace-shows-facebook-how-its-done-google-gears-to-power-messaging/" target="_blank">Gears 助力 MySpace 加速邮件系统</a>。其实 Google 早就加入了这场提供新 web API 的比赛，但是居然一年了都没有人注意到。</p>
	<p>将来的浏览器很可能会变成运行所有程序的虚拟机。在这种情况下，操作系统会变的透明，就像 Adobe 所作的，它的 Flash 技术是现在使用的最普遍、最统一的 web 虚拟机，而微软则要自保（它的利润的来源）了。Google 不隐瞒他们想瞄准并且攻击微软的野心，他们知道，要做到这点的最好方法就是上移一层把操作系统架空，让浏览器成为标准且强劲的应用程序虚拟机。</p>
<p>很难在一片评论里表达清楚 Gears 如何改变并且增加 web 程序的功能。以前使用基于浏览器的 Javascript 脚本，<a onclick="javascript: pageTracker._trackPageview('/extlink/myspace.com');"  href="http://myspace.com" target="_blank">MySpace</a> 中的一些类似邮件列表和排序、根据好友列表过滤这样的功能会让人感觉很慢，而当浏览器向服务器发送多个请求时，进度条还可能会定住，沙漏图标在不停的旋转。而现在，安装 Gears 只要在确认框点击一下并且等待几秒钟，安装之后，以前让用户抓狂的那些功能现在感觉起来就好象是浏览器自带功能一样。Google 给我们秀了一把 Gears 与 MySpace 集成后的能力，这唤醒了大部分人关注他真正的意图：不再仅是离线浏览，而是直接针对 Adobe 和微软所采取的行动。</p>
<p>截至目前为止，Google 拥有一系列共计 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.google.com.au/options/index.html');"  href="http://www.google.com.au/options/index.html" target="_blank">28 个</a>基于 web 的程序, 这些程序在全世界有数百万的用户。Google 开发 web 程序的技术都是基于标准的 HTML、CSS 和 Javascript。选择 <a onclick="javascript: pageTracker._trackPageview('/extlink/en.wikipedia.org/wiki/Ajax');"  href="http://en.wikipedia.org/wiki/Ajax" target="_blank">Ajax</a> 仅仅是因为这是最好的解决方案，但是 Google 还要做更多以面对现实，那就是每个类似的 web 开发技术体系都是被一个<a onclick="javascript: pageTracker._trackPageview('/extlink/crunchbase.com/company/microsoft');"  href="http://crunchbase.com/company/microsoft" target="_blank">直接</a>的<a onclick="javascript: pageTracker._trackPageview('/extlink/crunchbase.com/company/adobe');"  href="http://crunchbase.com/company/adobe" target="_blank">竞争者</a>所开发、控制。Google 对开源浏览器 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.getfirefox.com');"  href="http://www.getfirefox.com" target="_blank">Firefox</a> 的开发给予了强大的支持，并且支持开放 web 标准作为他们的技术体系之选。Google 这么做是因为他们的 web 程序都依赖于开放标准，Firefox 的失败会导致 Internet Explorer 复生并且把 web 的控制权拱手让给微软。</p>
<p>以前，只用基于浏览器的 Javascript 来支持 web 程序对 Google 来说不是个问题。直到竞争者领先一步发布了他们自己的第二代 web 平台，分别是 <a onclick="javascript: pageTracker._trackPageview('/extlink/en.wikipedia.org/wiki/Flex');"  href="http://en.wikipedia.org/wiki/Flex" target="_blank">Flex/AIR</a> 和 <a onclick="javascript: pageTracker._trackPageview('/extlink/crunchbase.com/product/silverlight');"  href="http://crunchbase.com/product/silverlight" target="_blank">Silverlight</a>，情况才发生了变化。基于 web 的程序在有了类桌面的界面和功能后能够做什么，从这一方面开说，微软和 Adobe 已经超前了一大步。用不了多久，大大小小的竞争者就会使用竞争性技术平台创建竞争性程序，那会使 Google 的产品看起来像是还停留在上个世纪九十年代的样子。</p>
<p>留给 Google 的选择现在很明了了：要么放弃使用基于浏览器的 Javascript 和开放标准进行开发，转而接受新技术中的一种，要么继续坚持使用核心 web 技术并且发展这些技术直到成为可行的替代技术。Google 的问题是，新标准和预期的浏览器功能很快就会带来富 web 技术，但是开发那些标准的进度却如此缓慢，以至于很可能需要几年时间才能看到那些标准被广泛的应用。新的 HTML 标准，<a onclick="javascript: pageTracker._trackPageview('/extlink/www.techcrunch.com/2008/06/05/the-next-gen-web-html5-will-we-ever-see-a-real-standard/');"  href="http://www.techcrunch.com/2008/06/05/the-next-gen-web-html5-will-we-ever-see-a-real-standard/" target="_blank">HTML5</a>，特别关注扩展本地浏览器对 web 程序的支持能力，在不用附加私有运行时的情况下。Google web API 的基础就是这些同样的功能以及其他的附加功能。</p>
<p>由于标准开发的极其缓慢，导致通向更快更好，而且仍旧免费开放的 web 程序之路被堵死了，所以 Google 决定通过 Gears 自己进入这个市场。想法其实很简单：把明天的 web 技术带到今天的浏览器里。这些特定的功能大部分都来自新的 HTML5 规范，但是标准制定小组已经在上面花费了好几年。不想再等这个小组完成规范，Google 自己通过件对浏览器进行扩展，实现了这些功能并且达到了那个小组能达到的最高水平。他们宁愿在短期内抛弃标准（原话是“以后再考虑实现”）也要把他们的 web 程序带到能够对抗 Flash 和 Silverlight 的下一代标准。</p>
<p><a onclick="javascript: pageTracker._trackPageview('/extlink/www.crunchbase.com/person/vic-gundotra');"  href="http://www.crunchbase.com/person/vic-gundotra" target="_blank"><img style="float: right;" src="http://www.crunchbase.com/assets/images/resized/0001/7940/17940v1-max-250x250.jpg"/></a></p>
<p>Gears 有一个 30 人左右的小组开发，这个小组是 Google 内部开源小组的一部分。这个小组由 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.crunchbase.com/person/vic-gundotra');"  href="http://www.crunchbase.com/person/vic-gundotra" target="_blank">Vic Gundotra</a> 带领，再一次讽刺的转变过程中，他由微软的传教士成为 Google 的高级开发者。这个一小组开发者着手进行开发，并且保持 Google 对 Javascript 和开放浏览器虚拟机的兴趣。理论上，他们看起来很可能被大组织或者微软和 Adobe 正在投入各自平台的预算所超过。为了改变这个状况，他们把 Gears 从 Google 中分离出来（字面上也是——现在这个项目名称就只是“Gears”）并且在开源协议下发布源代码。</p>
<p>第一个发行版将只关注于 HTML5 里面提议的新功能中他们认为最重要的功能：<a onclick="javascript: pageTracker._trackPageview('/extlink/www.techcrunch.com/2008/05/29/the-next-gen-web-browser-storage-support/');"  href="http://www.techcrunch.com/2008/05/29/the-next-gen-web-browser-storage-support/" target="_blank">基于客户端的结构化数据和对象存储</a>。由于选择了首先实现客户端存储，所以下一年里 Gears 会被构架成一个离线应用程序解决方案，由于其他的竞争者好像都没有注意到这个这么巨大目标，所以如果他们不是有意而为之，那么肯定会发展的很好。Google 本来有可能开发他们自己的浏览器，某些博客里的推测和谣言也都指出了这一点，但是浏览器市场竞争激烈，却平淡乏味，而且通常会失败。另外，即使他们开发了自己的新浏览器，他们还要驱使用户接受这个新浏览器，在决定性的市场聚集起来之前只能等待，就是这样，市场上还会有 70% 或者 80% 甚至 90% 的人不使用 Google 的浏览器，却想使用 Google 的程序。</p>
<p>这种情况下，可选的捷径就是跳过浏览器直接在上面增加一层——Google 自己的 web 层。所有常用浏览器都提供了让开发者扩展功能的机制，这样一来，Google 要做的就是对每个浏览器开发对应的插件。这能让新的 web API 能够适应所有的桌面而不需要用户去适应，最重要的，这比起进入浏览器市场来说见效快而且痛苦少。现在可以让浏览器来做所有无聊的事情：渲染 HTML、显示界面、用户选项等等，与此同时 Google 却在改变现状，埋头向前冲。</p>
<p>现在 Gears 支持大量完整的新功能，有一些新功能是和微软、Adobe 他们的下一代 web API 相同的，而其他的则是 Google 自己创造出来的。现在函数调用已经<a onclick="javascript: pageTracker._trackPageview('/extlink/code.google.com/p/gears/w/list');"  href="http://code.google.com/p/gears/w/list" target="_blank">对开发者开放</a>了，包括后台处理（不会再有沙漏出现）、客户端图像处理、位置感知、更好的文件上传功能，还有浏览器内本地数据库。</p>
<p>要让新 API 和开发平台的应用被采用需要两方面的支持，一方面是用户的支持，因为这需要用户安装新的插件；另一方面是开发者的支持，使用 Gears 不会让开发变得更容易，这是因为这和开发其他的使用基于浏览器的 Javascript 的程序没有区别，Gears 只是给开发者提供了一系列更多的可以在浏览器内实现的功能而已。Javascript 和 web 开发者不需要学习任何新知识，用户也要做的也只是安装一个插件（与浏览器绑定的交易肯定会发生，所以这一步都可以忽略了）。Flash 花了 5 到 6 年才足够普及，能够让开发者有信心专注于使用 Flash 开发，不过有了 Google 的支持，Gears 可能只需要用一半甚至更小的时间就能做到。</p>
<p>在这场竞赛中，Google 没有任何损失反而赢得盆满钵丰，Google 一下子就启动了这个新 web API 的基于标准且开源的替代方案。与其他的竞争对手不一样，Google 没有兴趣控制这个平台或者直接用来盈利。相反他们却在试图维持现状：大部分程序使用浏览器里的 Javascript 开发，如果有更多需求那就使用 Flash 或者类似的技术。</p>
<p>上一次平台大战结束了很久了，但是每次你都能看到类似的技术经验：大公司失败，小公司成功。给这个平衡增加点开源的砝码，结果还是没有一个单独的公司能够占优势。有这么多大公司的加入，而且如此的利益攸关，我们肯定要亲眼见证一场漫长的持久战。只有时间能够告诉我们 Google 的做法能不能带领 web 向前发展。</p>
<p><i>本文是 Nik Cubrilovic 写的下一代 web 系列中的一篇，<a href="http://blog.nulltao.net/plugin/tag/nextgenweb">在这阅读其他同系列文章</a>。</i></p> 
            </div>
        </content>
        <dc:subject>nextgenweb</dc:subject>
<dc:subject>techcrunch</dc:subject>
<dc:subject>translation</dc:subject>
<dc:subject>trashcan</dc:subject>

    </entry>
    <entry>
        <link href="http://blog.nulltao.net/archives/87-webHTML5.html" rel="alternate" title="下一代 web：HTML5——我们能等到真正的标准吗？" />
        <author>
            <name>Wei Geng</name>
            <email>nulltao@gmail.com</email>        </author>
    
        <published>2008-06-09T12:31:34Z</published>
        <updated>2008-06-16T02:59:04Z</updated>
        <wfw:comment>http://blog.nulltao.net/wfwcomment.php?cid=87</wfw:comment>
    
        <slash:comments>2</slash:comments>
        <wfw:commentRss>http://blog.nulltao.net/rss.php?version=atom1.0&amp;type=comments&amp;cid=87</wfw:commentRss>
    
            <category scheme="http://blog.nulltao.net/categories/3-TrashcaN" label="TrashcaN" term="TrashcaN" />
    
        <id>http://blog.nulltao.net/archives/87-guid.html</id>
        <title type="html">下一代 web：HTML5——我们能等到真正的标准吗？</title>
        <content type="xhtml" xml:base="http://blog.nulltao.net/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <p>原文：<a onclick="javascript: pageTracker._trackPageview('/extlink/www.techcrunch.com/2008/06/05/the-next-gen-web-html5-will-we-ever-see-a-real-standard/');"  href="http://www.techcrunch.com/2008/06/05/the-next-gen-web-html5-will-we-ever-see-a-real-standard/" target="_blank">The Next-Gen Web: HTML5 - Will We Ever See A Real Standard?</a>。</p>
<hr />
<p><img style="border-width: 0px; float: left;" alt="lame_logo" src="http://www.techcrunch.com/wp-content/nextgenweb2.jpg" border="0" height="158" width="244">
	</p><p>本地存储相关的 API 作为最新的 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.whatwg.org/specs/web-apps/current-work/multipage/introduction.html#introduction');"  target="_blank" href="http://www.whatwg.org/specs/web-apps/current-work/multipage/introduction.html#introduction">HTML5</a> 规范草案的一部分，我们在<a target="_blank" href="http://blog.nulltao.net/archives/86-web.html">上个星期</a>看到一些浏览器和插件已经开始采纳这些 API。虽然 <a onclick="javascript: pageTracker._trackPageview('/extlink/crunchbase.com/product/gears');"  target="_blank" href="http://crunchbase.com/product/gears">Gears</a>、<a onclick="javascript: pageTracker._trackPageview('/extlink/www.opera.com');"  target="_blank" href="http://www.opera.com">Opera</a> 还有 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.webkit.org');"  target="_blank" href="http://www.webkit.org">Webkit</a> 都已经实现了结构化存储部分的 API，但是 HTML5 规范里其他的部分当前还都没有怎么实现，而且前途不明。HTML5 尽了最大的努力来让所有的浏览器都统一在一个单一且标准化的标记语言和一系列 API 下——但是 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.silverlight.net');"  target="_blank" href="http://www.silverlight.net">微软</a>、<a onclick="javascript: pageTracker._trackPageview('/extlink/www.acrobat.com');"  target="_blank" href="http://www.acrobat.com">Adobe</a> 和 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.curl.com');"  target="_blank" href="http://www.curl.com">其他</a>的领先者们都有了自己的下一代 web 技术，那么我们还能看到真正的 HTML5 标准吗？</p>
<p><big><strong>历史的教训</strong></big></p>
<p><a onclick="javascript: pageTracker._trackPageview('/extlink/www.techcrunch.com/wp-content/netscape.jpg');"  target="_blank" href="http://www.techcrunch.com/wp-content/netscape.jpg"><img style="border-width: 0px;" alt="netscape" src="http://www.techcrunch.com/wp-content/netscape-thumb.jpg" align="right" border="0" height="184" width="244"></a>在适用范围和成果方面，HTML5的成果与历史上早期的 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.w3.org/MarkUp/html3/Contents.html');"  target="_blank" href="http://www.w3.org/MarkUp/html3/Contents.html">HTML 3.0 规范</a> 有所相似。返回到 1995 年 4 月，开始起草 HTML 3.0 规范，其目的是向后兼容 HTML 2.0 并且添加新的特性（例如表格）。当时 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.w3.org');"  target="_blank" href="http://www.w3.org">W3C</a> 刚刚成立，这个新工作组要完成的第一批规范之一就是 HTML 3.0 规范。
	 在那个时候，浏览器大战即将爆发，当时 <a onclick="javascript: pageTracker._trackPageview('/extlink/web.archive.org/web/19961020015116/http://www3.netscape.com/');"  target="_blank" href="http://web.archive.org/web/19961020015116/http://www3.netscape.com/">Navigator</a> 才发布了五个月，却占有了 80% 的市场份额。微软却才注意到这点，然后仓促的开始开发 Internet Explorer 1.0，并在几个月后发布。</p>
<p>在 1995 年，不同的浏览器支持不同系列的标记——一直到现在还是这样。随着 Navigator 1.1 新版本的发布，网景突飞猛进，而且还实现了表格、浮动图片和其他的导航元素（例如点击过的链接）。IE 1 是一个完全改造过的浏览器，因为它采用了最大化渲染的方法，就是说，如果 IE 无法确定用户对 HTML 所期望的表现，就尽量猜测并且显示猜测结果。 这导致了很多类似标签不匹配的问题（例如 <code>&lt;b&gt;&lt;p&gt;Header&lt;/b&gt;&lt;/p&gt;</code>）出现，因为 IE 能够自动纠错，所以这些问题又导致开发者变得懒惰。</p>
<p>随着 Internet Explorer 的市场占有率持续上升，以及网景和微软各自浏览器的每一次发布和更新，两个浏览器的距离越来越大，市场也随之分成了两个坚固的阵营。以前以 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.faqs.org/rfcs/');"  target="_blank" href="http://www.faqs.org/rfcs/">RFC</a> 形式出现的，现在叫做 HTML 的规范，本来的目的是重新统一浏览器，并且让浏览器已经支持的新功能规范化。但是在规范制定者中经常会弥漫着剑拔弩张的气氛，争论究竟哪个浏览器——Navigator 还是 Explorer——对新功能实现的更好。例如，Navigator 和 Explorer 对<a onclick="javascript: pageTracker._trackPageview('/extlink/www.free-cgi.com/freecgi/reference/multi.php');"  target="_blank" href="http://www.free-cgi.com/freecgi/reference/multi.php">图片映射图</a>的实现方式就很不一样，而且还互不兼容。微软要为制造那些混乱的 HTML 标签所负责，例如使用 &lt;top&gt; 和 &lt;bottom&gt; 标签来定义页面中不变的部分（拜网景所赐，这些标签后来演变成了很不友好的框架标签）。</p>
<p>问题不在于新功能无序的开发，而是两个竞争激烈的浏览器都在实现各自版本的 web，以保卫自己的市场份额并且或者更多的控制权。最后，网景和微软都放弃实现正统的 HTML 3.0 规范，例如<a onclick="javascript: pageTracker._trackPageview('/extlink/wp.netscape.com/assist/net_sites/html_extensions_3.html');"  target="_blank" href="http://wp.netscape.com/assist/net_sites/html_extensions_3.html">网景声明</a>：</p>
<blockquote><p>网景承诺继续支持 HTML 3.0。出于这样的原因，我们走在了前面，采纳了一些更加成熟的方案，我们希望这些方案能够被认可。我们坚信网景 Navigator 2.0 比其他的任何一个商用客户端对 HTML 3.0 规范支持的更好。</p>
<p><strong>此外，我们在网景 Navigator 中增加了一些现在还未被 HTML 3.0 规范包含的新功能</strong>。我们认为这些新功能应该被加进去，作为标准流程的一部分，我们正在<a onclick="javascript: pageTracker._trackPageview('/extlink/wp.netscape.com/assist/net_sites/new_html3_prop.html');"  target="_blank" href="http://wp.netscape.com/assist/net_sites/new_html3_prop.html">提议</a>标准加入这些新功能</p>
</blockquote>
<p>而微软被落在支持 HTML 小组成员的后面<a onclick="javascript: pageTracker._trackPageview('/extlink/www.macuser.co.uk/macuser/reviews/16110/microsoft-internet-explorer-21.html');"  target="_blank" href="http://www.macuser.co.uk/macuser/reviews/16110/microsoft-internet-explorer-21.html">紧紧追赶</a>：</p>
<blockquote><p>网景非常享受他在浏览器市场上的事实垄断地位（据估算约有 90%），这让网景可以通过引入非官方的，或者所谓的“扩展”标签来加固它的垄断地位。结果导致 web 上充斥着只能在 Navigator 里面正确的浏览的垃圾页面。等到其他的浏览器追上来的时候，网景完成了更多这样的扩展。</p>
</blockquote>
<p>但是持续了不长时间，微软就厌倦了这种玩法。新的发行版<a onclick="javascript: pageTracker._trackPageview('/extlink/www.microsoft.com/presspass/press/1996/apr96/iemompr.mspx');"  target="_blank" href="http://www.microsoft.com/presspass/press/1996/apr96/iemompr.mspx">甚至都不提及 HTML</a> 而是改为讨论构建在微软技术上的 web：</p>
<blockquote><p>微软 Internet Explorer 3.0 是第一个集成了<a onclick="javascript: pageTracker._trackPageview('/extlink/www.wiley.com/legacy/compbooks/catalog/16177-2.htm');"  target="_blank" href="http://www.wiley.com/legacy/compbooks/catalog/16177-2.htm">ActiveXTM</a> 技术的英特网客户端，这项技术能让开发者能够在英特网上创建具有很高交互性的程序和内容。这些技术能够让万维网站变得丰富、互动，就像动作游戏、多媒体百科全书或者生产力应用程序那样。有史以来，网站第一次不再被技术所限制，而仅仅受限于作者想象力。</p>
</blockquote>
<p>浏览器大战爆发了快一年的时候，战争从对 HTML 标签支持的斗争升级到了开发富客户端程序的格式和语言之争。在 1996 年 8 月，随着 Internet Explorer 3.0 的发布，<a onclick="javascript: pageTracker._trackPageview('/extlink/en.wikipedia.org/wiki/JavaScript');"  target="_blank" href="http://en.wikipedia.org/wiki/JavaScript">Javascript</a>（网景私有的客户端脚本语言）和 <a onclick="javascript: pageTracker._trackPageview('/extlink/en.wikipedia.org/wiki/ActiveX');"  target="_blank" href="http://en.wikipedia.org/wiki/ActiveX">ActiveX</a>（微软私有的对象容器）之间的斗争一触即发。</p>
<p>这个故事剩下的部分就是微软在哪里取得胜利的，以及更重要的，微软是怎么赢的，然后浏览器大战已经成为了历史。由于 Web 分裂的很严重，其影响持续了十几年，浪费了开发者很多的时间去开发跨浏览器技巧和各种库。尽管微软得到了浏览器市场的控制权，而且一直不遗余力的推销它私有的用于构建 web 程序的多层技术，但是不知怎么的，最简单的 <a onclick="javascript: pageTracker._trackPageview('/extlink/en.wikipedia.org/wiki/Ajax');"  target="_blank" href="http://en.wikipedia.org/wiki/Ajax">HTML、Javascript 和 CSS</a> 却赢得了广泛的支持，而且 Web 2.0 也没有构建在 ActiveX 的基础上。</p>
<p><big><strong>十年后</strong></big></p>
<p>随着网景逐渐消失并且被 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.getfirefox.com');"  target="_blank" href="http://www.getfirefox.com">Firefox</a> 替代，今天的 web 大战不仅仅发生在浏览器之间，而且还发生在新 web 平台和技术之间。<a onclick="javascript: pageTracker._trackPageview('/extlink/en.wikipedia.org/wiki/Usage_share_of_web_browsers');"  target="_blank" href="http://en.wikipedia.org/wiki/Usage_share_of_web_browsers">据估计</a>，Internet Explorer 的市场占有率已经降到了 78%（2004 年达到了最高的 95% 市场占有率），同时 Firefox 占有 16%，Safari、Opera 和其他的浏览器共同占有剩下的 6%。1999 年 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.w3.org/TR/REC-html40/');"  target="_blank" href="http://www.w3.org/TR/REC-html40/">HTML 4.01</a> 规范发布，因为大部分浏览器都内置了对该规范的支持使得该规范成为 ISO 标准。HTML 4.01 一直是支持的最广泛、最好的 HTML 标准，不过现在的问题已经转移到了其他的 web 技术上，尤其是 CSS 和 DOM 访问。</p>
<p>在现在被称之为 Web 2.0 领域内，上千个富 web 程序都是使用 HTML、CSS 和 XML 开发的——通常称之为 AJAX（很讽刺的是，AJAX中的 A 和 X 部分最开始时是 Internet Explorer 的私有插件，以 <a onclick="javascript: pageTracker._trackPageview('/extlink/msdn.microsoft.com/en-us/library/ms535874%28VS.85%29.aspx');"  target="_blank" href="http://msdn.microsoft.com/en-us/library/ms535874%28VS.85%29.aspx">xmlhttprequest</a> 的形式出现的）。虽然 AJAX 程序很快就达到了当前技术所能实现的极限，但是这些程序缩短了桌面程序和 web 程序之间的距离。很多厂商都发布了他们支持的 web 客户端平台作为浏览器之上的一层，例如 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.crunchbase.com/company/adobe');"  target="_blank" href="http://www.crunchbase.com/company/adobe">Adobe</a> 开发的 Flash、<a onclick="javascript: pageTracker._trackPageview('/extlink/www.crunchbase.com/company/microsoft');"  target="_blank" href="http://www.crunchbase.com/company/microsoft">微软</a>开发的 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.silverlight.net');"  target="_blank" href="http://www.silverlight.net">Silverlight</a> 等，这给开发者展示了一个丰富多彩的，开发类桌面化的 web 程序的开发环境。这些新的平台通过在现在的浏览器基础上增加插件来生效，由于这些商业解决方案的发布，导致当下没有一个合适的、开源的、基于开放标准的、超过 AJAX 的替代品出现。</p>
<p>在 W3，一组浏览器开发者受挫于 HTML5 缓慢的进展，他们独立出去成立了 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.whatwg.org/');"  target="_blank" href="http://www.whatwg.org/">WHATWG</a> 小组以促进该规范的开发。HTML5 的首要任务就是认清楚现状，那就是从最初的 HTML 规范发布以来，web已经发生了翻天覆地的变化，现在的 web 程序能够展示非常复杂的用户界面，能够利用更多的高级系统功能（以界面为例，Silverlight 使用 XAML，Flex/Flash 使用 MXML）。该标准开始成为 Web Applications 1.0，这个宽泛概念不仅包括有新的 HTML5 规范，还包括了其他相关的规范，例如 CSS2、DOM5、ECMAv4 和新的 API 调用（例如本地浏览器存储）。</p>
<p>WHATWG 工作组最终（4年后）又返回了 W3，微软也重新投入了力量。与此同时，开发者如果要搜索不是 AJAX 的富 web 程序平台，只会得到很少的结果，除非他们投入微软或者 Adobe 的怀抱。HTML5 规范的实现进展非常缓慢，直到 <a onclick="javascript: pageTracker._trackPageview('/extlink/gears.google.com');"  target="_blank" href="http://gears.google.com">Google</a> 意识到微软和 Adobe 正在统治 web 的威胁并且通过开发 <a onclick="javascript: pageTracker._trackPageview('/extlink/gears.google.com');"  target="_blank" href="http://gears.google.com">Gears</a> 介入才有所改观。Gears 是 Google 匆忙的在浏览器上实现 HTML5 的产物，他们使用 <a onclick="javascript: pageTracker._trackPageview('/extlink/crunchbase.com/product/gmail');"  target="_blank" href="http://crunchbase.com/product/gmail">Gmail</a> 和 <a onclick="javascript: pageTracker._trackPageview('/extlink/crunchbase.com/product/reader');"  target="_blank" href="http://crunchbase.com/product/reader">Reader</a> 这些自己的程序一步步的支持这些新的 API 调用</p>
<p><a onclick="javascript: pageTracker._trackPageview('/extlink/www.crunchbase.com/company/apple');"  target="_blank" href="http://www.crunchbase.com/company/apple">苹果</a>是另外一家全力支持使用非 HTML5 的开放技术开发富网络程序的公司。就在几年前，访问苹果主公司主页的浏览者所看见的是充斥着 Flash 和 PDF 文件的页面。现在，苹果拥有了 Safari——他们自己的基于开放标准的浏览器，并且支持 Webkit 这个开源项目。苹果使用 AJAX 而不是 Flash 这样的私有技术重新开发了他们的网站和程序，他们通过这样的方式来支持免费且开放的技术。</p>
<p>我们又回到了 1996 年，只不过现在 HTML5 成了新的 HTML 3.0， 当时只有两个主要浏览器厂商，而现在有很多的团体都对决定新的 web API 和虚拟机的样子充满兴趣。在这一九十年代的事件里，开放标准赢得了最终的胜利——微软和 Adobe 意识到这点后他们都公开了一些各自平台源代码和 API 细节。</p>
<p>Web 历史告诉我们，在通常情况下，只会有一个胜出者，然后所有的用户都逐渐迁移到这个胜出的解决方案上，并且使之成为一个标准（回想一下很多现在的“标准”最初都是私有技术）。尽管类似 Windows 操作系统这样的标准和类似 HTML5 这样的开放标准之间的差异巨大——但是类似 Google 和苹果这样的公司要面对的最大的威胁就是历史的重演。</p>
<p>&#160;</p>
<p><a onclick="javascript: pageTracker._trackPageview('/extlink/www.techcrunch.com/wp-content/current-web-tech.jpg');"  target="_blank" href="http://www.techcrunch.com/wp-content/current-web-tech.jpg"><img style="border-width: 0px;" alt="current-web-tech" src="http://www.techcrunch.com/wp-content/current-web-tech-thumb.jpg" border="0" height="204" width="554"></a> </p>
<p><em>“下一代 web”系列中的上一篇讨论的是本地浏览器存储，点击<a target="_blank" href="http://blog.nulltao.net/archives/86-web.html">这里</a>阅读。</em></p> 
            </div>
        </content>
        <dc:subject>nextgenweb</dc:subject>
<dc:subject>techcrunch</dc:subject>
<dc:subject>translation</dc:subject>
<dc:subject>trashcan</dc:subject>

    </entry>
    <entry>
        <link href="http://blog.nulltao.net/archives/86-web.html" rel="alternate" title="下一代 web：浏览器存储支持" />
        <author>
            <name>Wei Geng</name>
            <email>nulltao@gmail.com</email>        </author>
    
        <published>2008-06-06T18:40:17Z</published>
        <updated>2008-06-16T02:58:54Z</updated>
        <wfw:comment>http://blog.nulltao.net/wfwcomment.php?cid=86</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://blog.nulltao.net/rss.php?version=atom1.0&amp;type=comments&amp;cid=86</wfw:commentRss>
    
            <category scheme="http://blog.nulltao.net/categories/4-TranslatioN" label="TranslatioN" term="TranslatioN" />
    
        <id>http://blog.nulltao.net/archives/86-guid.html</id>
        <title type="html">下一代 web：浏览器存储支持</title>
        <content type="xhtml" xml:base="http://blog.nulltao.net/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <p>原文：<a onclick="javascript: pageTracker._trackPageview('/extlink/www.techcrunch.com/2008/05/29/the-next-gen-web-browser-storage-support/');"  href="http://www.techcrunch.com/2008/05/29/the-next-gen-web-browser-storage-support/" target="_blank">The Next-Gen Web: Browser Storage Support</a>。</p>
<hr />
<p><img width="244" height="158" border="0" src="http://www.techcrunch.com/wp-content/nextgenweb2.jpg" alt="lame_logo" style="border-width: 0px; float: left;"/> 下一代的 web 已经开始上路了，就在这个星期，<a onclick="javascript: pageTracker._trackPageview('/extlink/www.techcrunch.com/2008/05/28/myspace-shows-facebook-how-its-done-google-gears-to-power-messaging/');"  href="http://www.techcrunch.com/2008/05/28/myspace-shows-facebook-how-its-done-google-gears-to-power-messaging/" target="_blank">MySpace 集成了 Google Gears</a>，雅虎发布了<a onclick="javascript: pageTracker._trackPageview('/extlink/www.techcrunch.com/2008/05/28/yahoo-unveils-webtop-plugin-browserplus-before-its-ready/');"  href="http://www.techcrunch.com/2008/05/28/yahoo-unveils-webtop-plugin-browserplus-before-its-ready/" target="_blank">新的 BrowserPlus</a>，Google 的浏览器版<a onclick="javascript: pageTracker._trackPageview('/extlink/www.techcrunch.com/2008/05/28/google-earths-3d-goodness-comes-to-the-browser/');"  href="http://www.techcrunch.com/2008/05/28/google-earths-3d-goodness-comes-to-the-browser/" target="_blank">三维地球</a>也上线了。类似 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.adobe.com/products/air/');"  href="http://www.adobe.com/products/air/" target="_blank">AIR</a>、<a onclick="javascript: pageTracker._trackPageview('/extlink/www.silverlight.net');"  href="http://www.silverlight.net" target="_blank">Silverlight</a>、<a onclick="javascript: pageTracker._trackPageview('/extlink/www.techcrunch.com/java.sun.com/javafx/');"  href="http://www.techcrunch.com/java.sun.com/javafx/" target="_blank">JavaFX</a>、<a onclick="javascript: pageTracker._trackPageview('/extlink/gears.google.com');"  href="http://gears.google.com" target="_blank">Gears</a>、<a onclick="javascript: pageTracker._trackPageview('/extlink/www.mozilla.org/projects/xul/');"  href="http://www.mozilla.org/projects/xul/" target="_blank">XUL</a>、<a onclick="javascript: pageTracker._trackPageview('/extlink/www.whatwg.org/specs/web-apps/2005-09-01/');"  href="http://www.whatwg.org/specs/web-apps/2005-09-01/" target="_blank">Web Applications 1.0</a> (DOM5, HTML5 等) 这样的技术和格式让开发者能够超过 AJAX 加速冲向下一代的，有着更好的性能、更多的功能，而且和桌面集成的更加紧密的 web 程序。</p>
	<p>现在，因为各个公司都急于展示他们自己的下一代 web 的样子，导致开发者和用户都被前所未有的超多 web 技术所压迫；“DLL 地狱”也被“插件地域”所取代。但是在 web 上，这样过多的选择会导致用户和开发者的成本增加。第一次 web 格式大战已经过去十多年了，那个时候微软、网景、苹果、美国在线还有其他公司都在浏览器标准、脚本语言、web 服务等方面成立了不同的基金会。这次大战的影响一直持续到现在，例如 Javascript 来发展需要依赖<a onclick="javascript: pageTracker._trackPageview('/extlink/www.dojotoolkit.org/');"  href="http://www.dojotoolkit.org/" target="_blank">整套</a>的<a onclick="javascript: pageTracker._trackPageview('/extlink/developer.yahoo.com/yui/');"  href="http://developer.yahoo.com/yui/" target="_blank">代码库</a>来开发跨浏览器代码，CSS 开发者需要<a onclick="javascript: pageTracker._trackPageview('/extlink/www.webdevout.net/css-hacks');"  href="http://www.webdevout.net/css-hacks" target="_blank">一系列 hack</a> 才能让他们的站点能够在不同的浏览器中看起来都一样。</p>
	<p>现在新一代的富 web 程序技术还都在开发阶段，所以还有机会采用基于标准的态度，来避免重蹈覆辙。幸亏有了过去十多年的教训，现在连微软这样的公司都在以更加开放的姿态来接纳开放标准、数据迁移还有跨平台支持。不管是用户还是开发者，对开放标准的广泛支持都能简化他们用到的技术，但是明显的，并不是所有当前发布的新技术都能支持开放标准。</p>
<p>在 Techcrunch 这一系列帖子里，我们来看看这些组成新一代 web 的各种元素，并且评估可用的选项，当前支持的标准以及对标准的采用情况。由于 MySpace 刚刚宣布他们在程序里面使用了 Google Gears，那么我们的第一篇就来评估基于浏览器的本地缓存。</p>
<p><big><strong>基于浏览器的本地存储</strong></big></p>
<p>随着基于 web 的应用程序逐渐流行，就有了希望能够离线运行这些程序的需求。第一个不需要任何插件或者独立程序的解决方案是那些靠缓存 HTTP 头信息来在浏览器缓存里存储信息的方法。类似 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.sitepen.com/blog/2007/01/23/the-dojo-offline-api/');"  href="http://www.sitepen.com/blog/2007/01/23/the-dojo-offline-api/" target="_blank">Dojo 对离线 web 应用的支持</a>这样的 Javascript 库使用的就是这样的原理，但是这样的程序应用范围非常狭窄，因为没有一个好的办法在浏览器里存储结构化的数据。（Dojo 现在引用了很多<a onclick="javascript: pageTracker._trackPageview('/extlink/dojotoolkit.org/offline');"  href="http://dojotoolkit.org/offline" target="_blank">包括 Gears 在内的其他的存储引擎</a>——提示：<a onclick="javascript: pageTracker._trackPageview('/extlink/www.dylanschiemann.com/');"  href="http://www.dylanschiemann.com/" target="_blank">Dylan</a>）</p>
<p>在 2007 年 5 月，Google 发布了<a onclick="javascript: pageTracker._trackPageview('/extlink/gears.google.com');"  href="http://gears.google.com" target="_blank">Google Gears</a>，一个浏览器插件，它允许 web 程序把数据同步到本地存储器，然后可以离线使用这些 web 程序。在 Gears 发布会上，Google Reader 被重写以支持 Gears，Gears 的突出的重点是离线访问应用程序。但是不被所知的是，Gears 不仅仅能够用来离线访问，它还提供这三大功能：
</p><ul>
<li>缓存资源（HTML 页面、图片等）</li>
<li>在数据库中存储结构化数据</li>
<li>异步后台工作线程</li>
</ul>
<p>在这部分我们关注的是本地对象和结构化数据存储。Gears 通过 Javascript API 来提供相应的功能，这些 API 可以被任何 web 程序访问到。<a onclick="javascript: pageTracker._trackPageview('/extlink/www.sqlite.org');"  href="http://www.sqlite.org" target="_blank">Sqlite</a>，一个轻量级 RDBMS，提供了结构化存储的支持。由于使用了本地数据库，开发者不仅可以执行查询、插入新纪录这样的操作，还能执行更复杂的 SQL 操作，例如连接多表查询等。尽管你可以有多个使用 Gears 的程序，但是每个程序都要运行在一个基于域名的安全模型的沙盒环境里（类似 cookie 和 AJAX 请求）。虽然 Sqlite 已经<a onclick="javascript: pageTracker._trackPageview('/extlink/developer.mozilla.org/en/docs/Storage');"  href="http://developer.mozilla.org/en/docs/Storage" target="_blank">嵌入 Firefox 2.0 以后的版本</a>，但是它的 API 只能够被 Firefox 核心组件或者附加模块访问到。Gears 插件弥补了这个缺陷，让客户端脚本环境也能够访问到这些 API。</p>
<p>在 Gears 发布前，<a onclick="javascript: pageTracker._trackPageview('/extlink/www.whatwg.org/');"  href="http://www.whatwg.org/" target="_blank">万维网超文本应用程序技术工作组</a> (WHATWG) 已经着手制定 Web 程序规范 1.0 草案，这个草案把结构化数据存储包括到了 HTML5 里。该草案当前版本包含了对访问<a onclick="javascript: pageTracker._trackPageview('/extlink/www.whatwg.org/specs/web-apps/current-work/#structured');"  href="http://www.whatwg.org/specs/web-apps/current-work/#structured" target="_blank">数据库对象</a>和查询本地数据存储的定义。实现的细节虽然交给了各个公司去完成，不过规范里面已经详细说明了 API 的细节。Firefox 将会在 <a onclick="javascript: pageTracker._trackPageview('/extlink/developer.mozilla.org/en/docs/Firefox_3_for_developers');"  href="http://developer.mozilla.org/en/docs/Firefox_3_for_developers" target="_blank">3.0 版</a>里实现一部分和 WHATW 规范一样的存储 API，不过这个版本现在只有预览版可用。WHATWG 规范里的关键部分有：</p>
<ul>
<li><em><a onclick="javascript: pageTracker._trackPageview('/extlink/www.whatwg.org/specs/web-apps/current-work/#offline');"  href="http://www.whatwg.org/specs/web-apps/current-work/#offline" target="_blank">程序缓存</a> </em>——在本地浏览器缓存里存储对象（包含校验）。</li>
<li>navigator.onLine——测试浏览器是否在线（使用缓存，如果需要则加上本地数据存储）。</li>
<li><em><a onclick="javascript: pageTracker._trackPageview('/extlink/www.whatwg.org/specs/web-apps/current-work/#storage');"  href="http://www.whatwg.org/specs/web-apps/current-work/#storage" target="_blank">存储</a></em>界面和事件——用来通过 <u>sessionStorage</u> DOM 属性存储“名称／值”对。</li>
<li><em><a onclick="javascript: pageTracker._trackPageview('/extlink/www.whatwg.org/specs/web-apps/current-work/#sql');"  href="http://www.whatwg.org/specs/web-apps/current-work/#sql" target="_blank">数据库</a></em>界面——用来连接本地数据库。支持 SQL语法（或者其子集，取决于使用的服务器）、版本控制和错误回调事件。</li>
<li>线程和回调——这样多个请求就能够异步发送给本地数据存储。</li>
</ul>
<p>调用本地存储、缓存和离线访问相对来说很简单。程序首先检查是否支持相应的函数，然后通过在后台同步用户数据进程来设置本地缓存。当一个线程在运行的时候，不管是上传还是下载，你可以查询进程状态并且给用户一个反馈（例如一个进度条）。一旦数据本地化，由于是在本地机器上运行数据库，开发者就能<em>大幅度的</em>提高查询性能。当下很多 web 程序仅仅把浏览器用作展示层，例如，电子表格软件就是做 <em>=1+1</em> 这样简单的计算也要进行一次到服务器再返回的请求。通过使用本地数据存储和客户端代码，开发者可以减少到处理和存储到客户端的负荷，同时还能提供给用户更加平滑、类似桌面程序的体验。</p>
<p><big><strong>当前和将来的支持情况</strong></big></p>
<p>现在的问题是大部分 WHATW 规范都是在 Gears 发布后才写的，导致 Gears 使用的数据库和本地服务器对象和 WHATW 规范不兼容——至少当下是这样的。好消息是 Google 已经发现了这个问题，<a onclick="javascript: pageTracker._trackPageview('/extlink/gearsblog.blogspot.com/2008/04/gears-and-standards.html');"  href="http://gearsblog.blogspot.com/2008/04/gears-and-standards.html" target="_blank">完全支持</a> WHATWG HTML5 规范中的存储部分，因此，对于那些运行在安装了 Gears 的 Firefox 3 中的程序的开发者来说，他们可以选择使用 Firefox 原生的还是 Google 实现的存储。Google 还说他们很可能会提供额外的功能，以激励开发者关注那些 Gears 超越 HTML5 的实现（例如桌面快捷方式等）。</p>
<p>其他的本地数据存储可选方案，例如 Flash 本地存储，和 WHATW 规范完全不兼容。<a onclick="javascript: pageTracker._trackPageview('/extlink/webkit.org/blog/126/webkit-does-html5-client-side-database-storage/');"  href="http://webkit.org/blog/126/webkit-does-html5-client-side-database-storage/" target="_blank">WebKit 的开发人员很快声明</a>他们也开始实现 HTML5 规范中的存储部分。而且在每晚构建的代码里已经可用了，因此很快我们就能看到 Konquror 和 Safari 对本地存储的支持。Opera 也声明了类似的计划，而且当然他实现了 HTML5 和 web 表单后他们会领先于所有人。雅虎 BrowserPlus 昨天才发布，所以现在还不明确他们他们的本地存储支持和工作组发布的规范是否兼容。</p>
<p>本地存储是新一代的 web API 中重要的新功能，开发者不仅有跨浏览器的一致支持，还可以选择使用 Google Gears（已经可用）还是 Yahoo! BrowserPlus（取决于它如果工作）。还有一个浏览器厂商我们到现在一直没有谈到，那就是微软。微软发布了 IE8 的一个早期预览版，而且预告了大量的新特性，其中很多都是基于开放标准的，例如更好的 CSS 和 Javascript 支持（内涵一个更加标准化的对象模型）。最大问题是，IE8 在本地存储方面会不会遵循和其他浏览器厂商一致规范。IE 开发小组声称 IE8 <a onclick="javascript: pageTracker._trackPageview('/extlink/www.microsoft.com/windows/products/winfamily/ie/ie8/readiness/DevelopersNew.htm#ajax');"  href="http://www.microsoft.com/windows/products/winfamily/ie/ie8/readiness/DevelopersNew.htm#ajax" target="_blank">将会支持 DOM 存储</a>，但是这只是全部本次存储规范的一部分（即前面提到的 <em>Storage </em> 对象）。</p>
<p><strong><big>当前和将来的支持情况</big></strong></p>

<table width="100%" cellspacing="0" cellpadding="2" border="0">
<tbody>
<tr>
<td align="center" width="20%"> </td>
<td align="center" width="16%" align="center"><strong>Gears</strong></td>
<td width="16%"  align="center"><strong>BrowserPlus<