Feed 聚合器

自定Views 欄位輸出 Views fields display

JOE Tsui's Drupal site - 星期一, 2010-08-30 18:05

開發多了以後, 慢慢發展了一個自己比較喜歡的 views templating 方式, 分享一下

1. Row style
絕大部份 "Row style" 都會使用 "fields",
是為了靈活性, 可以在 "Fields" 取需要的欄位
相反 "Row style" "node" 只可以選擇 "full node" 或者 "teaser"
而且它的輸出就會使用 node.tpl.php
不方便, 我習慣自己建立 "frontpage" 資料夾專門用作放置該 views 的 template 的

2. *.tpl.php 儲存結構
續上, 一個 views 在該 theme 之內都有一個資料夾
甚至是一個 display 一個, 例如 views "frontpage":
--theme_joe (資料夾)
----frontpage (資料夾)
------views-view-fields--frontpage.tpl.php
----taxonomy (資料夾)
------views-view-fields--taxonomy.tpl.php

3. 專注在 "Row style" 自定輸出
在 theme information 中的 views-view-field*.tpl.php 是最好用的
可以自定以一個 result 為單位的 templates,
通常我都將views 自定的 HTML tags 全部移除
換上我需要的, 以一個 row 為單位重覆的 HTML,
<div class="row">
  <div class="pic"><?php echo $field_picture[0]['view']  ?></div>
  <div class="right">
    <div class="title"><?php echo $title; ?></div>
    <div class="description"><?php echo $field_description[0]['view']  ?></div>
  </div>
</div>
要留意的是, 使用 <?php echo $field_description[0]['view']  ?>
便要自己設定 "display as"
上例的的 picture 便要使用 "image" 或者 "image link to node"
而不可以使用 "generic file" 或者 "URL to file"

又或者, 你打算 image 的 alt 使用 title,
pic 用 "URL to file", views-view-fields*.tpl.php:
<img src="<?php echo $field_picture[0]['view']  ?>" alt="<?php echo $title; ?>" />


Render Imagecached image through PHP

JOE Tsui's Drupal site - 星期二, 2010-08-24 19:20

<?php
echo theme('imagecache', $preset, $imagepath, $alt, $image_title)
?>

在 node.tpl.php 內可用
其中 $preset 是imagecache profile 的 machine name

ref: http://drupal.org/node/163561


2010-08-16 Dedicated server or Amazon Cloud on Drupal? Drupal 適合使用雲端嗎?

JOE Tsui's Drupal site - 星期一, 2010-08-16 21:22

雲端服務早在上一年已經是非常火熱的題目
由 Amazon 帶起的新一輪伺服器競賽
為租用伺服器帶來很多新的概念,
如 "瞬間加大處理能力", "多樣化的備份, 儲存方案", "CDN 的普及化", 甚至專為Rails 使用的托管等等
伺服器巿場變得更多樣化, 更多競爭

但就 amazon系列 ec2, EBS 等是否適用於全部專案?
更特定講, Drupal上適合 aws嗎?

結論來講, aws沒有優勢

價錢上並沒有優勢.
在2010年中, aws 的價格實際上不是非常地便宜
aws 的真正優點在於平行計算時可以一瞬提供大量計算力
而不需要自己建立一組, 事後又放在一邊沒有用
但網站不會一週只開五日吧, 日常都 24x7 的

在網站伺服器的領域上, 日常都需要維持一定的處理能力
一般一週高峰流量和低之間大約相差只有50% 左右
低流量一樣需要付
"可以降為使用低一級的s1" 只是美麗的誤會
其實是 "一百部 s1 可以降為五十部"
但, 網站的負載不是加五十台 web tier 就可以的
始終不是真正的平行計算

EBS 不算是真正的 harddisk
需要自己mount, ec2 down了要自己重新 mount
都是新的技能, 網管可不是像 dedicated server 般輕鬆

其實最重要的是
瞬間增加計算力的功能已經出現在 dedicated server 巿場
Media temple 便提供短時間提升 MYSQL 的效能
MT, slicehost, linode 都可以一小時內升到更高級的伺服器plan, 而且月付
應付所謂 "digg effect", 其實真正需要的只是一個 monitor service 吧

當然, 像我的blog 的低流量 (<10k PV/m)
只需要 shared hosting 就可以了

待 inmediahk.net 轉到 rackspace 再講講到底為什麼最後都是使用 cloudservers

2bits 也有一文:
http://2bits.com/drupal-performance/drupal-on-a-dedicated-servers-vs-ama...


SA-CORE-2010-002 - Drupal core - Multiple vulnerabilities

Drupal安全公告 - 星期四, 2010-08-12 03:53
  • Advisory ID: DRUPAL-SA-CORE-2010-002
  • Project: Drupal core
  • Version: 5.x, 6.x
  • Date: 2010-August-11
  • Security risk: Critical
  • Exploitable from: Remote
  • Vulnerability: Multiple vulnerabilities

read more

webform module

JOE Tsui's Drupal site - 星期一, 2010-08-02 20:48

webform - http://drupal.org/project/webform

是另一個非常有用的 Module, 主要用於提供一張表單,
可以收集用戶的資料
可以做統計資料收集, 投票等等
而且可以方便的做種分析, 輸出資理到 Excel 方便處理

但問題是, "表單儲存資料" 的工作,
已經有 cck 在做, 那什麼時候使用 webform, 什麼時候用 cck?

最大的分別是, cck 儲存的資料會變成 node
而 webform 的不會
另一個角度看,
就是 webform 的資料不會被其他用戶看得到
因為一般情況, 訪客是可以看到全部已經發表的 node 的
所以更適合用於收集訪客的個人資料等等比較看重資安的應用

而 webform 提供的自建表單也提供很足夠的客製化
email, textfield, textarea, radio, checkbox, select 等等都有
又提供自定的 validation 機制 (PHP based)
更可以發確認電郵到提交者和網管 (可 cc/bcc)
可真是一應俱全的功能

所以我都開始用 webform 代替 Drupal 內建的 contact module
就是看中它的確認電郵功能


Node "back" referenc-ing 反向節點連結

JOE Tsui's Drupal site - 星期一, 2010-07-19 20:00


Node reference 是一種 cck 的欄位
用以放入另一個節點, 建立節點之間的關係
簡單的樹狀結構便可以使用 node reference 來建立主從關係

但今次要討論的是 "反向的 node reference"
想像兩個 content type "project" 和 "task"
"task" 需要一個 node reference 欄位指定它的所屬 "project"
但 "project" 頁面便需要一個 list of tasks
而也不可能在 "project" 同樣建立 node reference 到 "task"
太費時了, 既是雙重輸入 (double entry), 又 "project" 可以有很多 "task", 難以管理

其實反向 node reference 只是一個 views,
使用 node reference 作 filter, 限定某 NID 便可以
只是, 每新加一個 "project" 便需要一個 views
再推導出應該使用 views arguments 傳入 "NID from URL"
反向節點連結便 ok 了


2010-07-12 JQuery UI combobox

JOE Tsui's Drupal site - 星期一, 2010-07-12 20:09

jquery ui 是一個方便的 jquery 擴充庫,
Drupal 中最常用的就一定是 datepicker 了
免去了很多麻煩的日期選擇器
而且用法很多, 兩個一組的, "未來"限定的等等

而另一個很好用, 但不常用的就是一個 autocomplete 的擴充, combo box
它可以是單選 <select> 的完美替代品,
它包含一個 textfield 和一個button
在 textfield 輸入的時候就會將 <select> 內的相關選項以 autocomplete 方式顯示
或者按一下 button, 全個 <select> 內的選項都會顯示
令使用者可以使用類似 <select> 的方式選取

但它有兩個 bug
1. <select> 的 <option> 的 attribute selected=selected 不會預設被選中
做就了我在 github.com 的 commit (ref3)

2. autocomplete 的值不會被更新直至 autocomplete onblur
在選了combo box 後, 直接 submit 的話, 便會發現 <select> 的值沒有被更新
直至 <select> onblur 了, 使用 firebug 令會很清楚
而 fix 便是:
<script>
    minLength: 0,
    close: function(event, ui) {
        $(this).blur();
    }
</script>

ref: http://jqueryui.com/demos/datepicker/
ref2: http://jqueryui.com/demos/autocomplete/#combobox
ref3: http://github.com/joetsuihk/jquery-ui/commit/670f8bf4a3b1783db4733269c0b...


2010-07-05 Exploring ubercart

JOE Tsui's Drupal site - 星期一, 2010-07-05 20:45

Trying to setup a site for simple seats reservations.
ubercart is such a huge module set...
to be continue..


如何善用 settings.php 幫助 deployment, 區分 dev, live 伺服器

JOE Tsui's Drupal site - 星期一, 2010-06-28 20:01

Live 和 Dev (開發) 的伺服器雖然說是應該完全一樣 (無論數據庫還是代碼上)
但始終都需要區分它們
例如使用不同的數據庫連接, site name 變數不一樣等等
令 deployment 的時需要多花些功夫
例如使用 svn branch 分開兩份 settings.php
但方便的程度便不及我以下介紹的這個方法了

編程概念很簡單
利用 dev 伺服器使用 dev.example.com, 而live 使用 www.example.com 作區分
php 中的 <?php $SERVER['HTTP_HOST'] ?>便可以得出 domain name
settings 中便可以:
<?php
if ($_SERVER['HTTP_HOST']=='dev.example.com') {
  $db_url = 'mysql://root@localhost/dev_db';
} elseif ($_SERVER['HTTP_HOST']=='www.example.com') {
  $db_url = 'mysql://root@localhost/live_db';
}
?>

更可以配合使用 $conf 變數方便其他地方使用, 例:
<?php
$conf['env'] = 'dev';
$conf['site_name'] = 'Development server';
?>


Drupal 郵寄副送設定 mail add cc, bcc

JOE Tsui's Drupal site - 星期一, 2010-06-21 19:00

在公司應用的 Drupal 內, contact form 當然提供了一個方便的聯絡方式
只是 contact form 並沒有 cc 和 bcc 的收件者設定
需要自建立一個模組, 並使用 hook_mail_alter() 來自定義cc 收件者
實際使用的 code:
<?php
function joe_module_mail_alter(&$message) {
  if ($message['id'] == 'email_contact') {
    $message['headers']['cc'] = 'joe@example.com';
  }
}
?>
其中的 $message['id'] 是模組名加上 drupal_mail 的 $key 變數
例如 email_contact 其實是修改 email 模組的:
<?php
drupal_mail('contact',$array);
?> >Read more


svn import 的問題

JOE Tsui's Drupal site - 星期一, 2010-06-07 21:20

Svn import 的使用原意是, 將一個已經建立好的專案匯入到 svn 的管理之下
作為第一次的提交, 是假設專案已經開展了, 一次匯入多個檔案

但 svn import 最後卻得不到廣大使用者的支持
svn 的文檔中也建議使用另一個方法匯入 (ref2)
原因有二:
1. 匯入之後的本機文件不會處於svn 的客戶端管理之下 (ref1)
意思其實是 import 了 c:\htdocs\abc 之後,
你需要再從 repo 之中 checkout svn 中的檔案
因為 import 之後, 本機的文件是不會有任何改變, 包括svn 的改變

2. 匯入的文件結構指令很容易出錯
我應該匯入 c:\htdocs\abc 還是 c:\htdocs\abc\* ?
checkout 時應該 checkout 根目錄還是子目錄?

3. 應該習慣建立 trunk, branches, tags 等的根目錄作為分支時使用 (ref3)
但import 方法不支持先建立以上的目錄樹

所以, svn 的官方文件建議的做法是,
先 checkout 空的根目錄, 再用一般的 add + commit 的方式提交第一次的源代碼

ref1: http://svnbook.red-bean.com/en/1.0/re12.html
ref2: http://subversion.apache.org/faq.html#in-place-import
ref3: http://svnbook.red-bean.com/en/1.4/svn.tour.importing.html


分享扫描版古籍

kzeng 寱语 - 星期二, 2010-06-01 05:39

手头有很多年积攒下来的扫描版古籍,很适合在 Kindle DX 或者其他足够大的手持设备已经电脑上看。昨天正巧有人让我帮忙找一下 1956 年中华书局版的《资治通鉴》,所以就顺便想了一下分享这些已经版权过期的古籍的方式(按照中国的著作权法,这些古籍应该不存在版权问题,因为作者都已经过世超过五十年)。以前试过用比较复杂(当然也比较方便)的 Biblio 模块,但是那个输入起来太费时间了,所以对于希望有一种方式可以:

  • 支持 FTP 批量上传
  • 支持简单的文件描述
  • 可以使用 drupal 的访问控制和角色控制
  • 和 drupal 本身的各种功能更好的整合

其实符合这些要求的 drupal 模块很多,实验了一下,最后决定用 filebrowser 模块,完全符合上述的要求,并且支持三种下载管理模式(公开,私下,安全)。另外,它直接把 directory listing 作为一种新的内容类型,很方便管理,所以暂时使用这个模块继续实验一下。

在 blog 的导航中加入了“古籍”,点击就可以进入古籍列表了,可以直接利用浏览器的搜索功能进行搜索,也可以通过本 blog 的搜索功能。FTP 上传很便捷,一会儿功夫就上传了 2.1 G 的 PDF。同时重写了列表的 CSS ,使它和 blog 主题的风格一致。为了防止 Unicode 的文件名导致在某些浏览器中不能下载,所有文件名都改为数字名称。另外在本地写了一个小程序,可以快速的更改文件名和添加文件描述。

以后会陆续添加更多的古籍到这个目录,选录古籍的基本标准如下:

  • 实体书扫描版(这样才能确保质量)
  • 以中华书局、商务印书馆等主要出版社为主(也是为了确保质量)
  • 古籍的原作者必须过世五十年(以符合中国的著作版权法)
  • 只收录 PDF 格式,其它格式譬如 .djvu等也会先转为 PDF 格式再上传(方便 Kindle 阅读)

试一段时间看看。

views 表格頭 theming (table header theming)

JOE Tsui's Drupal site - 星期一, 2010-05-31 22:10

先修文章:
http://joetsuihk.com/node/94
http://joetsuihk.com/node/95

Views 的table header是可以使用 *.tpl.php 修改的,
常見的應用包括使用 icon 而不使用 text 作為 label
只要修改 style output 的 views-view-table.tpl.php
<?php
// $Id: views-view-table.tpl.php,v 1.8 2009/01/28 00:43:43 merlinofchaos Exp $
/**
* @file views-view-table.tpl.php
* Template to display a view as a table.
*
* - $title : The title of this group of rows.  May be empty.
* - $header: An array of header labels keyed by field id.
* - $fields: An array of CSS IDs to use for each field id.
* - $class: A class or classes to apply to the table, based on settings.
* - $row_classes: An array of classes to apply to each row, indexed by row
*   number. This matches the index in $rows.
* - $rows: An array of row items. Each row is an array of content.
*   $rows are keyed by row number, fields within rows are keyed by field ID.
* @ingroup views_templates
*/
?>
<table class="<?php print $class; ?>">
  <?php if (!empty($title)) : ?>
    <caption><?php print $title; ?></caption>
  <?php endif; ?>
  <thead>
    <tr>
<?php //表格頭輸出開始: ?>
      <?php foreach ($header as $field => $label): ?>
        <th class="views-field views-field-<?php print $fields[$field]; ?>">
          <?php print $label; ?>
        </th>
<?php //表格頭輸出完結:?>
      <?php endforeach; ?>
    </tr>
  </thead>
  <tbody>
    <?php foreach ($rows as $count => $row): ?>
      <tr class="<?php print implode(' ', $row_classes[$count]); ?>">
        <?php foreach ($row as $field => $content): ?>
          <td class="views-field views-field-<?php print $fields[$field]; ?>">
            <?php print $content; ?>
          </td>
        <?php endforeach; ?>
      </tr>
    <?php endforeach; ?>
  </tbody>
</table>
開發者只需要將 foreach 改成多個 if
就個別欄位表格頭輸出所需之 icon 圖像

看似簡單, 但如果表格頭需要 sortable, 並指示排序方向的話
便要再加一個 if case 檢查 $_GET['order'] 作不同輸出
奇怪 $views 變數之中竟然沒有 sort order 的資料

魔鬼都在細節之中...


Google Font API

kzeng 寱语 - 星期六, 2010-05-29 05:24

font_api-128[1]这两天又折腾了一下 drupal 主题。N. Design Studio 有一款很不错的 wordpress 主题 koiabthemes把它移植到了 drupal上,用了几天,找到了一些 bug,陆陆续续修正了,然后又做了一些我需要的更改,总算稳定下来。又安装了一些新的模块,譬如 Tagadelic,可以提供一个 tag 云 block (右下角)和一个tag 云的页面,这样blog里用的 tag 马上就多了一个维度出来,可以直观的看到各个话题所占的比重,譬如和历史相关的话题中,原来我这里关于三国秦国汉朝清朝的 blog 数目最多,在数量上差不多和生活相关的话题里的旅行一样多了。这倒正是一句古话:“一壶浊酒喜相逢。古今多少事,都付笑谈中。”

因为使用 Tagadelic block 的缘故,非常需要一款比较窄的字体,blog 的默认字体 Georgia 太宽大,使得 tag 云看起来很别扭,但是HTML普遍支持的字体中并没有窄字体,开始的时候想到了 Drupal 的Dynamic Rendering 模块(前阵子用它来生成 blog 标题所用的“华康丽黑”字体),它的原理是利用服务器端的字体生成 Flash 来替换原有的字体,但是这种方法的效率不高,也会拖慢网站的速度,正巧想起了 Google 前阵子推出的 Font API,试了一下,不仅效果很好,速度也很快。

Font API 通过调用 Google Font Directory 里的开源字体来达到在网页显示其他非常用高质量字体的目的。它的应用很简单,只需要一些简单的 CSS 知识,譬如我用的这款 Yanone Kaffeesatz 字体,只需要在我的 CSS 文档的开头加入字体的定义:

@import url(http://fonts.googleapis.com/css?family=Yanone+Kaffeesatz);

然后在需用使用这款字体的地方利用 font-family 来调用就可以了,我的 Tag 云 block 和 页面就是一个例子。在 blog 中也可以用嵌入的 CSS 任意调用:

Give a man a fish, you feed him for a day. Teach a man to fish, you feed him for a lifetime.

稍感缺憾的是现在只有对拉丁文字字体的支持,没有汉字字体。不过汉字字体除了文泉驿外,似乎其他开源并且美观的字体并不多,另外汉字字体文件的庞大尺寸也许会影响到网页的速度。当然还有另外一个最大的问题:如果 googleapis.com 这个域名被 GFW 喀嚓掉了,那再好的字体效果也显示不出来。哈哈,反正现在 GFW 还喀嚓着我的 blog,所以我倒可以无顾忌的放心使用了:)

PS:听说因为开世博会,GFW赦免了一大批网站,但是我的 blog 却不在其中,阿弥陀佛,看来我真的罪孽深重:)

Drupal7 的 模版改變 Drupal7 theming changes

JOE Tsui's Drupal site - 星期一, 2010-05-24 21:15

DrupalCon SF 之後, 有很多 video 和session 都放到網上了
花了幾天的時間看了些自己喜歡的, 例如 A peek at Drupal 7 theme system changes

翻譯一下 http://www.slideshare.net/pingv/grok-drupal-7-theming (不是全部的改變, 詳情參考 ref2)
1. Drupal 7 theme 需要有以下元素:

  • CSS file
  • image
  • template (*.tpl.php)
  • js
  • preprocess 和 process (new)
  • .info

2. 將 page.tpl.php 分成 html.tpl.php 和 page.tpl.php
html.tpl.php 會放 DOCTYPE 一類的 tag

3. node.tpl.php 需要用 <?php render($content['comments']); ?> 才會顯示留言 (D6是預設自動加上)

4. 新增 region.tpl.php

5. node-[contenttype].tpl.php 改成 node--[contenttype].tpl.php
單劃表示連接字, 例如 content type 為 "super story" 時, 便使用 node--super-stoty.tpl.php

ref1: A peek at Drupal 7 theme system changes http://pingv.com/blog/a-peek-at-drupal-7-theme-system-changes

ref2: Converting 6.x themes to 7.x http://drupal.org/update/theme/6/7


2010-05-18 Drupal db_query vs views 的比較, 開發時要注意的地方

JOE Tsui's Drupal site - 星期二, 2010-05-18 18:02

一直看到國內的進階 Drupal 教程都會提到使用 db_query() 用以代替 views, 例如: http://drupalchina.org/node/9021
觀點大概是 views 使用太多資源了, 使用 db_query() 能直接存取數據資料, 性能上會比較好,
也更自由等等

以下是我的個人意見:

雖然是進階的教程, 但開發者在有其他可使用的方法之下直接存取是不可取的, 原因:

1.安全問題
這是最重要的一點, 避開 sql-injection, xss
在自定義的代碼之中, 有太多入門的開發者忽視或不重視數據安全的問題
在不清楚如何編寫安全的 Drupal 代碼之前已經開始開發
而 views 的設計上已經極大量的考量安全問題
至少, views 之類的大型模組, 單單是測試者的數量可能已經比美你的訪客人數
所以, "自定義的代碼 會/可以 和 views 一樣安全" 是不成立的
views 一定比自定義的代碼安全
ref: http://drupal.org/writing-secure-code

2. 可變性
使用 views 的好處還有可變性強
這很明顯, 使用views 的 web admin 修改代碼一定會比修改自定義的快
在這個永遠活在 beta 版的網頁開發世界, 這一定是一個重要的優勢
多出的時間應該要用於編寫幫助文件或者用於測試等等的地方

3. 性能
這是一個沒有正確答案的問題:
使用views 是否一定會比較慢?
views 本身並不只是一個sql 產生器, 它還內建緩存機制
就好像 variables_get() 函數, Drupal 會將會個 variables table 放到一個 cache
一個 select 便可以存取全個 variables table 之內的數值
而類似的機制也出現在views
當然, 一個精心設計的 sql 會比 views 快,
但這個精心設計所帶來的性能是否可以補回以上的問題便值得仔細研究了

4. 培養良好的開發習慣
"良好的開發習慣" 很抽象
但基本的例如 *.tpl.php 之內不應該有顯示視圖以外的功能/代碼
又或者 CSS 應集中於一個css 檔之內而不應使用inline: <a style="color:red;">joe</a>
不應修改 Drupal 的核心代碼等等
這些習慣其實是可以由使用 contributed modules 來培養的
因為它們會定好習慣, 而你順著使用便會是最快的開發方式
然後藉此 "培養更多的良好的開發習慣"

最後, 這些都是我的觀點, 也是我見過的其他 Drupal 國外高手的潛規則
希望大家深入討論, 思考