2007年09月30日

[Web] 連結分享

PHP

Zend Framework

JavaScript

CSS

  • Vertical Centering in CSS

    如何讓元素在區塊垂直居中?主要是 IE 上會有一些問題。不過利用在屬性名前加上 # 號的這個技巧,可以在 IE 上達到類似的效果。

SQL

Other


Posted by jaceju at 15:40回應(0)連結分享

2007年09月28日

[JavaScript] window.onresize 連續觸發的問題

今天遇到了一個怪異的問題,就是在 IE6 底下 window 的 onresize 這個事件竟然會在視窗大小沒有改變的情況下被連續觸發;試了一下 Firefox 和 IE7 都沒有這個問題,所以我便懷疑是 IE6 有實作上的錯誤。

為了查證,我 Google 了一下,找到了以下這篇文章:

IE Fires Onresize When Body Resizes

原來 IE6 會在 body 被 resize 時,同時觸發 window 的 resize 事件。

不過 body 什麼時候會被 resize 呢?通常就是利用 display 來顯示或隱藏元素的時候,例如:

<!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>window.onresize</title>
<script type="text/javascript">
var link  = null;
var block = null;

var resizeWindow = function () {
    alert('resized');
};

window.onload = function () {
    link  = document.getElementById('link');
    block = document.getElementById('block');
    link.onmouseover = function () {
        block.style.display = 'block'
    };
    link.onmouseout  = function () {
        block.style.display = 'none'
    };
    window.onresize = resizeWindow;
};
</script>
</head>

<body>
<a href="window.onresize.html" id="link">Link</a>
<div id="block" style="display:none;">
<p>Show something.</p>
</div>
</body>
</html>

這時候當滑鼠移到 Link 上時,因為元素會有消長,所以 body 的 resize 就會被觸發 (也即 reflow 這個觀念) ,只是這時候 IE6 就會很雞婆地一起觸發 window 的 resize 事件,而且會一直連續觸發;如果這時我們在 window.onresize 有設定要處理某些東西的話 (例如上面的 resizeWindow 函式) ,就會使得真正的 mouseover 和 mouseout 事件無法正常動作。

而我會遇到這個狀況是因為我需要在 window.onresize 裡處理一些排版上的問題,也就是在視窗大小變化後,有些透過 JavaScript 來調整寬度的選單就需要重新調整。但是這時如果連續觸發了 window 的 resize 事件,就會造成整個程式執行起來頓頓的。

還好上面找到的文章提供了一個解法,那就是判斷 document.documentElement.clientHeight 是不是有被改變了。所以我只要把 resizeWindow 這個事件改成以下的樣子就可以了:

var currentClientHeight = 0;

var resizeWindow = function () {
    if (currentClientHeight != document.documentElement.clientHeight) {
        alert('resized');
    }
    currentClientHeight = document.documentElement.clientHeight;
};

雖然 window 的 resize 事件還是會被連續觸發,但是至少觸發時所需要執行的動作減少了,這樣就不會讓程式執行起來感覺頓頓的了。


Posted by jaceju at 20:00回應(0)JavaScript

2007年09月27日

[Web] 連結分享

PHP

  • Extra fields for Zend_Db_Table

    在 Zend_Db_Table 中增加資料表所沒有的欄位。

  • Zend Framework 1.0.2 Released

    ZF 1.0.2 釋出,主要有以下的更動:

    • New database adapter for PDO_IBM
    • Custom database profiler support
    • New Google Base support with Zend_Gdata_Gbase
    • Added CAPTCHA support to Zend Gdata
    • Improved PDF component documentation
    • Enhanced search performance
    • More flexible language translation facilities
    • Additional UTF-8 support for validation
    • Documentation of the Zend Framework system requirements
  • Zend Framework MVC Webinar posted

    很棒的 ZF MVC Web 教學,相關視訊、 PDF 教材與程式範例都可以在 Zend Recorded Webinars & Demos 找到。

JavaScript / CSS

Web

  • Learn Apache mod_rewrite: 13 Real-world Examples

    用實際的例子來介紹 Apache 的 mod_rewrite 模組。

  • [轉貼] 如果建築師必須如網頁設計師一般工作

    這種事情我也有慘痛的經驗,所以感受很深。看完以後有點想殺人的衝動...Orz

  • 10 Usability Nightmares You Should Be Aware Of

    10 個要儘可能避免的介面技術,沒用好的話可能會變成使用者操作上的惡夢。列舉如下:

    1. Hidden log-in link (不明顯的登入連結)

    2. Pop-ups for content presentation (利用 window.open 所建立的彈出視窗來呈現主要的網站內容)

    3. Dragging instead of vertical navigation (利用 Flash 建立的可拖動視窗,使得有些頁面無法被 Bookmark)

    4. Invisible links (不像連結的連結)

    5. Visual noise (沒辦法一眼看出主要訊息的雜亂畫面)

    6. Dead end (不想繼續卻無法取消的死路)

    7. Content blocks layering upon each other (擋路的圖層)

    8. Dynamic navigation (位置不定的導覽列)

    9. Drop-Down Menus (無法快速表明重點的階層式下拉選單)

    10. Blinking images (不斷閃動的 GIF 動畫)


Posted by jaceju at 10:53回應(0)連結分享

2007年09月26日

[PHP-ZF] Zend Framework 1.0.2 版釋出

這次 Zend Framework 1.0.2 主要是修正許多 1.0.1 所發現的 Bug ,詳細內容可以參考 Chagelog

Zend_Gdata 修得最多,看來外國人還滿喜歡把 Google 的服務整合到程式裡面。


Posted by jaceju at 16:08回應(0)Zend Framework

[Web] 連結分享

PHP

The Standard PHP Library (SPL)

Zend 終於有一篇很正式的 SPL 介紹文章了,這篇真的寫得很不錯,雖然都偏重於 Iterator 。

Funny __toString() behavior

PHP 的 __toString 這個魔術方法的行為有點怪,使用的時候要小心。不過我是覺得這個是沒搞清楚回傳值型態的關係,因為 __toString 回傳的一定是字串,所以給它別的型態都是不行的。

JavaScript

jQuery: jQuery 1.2 Cheat Sheet

簡睿那邊看到的,還不錯的速查表。


Posted by jaceju at 10:59回應(0)連結分享

2007年09月25日

[Web] 連結分享

PHP

JavaScript

CSS

Web

  • robots.txt Adventure

    介紹 robots.txt ,雖然擋君子不擋小人,有些機器人根本不理這個玩意,可是身為一個 Web 開發者,還是要懂相關的原理。

  • PNG8 - The Clear Winner

    PNG 8bits 這個格式是一般 Web 設計者常會忽略的,但是它的透明度在各家瀏覽器上的呈現算是有不錯的相容性。

Programming

Software


Posted by jaceju at 18:10回應(2)連結分享

2007年09月21日

[PHP-ZF] 初探 Zend_Db_Table Relationships (二)

前一篇文章提到了簡單的 Zend_Db_Table 的一對多關連,這次來談一對一 (多對一) 和多對多。

不過我對一對一的定義比較模糊,詳細的資訊請參考良葛格的 Hibernate 學習筆記

資料表範例

基本上還是前一篇文章的範例,這次加上標籤 (Tag) ;每篇文章 (Article) 可以標上多個標籤,而每個標籤則是可以對應到多篇文章。新增的資料表結構如下:

CREATE TABLE IF NOT EXISTS `tags` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `name` varchar(200) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

INSERT INTO `tags` (`id`, `name`) VALUES
(1, 'php'),
(2, 'zend framework');

CREATE TABLE IF NOT EXISTS `articles_tags` (
  `article_id` int(10) unsigned NOT NULL default '0',
  `tag_id` int(10) unsigned NOT NULL default '0',
  PRIMARY KEY  (`article_id`,`tag_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO `articles_tags` (`article_id`, `tag_id`) VALUES
(1, 1),
(1, 2),
(2, 1),
(2, 2);

其中我們多了一個中間表 articles_tags ,然後在邏輯上 articles.id 會關連到 articles_tags.article_id ,而 tags.id 則對應到 articles_tags.tag_id 。在 articles_tags 中, article_id 和 tag_id 為組合主鍵。

範例下載

下載位置

註:一樣沒包 Zend Framework ,請自行下載安裝。

說明

一對一 (多對一)

首先我們先來看看如何如何從文章中抓取對應的分類,從一篇文章上只會找到一個分類,也就是一對一關連。

註:其實嚴格來說文章對分類不是一對一的關係 (應該是多對一) ,只是在 Zend_Db_Table 裡,它們的作法是相似的。

然而一對多和多對一只是兩個相關的對應關係,因此我們並不用修改原來的 Articles 和 Categories 兩個 Classes 。在 Zend_Db_Table_Row 中,提供了一個 findParentRow 方法,讓我們能從 Articles 反推回去找到 Categories ;也就是在 IndexController::index 中,我們只要這樣做:

$phpArticle = $articles->find(2)->current();
$this->view->category = $phpArticle->findParentRow('Categories');

這裡會抓取 articles.id 等於 2 的文章,然後透過 findParentRow 來向 Categories 取得對應的分類。另外 Zend_Db_Table_Row 也提供了一個魔術方法,只要用 findParent<ParentClass> 就可以達到同樣的效果,例如:

$this->view->category = $phpArticle->findParentCategories();

然後我們就可以在 index.phtml 顯示相關的分類了:

<?php
var_dump($this->category->toArray());
?>

多對多

文章和標籤是以多對多的關係存在的,所以我們要先加入兩個 Classes ,一個是 Tags ,另一個是 ArticlesTags ;它們分別對應 tags 和 articles_tags 兩個資料表:

class Tags extends Zend_Db_Table_Abstract
{
    protected $_name = 'tags';
}

class ArticlesTags extends Zend_Db_Table_Abstract
{
    protected $_name = 'articles_tags';

    protected $_referenceMap    = array(
        'Tag' => array(
            'columns'           => array('tag_id'),
            'refTableClass'     => 'Tags',
            'refColumns'        => 'id',
        ),
        'Article' => array(
            'columns'           => array('article_id'),
            'refTableClass'     => 'Articles',
            'refColumns'        => 'id',
        ),
    );
}

註:這裡暫時不考慮 $_dependentTables 屬性,後面有用到再加。

在 ArticlesTags 這個 Class 的 $_referenceMap 屬性裡,我定義了兩個 Rule ,一個為 Tag 、另一個為 Article ;它們分別關連到 Tags 和 Articles 這兩個 Classes 。

在 Zend_Db_Table_Row 裡提供了一個 findManyToManyRowset 的方法,可以協助我們處理多對多的關係。我們沿續第一個例子,假設現在我們想知道該篇文章所對應的標籤有哪些,可以這樣寫:

$this->view->articleTags = $phpArticle->findManyToManyRowset('Tags', 'ArticlesTags', 'Article');

在 findManyToManyRowset 方法裡一般會用到三個參數,第一個參數表示要關連的資料表 Class ,第二個參數則是中間表所對應的 Class ,而第三個為 Rule 的名稱。而要特別注意的是, Rule 所對應的 refTableClass 要和 findManyToManyRowset 方法所在的物件其對應的資料表一樣。可以對照一下上面 $phpArticle 物件所對應的資料表和最後一個參數值 Article 所對應的資料表,這樣就很容易理解了。

最後一樣在 index.phtml 裡顯示結果:

<?php
var_dump($this->articleTags->toArray());
?>

當然反過來要從標籤去取得文章也就很簡單了,只要抓出目前的標籤,然後再利用 findManyToManyRowset 方法來取得關連的文章就可以了 (提示: Rule 要用 Tag) 。


Posted by jaceju at 0:09回應(0)Zend Framework

2007年09月20日

[Web] 連結分享

PHP

JavaScript

  • Javascript for hackers

    一些駭客可能會用的 JavaScript 技巧,我覺得很厲害的是,竟然可以在 GekoGecko based 瀏覽器上用以下方式來呼叫 eval 函式:

    0['eval']('alert(/XSS/)')

Posted by jaceju at 16:32回應(2)連結分享

[PHP-ZF] 初探 Zend_Db_Table Relationships (一)

早上四點半就醒了...睡不著,想說研究一下 Zend Framework DB 一對多的關連。先前一直搞不定其中的關係,沒想到簡單玩了一下,竟然就搞定了 (可見手冊我根本就沒看懂...Orz) 。

這裡記一下,以免之後又忘記了。

資料表範例

這裡我用文章 (Article) 及文章分類 (Category) 來做為例子,它們的 DB Schema 如下:

CREATE TABLE IF NOT EXISTS `articles` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `category_id` int(10) unsigned NOT NULL,
  `title` varchar(200) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `table1_id` (`category_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

INSERT INTO `articles` (`id`, `category_id`, `title`) VALUES
(1, 3, 'Zend_Db_Table'),
(2, 3, 'Zend_Controller_Action'),
(3, 2, 'jQuery'),
(4, 2, 'Prototype');

CREATE TABLE IF NOT EXISTS `categories` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `parent_id` int(10) unsigned NULL,
  `name` varchar(200) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

INSERT INTO `categories` (`id`, `parent_id`, `name`) VALUES
(1, NULL, 'PHP'),
(2, NULL, 'JavaScript'),
(3, 1, 'Zend Framework');

其中 articles.category_id 對應到 categories.id ,而 categories.parent_id 也對應到自己的 categories.id 。

程式碼架構

這裡主要我是拿 RobGetting Started with the Zend Framework 裡面範例來修改,詳細架構就先看看後面附的下載檔。

不過也不一定需要用這樣的架構才能跑 ZF ,這是因為我偷懶不想寫太多不相關的程式,所以直接拿別人的來改。事實上我們可以把 Zend_Db 獨立出來使用,只是這樣要寫的東西就會比較複雜一點點,跟我要研究的東西無關。

範例下載

下載位置

註:裡面沒包 Zend Framework ,請自行到官方網站下載,然後把 library 目錄解開放到範例資料夾下即可。

說明

首先我們需要兩個繼承 Zend_Db_Table_Abstract 的 Class ,它們分別是 Articles 和 Categories :

class Articles extends Zend_Db_Table_Abstract
{
    protected $_name = 'articles';
}

class Categories extends Zend_Db_Table_Abstract
{
    protected $_name = 'categories';
}

因為大部份工作已經被 Zend_Db_Table_Abstract 做掉了,所以 Articles 和 Categories 只要很簡單的指定 $_name 屬性即可;這樣一來, Articles 和 Categories 兩個 Classes 就能對應到 articles 和 categories 兩個資料表。

不過這樣還沒有辦法讓這兩個資料表在程式碼裡產生關連,我們必須在 Articles 和 Categories 這兩個 Classes 額外定義一些資訊,讓它們能互相認識。首先我們在 Articles Class 裡加上 $_referenceMap 屬性:

class Articles extends Zend_Db_Table_Abstract
{
    protected $_name = 'articles';

    protected $_referenceMap    = array(
        'Category' => array( // 給這個關連一個名字
            'columns'           => 'category_id', // 對應到 articles.category_id
            'refTableClass'     => 'Categories',  // 對應到 Categories Class
            'refColumns'        => 'id',          // 對應到 categories.id
        ),
    );
}

$_referenceMap 屬性是用來宣告要透過哪個欄位來和另一個資料表做關連,就上面的例子來看,我們可以很清楚的看到是 articles.category_id 關連到 categories.id 。然而 $_referenceMap 屬性可以同時定義多組關連,但為了簡化以便於理解,這裡我只用了一組。

在這裡的 $_referenceMap 屬性裡主要有三個項目:

  • columns :表示目前資料表關連到另一個資料表的欄位,一般就是 Foreign Key (FK) 。

  • refTableClass :關連資料表所對應的 Class ,這裡要注意大小寫。

  • refColumns :關連資料表所對應的欄位,一般就是 Primary Key (PK) 。

註: $_referenceMap 其實還有其他可設定的項目,這裡暫不介紹。

接著 Categories 這個 Class 也必須定義一個 $_dependentTables 屬性,宣告與 categories 有關連的資料表名稱;這是為了保證我們在透過 Categories Class 刪除資料時,能一併刪掉關連資料表裡的資料 (這裡我還在研究,尚無實例) 。

class Categories extends Zend_Db_Table_Abstract
{
    protected $_name = 'categories';

    protected $_dependentTables = array('Articles');  // 對應到關連的 Table Class
}

註:事實上 $_dependentTables 屬性在目前這個例子裡可以不加,因為我們還用不到關連更新或刪除的功能。

現在我們可以在 IndexController::indexAction 裡測試看看:

class IndexController extends Zend_Controller_Action 
{
    function indexAction()
    {
        $categories = new Categories();

        $zendframework = $categories->find(3)->current();
        $this->view->articles = $zendframework->findDependentRowset('Articles');
    }
}

其中 findDependentRowset 是 Zend_Db_Table_Abstract 提供的方法,它可以幫我們找出關連資料表的所有資料。我們在 index.pthml 裡可以將取得的結果表列出來:

<?php
var_dump($this->articles->toArray());
?>

是不是很簡單呢?

那麼第二個問題來了,如果我們要讓 categories._parent_id 和 categories.id 產生關連呢?

其實仿照上面的做法,我們只需要在 Categories Class 裡動手腳即可:

class Categories extends Zend_Db_Table_Abstract
{
    protected $_name = 'categories';

    protected $_referenceMap    = array(
        'ParentCategory' => array(
            'columns'           => 'parent_id',   // 對應到 categories.parent_id
            'refTableClass'     => 'Categories',  // 對應到 Categories Class
            'refColumns'        => 'id',          // 對應到 categories.id
        ),
    );

    protected $_dependentTables = array('Articles', 'Categories');   // 對應到關連的 Table Class
}

也就是說,我們在 Categories Class 加入一個 $_referenceMap 屬性關連到自己,然後在 $_dependentTables 加入自己。

接著在 IndexController::indexAction 中測試一下:

class IndexController extends Zend_Controller_Action 
{
    function indexAction()
    {
        $categories = new Categories();

        $php = $categories->find(1)->current();
        $this->view->subcategories = $php->findDependentRowset('Categories');

        $zendframework = $categories->find(3)->current();
        $this->view->articles = $zendframework->findDependentRowset('Articles');
    }
}

在 index.phtml 裡顯示結果:

<?php
var_dump($this->subcategories->toArray());
?>

以上就是簡單的 Zend_Db_Table_Actract 一對多關連取得資料集的方式,謝謝收看,下次見。 (補眠去...什麼?已經天亮要上班了喔?)


Posted by jaceju at 6:46回應(0)Zend Framework

2007年09月19日

[Web] 連結分享

PHP

  • Using the Observer Design Pattern with Static Data in PHP 5

    這篇可以學到怎麼利用 Observer Pattern 來處理表單資訊,不過我覺得如果直接利用 PHP5 的 SplObserver 介面來實作的話應該會比較有趣一點。

  • Refactoring PHP Code

    除了 Martin 大師的重構方式以外,這篇提到了一篇適用於 PHP 的重構手法。可惜 PHP 沒有一個好的 IDE 可以協助我們作重構,希望未來可以看到。

  • streams gem

    又是 stream ,簡單又好用。

  • View Helper Case Notes

    用 Zend Framework 要注意很多大小寫的問題,這篇提到的 View Helper 只是其中之一。另外分享幾個也是要注意的大小寫問題:

    • 在 Linux 系統下,在繼承 Zend_Db_Table_Abstract 的類別裡, $_name 屬性指定的 Table 名稱,其大小寫要和 MySQL 存放在檔案系統裡的資料檔名大小寫一致。

    • 在 Linux 系統下, Action Controller 的命名在 Controller 前一定是首個字母大寫,其他小寫。例如 ArticleCategoryController 是錯的,要寫成 ArticlecategoryController 才對。

  • Eclipse PDT (PHP Development Tools) 1.0 Released Today

    PDT 釋出了 1.0 版,大概也是因為 Zend Studio Neon 的關係吧。可以看一下 ChangeLog ,看看有什麼新特色。

JavaScript

CSS

Other


Posted by jaceju at 10:40回應(0)連結分享
 [1]  [2]  [3]  [4]  [最終頁]