PHP

multi-site 要如何共用 user 帳號密碼

multi-site 共用同一個 mysql 的話, 例如:
site1:

<?php
//settings.php:
$db_url = 'mysql://root@127.0.0.1/site1';
$db_prefix = array(
       
'default' => '',
       
'users' => 'shared_',
       
'sessions' => 'shared_'
);
?>

site2:

<?php
//settings.php:
$db_url = 'mysql://root@127.0.0.1/site2';
$db_prefix = array(
       
'default' => '',
       
'users' => 'site1.shared_',
       
'sessions' => 'site1.shared_'
);
?>

用 PHP 來提取 views 的結果: $view->preview()

EDIT 2010-01-13 <?php $view->access() ?>

之前有提及過用 PHP 來提取 views 的結果: 從 fid 提取上傳檔案的資料

但發覺這個方法不可以拿出 Filefield 的資料, 原因未明
因為效能問題不想使用 node_load(), 花了些時間挖
Views 的 AJAX paging 就是使用 <?php $view->preview()?> (可以參考右欄 Recent content 的 paging)

實際使用:

<?php
    $view
= views_get_view($name);
    if (
is_object($view)) {
     
$output .= $view->preview($display_id,array($taxonomy->name)); //第二個 arg array() 是給views 用的 argments
   
}
?>

此方法可以完全使用 views 的 templates, display options 等, 真正方便

EDIT:
要檢查權限:<?php $view->access($display_id) ?>

再加一個方法:

<?php
views_embed_view
($name, $display_id, $arg1, $arg2);
?>

2009-10-21 php copy array

我的code 很簡單, 做test driven development 寫test的時候
pass in 的data 很多時候都要重用
只是其中一個field 的值修改, 其餘的都不變
所以:

<?php
function testSubmit(){
//init. data
$data = array(
   
'user' => 'abc',
   
'password' => 'def',
);

//copy array
$test = array_merge($data);
//change value
$test['user'] = '';
//test
$this->assertTrue(foo($test));

//copy again
$test = array_merge($data);
//change value
unset($test['user']);
//test
$this->assertTrue(foo($test));
}
?>

那我便可以方便的修改pass in 的data (只修改一個地方)

重點是, array 的複製要使用 array_merge()...

2009-08-08 htmlentities() 和 html_entity_decode()

htmlentities() 和 html_entity_decode()

htmlentities()
http://www.php.net/manual/en/function.htmlentities.php

功能上很簡單, 就是將 < 變作 &lt;
當然, 還有其他的entities, 可以參考: http://www.w3schools.com/tags/ref_entities.asp
主要是給使用者輸入的 entities 會 escape, 輸出的時候便可以直接使用

另一方面, >Read more

專業級編程人員和普通編程員的分別

-

今天路過一個網站
What separates a professional PHP web developer from a scripter?
覺得不錯, 你可能不會完全同意他們說法,
但逐一看看相關的資料都會學到不少東西

翻譯:
我(原作者)三年來已經見過差不多第二百個php/web 應徵者了. 我得出一些作為一個高級(senior) 開發者所需的條件, 要求.
但發現98%的應徵者不能達到一半的要求, 你具備多少個?

PHP5 vs PHP4
你必需知道最少它們之間三個主要的功能差異

Networks(網路)
你必需懂得基本的接口(socket) 編程, 或最少, 如何連接到其他電腦

OOP
你必需對面向對象編程(object-oriented programming) 有深的認識, 知道簡單的問題, 如私有(private) 和內部(protected) 方法的分別.
並知道:(你可沒有用過, 但至少知道為何需要它們)
* 接口 interfaces
* 构造函數 constructors
* 私有, 內部, 公共 private, public, protected
* 繼承 inheritance
* 多態性 polymorphism
* static methods

Database(資料庫)
什麼是normalized database, 知道 primary 和 foreign keys,

Design Patterns(設計結構)
你不必覺得奇怪. 同樣的, 你不需使用很多, 但必需知道最少幾種結構

Source Control(源碼控制)
明瞭其中一種以上的版本控制系統. 知道cvs 的致命弱點可加分

Unit Testing(個體測試)
什麼是個體測試(unit test), 為什麼重要(test driven design, javascript 測試, 使用selenium 可加分)

Part of the Community(社區的一份子)
從google 上可以找到你的php, web 技術, 工作. 如果google 上找不到你, 基本上是一個警告(red flag)
(如果有一個企劃或你參與的都可以加分)

Javascript Skills
使用DOM(document object model)(appendChild, removeChild, nextSibling...),
在javascript 內建立類, 懂得建立私有變數可加分

CSS Skills
知道box model(padding, margin, border的分別, 關係, 內外), css 選擇器, 繼承

Passion for Improvement(進步的熱情)
愛你所做的, 不要只做到最低要求. 持續建立技術, 變得更有價值
四時五十九分check-in, 五時走人留下未build 的源碼等都是欠缺熱情的表現

譯者註:
從留言看, 有不少人覺得這幾個條件不錯,
但也有人覺得js, css 的要求相對不重要
socket 的使用次數六年都未有一次
好的開發者也未必有時間活躍於社區
五時離開只是時間管理好等等

我個人覺得, 這些都是概念上的東西
是編程第一課的東西
但反正大家都會忘記了
到了某一天, 你覺得php 應用起來得心應手
就應該回到概念, 你就會更上一層樓
進步的是mind-set, design-pattern, 更加可擴充
此乃"內功"之重要性
特別是非計算機科學出身的開發者更為顯著
內功心法就會隨著時間增長了

2007-05-12 jquery 在Drupal 的使用(二) -jquery recursive

續jquery

先說明一下callback
用fadeIn() 說明一下

fadeIn(speed, callback)

fadeIn() 有兩個參數
第一個speed
用作指定淡入的速度, 可以為字符串"slow" "normal" "fast"
也可以為數字, 指定毫秒(千分一秒)

第二個callback
參數可以是一個函數名, 也可以定義一個新函數(inline 的方式)
而這個函數會在fadeIn() 完成,
也即是效果完結的時候被呼叫.
例如

$("#joe").fadeIn( "normal" , "joe_example" )

function joe_example(){
    alert( "Element with id " + $(this).attr("id") + " fade in finished." );
}

這樣fadeIn 元成的時候便會呼叫 joe_example()
函數內可以用 $(this) 來指定"自己"
來獲得這個元素的相關資料
如果配合next(), sibling(), parent() 也可以得到附近的元素
再作其他處理

至於inline的方式, 語法為:

$("#joe").fadeIn( "normal" , function(){
  $(this).next().fadeIn();
});

例子中, id 是joe 的元素先淡入
淡入完成之後,
joe 元素的下一個元素淡入
完成一次兩個為一組的連還淡入效果
注意, 這個例子只會淡入joe 元素和joe 元素的下一個元素
共兩個元素
並不會連鎖的淡入第三個元素

如果要發生無限的連鎖,
像這站的menu 的效果
便要使用遍歷(recursive) 結構了
首先介紹一下遍歷結構,
簡單的遍歷一般是指一個函數會自己呼叫自己
一直到符合某一個條件才停下
所以一個完整的遍歷結構一定有兩個條件
一個是呼叫自己的呼叫
另一個是一個停止呼叫的條件
用一個簡單的例子說明

function recursive(count){
  //完結條件
  if ( count>5 ){
    return;
  }
  alert( count++ );
  //呼叫自己
  recursive( count );
}

上面展示了一個遍歷函數
但這個函數不會開始, 直到代碼第一次呼叫 recursive(0)
一但被第一次呼叫(initialize)
便不會停, 直到count>5

同樣的原理可以放到menu 的連鎖反應之中
javascript 的代碼都分為兩個部份
一個遍歷的函數,
一次呼叫(initialize)

//initialize
$(document).ready(function(){
  $("ul.primary-links").children().eq(0).fadeIn("slow",function(){nextFadeIn(this)});
});
//遍歷函數
function nextFadeIn(obj){
  $(obj).next().fadeIn("slow",function(){nextFadeIn(this)});
}

下一次介紹drupal 加入javascript 的方法和總結一下jquery 的用法, 思考方向等

2007-04-26 Tutorial on Drupal form API, Drupal 表單使用教學

原本打算先寫一個cck 的教學
但因為工作上的需要, 急需對Drupal form API 有深一點的認知
所以就埋頭苦幹, 翻讀又翻讀Drupal 主站的手冊
定要打好form 處理的根基

本文既翻譯官方手冊關於form API的一些部分
再加上自己的一點研發而成

表單乃任何應用系統的中心
令使用者和系統之間的交流具體化
確實請求, 遞交的介面, 公用接口等
如果沒有表單, 用戶只可被動的接受系統的一切
用戶的要求並不能傳到系統中,
像啞巴, 不能表達自己的訴求
用了表單, 用戶可以在系統允許的情況之下要求
如排序, 提交等等
所以一個小型的模組很可能已經需要使用表單,
作了解用戶的設定, 請求之用
可惜, Drupal 的 form API 使用概念上和html form 有頗大差異
但的確簡化了傳統上 顯示, 處理, 儲存 三個部分的處理

用form API 生成表單, 大概有三個地方可放代碼
*.module 文件, template 文件, block boxes.(hook_form_alter() 只用作修改, 而非建設表單)

*.module 文件中放代碼這方法為主流, 也正統, 又萬能
官網的教學全都集中在這個地方.
主要目的多是開發一個新的模組, 要設定模組的各參數而使用表格
學習上, 因為有很多現成模組的例子, 算是簡單
生成方法要從hook_menu 說起
user.module 為例:

<?php
$items
[] = array(
 
'path' => 'user',
 
'title' => t('User account'),
 
'callback' => 'drupal_get_form',
 
'callback arguments' => array('user_login'),
 
'access' => !$user->uid,
 
'type' => MENU_CALLBACK
);
?>

設定:
路徑(path) /%DRUPAL%/user
頁面標題(title) t('User account') (t()為可以翻譯)
存取時轉到函數(callback) drupal_get_form()
函數參數(callback arguments) array('user_login')
權限(access) !$user->uid (指已經登入者)

實際上呼叫函數drupal_get_form('user_login')
drupal_get_form('user_login') 呼叫 user_login(),

<?php
user_login
(){
...
 
$form['name'] = array(
   
'#type' => 'textfield',
   
'#title' => t('Username'),
   
'#size' => 60,
   
'#maxlength' => USERNAME_MAX_LENGTH,
   
'#required' => TRUE,
   
'#attributes' => array('tabindex' => '1'),
  );
...
  return
$form;
}
?>

例子中定義了一個textfield (#type)
field 的題目(類似說明)為t('Username') (t()為可以翻譯)
等等, 詳細參數表請參考API http://api.drupal.org/api/5/file/developer/topics/forms_api_reference.html
user_login() 最後返回變數$form, 給drupal_get_form()
表單顯示輸出部份到此完成
只要設定好 user_login, hook_menu,
其餘的部分(action, method, form_id, form tags)由Drupal 負責

接著是確認表單有效的步驟: ( 按了submit, button type 後 )
續用user_login 為例,
定義一個函數: 函數名_validate()

<?php
function user_login_validate($form_id, $form_values) {
  if (
$form_values['name']) {
 
//略
?>

$form_id 為 函數名
$form_values 為array, 像一般的$_POST 般使用
_validate() 認證錯誤的話, 使用form_set_error('login' , $message);
Drupal 自動跳回表單
否則不用返回, Drupal 跳到儲存函數

儲存函數: 函數名_submit
(按下type 為 submit 的元素後)

<?php
function user_login_submit($form_id, $form_values) {
/**
*  數據庫處理等等
*/
 
$message = 'submit complete';
  return
"/user".$user->uid;
}
?>

$form_id 為 函數名
$form_values 為array, 像一般的$_POST 般使用
返回值為路徑, Drupal 會跳到該路徑
並顯示$message

到此, 基本, 主要, 一般使用form API 的方法完成

Template 文件上使用form API 實際上違反了MVC 的概念
但卻能快速的實現表單, 添加和修改頁面隨意
如 "加一個表單到關於我們, 填電話吧" 之類的請求
用一個模組加上hook_form_alter, hook_node_api 會令模組管理混亂
系統效能下降的問題
而更麻煩的是開發時間長
使用template 能減輕一定程度的工作量,
特別當改動少, 但又不得不改代碼, CSS 不能代勞時.

使用概念跟使用druapl_get_form() 大致相約
template 中一樣要定義三個函數, 如

<?php
function user_login2(){
 
$form[]=array(
    ..........................
  );
  return
$form
}

function
user_login2_submit($form_id, $form_values){
  .............
}

function
user_login2_validate($form_id, $form_values){
  .............
}

print_r (drupal_get_form('user_login2'));

?>

最後用一句 print_r 就可以了,
Drupal 會顯示表單.
也使用 user_login2_validate() 確認
user_login2_submit() 提交

但留意, 切忌過份使用, 否則只會做成維護的困難
又,
如果只改動現有模組, 可先作處理, 再呼叫原模組:

<?php
function user_login2(){
 
$form[] = user_login();
 
$form[] = array(
    ....
  );
}
function
user_login2_submit($form_id, $form_values){
 
//more operation here
 
user_login($form_id,$form_values);
}
?>

至於block boxes,
block 可以自己定制, 可以使用php code內建到block
在site build->block 內有add block 選項
code 的使用和template 使用form API 的方法一樣
不再重覆, 主要使用print_r(drupal_get_form())
但值得一提的是block 的擺放位置, 如加上panels
幾乎可以放到任何位置, block 又可以設定何時顯示, 何時隐藏
又開發快速
唯一缺點, 如果php 代碼有錯, 將會做成修改不能的錯誤
要手動到資料庫修改, 故只適用於對php 非常熟悉的人使用

Originally want to write a tutorial about cck first.
However, because of my job, there is an emergency that i need to have a deeper knowledge about Drupal's form API.
So here comes hours ad hours study, rushing through drupal's handbook,
build up so solid base about form.

form system is a concrete base of any application.
it makes the communication between user and system become practical, applicatable,
include confirm requests, submit interface, public sockets etc etc.
if there is no forms at all, users can only accept the information from server passively.
user's request cannot be sent to server,
like mute, who cannot present themselves.
under forms, users can submit request upon their needs,
for example sorting or submit etc etc.
as a result, there may be already a need for forms even inside a small module.
but unluckily, the concept between Drupal's form API and HTML form is very different,
in terms of three core part of form: presentation, process, save.

To use from API to generate forms, there are three places that your code may place
*.module file, templates, boxes block. ( hook_form_alter() can only edit a form, but not create one )

form API inside *.module is the most popular method, Drupal style, and also powerful.
the tutorial inside drupal.org is mainly focus in this scoop.
This method is mainly used to configure the parameters of the module, during development a new module.
This method ie relatively easy to learn as there is many existing modules that you can refer to.
the start point is hook_menu():
use user.module as an example,

<?php
$items
[] = array(
 
'path' => 'user',
 
'title' => t('User account'),
 
'callback' => 'drupal_get_form',
 
'callback arguments' => array('user_login'),
 
'access' => !$user->uid,
 
'type' => MENU_CALLBACK
);
?>

details:
path /%DRUPAL%/user
title t('User account') (t()means translatable)
callback drupal_get_form()
callback arguments array('user_login')
access !$user->uid (means logged-in user)

in practical, this will have call a function drupal_get_form('user_login')
drupal_get_form calls user_login():

<?php
user_login
(){
//...some code before...
 
$form['name'] = array(
   
'#type' => 'textfield',
   
'#title' => t('Username'),
   
'#size' => 60,
   
'#maxlength' => USERNAME_MAX_LENGTH,
   
'#required' => TRUE,
   
'#attributes' => array('tabindex' => '1'),
  );
//...some more code...
 
return $form;
}
?>

In this example, it defines a textfield by #type,
the title of this field is Username (t()means translatable)
etc etc. and the parameters reference: http://api.drupal.org/api/5/file/developer/topics/forms_api_reference.html
finally, user_login() return the $form variable, back to drupal_get_form()
the output part of form finished.
you only have to setup user_login, hook_menu, the elements inside the form,
the rest part( action, method, form_id, form tags ) will left to Drupal.

next is the validation of form( by pressing any button, submit type ):
user_login() as example again,
define a new function inside *.module, named function _name_validate()

<?php
function user_login_validate($form_id, $form_values) {
  if (
$form_values['name']) {
 
// some code
?>

$form_id is the name of the form function,
$form_values is an array, like normal $_POST,
if validation fails, you may use form_set_error('login' , $message);
Drupal will jump back to the form
otherwise, drupal will jump to save process.

save function: function_name_submit()
(when press element that is 'submit' type)

<?php
function user_login_submit($form_id, $form_values) {
/**
*  database process
*/
 
$message = 'submit complete';
  return
"/user".$user->uid;
}
?>

$form_id is the name of the form function,
$form_values is an array, like normal $_POST,
return the path that will be redirected,
and display $message

up to this point, the basic use of form API finish.

The use of form API inside template file actually contradict the MVC concept,
but this method can build up form quickly, edit them quickly.
for example, a need of "add a form to about us, user may enter their phone number"
this kind of need is not worth to open a new module because of performance, long develop time
using template can reduce some workload,
especially when changes is small, but CSS cannot help.

the basic concept is the same, also use drupal_get_form(),
define three function inside the template file:

<?php
function user_login2(){
 
$form[]=array(
    ..........................
  );
  return
$form
}

function
user_login2_submit($form_id, $form_values){
  .............
}

function
user_login2_validate($form_id, $form_values){
  .............
}

print_r (drupal_get_form('user_login2'));

?>

finally use print_r, drupal will display the form.
user_login2_validate to process validation the form
user_login2_submit to save to database,

but keep in mind, do not use it frequently, which will increase the difficulties to maintain

finally, about from API inside block boxes,
as blocks can embed php code inside,
form can also embedded inside blocks.
the use of code is just like the use inside template,
use print_r(drupal_get_form()) again,
define three function....
one more to note, in combination with panels modules,
blocks can be placed everywhere, in specific page, specific place,
with fast development
the only disadvantage is, if there is php code error inside block,
you may face down site, which can only be repair from database.
so it is only advice to advance php users

2007-04-11 Add digg it to your wordpress

2007-04-21 修正:這站已經換成Drupal Based.

現今首屈一指的用戶驅動的新聞網站中
digg.com 絕對為大龍頭
透過用戶的點?量為新聞評分
真正一人一票選新聞

這個資訊爆炸的年代,
用一個資訊爆炸的方法
自動, 實時的排序出最熱的新聞
無人運作, 卻一日二十四小時不停更新

所以介紹一個wordpress plugin: Gregarious
為你的wordpress 自動加上digg, tailrank 等大量用戶驅動網站的連結
方便訪客, 方便自己

安裝:
將 gregarious folder 放到 wp-contentplugins 下
然後到wordpress plugin admin 啟用後
便可以到options 中找到 gregarious 的管理介面
一開始有數個選項
但其實只會用到post badge 和 share-this 兩個
post badge 就是那個顯示有多少個digg 的buttom
share-this 就是一個綜合的buttom,
令用戶可以一click 即可將你的網頁放到十多個網站的popup.

tips:
post badge 的位置可以在post badge 的option 中config
diggWrap 就是digg buttom 的 class 了
而askt_form 就可以apply share-this 的CSS