2008年11月20日

[Web] 連結分享

PHP

Zend Framework

JavaScript

jQuery

CSS

Web Development

Database

MySQL

Project

Security

Software

System

Other


Posted by jaceju at 樂多Roodo!10:13回應(0)連結分享

2008年11月17日

[JavaScript] 複製物件

前幾天遇到了一個 JavaScript 的小問題,就是物件的複製。

這個問題主要是我先設定了一個全域變數,然後在函式裡去重新定義一個變數,並將全域變數的內容指定給新變數。

我以為這樣就是「複製了 JavaScript 的物件」,但事實上是錯的。

我特地上網找了一下,發現 JavaScript 本身並沒有提供比較方便的 clone 機制,這時我的腦筋就動到 jQuery 上了。

不過這裡我可不是說 jQuery 的 clone 方法,而是 extend 方法。

先來看看例子好了:

<html>
<head>
<script type="text/javascript" src="jquery/1.2.6.js"></script>
<script type="text/javascript">
function w(s) {
    document.write(s + '<br />\n');
}
function d(o) {
    var s = '';
    for (var i in o) {
        s += i + ': ' + o[i] + '<br />\n';
    }
    w(s);
}
</script>
</head>
<body>
<script type="text/javascript">
var o1 = {
    a1: '123',
    a2: '456'
};
var o2 = o1;
$.extend(o2, { a3: '789' });

var o3 = $.extend({}, o1);
$.extend(o3, { a4: '000' });

w('o1');
d(o1);
w('o2');
d(o2);
w('o3');
d(o3);
</script>
</body>
</html>

在上面的程式中,請將重點放在我強調的部份。

這裡我先定義一個自訂物件 o1 ,然後我將 o2 指定為 o1 ;在 JavaScript 的意義裡, o2 就會是 o1 的「別名」,兩個都指到同一個物件。

因此接下來我對 o2 進行任何操作,都會影響到 o1 ;也就是說如果我們要複製 o1 的話,就不能用等號 (=) 。

jQuery 的 extend 方法可以幫我們這個忙。

原因是 extend 會將第二個參數裡的物件成員,一項一項地複製到第一個參數上。因此我們可以用它來解決 JavaScript 複製物件的問題。

在 o1 複製到 o3 中,很重要的一個關鍵就是我們需要把 $.extend 的第一個參數設為空物件;這是因為 $.extend 會回傳第一個參數,我們就省掉先行定義 o3 為空物件的動作了。

接下來我們不論怎麼對 o3 進行處理,也不會影響到 o1 ;換句話說,我們已經成功達成 clone JavaScript Object 的目標啦。


Posted by jaceju at 樂多Roodo!12:47回應(0)JavaScript

2008年11月2日

[Web] 連結分享

PHP

Zend Framework

JavaScript

jQuery

CSS

Web Development

Database

MySQL

Security

Service

System

Other


Posted by jaceju at 樂多Roodo!23:21回應(0)連結分享

2008年10月20日

[Web] 連結分享

PHP

Zend Framework

JavaScript

jQuery

CSS

Database

MySQL

Design

Web Development

HTML

Browser

Programming

Project

SCM

Security

Software

System


Posted by jaceju at 樂多Roodo!17:02回應(0)連結分享

2008年10月16日

[PHP] Smarty 樣版小技巧整理

在 Smarty 中,我們可以用以下的語法來完成類似 for 迴圈的效果:

{section name="forLoop" start=1 loop=10}
{/section}

其中 start 即為起始值, loop 為小於而不等於的終值。

如果以 PHP 語法來表示,則如下所示:

for ($i = 1; $i < 10; $i ++) {
    // ...
} 

使用無參數原生 PHP 函式

我們可以在樣版中使用許多原生的 PHP 函式 (但還是有例外) 來當做變數修飾函式,不過如果有些函式不需要參數時,我們可以用以下語法來呼叫:

{''|@time}

當然這裡的空字串對 time 函式來說是沒有意義的,而在函式前加上 @ 號,表示要直接呼叫原生 PHP 函式。

在 assign 設定 default 值

假設當樣版變數不存在或可轉換為 false 值時,我們會希望顯示一個預設值;而 Smarty 剛好就提供了一個 default 變數修飾函式讓我們使用,語法如下:

{$test|default:'NULL'}

而 default 變數修飾函式不僅只有在呈現變數能用,也能在樣版 assign 變數時使用,如下:

{assign var=value2 value=$value1|default:0}

註:當然不只有 default ,幾乎所有變數修飾函式都能在 assign 或其他可接受變數的樣版函式裡使用。

物件導向語法

Smarty 也支援 PHP 的物件導向語法,例如呼叫某物件函式:

{$test->getFakeValue()}

我們也能在樣版函式中,使用物件導向語法,而且後面也能串接變數修飾函式:

{assign var=nullValue value=$test->getNullValue()|default:'NULL'}

利用 config 變數或常數來當做變數修飾函式的參數

通常我們會用到設定值來避免重複設定一些常數值,例如用 PHP 陣列的方式指定給 Smarty :

$config = array(
    'date' => '%Y/%m/%d',
    'time' => '%H:%M',
);
$smarty->assign($config);

在樣版裡就可以這樣用:

{$date|date_format:$config.date}

我們也可以利用 PHP 的常數來當做設定,在樣版可以用「 $smarty.const.常數名稱」來取得常數內容:

{$date|date_format:$smarty.const.DATE_FORMAT}

當然,我們也可以透過 Smarty 內建的 config 機制;例如我們有個 config.conf ,內容如下:

date = "%Y/%m/%d"
time = "%H:%M" 

然後在樣版內改用:

{config_load file="config.conf"}
{$date|date_format:#date#} {$time|date_format:#time#}

其中  #date# 與 #time# 就是從 config.conf 中讀取的。

註:感謝 Smarty 頭號粉絲 - 小魚提供以上技巧。

用 {cycle} 配合 CSS 來做表格列交替變色

我們可以用 cycle 配合 sction 或 foreach ,來做出交替變色的表格,語法如下:

{secion ....}
.....
<tr class="{cycle values="normal,alt"}">
.....
{/secion}

可以看出,它比使用 {if} 來得簡潔許多:

<tr class="{if $smarty.section.forLoop.iteration is odd}normal{else}alt{/if}">

註:感謝 Smarty 頭號粉絲 - 小魚提供以上技巧。

如果還有相關技巧的話,將會陸續再更新。


Posted by jaceju at 樂多Roodo!22:27回應(0) PHP

[PHP] Session 相關文章

身為 PHP 開發者,我其實對 PHP Session 的處理機制還是一知半解。

這次因為有個大案子上線的關係,讓我真的遇到了 Session 過多的問題。

這裡強力推薦宗董寫的一篇好文: PHP session 暫存檔過多的注意事項

不過基本上在連線數會很高的網站,還是建議使用 MySQL 或 memcache 來當做 Session 的儲存媒體。

如果要使用 MySQL 的話,我們可以利用 session_set_save_handler 來建立資料庫連線並存取 Session 資料。

而使用 memcache 的話,可以參考 PHP 官方提供的方法,程式如下:

<?php
$host = 'localhost';
$port = '11211';
$session_save_path = "tcp://$host:$port?persistent=1&weight=2&timeout=2&retry_interval=10,  ,tcp://$host:$port  ";
ini_set('session.save_handler', 'memcache');
ini_set('session.save_path', $session_save_path);

希望以上的資訊能提供大家對 PHP 處理 Session 有更進一步的瞭解。


Posted by jaceju at 樂多Roodo!12:34回應(2) PHP

2008年09月23日

Bug Tracker 安裝紀錄

我之前介紹過 Trac 這個軟體的安裝簡略的使用方式,但是 Trac 是一套基於 Python 開發的軟體缺陷追蹤系統,在安裝上有一定的複雜度。

這次,我推薦大家一套國人自行開發的 Bug Tracker ,它是一套以 PHP 所開發的軟體缺陷追蹤系統,相當適合不想安裝複雜開發環境的 PHP 開發者使用。

這裡有 Neo 寫的簡介:國人自製 Bug Tracker

下載

網址: http://www.twbsd.org/cht/bug_tracker/index.php?page=download.htm

在「按此下載」的連結上點一下,把 BugTracker-2.x.x.tar.gz 存放到網站根目錄就可以了。

安裝

Bug Tracker 號稱安裝非常容易,但其實在 PHP5 的環境上,還是有一些要特別注意的地方。

解開剛剛的 BugTracker-2.x.x.tar.gz ,然後我們會得到一個 bug 目錄;所以到時候我們可以用 http://localhost/bug 的網址來使用這套系統。

假設你的開發環境是 PHP5 ,那麼 short_open_tag 這個選項預設應該是 Off 。而 Bug Tracker 的程式碼大部份都是以 <? 開頭,因此我們需要把 short_open_tag 設為 On 。

不過因為我個人不喜歡去更動系統預設值,所以我改用 .htaccess 來改變 short_open_tag 的設定。請將以下內容存為 .htaccess 後,存在 bug 資料夾下。

php_flag short_open_tag on

接著我們要修改應用程式的設定,請用文字編輯器開始 bug/include/config.php ,找到:

$GLOBALS['BR_dbtype'] = "postgres";

將它註解掉 (前面加上 //) 。

然後取消以下程式碼開頭的註解:

$GLOBALS['BR_dbtype'] = "mysqlt";

然後往下看到:

$GLOBALS['BR_dbpwd'] = "";

在設定值上寫上 MySQL 的 root 密碼,讓程式可以自動建立資料庫。

最後修改應用程式的路徑:

$GLOBALS["SYS_PROJECT_PATH"] = '/home/synosrc/bug';

將 /home/synosrc/bug 改為你安裝程式的路徑。

現在開啟以下連結,進行安裝動作:

http://localhost/bug/setup/

基本上就是一直按 Next Step 而已,安裝程式會告訴你一切需要的資訊,並自動執行相關的動作。

安裝完後,請記得移除 bug/setup 這個資料夾。

這樣就完成安裝 Bug Tracker 囉~

設定語系

一開始 Bug Tracker 的登入畫面是正體中文:

登入畫面

但用 admin 登入後,我們會發現預設的語系還是英文的:

主畫面

這時我們可以點選上面的 System (系統設定) 功能,然後選擇 Preference (偏好設定) 項目,將 System Language (系統語言) 改為 Chinese Traditional 即可。

搭配 Subversion 使用

Bug Tracker 目前還沒辦法像 Trac 一樣直接支援 Subversion ,也就是說它目前無法直接讓專案回報與源碼相結合。

這裡我找到一篇反過來讓 TortoiseSVN 配合 Bug Tracker 使用的文章:如何設定 TortoiseSVN 整合 Bug Tracker 系統

依照文章上的解說,我們可以在 Subversion 的 log 上直接連結到 Bug Tracker 回報的畫面。

其實 PHP 是可以支援 Subversion 的,但必須配合 php_svn 這個外掛模組。不過 php_svn 還不支援新版的 Subversion ,這是比較可惜的地方。請參考:安裝php_svn.dll

結論

其實不論是團隊合作還是個人開發,一套好的追蹤系統都可以協助我們管理好專案的進度;而 Bug Tracker 可以說是慣用中文的 PHP 開發者一個不錯的選擇。

大家有任何使用上的經驗嗎?也歡迎分享喔~


[jQuery] IE 上的 clone 陷阱

前陣子在處理客戶更改版面的需求時,為了偷懶,結果發現了一個 jQuery 在 IE 上 clone 元素的問題。

先簡單說明一下例子:

FF未複製前

如上圖所示,我希望在按下「複製」按鈕後,藍色區塊中的 checkbox 被勾選的項目會被複製到紅色區塊中:

FF複製後

這裡我簡單的使用 jQuery 的 clone 方法來完成它,原始程式如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>測試</title>
<script type="text/javascript" src="jquery/1.2.6.js"></script>
<script type="text/javascript">
$(function () {
    $('#copy').click(function () {
        $('#target').html('').append($('input.test:checked').clone());
    });
});
</script>
</head>
<body>

<div id="source" style="border:1px solid #33F; padding: 20px; width: 200px;">
<input type="checkbox" name="test[]" class="test" value="1" />
<input type="checkbox" name="test[]" class="test" value="2" />
<input type="checkbox" name="test[]" class="test" value="3" />
<input type="checkbox" name="test[]" class="test" value="4" />
</div>

<br />

<div id="target" style="border:1px solid #F33; padding: 20px; width: 200px;">
</div>

<br />

<input type="button" value="複製" id="copy" />

</body>
</html>

在非 IE 的瀏覽器上, jQuery 的 clone 方法可以正確的把已勾選的 checkbox 的 checked 狀態複製下來,但在 IE 上卻不行,如下圖:

IE複製後

所以這裡只好針對 IE 再進行一次特別的處理:

$(function () {
    $('#copy').click(function () {
        var $checkedValues = $('input.test:checked').clone();
        if ($.browser.msie) {
            $checkedValues.attr('checked', true);
        }
        $('#target').html('').append($checkedValues);
    });
});

原理很簡單,就是遇到 IE 時,再將複製下來的 checkbox 的 checked 屬性設為 true 即可。

補充:IE6 的逆襲

不過上述程式在 IE6 又會出現問題了,在 IE6 上執行時,會發現 checked 屬性無法正常被設為 true 。

雖然沒有深入去研究,但我猜想是 IE6 在處理 DOM 時的問題,因此我祭出了 setTimeout 大法:

$(function () {
    $('#copy').click(function () {
        var $checkedValues = $('input.test:checked').clone();
        if ($.browser.msie) {
            setTimeout(function () { $checkedValues.attr('checked', true); }, 0);
        }
        $('#target').html('').append($checkedValues);
        
        setTimeout(function () {
            // 其他可能會對處理到 checkbox 的動作
        }, 0);
    });
});

這裡 setTimeout 可以確保程式在 DOM 完全更新後,再執行下一步的動作。


Posted by jaceju at 樂多Roodo!14:07回應(0)JavaScript