2010年11月26日 星期五

CCK型態

從頭開始試真的是件痛苦的事@@
首先新增一個內容類型
然後開始新增fields(欄位)
麻煩的是fields的TYPE有6個:
Float – 浮點數
Integer – 整數
Decimal – 實數
Text – 文字
Node Reference – 節點參照
User Reference – 使用者參照

再來就是一個一個設來測試囉
把測試的重點記一下…
Float:
check boxes/redio buttons
Number of values: 2
Allowed values list:
1.222
3.4
5.6666
Integer:
check boxes/redio buttons
Number of values: 1
Allowed values list:
123,456
789
Decimal:
Select list(下拉式選單欄位)
Allowed values list:
aaa,bbb
ccc
Text:
text feild
Node Reference:
Select list(下拉式選單欄位)
Number of values: 5
User Reference:
Autocomplete text filed(會自動拼出符合的字串的文字欄位)

水滴關鍵說明

  • ontent type: 就是一種文件的形式、內容。譬如說,卡片的格式和書信的格式不同,公文的格式跟相片集的格式不同。
  • node: 就是每一個單一的文件,在drupal被視為節點,每一個單一文件是依據不同的形式發表出來。
  • taxonomy terms: 就是為該文件標注分類,跟文件的「形式」不同。分類的重要任務,是為了將不同形式的文件串連在一起整合運用,或對文件做歸檔整理以供日後用途,並且可以定義樹狀結構表現出不同類別的父子關係。他的範疇可能包含每一個node(如tag),也可能是針對某幾種文件的形式來做分類。如公文裡頭可以分成不同年度,書信可以分成札記和散文,相片文件可以分成不同的相簿...等。
  • views: views如名,就是專門管理呈現的部份。因為一個站可能有上萬個nodes,views可以用各種交叉條件篩選出畫面中想呈現的nodes(通常是文件)。可能是不同分類(taxonomy)不同文章形式(content type)還是不同的欄位(年度)的交集。views也提供呈現的方式的設定,如地圖的方式、表格的方式、摘要文的方式、全文的方式、清單的方式...等。

參考:

content-type決定content-template 資料形式決定資料樣板

drupal 中 node是用來記錄資料的一個單位
會依content-type決定content-template

假設comment-book.tpl.php樣板存在,所訪問
的note-type是book時,drupal會使用comment-book.tpl.php
而不是預設的comment.tpl.php




http://www.joetsuihk.com/define-comment-template

2010年11月13日 星期六

Blog的按月歸檔

第一種

$allvaliddates=$blog->getarraybyquery("SELECT `pubtime` FROM `{$db_prefix}blogs` ORDER BY `pubtime` DESC");
$allvaliddates=$allvaliddates['pubtime'];
$resultdates=array();
$result="";
if (is_array($allvaliddates)) {
foreach ($allvaliddates as $time) {
$y=gmdate('Y', $time+3600*$config['timezone']);
$m=gmdate('n', $time+3600*$config['timezone']);
$resultdates[$y][$m]+=1;
}

第二種

$archives = $DMC->query("SELECT postTime FROM ".$DBPrefix."logs where $saveType ORDER BY postTime DESC");
$articledb = array();
while ($article = $DMC->fetchArray($archives)) {
$article['dateline'] = format_time("Y,m",$article['postTime']);
$articledb[]=$article['dateline'];
}
unset($article);
$archivedb = array_count_values($articledb);
unset($articledb);

2010年11月1日 星期一

include 和 require

  • 引用方式的不同
    require 的使用方法通常使用在PHP程式的前頭,在執行前會將因入的檔案展開至原本的程式,實際上文件的內容是去替換該語句。

    include 通常放在流程控制中,在讀到那一行時才去讀取該文件內容。


  • 警告方式的不同

    include()會產生一個警告,而require()則導致一個致命的錯誤(出現錯誤,腳本停止執行)

    require() :如果文件不存在,會報出一個fatal error.腳本停止執行

2010年9月29日 星期三

ZF快速建模的工具zend-db-model-generator

羨慕ROR有好用的工具可以掃描資料庫並建出model嗎?
最近發現一個好工具,zend-db-model-generator

在開發時可以先下載這個工具

http://code.google.com/p/zend-db-model-generator/

svn checkout http://zend-db-model-generator.googlecode.com/svn/trunk/ zend-db-model-generator-read-only

然後將config資料夾下的config.php-default 複製一份成為 config.php

並修改裡面資料庫的設定


回到上一層後

執行zend-db-model-generator.php 看有什麼功能好用

--database : database name
--location : specify where to create the files (default is current directory)
--namespace : override config file's default namespace
* --table : table name (parameter can be used more then once)
--all-tables : create classes for all the scripts in the database
* --ignore-table : not to create a class for a specific table
* --ignore-tables-regex : ignore tables by perl regular expression
* --tables-regex : add tables by perl regular expression

先來試用一下

php zend-db-model-generator.php --database musicscript --all-tables

他會將你資料庫中的musicscript所有的資料表都建立model在目前資料夾底下
如果想指定位置只要設定--location參數即可。

也能指定資料表user

php zend-db-model-generator.php --database musicscript --table user

測試下--all-tables好像有錯誤訊息!!但不影響建模

當然如果你不喜歡他所建立的內容,也有模版可以自己修改在templates資料夾下

2010年9月27日 星期一

一個用php操控Mysqlnd的接口mysqlnd_uh

以往我們使用PHP連接MySQL時,大部分都是C接口
而這個是使用純粹PHP寫出的PHP功能

http://pecl.php.net/package/mysqlnd_uh


可以用來使用PHP Mysql Proxy的功能


關於Mysqlnd是PHP5.3以上提供的庫,為資料源提供緩衝
也可節省更多資源的消耗詳情請看

http://www.javaeye.com/news/380

2010年9月22日 星期三

PHP的Include與Autoload性能比較

直譯語言在運行期時可以動態載入欲執行的物件,在速度上都會認為Autorun其實不然

請看autoload 與 include性能比較
http://calos-tw.blogspot.com/2009/08/php-autoload-include.html

文中測試結果
迴圈為1 時 . include_once 比較快
迴圈為1000時. __autoload 快很多

當重覆載入時__autoload比較快,但實際上在開發,要重覆載入一個物件的機會可能比較少,使用時
Autorun倒是可以減少許多手工寫code的部份&^^

2010年9月20日 星期一

取得PHP物件中的屬性及方法

在使用第三方的物件時由於文件缺乏,可以使用

get_class_vars 返回由類的默認屬性組成的數組
get_class_methods 返回由類的方法名組成的數組

method_exists(物件名稱, 屬性) 該物件是否有該方法


來取得該物件的屬性及方法

2010年9月9日 星期四

字串切隔取得副檔名

$aryExtend = explode('.', 'abc.gif');
# /**
# * $filename 是 abc.gif
# * $aryExtend為陣列
# */
$extend = end($aryExtend);

2010年9月7日 星期二

使用ZendFrame Work達到跨站使用Session(同個網域下)

Memo(有空再來測試)

實現多個伺服器使用同一份SESSION
http://hi.baidu.com/renyuan1985/blog/item/081d8ff3f431cf58352accb9.html

為Zend_Session 添加一個Memcache_ SaveHandler
http://hi.baidu.com/billdkj/blog/item/049d04f0b2a896c47831aa1c.html

2010年9月6日 星期一

PHP中讀取YAML

先至http://sourceforge.net/projects/spyc/files/

下載spyc可供使用
基於Ruby帶動了一股使用YAML的風潮,想在PHP中使用可以試試spyc物件。
YAML就結構上比XML更簡潔。


include('spyc.php');

// 讀取YAML文件,生成陣列
$yaml = Spyc::YAMLLoad('spyc.yaml');

// 將陣列轉換成YAML文件
$array['name'] = 'lrenwang';
$array['site'] = 'blog.lrenwang.com';
$yaml = Spyc::YAMLDump($array);

Spyc::YAMLDump只是提供轉換,想修改檔案可以參考一下

file_put_contents('spyc.yaml',$yaml);

2010年8月23日 星期一

centos 安裝pdo-mysql

透過pear來安裝^^",yum沒有辦法直接裝pdo-mysql

yum install php-devel php-pear mysql-devel httpd-devel
pecl install pdo
pecl install pdo_mysql

Fedora 安裝PDO_MYSQL

yum install php-pdo gcc php-devel
wget  http://pecl.php.net/get/PDO_MYSQL
phpize
./configure
make ;make install

2010年5月17日 星期一

最近關注的網站

http://code.google.com/p/memcache-cluster-failover-php/


http://code.google.com/p/phuselage/

http://www.agavi.org/

http://www.michaelheid.de/gophe-search-service/

2010年5月4日 星期二

2010年4月27日 星期二

常用的PHP function

在php開發中,我們經常會遇到一些函數,下面是整理好的,可以直接使用,方便開發效率,不過建議大家一定要先看懂,然後在這個基礎上增加功能就提高了自身能力了

1.產生隨機字符串函數

function random($length) {

$hash = @#@#;

$chars = @#abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz@#;

$max = strlen($chars) - 1;

mt_srand((double)microtime() * 1000000);

for($i = 0; $i < $length; $i ) { $hash .= $chars[mt_rand(0, $max)]; } return $hash; } 2.截取一定長度的字符串 注:該函數對gb2312使用有效 function wordscut($string, $length ,$sss=0) { if(strlen($string) > $length) {

if($sss){

$length=$length - 3;

$addstr=@# ...@#;

}

for($i = 0; $i < $length; $i ) { if(ord($string[$i]) > 127) {

$wordscut .= $string[$i].$string[$i 1];

$i ;

} else {

$wordscut .= $string[$i];

}

}

return $wordscut.$addstr;

}

return $string;

}

3.取得客戶端ip 地址

function getip(){

if (getenv("http_client_ip") && strcasecmp(getenv("http_client_ip"), "unknown"))

$ip = getenv("http_client_ip");

else if (getenv("http_x_forwarded_for") && strcasecmp(getenv("http_x_forwarded_for"), "unknown"))

$ip = getenv("http_x_forwarded_for");

else if (getenv("remote_addr") && strcasecmp(getenv("remote_addr"), "unknown"))

$ip = getenv("remote_addr");

else if (isset($_server[@#remote_addr@#]) && $_server[@#remote_addr@#] && strcasecmp($_server[@#remote_addr@#], "unknown"))
$ip = $_server[@#remote_addr@#];

else

$ip = "unknown";

return($ip);

}
4. 創建相應的文件夾

function createdir($dir=@#@#)

{

if (!is_dir($dir))

{

$temp = explode(@#/@#,$dir);

$cur_dir = @#@#;

for($i=0;$i
if(!empty($url))

$html .="";

$html .="";

$html .="



";

$html .="";

$html .="";

$html .="";

$html .="";

$html .="".$title."";

$html .="";

$html .="
".$message."

";

if (!empty($url))

$html .="系統將在3秒後返回
如果您的瀏覽器不能自動返回,請點擊[這裡]進入";
else

$html .="[返回]";

$html .="";

$html .="";

echo $html;

exit;

}

7. 分頁(兩個函數配合使用)

function getpage($sql,$page_size=20)

{
global $page,$totalpage,$sums; //out param

$page = $_get["page"];

//$eachpage = $page_size;

$pagesql = strstr($sql," from ");

$pagesql = "select count(*) as ids ".$pagesql;

$result = mysql_query($pagesql);

if($rs = mysql_fetch_array($result)) $sums = $rs[0];

$totalpage = ceil($sums/$page_size);

if((!$page)||($page<1)) $page=1; $startpos = ($page-1)*$page_size; $sql .=" limit $startpos,$page_size "; return $sql; } function showbar($string="") { global $page,$totalpage; $out="共& lt;font ".$totalpage."color=@#red@#>".$totalpage."< /font>頁";

$linknum =4;
$start = ($page-round($linknum/2))>0 ? ($page-round($linknum/2)) : "1";

$end = ($page round($linknum/2))<$totalpage ? ($page round($linknum/2)) : $totalpage; $prestart=$start-1; $nextend=$end 1; if($page<>1)

$out .= "第一頁 ";

if($start>1)

$out.="..<< ";

for($t=$start;$t<=$end;$t ) { $out .= ($page==$t) ? "[".$t."] " : "$t ";
}

if($end<$totalpage) $out.=">>..";

if($page<>$totalpage)

$out .= " 最後頁";

return $out;

}

8.獲取新插入數據的 id

2010年4月26日 星期一

帥氣的輸入框樣式

平淡無奇的輸入框,看到膩了嗎?

嘗試一下
http://buildinternet.com/2009/01/changing-form-input-styles-on-focus-with-jquery/

DEMO頁面
http://buildinternet.com/live/jqueryform/jqueryform1.php?status=20

透過Jquery及CSS就可以讓你的輸入框,自動對齊。

如標題!!
想自動對齊,請服用。
http://www.jankoatwarpspeed.com/post/2008/07/09/Justify-elements-using-jQuery-and-CSS.aspx

jquery 自動完成 autoComplete插件

紀錄一下各參數的意思!!
http://ltl3884.javaeye.com/blog/512738

2010年4月25日 星期日

Zend Framework中,View的From組件

如PEAR一樣,ZF的View也有好用的From組件

$this->formText('date' , '',array('size'=>4))




以上就是,建立一個id為Date,

name也是Date


無預設內容,文字長度為4的輸入框。

2010年4月23日 星期五

檢查數值是否存在於陣列的Key或Value

在PHP中常用的in_array是用來檢查

$array = array("a", "b, "c");


in_array("a",$array);

這樣結果為真,那當你想知道是否在鍵中可以用

$array = array("a"=>0, "b"=>1, "c"=>0);

array_key_exists("a", $array)

結果為真

2010年4月20日 星期二

查詢中文編碼,的資料庫

http://www.unicode.org/cgi-bin/GetUnihanData.pl?codepoint=%E6%96%87


Decimal UTF-8 UTF-16 UTF-32

2010年4月13日 星期二

使用PHP來做人臉辨識

透過利用OPENCV來製作人臉辨識的效果



http://ithelp.ithome.com.tw/question/10036727

2010年4月6日 星期二

Notepad++

Notepad++
自動完成



quicktext

結合!!超強

2010年4月5日 星期一

在GAE中寫php

介紹
http://www.youtube.com/watch?v=bXZlF-HPSq8&feature=related

用Google App Engine跑CodeIgniter

http://fillano.blog.ithome.com.tw/post/257/25696

在GAE中下SQL語法jiql

http://www.jiql.org/xwiki/bin/view/Main/

2010年3月13日 星期六

ZendX的下載點

在使用ZendFramework時,有時會用到jquery

可以透過SVN下載ZendX

http://framework.zend.com/svn/framework/extras/trunk

2010年3月9日 星期二

Zend Framework Session

ZF的Session可以在全域使用
可用再換頁時的資料傳遞

$DF = new Zend_Session_Namespace('DF');

指定
$DF->contacts = array('A', 'B','C');

取用

$contacts = (array) $DF->contacts;

2010年3月5日 星期五

jquery自動登入!!抓按鍵事件

$(document).keydown(function(e){
//keyCode為Enter
if (e.keyCode == 13) {
$("#form1").submit();
}
});

2010年3月2日 星期二

Zend-framework設定快取

$this->getResponse()->setHeader('Expires', '', true);
$this->getResponse()->setHeader('Cache-Control', 'public', true);
$this->getResponse()->setHeader('Cache-Control', 'max-age=3800');
$this->getResponse()->setHeader('Pragma', '', true);
透過重寫ZendFramework的Header可以設定快取

也可以輸出XML的Header
$this->getResponse()->setHeader('Content-Type', 'text/html; charset=UTF-8');

2010年2月28日 星期日

Zend_Auth、Zend_Acl的使用實例(在Action中使用Acl)

數據庫表:

CREATE TABLE `user` (

`uid` SMALLINT( 5 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`username` VARCHAR( 20 ) CHARACTER SET gbk COLLATE gbk_chinese_ci NOT NULL ,
`password` CHAR( 32 ) NOT NULL ,
`role` ENUM( 'user', 'staff', 'admin' ) NOT NULL ,
`truename` VARCHAR( 20 ) CHARACTER SET gbk COLLATE gbk_chinese_ci NOT NULL ,
INDEX ( `role` , `truename` ) ,
UNIQUE (

`username`

)

) ENGINE = MYISAM CHARACTER SET gbk COLLATE gbk_chinese_ci COMMENT = '用戶表';

在數據庫中存儲了一個role字段(枚舉類型),以保存用戶角色信息!

add(new Zend_Acl_Resource('Default'));
$acl->add(new Zend_Acl_Resource('News'));
//上面對應我的兩個module,一個Default,一個News
$acl->addRole(new Zend_Acl_Role('guest'));
$acl->addRole(new Zend_Acl_Role('user'), 'guest');
$acl->addRole(new Zend_Acl_Role('staff'), 'user');
$acl->addRole(new Zend_Acl_Role('admin'));

$acl->allow('guest', array('Default', 'News'), 'view');
$acl->allow('user', array('Default', 'News'), array('reply', 'download'));
$acl->allow('staff', array('Default', 'News'), array('delete', 'update'));
$acl->allow('admin');

//驗證權限,如果沒有登錄則以遊客身份登錄
$auth = Zend_Auth::getInstance();
if(!$auth->hasIdentity())
{
$auth->getStorage()->write((object)array('username' => 'Guest',
'role' => 'guest',
'truename' => '遊客'));
}
$router = new Zend_Controller_Router_Rewrite();
//$router->addRoute('root',new Zend_Controller_Router_Route('/',array('module' =>'News', 'controller' => 'Index', 'Action' => 'index'))); 也是給出默認控制器的
$front = Zend_Controller_Front::getInstance()->setControllerDirectory(array(
'default' => './Default/Controllers',
'News' => './News/Controllers'
))
->setRouter($router)
->setParam('Zend_Acl', $acl)
->setParam('Zend_Auth', $auth)
->setBaseUrl('/zf/index.php')
->setParam('noViewRenderer', true)
->setParam('useDefaultControllerAlways',true)
->throwExceptions(true)->returnResponse(false)
->dispatch();
?>

在Action中使用Zend_Acl(Default模塊中的IndexController,訪問他的downloadAction):

name = '張心靈';
$view->title = '測試';
$view->setScriptPath('./Default/Views/Index');
$view->addScriptPath('./Default/Views');
$this->getResponse()->appendBody($view->render('Index.phtml'));
}
public function downloadAction()
{
$acl = $this->getInvokeArg('Zend_Acl');
if(!$acl->isAllowed($this->getInvokeArg('Zend_Auth')->getStorage()->read()->role, 'Default', 'download')) $this->getResponse()->appendBody('訪問不合法');
else $this->getResponse()->appendBody('合法訪問');
}
}

測試地址:http://localhost/zf/index.php/index/download

當然,據稱更好的辦法是在 preDispatch 方法中控制權限

測試代碼如下:

getInvokeArg('Zend_Acl')->isAllowed($this->getInvokeArg('Zend_Auth')->getStorage()->read()->role, ucfirst($this->getRequest()->getModuleName()), $this->getRequest()->getActionName()))
$this->_forward('index', 'user', 'Default');
}
public function indexAction()
{
$view = new Zend_View;
$view->name = '張心靈';
$view->title = '測試';
$view->setScriptPath('./Default/Views/Index');
$view->addScriptPath('./Default/Views');
$this->getResponse()->appendBody($view->render('Index.phtml'));
}
public function downloadAction()
{
$acl = $this->getInvokeArg('Zend_Acl');
if(!$acl->isAllowed($this->getInvokeArg('Zend_Auth')->getStorage()->read()->role, 'Default', 'download')) $this->getResponse()->appendBody('訪問不合法');
else $this->getResponse()->appendBody('合法訪問');
}
}

執行結果還是OK的!不過就是感覺在 preDispatch 中控制權限比較呆板啦!

運行的Perfect!(感謝CCTV、感謝Channal V................)

很簡單的是,您可以將 訪問不合法那句 改為 _froward 等等,讓用戶登錄就行了,看起來Zend Framework使用還是蠻方便的(除了Zend_XmlRpc,那麼大個Bug,居然這麼就了都沒修復)

2010年2月24日 星期三

圖片縮圖的好用物件

裡面封裝有:
1、上傳圖片功能
2、按指定大小(單位PX)生成縮略圖
3、按指定百分比(原圖百分比)生成縮略圖
4、自動水印功能,包括文字水印和圖片水印。
5、外圍封裝了調用接口,一條語句實現圖片從上傳>>生成縮略圖>>打上水印三部曲。
6、自動識別,當圖片少於多少時不生成縮略圖。
7、自動識別,當圖片小於多少時,不打水印。
8、外圍封裝接口,可以直接調用子功能(上傳、縮略圖、水印)

調用方法:
autoimg(表單中NAME名稱,圖片根目錄下的子目錄名,文件最大上傳大小, 縮略圖寬, 縮略圖高);
//完成,後續處理,將圖片資訊存放數據庫
?>


image.inc.php
base_name = $this->base_name ? $this->base_name : './'.time().'_'.random(6);
return $this->base_name;
}
function get_info($old_img){
if (is_file($old_img)){
$this->img_info = GetImageSize($old_img);
if ($this->img_info['2'] == 2){
$this->func['create'] = 'imagecreatefromjpeg';
$this->func['copy'] = 'imagejpeg';
$this->img_info['extension'] = 'jpg';
}elseif ($this->img_info['2'] == 1){
$this->func['create'] = 'imagecreatefromgif';
$this->func['copy'] = 'imagegif';
$this->img_info['extension'] = 'gif';
}elseif ($this->img_info['2'] == 3){
$this->func['create'] = 'imagecreatefrompng';
$this->func['copy'] = 'imagepng';
$this->img_info['extension'] = 'png';
}else{
$this->error('not image file');
}
}else{
$this->error('file no find');
}

}
function thumb_per($img_url, $img_dir='./together/0/', $in_percent=0.35,$obj_filename=''){
$in_percent = ($in_percent>1 || $in_percent<=0) ? 0.35 : $in_percent ; $this->get_info($img_url);
if ($in_percent != 0){
$this->new_width = ceil($this->img_info['0'] * $in_percent);
$this->new_height = ceil($this->img_info['1'] * $in_percent);
}else{
$this->new_width = ceil($this->img_info['0']);
$this->new_height = ceil($this->img_info['1']);
}
if ($obj_filename!=''){
$this->new_thumb_name = $obj_filename;
}
$this->create_sub($img_url,$img_dir);
return $this->file_dir.$this->base_name.'.'.$this->img_info['extension'];
}
function thumb_abs($img_url, $img_dir='./together/0/', $new_width=120, $new_height=120,$obj_filename=''){
$this->get_info($img_url);
$this->new_width = ceil(abs($new_width))>1 ? ceil(abs($new_width)) : $this->new_width ;
$this->new_height = ceil(abs($new_height))>1 ? ceil(abs($new_height)) : $this->new_height;
if (($this->new_width > $this->img_info['0']) && ($this->new_height > $this->img_info['1'])){
$this->new_width = $this->img_info['0'];
$this->new_height = $this->img_info['1'];
}else{
if ($this->new_width && ($this->img_info['0'] < $this->img_info['1'])) {
$this->new_width = ($this->new_height / $this->img_info['1']) * $this->img_info['0'];
} else {
$this->new_height = ($this->new_width / $this->img_info['0']) * $this->img_info['1'];
}
}
if ($obj_filename!=''){
$this->new_thumb_name = $obj_filename;
}
$this->create_sub($img_url,$img_dir);
return $this->file_dir.$this->base_name.'.'.$this->img_info['extension'];
}
//子創建
function create_sub($img_url,$img_dir){
$image_o = $this->func['create']($img_url);
if(function_exists("imagecopyresampled")){
$image_n = imagecreatetruecolor($this->new_width, $this->new_height);
imagecopyresampled($image_n, $image_o, 0, 0, 0, 0, $this->new_width, $this->new_height, $this->img_info['0'], $this->img_info['1']) ;
}else{
$image_n = imagecreate($this->new_width, $this->new_height);
imagecopyresized($image_n, $image_o, 0, 0, 0, 0, $this->new_width, $this->new_height, $this->img_info['0'], $this->img_info['1']) ;
}
$this->file_dir = $this->file_dir ? $this->file_dir : $img_dir;
$this->new_thumb_name = (!empty($this->new_thumb_name)) ? $this->new_thumb_name : $this->get_name().'_s.'.$this->img_info['extension'] ;
$this->func['copy']($image_n,$this->file_dir.$this->new_thumb_name);
imagedestroy($image_n);
return true;
}
function upload($attach_value,$attach_dir='',$attach_size='1024000'){
global $_FILES;
if(COUNT($_FILES)==0){
$this->error('no files');
}
$this->file_error = $_FILES[$attach_value]['error'];
if ($this->file_error != 0){
$this->error('upload error');
}
$this->file_name = $_FILES[$attach_value]['name'];
$this->file_type = $_FILES[$attach_value]['type'];
$this->file_size = $_FILES[$attach_value]['size'];
$this->file_tmpname = $_FILES[$attach_value]['tmp_name'];
$this->get_info($this->file_tmpname);

if($attach_size && $this->file_size > $attach_size) {
$this->error('max size:'.$this->file_size);
}
if(!is_dir(MK_IMGROOT.$attach_dir)) {
mkdir(MK_IMGROOT.$attach_dir, 0777);
}
$this->file_dir = MK_IMGROOT.$attach_dir;
$this->file_newname = $attach_dir.'/'.$this->get_name().'.'.$this->img_info['extension'];
$this->file_thumbname = $attach_dir.'/'.$this->get_name().'_s.'.$this->img_info['extension'];
$this->file_dirname = MK_IMGROOT.$this->file_newname;

if(function_exists('move_uploaded_file')) {
if(@move_uploaded_file($this->file_tmpname, $this->file_dirname)) {
$attach_saved = true;
}
} elseif(@copy($this->file_tmpname, $this->file_dirname)) {
$attach_saved = true;
}
$return_data = '';
if ($attach_saved){
$return_data = array('name'=>$this->file_newname , 'size'=>$this->file_size , 'type'=>$this->file_type, 'ext'=>$this->img_info[' extension'], 'imgdir'=>$this->file_dirname, 'thumb'=>$this->file_thumbname, 'width'=>$this->img_info['0'], 'height'=>$this- >img_info['1']);

}
return $return_data;
}
function watermark_img($img_url){
if (is_readable(MK_IMGROOT.'./watermark.png')){
$watermark_file = MK_IMGROOT.'./watermark.png';
$image_w = imagecreatefrompng($watermark_file);
}else{
$watermark_file = MK_IMGROOT.'./watermark.gif';
$image_w = imagecreatefromgif($watermark_file);
}
$this->get_info($watermark_file);
$watermark_width = $this->img_info['0'];
$watermark_height = $this->img_info['1'];
$this->get_info($img_url);
if ($this->img_info['2'] <= 3){ $image_o = $this->func['create']($img_url);
if (function_exists("imagecreatetruecolor")){
$image_n = imagecreatetruecolor($this->img_info['0'], $this->img_info['1']);
}else{
$image_n = imagecreate($this->img_info['0'], $this->img_info['1']);
}
imageCopy($image_n, $image_o, 0, 0, 0, 0, $this->img_info['0'], $this->img_info['1']);
unset($watermark_file);
$watermark_x = $this->img_info['0'] - $watermark_width;
$watermark_y = $this->img_info['1'] - $watermark_height;
imageCopy($image_n, $image_w, $watermark_x, $watermark_y, 0, 0, $watermark_width, $watermark_height);

$this->func['copy']($image_n,$img_url);
imagedestroy($image_n);
}else{
return false;
}
}
function watermark_text($img_url,$text_message='www.7ego.cn'){
$this->get_info($img_url);
if ($this->img_info['2'] <= 3){ $image_o = $this->func['create']($img_url);
if (function_exists("imagecreatetruecolor")){
$image_n = imagecreatetruecolor($this->img_info['0'], $this->img_info['1']);
}else{
$image_n = imagecreate($this->img_info['0'], $this->img_info['1']);
}
imageCopy($image_n, $image_o, 0, 0, 0, 0, $this->img_info['0'], $this->img_info['1']);
$text_font = MK_ROOT.'en.fon';
$text_color = imagecolorallocate($image_n, 0, 0, 0);
$text_bgcolor = imagecolorallocate($image_n, 150, 150, 150);
$bg_color = imagecolorallocate($image_n, 250, 250, 200);
$text_width = imagefontwidth($text_message)*(strlen($text_message)-1)*2;
$text_height = imagefontheight($text_message)*2;
imagefilledrectangle($image_n, 2, 0, $text_width, $text_height, $bg_color);
@imagettftext($image_n, 2, 0, 11, 11, $text_bgcolor, $text_font, $text_message);
imagettftext($image_n, 2, 0, 10, 10, $text_color, $text_font, $text_message);
$this->func['copy']($image_n,$img_url);
imagedestroy($image_n);
}
}
function autoimg($attach_value,$attach_dir='',$attach_size='1024000', $new_width=120, $new_height=120){
$imgreturn = $this->upload($attach_value,$attach_dir,$attach_size);
//if ($imgreturn['width']>800){
// $this->thumb_abs($imgreturn['imgdir'], $this->file_dir, 640, 480,$imgreturn['imgdir']);
//}
$this->thumb_abs($imgreturn['imgdir'], $this->file_dir, $new_width, $new_height);
if ($imgreturn['width']>160 OR $imgreturn['height']>160){
$this->watermark_img($imgreturn['imgdir']);
$this->watermark_text($imgreturn['imgdir'],'www.7ego.cn');
}
return $imgreturn;
}
function error($msg){
global $_MK;
showmessage($msg,$_MK['reff']);
function_exists('mexit') ? mexit() : exit();
}
}
?>

PHP生成靜態網頁

最近研究PHP的一些開發技術,發現PHP有很多ASP所沒有的優秀功能,可以完成一些以前無法完成的功能,例如動態生成HTML靜態頁面,以減少服務器CPU的負載,提高用戶訪問的速度。

我們知道,PHP讀取MYSQL動態顯示,在訪問量大的情況下,會有很多性能問題,如果租用別人的虛擬主機,則會因為CPU消耗過多而被限制CPU,導致網頁無法訪問。我這裡給出一個PHP動態生成HTML的方法,可以極大降低服務器CPU負荷。

首先設置.htaccess文件,將動態調用的參數轉換為靜態的HTML的URL地址,例如將在post目錄下的文件,轉發到根目錄的wp- post.php文件中,加入的語句類似:RewriteRule ^post /([a-z0-9\-]+\.html)$ wp- post.php?$1$2

然後修改wp-post.php文件,在文件的開頭加入以下PHP代碼:
ob_start();
$qstring = isset($_SERVER["QUERY_STRING"]) ? $_SERVER["QUERY_STRING"] : "";
define("HTML_FILE", $_SERVER['DOCUMENT_ROOT']."/post/".$qstring);
if (file_exists(HTML_FILE))
{
$lcft = filemtime(HTML_FILE);
if (($lcft + 3600) > time()) //判斷上次生成HTML文件是否超過1小時,若沒有才直接輸出文件內容
{
echo(file_get_contents(HTML_FILE));
exit(0);
}
}


之後是現有的PHP的代碼,然後在當前代碼的最後面加上如下的PHP代碼:
define("HTMLMETA","");
$buffer = ob_get_flush();
$fp = fopen(HTML_FILE, "w");
if ($fp)
{
fwrite($fp, $buffer.HTMLMETA);
fclose($fp);
}


好了,然後查看你的靜態HTML頁面,如果頁面尾部出現了註釋行,說明已經成功的創建了靜態HTML文件。

這個方法的一個應用就是我先前寫的那個“WordPress年度博客統計插件”,這個統計插件由於查詢十多次數據庫,很多人訪問的時候會有很大性能問題,使用我介紹的這種動態生成HTML技術後,一天就查詢一次,生成一次統計排行,完美解決了查詢數據庫的性能問題。

MySQL的隨機數、MySQ隨機選取數據、MySQ隨機查詢數據、MySQ隨機更新數據

本文實現了MySQL的隨機數、MySQ隨機選取數據、MySQ隨機查詢數據、MySQ隨機更新數據。

MySQ隨機查詢數據

以前在群裡討論過這個問題,比較的有意思。 mysql的語法真好玩。他們原來都想用PHP的實現隨機,但取出多條好像要進行兩次以上查詢。翻了手冊,找到了下面這個語句,可以完成任務了:
SELECT * FROM table_name ORDER BY rand() LIMIT 5;


MySQL的rand()函數在手冊裡是這麼說的:
RAND()
RAND(N)
返回在範圍0到1.0內的隨機浮點值。如果一個整數參數N被指定,它被用作種子值。


關於MySQL的rand()函數的效率問題,大家可以參考《MySQL Order By Rand()效率》:http://www.phpq.net/mysql/mysql-order-by-rand.html。

實際效果:
> select RAND();
-> 0.5925
mysql> select RAND(20);
-> 0.1811
mysql> select RAND(20);
-> 0.1811
mysql> select RAND();
-> 0.2079
mysql> select RAND();
-> 0.7888


MySQ隨機更新數據

如何寫一個語句能一下更新幾百條MYSQL數據?

需要測試的MYSQL數據庫裡面有一個上萬條數據的數據庫,如何寫一個PHP文件一下每次更新幾百條信息?我都是寫一個循環一次更新一條信息,這樣我知道用WHILE寫就可以了,要是一次更新好比100條數據改如何寫呢?

正確答案:
UPDATE cdb_posts SET views = rand();


其實在insert命令中,value()裡面用rand(),注意字段寬度是否夠,一直以為mysql隨機查詢幾條數據,就用下面的語句就可以了:
SELECT * FROM `table` ORDER BY RAND() LIMIT 5

2010年2月19日 星期五

Ubuntu中安裝LAMP

安裝Apache2

sudo apt-get install apache2

安裝MySQL
sudo apt-get install mysql-server libmysqlclient15-dev

安裝PHP
sudo apt-get install php5 php5-common libapache2-mod-php5 php5-gd php5-dev curl libcurl3 libcurl3-dev php5-curl

安裝phpmyadmin
sudo aptitude install phpmyadmin

安裝SSL
sudo apache2-ssl-certificate

sudo a2enmod ssl

echo "Listen 443" | sudo tee -a /etc/apache2/ports.conf

sudo ln -s /etc/apache2/sites-available/ssl /etc/apache2/sites-enabled/ssl


sudo cp /etc/apache2/sites-available/default /etc/apache2/sites-available/ssl

sudo gedit /etc/apache2/sites-available/ssl


設定443port的網站

NameVirtualHost *:443


ServerAdmin webmaster@localhost

SSLEngine On
SSLCertificateFile /etc/apache2/ssl/apache.pem

DocumentRoot /var/www/

Options FollowSymLinks
AllowOverride None



Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
# This directive allows us to have apache2's default start page
# in /apache2-default/, but still have / go to the right place
# Commented out for Ubuntu
#RedirectMatch ^/$ /apache2-default/


ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/

AllowOverride None
Options ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all


ErrorLog /var/log/apache2/error.log

# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn

CustomLog /var/log/apache2/access.log combined
ServerSignature On

Alias /doc/ "/usr/share/doc/"

Options Indexes MultiViews FollowSymLinks
AllowOverride None
Order deny,allow
Deny from all
Allow from 127.0.0.0/255.0.0.0 ::1/128




安裝apache的模組

sudo a2enmod rewrite


設定Apche轉送

sudo gedit /etc/apache2/sites-available/default


AllowOverride All

重啟Apache2

sudo apache2 -k restart


PS要安裝php-pear要先有phpize 所以要先安裝php5-dev

sudo apt-get install php5-dev

sudo apt-get install php-pear

sudo pecl install pdo

sudo pecl install pdo_mysql

如果有錯誤必須先安裝
ERROR: `/tmp/tmpRiQ5ax/PDO_MYSQL-1.0.2/configure' failed

先裝好mysql的lib,再試著安裝pdo_mysql
sudo apt-get install libmysqlclient15-dev


接下來修改php.ini檔

sudo gedit /etc/php5/apache2/php.ini

sudo vim /etc/php5/apache2/php.ini

2010年2月11日 星期四

用PHP來做Cluster的FILE

http://code.google.com/p/finefs/

2010年2月4日 星期四

ZendFrameWork 下載檔案

關閉layout

$this->blankPage();
header("Content-type: application/vnd.ms-excel");
header("Content-disposition: csv" . date("Y-m-d") . ".csv");
header("Content-disposition: filename=" . $filename . ".csv");
print $contactsHeader . "\r\n" . $csv_output;exit;

ZendFramework 代碼片段

config.ini 文件
[general]
db.adapter = PDO_MYSQL
db.config.host = localhost
db.config.username = root
db.config.password =
db.config.dbname = zftest

$config=new Zend_Config_Ini('./config/config.ini','general');
//zend_config_ini加載配置文件用
$db=Zend_Db::factory($config->db->adapter,
$config->db->config->toArray());
Zend_Db::factory("資料庫的類型","把config文件中的内容换成陣列")

防止資料庫攻擊方法:
1、$value=$db->quote('ADFA'DF');
quote自動為單引號行過濾加上雙引号
2、quoteInto()
$value=$db->quoteInto();
多筆查詢


$db->quoteInto('(a =? AND ', $a) .
$db->quoteInfo('b = >)', $b) . 
$db->quoteInfo(' OR ( c != ?)', $c)

3、直接查询
$sql=$db->quoteInto('select * from example where date>?','2006-01-01');
$result=$db->query($sql);
$rows=$result->fetchAll();
4、或者使用占位符号:placeholder 如:
$result=$db->query('select * from exaple where date>:placeholder',
array('placeholder'=>'2006-01-01')
$rows=$result->fetchAll();
5、prepare()方法绑定
$stmt=$db->prepare('select * from example where date>:placeholder');
$stmt->bindvalue('placeholder','2006-01-01');
$stmt->execute();
$rows=$stmt->fetchAll();
6、交易處理
$db->beginTransaction();
try{
$db->query(...);
$db->commit();
}catch(Exception $e){
$db->rollback();
echo $d->getMessage();
}
7、插入數據行
$row=array('title'=>'king','name'=>'baobao',color=>'blue');
$table='uer_table';
$rows_affected=$db->insert($table,$row);
$last_insert_id=$db->lastInsertId();
8、更新數據行
$set=array('name'=>'lailai')
$table='user_table'//更新的数据表
//where語法
$where=$db->quotuinto('name=?','baobao');
//更新資料表,回傳行數
$rows_affected=$db->update($table,$set,$where);
9、刪除資料航
$table='user_table'
where 語句
$where =$db->quoteinto('first_name=?','patsy');
//删除資料並得到影響的行數
$rows_affected=$db->delete($table,$where);
10、取回查詢結果
fetchAll();fetchAssoc();fetchCol();fetchOne();fetchPairs();fetchRow();
//fetchAll取回所有結果集合,並作為連續的雜湊返回
$result=$db->fetchAll(
'select * from round_table where noble_title=:title',
array('title'=>'sir')
);
fetchAssoc()//作为关联数组返回
fetchcol()//取回结果行的第一个字段名
fetchOne()//取回第一个字段值
fetchPairs()//取回一个相关数组,第一个字段为码,第二个字段为值
fetchRow()//取得结果集中的第一行
$config = new Zend_Config_Ini(APP_DIR . '/config/config.ini', 'general');

$this->getHelper('layout')->disableLayout();
$this->getHelper('viewRenderer')->setNoRender();

headScript()->captureStart(); ?>
headScript()->captureEnd(); ?>


$this->view->getHelper('userMemUrl')->userMemUrl('info')

// 分頁頁碼
$this->per = 10;
$len = $this->db->fetchOne("select count(*) from `feedback` where `active`=1 and `memorial_id`=$this->mid");
$pager = new Pager($len, $this->per);
$pager->setAlign('right');
$this->view->pager = $pager->getNavigation();
$start = ($pager->getCurrentPage()-1)*$this->per;
$obj = new Feedback();
$this->view->list = $obj->fetchAll("`active`=1", 'poscode desc', $this->per, $start);


/* 读取上一张,下一张 */
$this->view->prevRow = $obj->fetchRow("`active`=1 and `id`='$row->id' and `poscode`>'$row->poscode'", 'poscode asc', 1, 0);
$this->view->nextRow = $obj->fetchRow("`active`=1 and `id`='$row->id' and `poscode`<'$row->poscode'", 'poscode desc', 1, 0);

上一条:
prevRow): ?>
prevRow->title; ?>


这是第一条


下一条:
nextRow): ?>
nextRow->title; ?>

这是最后一条



$this->view->headLink()->appendStylesheet($this->baseDir . '/css/gardens.css');

$this->view->headScript()->appendFile($this->baseDir . '/js/jquery.js');
$this->view->headScript()->appendFile($this->baseDir . '/js/common.js');


if(!$this->_request->isPost()) {
$this->view->useIframe = true;
} else {
$data = $this->_request->getPost();
if(!$data['content']) {
echo Func::feedtop('alert("生平簡介不能為空,請重新輸入!");');
exit();
}
$row->content = $data['content'];
$rs = $row->save();
if($rs) {
echo Func::feedtop('alert("生平簡介更新成功!");');
exit();
} else {
echo Func::feedtop('alert("生平簡介更新失敗,請稍後重試!");');
exit();
}
}

// ajax 響應
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('select-wish', 'html')
->addActionContext('send-wish', 'html')
->initContext();


$this->_flashMessenger = $this->_helper->getHelper('FlashMessenger');

$this->_flashMessenger->addMessage('修改成功!');
$this->view->messages = $this->_flashMessenger->getMessages();


echo Func::feedtop('winFunc.go("' .$this->view->getHelper('baseUrl')->baseUrl() . '/user/pay/cart/id/' .$rs. '");');



// 刷新 SESSION
$auth = $this->getInvokeArg('auth');
$auth->getStorage()->write($row);


//驗證碼
$this->vcode = new Zend_Session_Namespace('vcode');
if ($data['vcode'] != $this->vcode->user_login) {
echo Func::feedtop('alert("驗證碼輸入有誤,請確認!");$("#vcode")[0].focus()');
exit();
}

Zend Framework添加CSS 和 JS的方法

$this->view->headLink()->appendStylesheet('/c/css/homepage.css');
$this->view->headLink()->appendStylesheet($baseUrl.'/css/admin/tinybrowser.css');
$this->view->jQuery()->addJavascriptFile($baseUrl . '/js/admin/tiny_functions.js');

Zend Framework轉向

Zend Framework

Zend, PHP
一. render
不指定render
结果: {当前Module}/{当前Controller}/{当前Action}.phtml

$this->render('bar') ;
结果: {当前Module}/{当前Controller}/bar.phtml

二. forward
$this->_forward('bar') ;
结果: {当前Module}/{当前Controller}/bar

$this->_forward('bar', 'foo') ;
结果: {当前Module}/foo/bar

$this->_forward('bar', 'foo', 'hoge') ;
结果: hoge/foo/bar

$params = array(
'a' => '1',
'b' => '2'
) ;
$this->_forward('bar', 'foo', 'hoge', $params) ;
结果: /hoge/foo/bar/a/1/b/2

三. redirect
$this->_redirect('/hoge') ;
结果: /hoge

$this->_redirect('/hoge/foo') ;
结果: /hoge/foo

$this->_redirect('/hoge/foo/bar') ;
结果: /hoge/foo/bar

$this->_redirect('http://localhost/hoge/foo/bar') ;
结果: http://localhost/hoge/foo/bar

$this->_redirect('http://localhost/hoge/foo/bar?a=1&b=2') ;
结果: http://localhost/hoge/foo/bar?a=1&b=2

四. 特殊情况
不使用 layout
结果: $this->_helper->layout()->disableLayout() ;

不使用 view
结果: $this->_helper->viewRenderer->setNoRender() ;

2010年1月1日 星期五

MVC與肯X基

MVC與肯X基

晚上睡不著覺,妹妹在肯X基上班,跟他聊上班的事情,聊著聊著感覺很熟悉
MVC架構為什麼跟肯X基的的工作流程這麼像,所以就記錄下來,希望對想了解
架構的人能有所幫助。

註:mvc是Xeroe PARC在20世紀80年代為程式語言Smalltalk-80所發明的一種開發模式


演出人員:

櫃檯V小姐(通常都要有點好看,所以view很重要)
總配C阿姨(通常就是看客人多少負責發落漢堡手、麵包手做事的人)
漢堡手M1、麵包手M2、飲料手M3(就是壓麵包然後做漢堡出來跟把炸雞的人)
最後當然還有客人(就是所謂的Client、EndUser)


動作是這樣的
1.等了好久客人終於進門了
2.櫃檯V小姐展示一下產品並問客人說請問你要點什麼
3.客人:我要一份X號餐(一份漢堡、一杯可樂、一份薯條)
4.櫃檯V小姐把他key在收銀機上
5.總配C阿姨從後面的螢幕上看到了客人訂餐的資料
6.依照客人的需要總配C阿姨發落漢堡手M1、麵堡手M2及飲料手M3製作各自的東西
7.漢堡手去找漢堡皮、肉片、萵苣絲,薯條手開始鏟薯條,飲料手開始做飲料
8.總配檢查了一下做好的東西,看看是內用還是點餐車道,把它呈上透明的保溫箱裡或外帶的車道窗口
9.櫃檯小姐把產品拿給客人


如果換成網頁程式的MVC架構是這樣解釋的
1.也是在等使用者上這個網站
2.使用者GET網頁,展示網頁畫面至使用者的瀏覽器(VIEW)
3.使用者點擊某一頁,告訴Server我要這一頁
4.無對應的動作
5.Ctrl接受到使用者的要求
6.依照使用者點擊的頁面的功能,開始跟Model要資料
7.Model會依需求跟資料庫來自同一個表或不同的表查詢出資料,並做成Ctrl所能接受的資料
8.Ctrl依照剛剛使用者的要求,看回傳給View用頁面呈現,還是Ajax來呈現
9.View將所需求的資料呈現出來