<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" 
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>網站製作學習誌-Web 開發</title>
<link>http://blog.roodo.com/jaceju/archives/cat_447589.html</link>
<description>
首頁
讀者留言版
管理介面












_uacct = &quot;UA-450710-1&quot;;
urchinTracker();
</description>
<language>zh-tw</language>
<generator>Roodo Blog System</generator>
<copyright>All Rights Reserved</copyright>
<atom:link href="http://blog.roodo.com/jaceju/archives/cat_447589.xml" rel="self" type="application/rss+xml" />
<item>
	<title>關於 HTML label 元素無法作用</title>
	<description><![CDATA[
	石頭成老大在我的「終於用 jQuery 做了一個有趣的服務」提到了在 IE 裡 label 元素的 for 屬性是有 bug 的，我研究了一下，把心得分享給大家。
原本我一直以為表單中的 input 元素只要設定 display: none 或是 visibility: hidden 的話，就沒辦法送出；不過 W3C 中在「 17.13.2 Successful controls 」一節中有明確的規範：
Hidden controls and controls that are not rendered because of style sheet settings may still be successful.
也就是說不論是 display:none 或是 visibility: hidden ，只要是利用 CSS 來讓 control 消失的，都還是應該把值送給後端。
我用了以下的程式測試了一下：
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;
 &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
&lt;title&gt;TEST&lt;/title&gt;
&lt;style type=&quot;text/css&quot;&gt;
.hide {
    visibility: hidden;
}
.none {
    display: none;
}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;form action=&quot;&quot; method=&quot;post&quot;&gt;

&lt;label for=&quot;type1&quot;&gt;Type1&lt;/label&gt;
&lt;input type=&quot;radio&quot; class=&quot;hide&quot; id=&quot;type1&quot;
 name=&quot;type[]&quot; value=&quot;1&quot; checked=&quot;checked&quot; /&gt;

&lt;label for=&quot;type2&quot;&gt;Type2&lt;/label&gt;
&lt;input type=&quot;radio&quot; class=&quot;none&quot; id=&quot;type2&quot;
 name=&quot;type[]&quot; value=&quot;2&quot; /&gt;

&lt;input type=&quot;submit&quot; value=&quot;送出&quot; /&gt;
&lt;/form&gt;
&lt;a href=&quot;&lt;?php echo $_SERVER['PHP_SELF']; ?&gt;&quot;&gt;重新整理&lt;/a&gt;
&lt;?php var_dump($_POST); ?&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
window.onload = function () {
    var t2 = document.getElementById('type2');
    t2.focus();
}
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
結果發現 Firefox 、 Opera 不論有沒有預設的 checked ，在點選 label 後都會正確送出對應的 radio 欄位值。
而 IE6 、 IE7 事實上也是支援，只是它們僅能送出有預設 checked 的 radio 欄位；如果完全沒有預設 checked 的 radion 欄位時，因為點選 label 仍無法讓 radio 的值改變，因此也無法送出任何 radio 值 (就如石頭成老大所說明的) 。
所以我原先誤認 IE 不會理會 display: none 或是 visibility: hidden 的元素，其實是 label 無法作用；但更正確的來說，則是因為 IE 無法接受把 focus 放在不可見的元素上。
換句話說，我們沒辦法在 IE 上 focus 任何被 display: none 或是 visibility: hidden 的元素；而 label 則是 HTML 用來 focus 對應 input 元素的捷徑，也因此就不會有作用了。
註：所以我在「終於用 jQuery 做了一個有趣的服務」裡的作法就是為了避開這個問題。
最後這是不是 bug 呢？我個人倒覺得像是 IE 開發團隊自己的想法。不過 IE 無視於 W3C 標準也不是第一次了，所以石頭成老大說這是 IE 在 W3C 實作上的 bug 其實也不為過。至於解法，大家可以直接參考石頭成老大的說明，這裡我就不多寫了。

	]]>
	</description>
	<content:encoded><![CDATA[
	<p>石頭成老大在我的「<a href="http://blog.roodo.com/jaceju/archives/3091221.html#comment-10126569">終於用 jQuery 做了一個有趣的服務</a>」提到了在 IE 裡 label 元素的 for 屬性是有 bug 的，我研究了一下，把心得分享給大家。</p>
<p>原本我一直以為表單中的 input 元素只要設定 display: none 或是 visibility: hidden 的話，就沒辦法送出；不過 W3C 中在「 17.13.2 Successful controls 」一節中有明確的規範：</p>
<p><cite>Hidden controls and controls that are not rendered because of style sheet settings may still be successful.</cite></p>
<p>也就是說不論是 display:none 或是 visibility: hidden ，只要是利用 CSS 來讓 control 消失的，都還是應該把值送給後端。</p>
<p>我用了以下的程式測試了一下：</p>
<pre><code>&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;
 &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
&lt;title&gt;TEST&lt;/title&gt;
&lt;style type=&quot;text/css&quot;&gt;
.hide {
    visibility: hidden;
}
.none {
    display: none;
}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;form action=&quot;&quot; method=&quot;post&quot;&gt;

&lt;label for=&quot;type1&quot;&gt;Type1&lt;/label&gt;
&lt;input type=&quot;radio&quot; class=&quot;hide&quot; id=&quot;type1&quot;
 name=&quot;type[]&quot; value=&quot;1&quot; checked=&quot;checked&quot; /&gt;

&lt;label for=&quot;type2&quot;&gt;Type2&lt;/label&gt;
&lt;input type=&quot;radio&quot; class=&quot;none&quot; id=&quot;type2&quot;
 name=&quot;type[]&quot; value=&quot;2&quot; /&gt;

&lt;input type=&quot;submit&quot; value=&quot;送出&quot; /&gt;
&lt;/form&gt;
&lt;a href=&quot;&lt;?php echo $_SERVER['PHP_SELF']; ?&gt;&quot;&gt;重新整理&lt;/a&gt;
&lt;?php var_dump($_POST); ?&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
window.onload = function () {
    var t2 = document.getElementById('type2');
    t2.focus();
}
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>結果發現 Firefox 、 Opera 不論有沒有預設的 checked ，在點選 label 後都會正確送出對應的 radio 欄位值。</p>
<p>而 IE6 、 IE7 事實上也是支援，只是它們僅能送出有預設 checked 的 radio 欄位；如果完全沒有預設 checked 的 radion 欄位時，因為點選 label 仍無法讓 radio 的值改變，因此也無法送出任何 radio 值 (就如石頭成老大所說明的) 。</p>
<p>所以我原先誤認 IE 不會理會 display: none 或是 visibility: hidden 的元素，其實是 label 無法作用；但更正確的來說，則是因為 <strong>IE 無法接受把 focus 放在不可見的元素上</strong>。</p>
<p>換句話說，我們<strong>沒辦法在 IE 上 focus 任何被 display: none 或是 visibility: hidden 的元素</strong>；而 label 則是 HTML 用來 focus 對應 input 元素的捷徑，也因此就不會有作用了。</p>
<p class="note">註：所以我在「<a href="http://blog.roodo.com/jaceju/archives/3091221.html">終於用 jQuery 做了一個有趣的服務</a>」裡的作法就是為了避開這個問題。</p>
<p>最後這是不是 bug 呢？我個人倒覺得像是 IE 開發團隊自己的想法。不過 IE 無視於 W3C 標準也不是第一次了，所以石頭成老大說這是 IE 在 W3C 實作上的 bug 其實也不為過。至於解法，大家可以直接參考石頭成老大的說明，這裡我就不多寫了。</p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/3116303.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/3116303.html</guid>
	<category>Web 開發</category>
	<pubDate>Thu, 03 May 2007 14:23:03 +0800</pubDate>
</item>
<item>
	<title>IE7 對錯誤 Hostname 在處理 Cookie 上的問題</title>
	<description><![CDATA[
	昨天凱發現了一個 IE7 的問題，我們兩個做了一個討論後在這裡把結果記錄下來。
要重現這個問題很簡單，請照著以下的步驟試試看。
首先在 Windows 的 hosts 檔裡加入粗體部份：
127.0.0.1    localhost 
127.0.0.1    host_name
然後在網站根目錄底下建立一個 session.php ，內容如下：
&lt;?php
session_start();
$test = (isset($_SESSION['test']))
      ? (int) $_SESSION['test']
      : 0;
echo $test;
$test ++;
$_SESSION['test'] = $test;
然後試試用 IE7 瀏覽以下網址：
http://host_name/session.php
試試看去重新整理這個頁面，會發現 Session 沒辦法動作。 
不過同樣的網址在 IE6 和 Firefox 上， Session 都會在每次重新整理時正常加一；但如果把 host_name 換成 localhsot ，則每個瀏覽器都會正常動作。
一開始我以為是 IE7 有支援 HttpOnly Cookie 的設定，不過這項設定是在 PHP 5.2 以後才會有，而凱用的是 PHP 5.1.6 ；然而 Firefox 也支援 HttpOnly Cookie 卻能正確運作，所以並不是這個問題。
凱告訴我，他在 hosts 上加入 127.0.0.1 my.xxx.net 的設定，然後再用以上三種瀏覽器去瀏覽 http://my.xxx.net/session.php ，發現 Session 是可以運作的。這時我們就想到會不會是 host_name 有底線的關係，所以凱很快地重新把底線去掉後再用 IE7 測試，結果就正常了。
最後我們兩個人的結論是：
在 IE7 中，有底線的 hostname 會沒辦法正確使用 Cookie 。
其實微軟不建議 Hostname (或 Domain Name ) 使用底線字元，這個可以參閱「為電腦、 網域、 站台及 OU 命名慣例在 Active Directory 」一文。 

	]]>
	</description>
	<content:encoded><![CDATA[
	<p>昨天<a href="http://blog.darkhero.net/">凱</a>發現了一個 IE7 的<a href="http://blog.darkhero.net/articles/view/222">問題</a>，我們兩個做了一個討論後在這裡把結果記錄下來。</p>
<p>要重現這個問題很簡單，請照著以下的步驟試試看。</p>
<p>首先在 Windows 的 hosts 檔裡加入粗體部份：</p>
<pre><code>127.0.0.1    localhost 
<strong>127.0.0.1    host_name</strong></code></pre>
<p>然後在網站根目錄底下建立一個 session.php ，內容如下：</p>
<pre><code>&lt;?php
session_start();
$test = (isset($_SESSION['test']))
      ? (int) $_SESSION['test']
      : 0;
echo $test;
$test ++;
$_SESSION['test'] = $test;</code></pre>
<p>然後試試用 IE7 瀏覽以下網址：</p>
<pre><code>http://host_name/session.php</code></pre>
<p>試試看去重新整理這個頁面，會發現 Session 沒辦法動作。 </p>
<p>不過同樣的網址在 IE6 和 Firefox 上， Session 都會在每次重新整理時正常加一；但如果把 host_name 換成 localhsot ，則每個瀏覽器都會正常動作。</p>
<p>一開始我以為是 IE7 有支援 HttpOnly Cookie 的設定，不過這項設定是在 PHP 5.2 以後才會有，而凱用的是 PHP 5.1.6 ；然而 Firefox 也支援 HttpOnly Cookie 卻能正確運作，所以並不是這個問題。</p>
<p>凱告訴我，他在 hosts 上加入 127.0.0.1 my.xxx.net 的設定，然後再用以上三種瀏覽器去瀏覽 http://my.xxx.net/session.php ，發現 Session 是可以運作的。這時我們就想到會不會是 host_name 有底線的關係，所以凱很快地重新把底線去掉後再用 IE7 測試，結果就正常了。</p>
<p>最後我們兩個人的結論是：</p>
<p><strong>在 IE7 中，有底線的 hostname 會沒辦法正確使用 Cookie 。</strong></p>
<p>其實微軟不建議 Hostname (或 Domain Name ) 使用底線字元，這個可以參閱「<a href="http://support.microsoft.com/kb/909264">為電腦、 網域、 站台及 OU 命名慣例在 Active Directory</a> 」一文。 </p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/3026457.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/3026457.html</guid>
	<category>Web 開發</category>
	<pubDate>Thu, 19 Apr 2007 10:32:56 +0800</pubDate>
</item>
<item>
	<title>透視 WebMVC</title>
	<description><![CDATA[
	這篇寫超久的...大概從去年九月開始寫的，不過因為中間事情太多，因此是以牛步進行；之間有跟幾位 PHP 界的長輩們預告過本文的誕生，還好沒有跳票。
本文主要是把我所認知的 WebMVC 概念，以實作的方式來說明。而範例本來寫得很複雜，也請過丫凱兄幫忙測試。不過後來想想其實不必要在範例裡加入太多功能，因此就簡化了很多部份。
希望大家看完後，能給我一些建議與指導。 
文章網址：透視 WebMVC
	]]>
	</description>
	<content:encoded><![CDATA[
	<p>這篇寫超久的...大概從去年九月開始寫的，不過因為中間事情太多，因此是以牛步進行；之間有跟幾位 PHP 界的長輩們預告過本文的誕生，還好沒有跳票。</p>
<p>本文主要是把我所認知的 WebMVC 概念，以實作的方式來說明。而範例本來寫得很複雜，也請過<a href="http://www.darkhero.net/">丫凱兄</a>幫忙測試。不過後來想想其實不必要在範例裡加入太多功能，因此就簡化了很多部份。</p>
<p>希望大家看完後，能給我一些建議與指導。 </p>
<p>文章網址：<a href="http://www.jaceju.net/resources/webmvc/">透視 WebMVC</a></p>		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/2862001.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/2862001.html</guid>
	<category>Web 開發</category>
	<pubDate>Fri, 16 Mar 2007 18:26:35 +0800</pubDate>
</item>
<item>
	<title>5 個我在舊專案的 XHTML 中常發現的問題</title>
	<description><![CDATA[
	最近在一些維護一些舊專案裡的頁面，它們都已經採用了 XHTML 1.0 Transitional 。一個正確的 XHTML 1.0 Transitional 頁面的範例如下：
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=big5&quot; /&gt;
&lt;title&gt;Page Title&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
...
&lt;/body&gt;
&lt;/html&gt;
當然大部份頁面是符合的，不過我還是發現了一些問題；在這裡我把它們記下來，供往後開發時參考。

	]]>
	</description>
	<content:encoded><![CDATA[
	<p>最近在一些維護一些舊專案裡的頁面，它們都已經採用了 XHTML 1.0 Transitional 。一個正確的 XHTML 1.0 Transitional 頁面的範例如下：</p>
<pre><code>&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=big5&quot; /&gt;
&lt;title&gt;Page Title&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
...
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>當然大部份頁面是符合的，不過我還是發現了一些問題；在這裡我把它們記下來，供往後開發時參考。</p>
		<a href="http://blog.roodo.com/jaceju/archives/2695133.html">(繼續閱讀...)</a>;
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/2695133.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/2695133.html</guid>
	<category>Web 開發</category>
	<pubDate>Sun, 04 Feb 2007 16:28:15 +0800</pubDate>
</item>
<item>
	<title>將資料和程式分離</title>
	<description><![CDATA[
	有位 jocosn 網友問了一個我覺得很棒的問題，我把我的觀點提出來供大家參考。
註：以下我會以引用區塊的方式來標示該網友的問題，然後以回答該問題的語氣說明。且基於本人龜毛的個性，也會把內容稍作排版。

如果我有一個 welcome.php，它的樣版檔是 welcome.tpl.htm，但是兩個檔案的編碼不相同，也就是 php 使用 &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt; ， tpl.htm 使用 &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=big5&quot;&gt;，結果螢幕顯示時會以  utf-8 編碼格式顯示 tpl.htm 檔案，必須再手動挑選 big5，請問這種情況有辦法解決嗎？還是程式這種架構有問題？
使用 big5 是因為 tpl.htm 檔案有用到 mailto，像這樣：
&lt;a href='mailto:h...@yahoo.com.tw?subject=其他問題&amp;body=問題描述：%0A%0A%0A%0A聯絡方式%0A地址：%0A電話：%0A聯絡人：%0A'&gt;寫信連絡&lt;/a&gt;
如果改用 utf8，點下 mailto 開啟 outlook 6 會出現亂碼。所以採用 big5 才會正常顯示中文字。但是 php 檔案因有些部份未使用樣板處理一些簡單的小訊息 (如顯示&quot;檔案建立成功&quot;) ，所以採用 utf8，以免顯示中文像「功」字會出現問題。
像這種情況下，請問該怎麼處理，或是有更好的解決方式嗎？

事實上你的 template 還是可以用 utf-8 的，只不過有些地方要做一些手腳。
在這之前，先給你一個觀念：把資料和程式分離。怎麼說呢？直接給你看例子好了：
首先我把 mailto 會用到的中文字另存成一個 ini 檔：
[mailto]
subject = &quot;其他問題&quot;
body = &quot;問題描述：\n\n\n\n聯絡方式\n地址：\n電話：\n聯絡人：\n&quot;
特別要注意的是，這個 ini 檔是用 big5 來存檔的。
然後我在 index.php 裡把它載入：
&lt;?php
$mailto = parse_ini_file('mailto.ini');
  
$subject = urlencode($mailto['subject']);
$body = str_replace('%250A', '%0A', urlencode(str_replace('\n', '%0A',  $mailto['body'])));
  
include('template.php');
這邊要特別注意的是 php 檔是用 utf-8 來存檔 (事實上你也可以用 ANSI 來存) 。
最後來看看 template.php ：
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
&lt;title&gt;測試 mailto&lt;/title&gt;
&lt;/head&gt;

&lt;body&gt;
&lt;a href=&quot;mailto:jxxxxxxxxx@gmail.com?subject=&lt;?php echo $subject; ?&gt;&amp;body=&lt;?php echo $body; ?&gt;&quot;&gt;寫信連絡&lt;/a&gt;
&lt;/body&gt;
&lt;/html&gt;
這裡一樣也是用 utf-8 存檔。
執行它看看，跑出來的結果是不是符合你的需要呢？
這裡就導出一個觀念了： PHP 在處理資料時，其程式檔案的編碼是不會影響資料本身的編碼的。
在上面的例子裡， parse_ini_file 取得的資料就是 mailto.ini 本身的編碼 (也就是 big5) ，而 PHP 也不會因為自己的檔案編碼是 utf-8 而改變 parse_ini_file 所取得的資料編碼。因此這時候的「其他問題」和「問題描述...」都能夠用在 template 上...
不過等一下，如果你直接把 $mailto['subject'] 和 $mailto['body'] 套入 template.php 的話，那就慘了。為什麼呢？因為 big5 編碼的內容在 utf-8 編碼的網頁裡，瀏覽器不知道該怎麼解釋它們 (也就是一堆亂碼啦) 。所以這裡我們要利用 urlencode 這個函式，來將 big5 的文字做 URL 編碼。
至於 \n 的部份只是個表示方式，實際上我們還是要手動將它換成 %0A (雖然我換的方式還滿醜的) 。
當然不只是文字檔案，就連資料庫中取出的資料也是相同的道理。這點你可以參考我先前寫的 MySQL 中文編碼徹底研究，裡面有詳細的內容。

再請問，如果用 smarty 時，php 檔案是不是應該儘量只有 php 程式碼？

依照上面的觀念，你認為我這裡會給什麼樣的答案呢？想想看吧 :)

另外 php 檔案存成 utf-8 或 big5 有差嗎？還是說網頁儘量不要存成 big5，以免特殊中文字會出現錯誤？
例如 php 檔案中像這樣 $mysmarty-&gt;assign('myVar1','許蓋功') ，存成 big5，我在測試時，就會出現錯誤 Parse error: parse error, unexpected T_STRING 

PHP 引擎會對 &lt;?php ?&gt; 裡面的特殊字元很敏感，所以上面的觀念一樣適用在這裡；當然如果是在 &lt;?php ?&gt; 外的話 (通常是 HTML ) 就沒問題了。
希望上面的說明能讓你清楚相關的觀念 :)

	]]>
	</description>
	<content:encoded><![CDATA[
	<p>有位 jocosn 網友問了一個我覺得很棒的問題，我把我的觀點提出來供大家參考。</p>
<p class="note">註：以下我會以引用區塊的方式來標示該網友的問題，然後以回答該問題的語氣說明。且基於本人龜毛的個性，也會把內容稍作排版。</p>
<blockquote>
<p>如果我有一個 welcome.php，它的樣版檔是 welcome.tpl.htm，但是兩個檔案的編碼不相同，也就是 php 使用 &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt; ， tpl.htm 使用 &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=big5&quot;&gt;，結果螢幕顯示時會以  utf-8 編碼格式顯示 tpl.htm 檔案，必須再手動挑選 big5，請問這種情況有辦法解決嗎？還是程式這種架構有問題？</p>
<p>使用 big5 是因為 tpl.htm 檔案有用到 mailto，像這樣：</p>
<pre><code>&lt;a href='mailto:h...@yahoo.com.tw?subject=其他問題&amp;body=問題描述：%0A%0A%0A%0A聯絡方式%0A地址：%0A電話：%0A聯絡人：%0A'&gt;寫信連絡&lt;/a&gt;</code></pre>
<p>如果改用 utf8，點下 mailto 開啟 outlook 6 會出現亂碼。所以採用 big5 才會正常顯示中文字。但是 php 檔案因有些部份未使用樣板處理一些簡單的小訊息 (如顯示&quot;檔案建立成功&quot;) ，所以採用 utf8，以免顯示中文像「功」字會出現問題。</p>
<p>像這種情況下，請問該怎麼處理，或是有更好的解決方式嗎？</p>
</blockquote>
<p>事實上你的 template 還是可以用 utf-8 的，只不過有些地方要做一些手腳。</p>
<p>在這之前，先給你一個觀念：把資料和程式分離。怎麼說呢？直接給你看例子好了：</p>
<p>首先我把 mailto 會用到的中文字另存成一個 ini 檔：</p>
<pre><code>[mailto]
subject = &quot;其他問題&quot;
body = &quot;問題描述：\n\n\n\n聯絡方式\n地址：\n電話：\n聯絡人：\n&quot;</code></pre>
<p>特別要注意的是，這個 ini 檔是用 <strong>big5</strong> 來存檔的。</p>
<p>然後我在 index.php 裡把它載入：</p>
<pre><code>&lt;?php
$mailto = parse_ini_file('mailto.ini');
  
$subject = urlencode($mailto['subject']);
$body = str_replace('%250A', '%0A', urlencode(str_replace('\n', '%0A',  $mailto['body'])));
  
include('template.php');</code></pre>
<p>這邊要特別注意的是 php 檔是用 <strong>utf-8</strong> 來存檔 (事實上你也可以用 ANSI 來存) 。</p>
<p>最後來看看 template.php ：</p>
<pre><code>&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
&lt;title&gt;測試 mailto&lt;/title&gt;
&lt;/head&gt;

&lt;body&gt;
&lt;a href=&quot;mailto:jxxxxxxxxx@gmail.com?subject=&lt;?php echo $subject; ?&gt;&amp;body=&lt;?php echo $body; ?&gt;&quot;&gt;寫信連絡&lt;/a&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>這裡一樣也是用 <strong>utf-8</strong> 存檔。</p>
<p>執行它看看，跑出來的結果是不是符合你的需要呢？</p>
<p>這裡就導出一個觀念了： PHP 在處理資料時，其程式檔案的編碼是不會影響資料本身的編碼的。</p>
<p>在上面的例子裡， parse_ini_file 取得的資料就是 mailto.ini 本身的編碼 (也就是 big5) ，而 PHP 也不會因為自己的檔案編碼是 utf-8 而改變 parse_ini_file 所取得的資料編碼。因此這時候的「其他問題」和「問題描述...」都能夠用在 template 上...</p>
<p>不過等一下，如果你直接把 $mailto['subject'] 和 $mailto['body'] 套入 template.php 的話，那就慘了。為什麼呢？因為 big5 編碼的內容在 utf-8 編碼的網頁裡，瀏覽器不知道該怎麼解釋它們 (也就是一堆亂碼啦) 。所以這裡我們要利用 urlencode 這個函式，來將 big5 的文字做 URL 編碼。</p>
<p>至於 \n 的部份只是個表示方式，實際上我們還是要手動將它換成 %0A (雖然我換的方式還滿醜的) 。</p>
<p>當然不只是文字檔案，就連資料庫中取出的資料也是相同的道理。這點你可以參考我先前寫的 <a href="http://blog.roodo.com/jaceju/archives/2019474.html">MySQL 中文編碼徹底研究</a>，裡面有詳細的內容。</p>
<blockquote>
<p>再請問，如果用 smarty 時，php 檔案是不是應該儘量只有 php 程式碼？</p>
</blockquote>
<p>依照上面的觀念，你認為我這裡會給什麼樣的答案呢？想想看吧 :)</p>
<blockquote>
<p>另外 php 檔案存成 utf-8 或 big5 有差嗎？還是說網頁儘量不要存成 big5，以免特殊中文字會出現錯誤？</p>
<p>例如 php 檔案中像這樣 $mysmarty-&gt;assign('myVar1','許蓋功') ，存成 big5，我在測試時，就會出現錯誤 Parse error: parse error, unexpected T_STRING </p>
</blockquote>
<p>PHP 引擎會對 &lt;?php ?&gt; 裡面的特殊字元很敏感，所以上面的觀念一樣適用在這裡；當然如果是在 &lt;?php ?&gt; 外的話 (通常是 HTML ) 就沒問題了。</p>
<p>希望上面的說明能讓你清楚相關的觀念 :)</p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/2617536.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/2617536.html</guid>
	<category>Web 開發</category>
	<pubDate>Wed, 03 Jan 2007 16:38:02 +0800</pubDate>
</item>
<item>
	<title>[心得] 網頁程式開發建議</title>
	<description><![CDATA[
	這篇是寫給新同事以及我自己備忘用的，也歡迎大家提出指正。
在撰寫網頁程式時，有些基本的東西要非常注意，這樣寫出來的程式才不容易出現問題，也才能夠交給客戶。以下就是我自己的開發心得，供大家參考。
利用明確的指定方式來取得頁面傳來的變數
不管是 GET 或 POST 的參數，我會希望明確地指定它的型態，例如 id 應該是整數， content 是文字等。而且我也常常發現有人把接到這些變數後，沒有事先做處理就直接串到程式中，這是非常危險的一件事情！
最明顯的例子就是 SQL Injection 了，我想這應該不用多說了。總而言之，不要過份相信用戶端傳來的資訊，把它轉換成你能掌握的型態再用吧。
資料庫的連結每個頁面只作一次
資料庫連結是網站頁面常做的事情，但是儘可能不要讓一個頁面產生太多的資料庫連結。我們可以利用 Singleton 模式來取得資料庫連結物件，這樣可以確保程式裡只會用到一個資料庫連結；當然需要連結不同資料庫的話就另當別論。
所以我們要確定資料庫會在頁面初始化時連結，頁面結束時關閉。這樣有單一的入口與出口，程式也就不容易出現奇怪的問題。
相同的邏輯不要寫兩遍以上
如果發現有兩支程式會用到相同的程式邏輯時，不要猶豫，把它抽出來變成類別或函式 (最好是類別，原因在下一則) 。因為如果哪一天需要更新程式的邏輯時，你只需要更改一支程式即可。對健忘的人來說，這點尤其重要。
我就遇過有人把產生選單的邏輯重複寫在十多支程式裡，結果有次客戶要求要修正其中一個地方，可憐的維護人員 (就是我啦) 就得一支一支地去翻出來改。
利用物件來管理錯誤
我這裡指的錯誤是任何預期中的狀況，也就是你不希望使用者操作的方式，例如編號不存在或是檔案大小超過限制等。
當錯誤發生時，不要立刻結束，應該利用錯誤上升機制來讓通知上一層的程式，最後再由頁面控制程式來決定要如何處理錯誤。我常常會遇到有人在函式裡利用 exit 離開程式，但是這時候頁面的資料庫或其他物件等等都還沒釋放掉；雖然程式平台可能會幫你做，但那總是很難預期。
所以我建議不要使用函式，而改為使用物件的方法，然後利用類似 PEAR::isError() 來判斷是否執行成功；如果失敗的話就把錯誤往上丟，直到頁面能夠控制為止。
該釋放的要記得釋放
不管是物件還是資料庫，都應該在頁面結束前將它們銷毀或關閉，而不要過於依賴程式執行平台。網頁程式是很多人會同時存取的，如果沒有正確地將資源即時釋放掉的話，久而久之就會造成系統效能上的不穩定。
而釋放的動作要什麼時候做呢？記住一句話：誰開的就誰負責關。例如上面頁面控制程式開啟資料庫連結，那就在頁面控制程式的最後把資料庫連結關閉。類別建構函式產生的物件，就在類別解構程式裡銷毀。函式開的頭，當然就在函式尾收掉；不過有個例外，那就是這個函式如果本身就是要回傳產生的物件時，那就不能把它給釋放囉，而是要改為呼叫這個函式的程式來釋放。
利用樣版技術
樣版是用來分離程式邏輯與視覺頁面的，也常常有人用 MVC 這個模式來稱呼它。然而兩者分離除了不相互干擾外，其實還有一個好處：那就是程式可以在錯誤發生後，決定要顯示的結果。就像上面提到的錯誤管理，當我們在頁面控制程式取得錯誤訊息時，我們就可以而用置換樣版來避免掉頁面的錯誤，或者是導向別的處理程式。
這點我覺得 PHP 的 Smarty 就考慮得很好，因為它是後期頁面綁定 (Binding) ，而不會像傳統樣版引擎在前期就把頁面拉進程式處理，導致錯誤發生時徒然浪費處理時間 (當然要看怎麼設計的) 。
徹底瞭解開發環境的性質
網頁程式和一般應用程式 (例如視窗應用程式) 在本質上是有差異的，這些差異不僅是在操作上，就連執行的過程都非常的不一樣。雖然現在有 AJAX 或其他技術可以縮小彼此的差距，但是它還是建構在 HTTP 這個無狀態協定之上。身為網站程式開發人員，其實應該要瞭解這些基礎，而不要只熟稔某些已經被包裝過的技術就顯得自得意滿。
最簡單的就是伺服端程式與用戶端程式之間的溝通，例如 PHP 和 JavaScript 。我常常在網路上看見有人問道：要如何讓 PHP 和 JavaScript 之間的變數互通？如果瞭解 HTTP 執行的過程，那麼你就會自己發現這些問題的答案。

	]]>
	</description>
	<content:encoded><![CDATA[
	<p>這篇是寫給新同事以及我自己備忘用的，也歡迎大家提出指正。</p>
<p>在撰寫網頁程式時，有些基本的東西要非常注意，這樣寫出來的程式才不容易出現問題，也才能夠交給客戶。以下就是我自己的開發心得，供大家參考。</p>
<h2>利用明確的指定方式來取得頁面傳來的變數</h2>
<p>不管是 GET 或 POST 的參數，我會希望明確地指定它的型態，例如 id 應該是整數， content 是文字等。而且我也常常發現有人把接到這些變數後，沒有事先做處理就直接串到程式中，這是非常危險的一件事情！</p>
<p>最明顯的例子就是 SQL Injection 了，我想這應該不用多說了。總而言之，不要過份相信用戶端傳來的資訊，把它轉換成你能掌握的型態再用吧。</p>
<h2>資料庫的連結每個頁面只作一次</h2>
<p>資料庫連結是網站頁面常做的事情，但是儘可能不要讓一個頁面產生太多的資料庫連結。我們可以利用 Singleton 模式來取得資料庫連結物件，這樣可以確保程式裡只會用到一個資料庫連結；當然需要連結不同資料庫的話就另當別論。</p>
<p>所以我們要確定資料庫會在頁面初始化時連結，頁面結束時關閉。這樣有單一的入口與出口，程式也就不容易出現奇怪的問題。</p>
<h2>相同的邏輯不要寫兩遍以上</h2>
<p>如果發現有兩支程式會用到相同的程式邏輯時，不要猶豫，把它抽出來變成類別或函式 (最好是類別，原因在下一則) 。因為如果哪一天需要更新程式的邏輯時，你只需要更改一支程式即可。對健忘的人來說，這點尤其重要。</p>
<p>我就遇過有人把產生選單的邏輯重複寫在十多支程式裡，結果有次客戶要求要修正其中一個地方，可憐的維護人員 (就是我啦) 就得一支一支地去翻出來改。</p>
<h2>利用物件來管理錯誤</h2>
<p>我這裡指的錯誤是任何預期中的狀況，也就是你不希望使用者操作的方式，例如編號不存在或是檔案大小超過限制等。</p>
<p>當錯誤發生時，不要立刻結束，應該利用錯誤上升機制來讓通知上一層的程式，最後再由頁面控制程式來決定要如何處理錯誤。我常常會遇到有人在函式裡利用 exit 離開程式，但是這時候頁面的資料庫或其他物件等等都還沒釋放掉；雖然程式平台可能會幫你做，但那總是很難預期。</p>
<p>所以我建議不要使用函式，而改為使用物件的方法，然後利用類似 PEAR::isError() 來判斷是否執行成功；如果失敗的話就把錯誤往上丟，直到頁面能夠控制為止。</p>
<h2>該釋放的要記得釋放</h2>
<p>不管是物件還是資料庫，都應該在頁面結束前將它們銷毀或關閉，而不要過於依賴程式執行平台。網頁程式是很多人會同時存取的，如果沒有正確地將資源即時釋放掉的話，久而久之就會造成系統效能上的不穩定。</p>
<p>而釋放的動作要什麼時候做呢？記住一句話：誰開的就誰負責關。例如上面頁面控制程式開啟資料庫連結，那就在頁面控制程式的最後把資料庫連結關閉。類別建構函式產生的物件，就在類別解構程式裡銷毀。函式開的頭，當然就在函式尾收掉；不過有個例外，那就是這個函式如果本身就是要回傳產生的物件時，那就不能把它給釋放囉，而是要改為呼叫這個函式的程式來釋放。</p>
<h2>利用樣版技術</h2>
<p>樣版是用來分離程式邏輯與視覺頁面的，也常常有人用 MVC 這個模式來稱呼它。然而兩者分離除了不相互干擾外，其實還有一個好處：那就是程式可以在錯誤發生後，決定要顯示的結果。就像上面提到的錯誤管理，當我們在頁面控制程式取得錯誤訊息時，我們就可以而用置換樣版來避免掉頁面的錯誤，或者是導向別的處理程式。</p>
<p>這點我覺得 PHP 的 Smarty 就考慮得很好，因為它是後期頁面綁定 (Binding) ，而不會像傳統樣版引擎在前期就把頁面拉進程式處理，導致錯誤發生時徒然浪費處理時間 (當然要看怎麼設計的) 。</p>
<h2>徹底瞭解開發環境的性質</h2>
<p>網頁程式和一般應用程式 (例如視窗應用程式) 在本質上是有差異的，這些差異不僅是在操作上，就連執行的過程都非常的不一樣。雖然現在有 AJAX 或其他技術可以縮小彼此的差距，但是它還是建構在 HTTP 這個無狀態協定之上。身為網站程式開發人員，其實應該要瞭解這些基礎，而不要只熟稔某些已經被包裝過的技術就顯得自得意滿。</p>
<p>最簡單的就是伺服端程式與用戶端程式之間的溝通，例如 PHP 和 JavaScript 。我常常在網路上看見有人問道：要如何讓 PHP 和 JavaScript 之間的變數互通？如果瞭解 HTTP 執行的過程，那麼你就會自己發現這些問題的答案。</p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/1553803.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/1553803.html</guid>
	<category>Web 開發</category>
	<pubDate>Mon, 08 May 2006 16:39:58 +0800</pubDate>
</item>
</channel>
</rss>