您在這裡

theme()的問題

hanamizuki's 的頭像
hanamizuki 在 2008-10-10 (週五) 17:06 發表

hi,最近在用Ubercart,有個關於theme的問題。

在Drupal核心常看到這樣的東西:

$output .= theme('item_list', $section['items']);

我目前的理解是,item_list是核心格式化過的一種東西,直接呼叫,餵入陣列,就會把資料顯示成item_list的格式。

我想問的是,有辦法改嗎?因為Ubercart有自己的theme格式,比方說

$output .= theme('uc_catalog_products', $products);

但是這樣輸出的格式不是我想要的,有辦法不要用theme(),直接使用$products嗎?但我不知道這個東西裡面有什麼可以讓我自己排版。
很苦惱。

------------------

具體問題是,我安裝了Best Seller的Block,但我想要是顯示圖、下面有文字,並且是並排的,但他的原始碼出來之後,
是用表格的方式顯示,很討厭。

以下是我找到這個block的theme,然後弄成phptamplate的原始碼:

/**
* Display the content for best sellers products list
* JTR
*/
function phptemplate_uc_marketing_bestsellers_products() {
$product_types = module_invoke_all('product_types');
$gridwidth = variable_get('uc_catalog_grid_display_width', 3);
if (variable_get('uc_catalog_grid_display', false)) {
$gridlines = variable_get('uc_marketing_bestsellers_block_lines', 1);
$gridwidth = $gridwidth * $gridlines;
}

$products = array();
$sql = "SELECT nd.nid, nd.title,
(SELECT SUM(op.qty)
FROM {uc_order_products} AS op
WHERE op.nid = nd.nid) AS sold
FROM {node} AS nd
WHERE nd.type IN ('". implode("','", $product_types) ."')
AND nd.status = 1
ORDER BY sold DESC";
$result = db_query_range($sql, 0, $gridwidth);
while ($node = db_fetch_object($result)) {
$products[] = $node->nid;
}

if (count($products)) {
$output .= '

22' . variable_get('uc_marketing_bestsellers_block_title', t('Best Sellers')) . '

';
$output .= theme('uc_catalog_products', $products);
if (variable_get('uc_marketing_bestsellers_block_help_allowed', true)) {
$output .= '' . variable_get('uc_marketing_bestsellers_block_help', t("So many people can't be wrong. These products have been ordered the most.")) . '';
}
}
return $output;
}

我可以修改到h2的部分,但他的重點只用
$output .= theme('uc_catalog_products', $products);

這樣帶過去,然後我在Ubercart核心搜尋uc_catalog_products,又找不到相關的資料,
只好來這求助囉!

我不是很懂php的程式我只提供想法讓你參考
$output .= theme('uc_catalog_products', $products);裡頭的uc_catalog_products應該就是輸出的樣式來源,那一段在ubercart/uc_catalog/目錄裡,要自訂樣式應該是改用theme API的其他函式或是自訂輸出函式放到uc_catalog_products裡,這裡http://api.drupal.org/api/function/theme/5/references" 應該有你想要的資料

theme('uc_catalog_products', $products);
實際上呼叫的 function 是 theme_uc_catalog_products($products)
這種格式都是留給讓開發人員可以在版型內去覆寫的

在版型裡 可以在 template.php 內加上 (沒有的話需要自己手動建立)
garland_uc_catalog_products($products) => 把 function 開頭的 theme 換成版型的名字
phptemplate_uc_catalog_products($products) => 把 function 開頭的 theme 換成版型引擎的名字
其中一種格式來覆寫

在復寫的順序上是 garland_ -> phptemplate_ -> theme_
越前面的會先被使用
通常模組裡會使用 theme_ 定義一個預設的輸出
所以在版型裡起碼要使用 phptemplate_ 來做覆寫

嗯!感謝!又學了一課。

我去找了,原始碼是這樣

function theme_uc_catalog_products($products) {
if (!$products) {
$output .= '

'. t('No products are available in this category.') .'

';
return $output;
}
else {
if (variable_get('uc_catalog_grid_display', false)) {
return theme('uc_catalog_product_grid', $products);
}
else {
$table_args = array('nids' => $products, 'attributes' => array('class' => 'category-products'));
return tapir_get_table('uc_product_table', $table_args);
}
}
}

所以,除了第一種情況是「無商品」可以編輯,接下來又是
return theme('uc_catalog_product_grid', $products);

$table_args = array('nids' => $products, 'attributes' => array('class' => 'category-products'));
return tapir_get_table('uc_product_table', $table_args);

我知道可以找uc_catalog_product_grid,不過,實際上出來的是這段原始碼:
$table_args = array('nids' => $products, 'attributes' => array('class' => 'category-products'));
return tapir_get_table('uc_product_table', $table_args);

所以tapir_get_table又是什麼呢?可以複寫嗎?

你可以先去啟用 grid 的顯示模式
再去覆寫 theme_uc_catalog_product_grid($products) 應該是比較快的做法
這樣就不需要覆寫 theme_uc_catalog_products($products)

或是乾脆直接修改 theme_uc_catalog_products($products) 的輸出值也是可以的

<?php
function phptemplate_uc_catalog_products($products) {
if (!$products) {
$output .= '

'. t('No products are available in this category.') .'

';
return $output;
}
else {
/*
if (variable_get('uc_catalog_grid_display', false)) {
return theme('uc_catalog_product_grid', $products);
}
else {
$table_args = array('nids' => $products, 'attributes' => array('class' => 'category-products'));
return tapir_get_table('uc_product_table', $table_args);
}
*/
foreach($products as $key => $product){
$output .= '

[自訂的輸出]

';
}
return $output;
}
}
?>

tapir_get_table() 應該是 tapir 模組提供的用來產生一個 table 的 function
在 Ubercart 的設定裡有一項是列出表格 你可以直接在這裡把表格的欄位名稱改成自己想要的
這部分應該就是用 tapir_get_table() 來輸出的表格
tapir 我沒有研究過 不過感覺上要修改輸出不是那麼容易
所以我認為上面兩種方式是比較簡單的

我找到解答了,以下是我的理解。

1.我用了Views來輸出List,再用CSS來format

CSS如下
/*
* block-views-block_products*
*
*
*/

#block-views-block_products {
clear:both;
width:700px;
height:300px;
}
#block-views-block_products h2{
font-size:17px;
font-family:simhei;
padding-top:20px;
padding-left:20px;
}
#block-views-block_products li{
float:left;
width:200px;
margin-left:15px;
}

#block-views-block_products .view-data-node-data-field-image-cache-field-image-cache-fid{
float:left;
margin-right:7px;
}
#block-views-block_products .view-data-node-title{
height:55px;
}
#block-views-block_products .view-data-uc-products-sell-price{
text-align:right;
color:#FFCCCC;
}
#block-views-block_products input.node-add-to-cart{
border:1px solid #ddd;
background-color:#FFFFFF;
width:90px;
vertical-align:bottom
}

2.但後來發現其實應該是要去修改tapir的設定,
tapir_get_table('uc_product_table', $table_args);
上面這行代表他是用tapir (Table API)生成表格的,既然都是Table API了,他就當然會是表格,也沒必要改。
Table API很方便,修改畫面如圖:

3.到Ubercart後台(admin/store/settings/catalog/edit/grid)把grid打開的話,再設定一列的數量,就會以grid顯示。
這就是grid

最後想請問hom一個問題,關於「自訂的輸出」那邊。

foreach($products as $key => $product){
$output .= '

[自訂的輸出]

';
}

自訂的輸出有哪些變數可以用呢?是像$product->name這樣嗎?
我要如何知道$product裡面有哪些東西呢?
抱歉,我不會PHP.....

抱歉,我真的很菜,請問print_r($product)是要放在?
我放成這樣
foreach($products as $key => $product){
$output .= '

[自訂的輸出]

';
print_r($product);

}

結果輸入結果最上面出現2315這個數字!好詭異!

theme('uc_catalog_product_grid', $products) 的原始碼:

<?php
function theme_uc_catalog_product_grid($products) {
$product_table = '

';
$count = 0;
foreach ($products as $nid) {
$product = node_load($nid); //讀取商品資料

if ($count == 0) {
$product_table .= ""; //第一筆的時候輸出
}
else if ($count % variable_get('uc_catalog_grid_display_width', 3) == 0) {
$product_table .= ""; //依據 grid 設定的換行格數 輸出
}

$titlelink = l($product->title, "node/$nid", array(), null, null, false, true); //標題連結
if (module_exists('imagecache') && isset($product->field_image_cache) && file_exists($product->field_image_cache[0]['filepath'])) {
//如果可以顯示圖片則輸出圖片連結
$imagelink = l(theme('imagecache', 'product_list', $product->field_image_cache[0]['filepath']), "node/$nid", array(), null, null, false, true);
}
else {
$imagelink = '';
}

$product_table .= '';
if (variable_get('uc_catalog_grid_display_title', TRUE)) {
$product_table .= ''. $titlelink .''; //設定顯示標題欄位時 輸出 $titlelink
}
if (variable_get('uc_catalog_grid_display_model', TRUE)) {
$product_table .= ''. $product->model .'';//設定顯示 model 欄位時 輸出 $product->model
}
$product_table .= ''. $imagelink .''; //輸出 $imagelink
if (variable_get('uc_catalog_grid_display_sell_price', TRUE)) {
//設定顯示售價欄位時 依據設定的格式輸出 $product->sell_price
$product_table .= ''. uc_currency_format($product->sell_price) .'';
}
if (variable_get('uc_catalog_grid_display_add_to_cart', TRUE)) {
//啟用在 grid 內顯示"加入購物車"的按鈕
if (variable_get('uc_catalog_grid_display_attributes', TRUE)) {
//啟用在 grid 內顯示 attributes
$product_table .= theme('uc_product_add_to_cart', $product);
}
else {
//停用在 grid 內顯示 attributes
$product_table .= drupal_get_form('uc_catalog_buy_it_now_form_'. $product->nid, $product);
}
}
$product_table .= '';

$count++;
}
$product_table .= "

";
return $product_table;
}
?>

看起來 $products 應該只是一個 nid 的陣列
所以 print_r() 的輸出應該是正常的
另外
我在原始碼內加了一些註解
也許可以給你一點幫助

大哭!真是太感動了。這樣果然比較清楚了!!!

所以像$product->title
是指,$products是一堆nid,然後用node_load()把這些nid的產品資訊都抓出來,
就可以用$product->title來顯示了!是這樣嗎?

照這樣寫,

<?php
function phptemplate_uc_catalog_products($products) {
if (!$products) {
$output .= '

'. t('No products are available in this category.') .'

';
return $output;
}
else {
foreach($products as $nid){
$product = node_load($nid);
$output .= '

' . $product->title . '

';
}
return $output;
}
}
?>

成功地輸出商品名稱了!!!!!!(抱)

謝謝hom的耐心。

然後我又用您剛才說的print_r($product);,結果跑出一堆東西。


stdClass Object ( [nid] => 2 [vid] => 2 [type] => product [status] => 1 [created] => 1223799355 [changed] => 1223869838 [comment] => 2 [promote] => 1 [sticky] => 0 [revision_timestamp] => 1223869838 [title] => 紐西蘭100%天然有機鹿肝【150g】240元 [body] => [teaser] => [log] => [format] => 1 [uid] => 1 [name] => admin [picture] => [data] => a:4:{s:14:"picture_delete";s:0:"";s:14:"picture_upload";s:0:"";s:16:"privatemsg_allow";i:1;s:28:"privatemsg_setmessage_notify";i:1;} [model] => 123456 [list_price] => 0.00 [cost] => 0.00 [sell_price] => 240.00 [weight] => 150 [weight_units] => g [length] => 0 [width] => 0 [height] => 0 [length_units] => in [pkg_qty] => 1 [default_qty] => 1 [unique_hash] => b20a1e3c55fb0600a741aee7ec3a3fda [ordering] => 0 [shippable] => 1 [path] => product/2 [field_image_cache] => Array ( [0] => Array ( [fid] => 1 [title] => [alt] => [nid] => 2 [filename] => 2008-10-12_161707.jpg [filepath] => files/2008-10-12_161707.jpg [filemime] => image/jpeg [filesize] => 10969 ) ) [signup] => 0 [0] => [last_comment_timestamp] => 1223799488 [last_comment_name] => [comment_count] => 0 [taxonomy] => Array ( [46] => stdClass Object ( [tid] => 46 [vid] => 1 [name] => 寵物用品 [description] => [weight] => 0 ) ) [flatrate] => Array ( ) [shipping_type] => small_package [shipping_address] => stdClass Object ( ) [custom_code] => $item->price = $item->price; )

照這堆像亂碼的東西看,我能用在$product->之後的,是不是就是像[status]這樣框起來的呢?
$product->status就會顯示1,真有趣耶!!!!!

好開心!

有個題外的問題,就是資料庫裡面的時間,都是這樣
1223799355
有什麼function可以把這串字變成幾月幾日幾點幾分嗎?
---自己回,php的function是這樣
date('y-m-d', $product->created)
會出現2008-10-12
drupal本身應該也有許多日期顯示的function,不知要去哪找?

另外,您是如何讓您發表的code有php的lighlight呢?我都是黑的嗚!!

沒錯
print_r() 所輸出的就是所有的資料與結構
而且會在開頭顯示資料的類型 => stdClass Object
如果是顯示 Array 的話 那就需要改成 $product['status'] 的格式來讀取資料
你可以去對照一下 pro drupal development 內 node 那張開頭所介紹關於 node 底下的資料所代表的意義
像 status 就是代表該篇文章(商品)是否啟用 0:停用, 1:啟用
pro drupal development 內沒有列出來的 則有可能是其他模組透過 nodeapi 等 hook 額外附加上去的資料了

日期的部份
在版型的 node.tpl.php 找到的是 format_date() (官網 API)
會依照 drupal 網站設定 -> 日期與時間 內設定的格式來輸出日期與時間

highlight 的部份
code 裡面頭尾記得要加上 <?php ?>

呵呵!我剛才就已經在書上做一堆筆記了,就是您說的那邊。

不過因為他只有列出基本的資料,所以我在弄版型的時候,很希望能看到「所有我能運用的參數」,
print_r真是好東西。

若是顯示array,我用print_r就沒辦法知道有哪些項目了嗎?

所以如果是物件(Object)的話,就要用$foo->param
如果是陣列(Array)的話,就要用$foo['param']
這樣嗎?

好複雜啊!