2011年8月13日 星期六

php中顯示當前檔案與當前路徑的方法

顯示當前檔案可使用一個當前檔案的全域變數:__FILE__。
所以要顯示檔案名稱就搭配basename()函數即可;而顯示當前路徑就搭配dirname()函數即可,範例如下:
<?
echo __FILE__;
echo basename(__FILE__);
echo dirname(__FILE__);
?>

2011年7月23日 星期六

PHP處理POST File中文檔名的問題....

*如果沒問題,表示你的網頁用的是Big5編碼,剛好跟Windows 中文版作業系統的一樣*
若是Server是用Windows中文版,那麼檔名是使用Big5編碼,網頁若是用了UTF-8編碼,那麼copy()這個函式裡的中文檔名(UTF-8編碼的)就會導致出錯。因此要做轉碼,範例程式如下:
<head>
<meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=utf-8">
</head>
<?php
copy($userfile,iconv("UTF-8","big5",$userfile_name));
?>
<form enctype="multipart/form-data" action="" method="post"
 name="uploadf" onsubmit="return validate()">
  Send this file: <input name="userfile" type="file">
  <input type="submit" value="Send File">
</form>

2011年7月9日 星期六

PHP的header可以設定等待幾秒後再轉向哦~~

其實應該說HTML的Header可以設定等待幾秒後再轉向,所以PHP的header當然也可以囉~~
用一個範例就可以代替千言萬語:
header("refresh:2;url=index.php");
//refresh:[秒數]

另外若是轉頁前有顯示訊息到瀏覽器上,那header一定會有警告,所以可以在最前面加上:
ob_start()來清掉緩衝區資料以避免警告~~

2011年7月2日 星期六

PHP產生特定日期的超棒方法

今天發現一個超好用的方法來產生特定日期,先來看一下例子吧:
date("Y-m-d",strtotime("+7 day"));
上面的程式會產生今天七天後的日期!
至於strtotime可以傳的參數有多少呢?以下是從php manual裡面擷取的一些範例:
# on 2/8/2010 
date('m/d/y', strtotime('first day'));  # 02/01/10 
date('m/d/y', strtotime('last day'));  # 02/28/10 
date('m/d/y', strtotime('last day next month')); # 03/31/10 
date('m/d/y', strtotime('last day last month')); # 01/31/10 
date('m/d/y', strtotime('2009-12 last day')); # 12/31/09
- this doesn't work if you reverse the order of the year and month 
date('m/d/y', strtotime('2009-03 last day')); # 03/31/09 
date('m/d/y', strtotime('2009-03')); # 03/01/09 
date('m/d/y', strtotime('last day of march 2009')); # 03/31/09
date('m/d/y', strtotime('last day of march')); # 03/31/10
還有這些用法也測過OK
date("Y-m-d H:i:s",strtotime("+ 1 month - 2 day"));
date("Y-m-d H:i:s",strtotime("+ 1 year 3 month 2 day 4 hour"));
我想還有很多吧,不過這些看來就很夠用了~~

2011年6月30日 星期四

Android Activity有新的Life Cycle??

這是我今天在網路上看到的:
 
(This picture is copy from http://www.anddev.org/lifecycle_of_an_activity-t81.html ,
I will remove it if auther disagree.)

發現這一張圖中在onPause()之前增加了onFreeze(),以前在API  Level 8時沒印象有這一個call back阿!難不成是新加的嗎?一時找不到答案所以先不深究了,google了一下,發現onFreeze被call的時機發生在於一個Activity (A)去呼叫另一個Activity (B)時,A在onPause()之前會先進行onFreeze();但是當B返回A時,不會onFreeze()就直接onPause()了。目前對它的認識就到這邊,以後要是有時間深入trace後有新的心得再跟大家分享吧!若有不對之處也請各位先進不吝指正!

2011/07/02更正....
原來onFreeze()是一個很舊的方法,後來的版本中被更名為onSaveInstanceState()以更符合狀態的意義,可參考官方文件:http://developer.android.com/sdk/OLD_RELEASENOTES.html
至於onSaveInstanceState被call的時機發生在於一個Activity (A)去呼叫另一個Activity (B)時,A在onPause()之前會先進行onSaveInstanceState();但是當B返回A時,不會onSaveInstanceState()就直接onPause()了,這個原先查詢到的資訊(onFreeze()改為onSaveInstanceState())經過程式trace後證實是沒有錯的~


smarty在Linux下面無法顯示的問題解決

最近在ubuntu下安裝了smarty,卻一直無法像在Windows下正確顯示。
整個頁面就是空白一片......
這個小問題後來到php.ini中設定display_errors = On再重新起動Apache2就搞定了!
有了錯誤提示後,問題就好解決多了,原來還是權限問題在作祟阿!!
1.我改了libs目錄下的所有權限為755,在libs目錄下執行:
sudo chmod -R 755 *
PS.其實只有目錄部份需要755,檔案部分應該只要644就可以了,但是.....懶ㄇㄟ
2.又有了新的錯誤,所以我改了templates_c的權限為777,在網站目錄下執行:
sudo chmod 777 templates_c
然後......大功告成了~~~

2011年6月26日 星期日

如何在JPGraph的圖表中顯示中文

這邊介紹的方法不用去修改到JPGraph的source!
1.首先,PHP必須存成utf-8 no bom的格式,為什麼?因為JPGraph會使用你指定的中文字型檔來畫出你想秀出的中文字,但是它在對應字型時使用的是utf-8的編碼,所以你要是存成Big5,那就永遠畫不出正確的中文字囉!
2.將中文字型檔複製到跟你的程式相同的資料夾中。這樣做的好處是將來搬移主機時,可以無痛轉移(虛擬主機環境中特別建議這樣,因為字型檔的預設路徑可能不同或無存取權限)。
3.在require跟JPGraph有關的所有php檔前,先定義TTF_DIR及CHINESE_TTF_FONT這兩個常數,記住一定要定義在跟JPGraph有關的所有php檔前面,因為PHP是不允許redefine的,所以我們要先搶先贏。我們用一個3D圓餅圖作為範例:
<?php
define('TTF_DIR', './');
//字型檔的路徑,因為我們將字型檔放在同一資料夾,所以此處給空字串。
//經測試在某些linux主機上使用空字串不能正確讀到同一資料夾的字型檔(2011/06/28修正)
//字型檔的路徑,因為我們將字型檔放在同一資料夾,所以此處給"./",表示當前路徑。
//若是你想使用作業系統的字型檔路徑中的字型檔,這一行可以省略。
define('CHINESE_TTF_FONT','mingliu.ttc');
//使用細明體(mingliu.ttc),注意,若是在linux主機大小寫必須完全相符。
require_once ('../jpgraph/jpgraph.php');
require_once ('../jpgraph/jpgraph_pie.php');
require_once ('../jpgraph/jpgraph_pie3d.php');
// Some data
$data = array(40,60,21,33);
// Create the Pie Graph.
$graph = new PieGraph(350,250);
$theme_class= new VividTheme;
$graph->SetTheme($theme_class);
$graph->title->SetFont(FF_CHINESE, FS_NORMAL);
$graph->xaxis->SetFont(FF_CHINESE, FS_NORMAL);
$graph->yaxis->SetFont(FF_CHINESE, FS_NORMAL);
$graph->legend->SetFont(FF_CHINESE, FS_NORMAL);
$graph->subtitle->SetFont(FF_CHINESE, FS_NORMAL);
$graph->subsubtitle->SetFont(FF_CHINESE, FS_NORMAL);
$graph->tabtitle->SetFont(FF_CHINESE, FS_NORMAL);

//設定title使用中文顯示,注意,要是要在其他部份顯示中文,要去使用相對應的SetFont!
//2011/06/30:稍微看了一下他的文件,以上設定應該可以讓所有顯示字的地方都顯示中文
//若有不能的麻煩告知,我會再更正!
// Set A title for the plot
$graph->title->Set("一個簡易的3D圓餅圖");
// Create
$p1 = new PiePlot3D($data);
$graph->Add($p1);
$p1->ShowBorder();
$p1->SetColor('black');
$p1->ExplodeSlice(1);
$graph->Stroke();
?>
最後補充一下,標題雖然說是如何顯示中文,但是當然不侷限於中文,你也可以用別的語言的字型檔來試試囉!我相信一樣會成功的。

2011年6月18日 星期六

php連接mysql跟資料編碼有關的問題解決

php連接mysql時常發生資料庫內的編碼跟網頁顯示的不一樣,有時從phpmyadmin看不正確但是網頁顯示卻又正常,其實最好的習慣是在connect後就加上一個明確的編碼函式:
$link = mysql_pconnect("localhost","user","1234");
mysql_select_db("database");
mysql_set_charset("utf8",$link);
另外:
mysql_set_charset("utf8",$link);
也可以使用下面的方式:
mysql_query("set names utf8");
最後值得注意的是,utf8千萬不要寫成utf-8哦!

2011年6月17日 星期五

如何讓PHP支援不同的資料庫之間轉換

假設我們今天利用PHP+MSSQL架設了一個網站,結果有一天我們想把網站移到虛擬主機上面,但是虛擬主機只支援MySQL,資料庫的轉換不免要花不少功夫。轉換完成後再看看我們眾多的PHP程式碼,逐一取代還真是大工程阿,更危險的是萬一漏了幾支沒改到,又剛好在不常用的功能頁面中,我們也沒發現。等到使用者遇到問題時,若是反應了我們還能及時改正;若是他們選擇放棄使用了,那我們就不知道要流失多少的使用者了!
PHP可以支援很多常用的資料庫,妥善利用PHP物件導向的能力,可以讓我們的網站能很容易的在各種不同的資料庫間轉換,廢話不多說,快來看看怎麼做吧!
首先我們建立一個通用的資料庫抽象類別mydb:
abstract class mydb
{
 var $rs;
 var $link;

 function mydb(){}
 
  abstract function connect($host,$db,$id,$password);
  abstract function close($rs); 
  abstract function query_exec($sql);
  abstract function query_exec_new($sql);
  abstract function num_rows_exec($rs);
  abstract function fetch_row_exec($rs);
 
  function query() //傳入參數:$query,[new]
  {
   $numargs = func_num_args();
    if ($numargs == 2 && func_get_arg(1)=="new")
    {
     return $this->query_exec_new(func_get_arg(0));
    }
    if ($numargs == 1)
    {
     return $this->query_exec(func_get_arg(0));
    } 
  }
 
  function num_rows() //傳入參數:[$rs]
  {
   $numargs = func_num_args();
    if ($numargs == 0)
    {
     return $this->num_rows_exec($this->rs);
    }
    if ($numargs == 1)
    {
     return $this->num_rows_exec(func_get_arg(0));
    }
  }
  
  function fetch_row()
  {
   $numargs = func_num_args();
    if ($numargs == 0)
    {
     $rows = $this->fetch_row_exec($this->rs);
    }
    if ($numargs == 1)
    {
     $rows = $this->fetch_row_exec(func_get_arg(0));
    }
    for($i=0;$i < sizeof($rows);$i++)
     $rows[$i] = str_replace("\\\\","\\",$rows[$i]);
    return $rows;
  }
}
這樣做有幾個好處:
1.所有實際操作的資料庫類別繼承於mydb,這樣共通的程式碼寫在mydb類別的方法中,專屬的程式碼就寫在各個資料庫類別的方法中。如此一來萬一共通的程式部分有修正時就不用到各類別中逐一修正,可以避免遺漏了某個資料庫類別。例如下面這個方法中就包含了共同的程式碼部分:
function fetch_row()
  {
   $numargs = func_num_args();
    if ($numargs == 0)
    {
     $rows = $this->fetch_row_exec($this->rs);
    }
    if ($numargs == 1)
    {
     $rows = $this->fetch_row_exec(func_get_arg(0));
    }
    for($i=0;$i < sizeof($rows);$i++)
     $rows[$i] = str_replace("\\\\","\\",$rows[$i]);
    return $rows;
  }
程式中我們都呼叫這個fetch_row()方法,然後再依照參數,這個方法會再呼叫子類別中的fetch_row_exec()方法,fetch_row_exec()方法中放的就是各資料庫類別自己專屬的程式碼。
PS.這段程式是有點小問題的,大家自己想一想該如何修正會比較完整哦~
2.利用抽象方法來避免繼承的類別中忘了實做必要的方法:
abstract function connect($host,$db,$id,$password);
abstract function close($rs); 
abstract function query_exec($sql);
abstract function query_exec_new($sql);
abstract function num_rows_exec($rs);
abstract function fetch_row_exec($rs);
未來加入新的資料庫類別時,這些方法都是必須實做的,若是忘了實做其中一個方法,會得到如下的錯誤訊息:
Fatal error: Class myaccessdb contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (mydb::[未實做的方法名稱])
接下來看看Mysql的實做類別,我們把它取名叫做mymysqldb:
class mymysqldb extends mydb
{
 function mymysqldb()
  {}
 
 function connect($host,$db,$id,$password)
  {
   $this->link=mysql_pconnect($host,$id,$password);
  mysql_select_db($db,$this->link);
  return $this->link;
  }
 
  function close($rs)
  {}
 
  function query_exec($sql)
  {
   $this->rs = mysql_query($sql,$this->link);
   return $this->rs;
  }
 
  function query_exec_new($sql)
  {
   return mysql_query($sql,$this->link);;
  }
 
  function num_rows_exec($rs)
  {
   return mysql_num_rows($rs);
  }
 
  function fetch_row_exec($rs)
  {
   return mysql_fetch_row($rs);
  }
}
再來看看MSSQL的類別實做,我們把它取名叫做mymssqldb:
class mymssqldb extends mydb
{
 function mymssqldb()
  {}
 
 function connect($host,$db,$id,$password)
  {
   $this->link=mssql_pconnect($host,$id,$password);
  mssql_select_db($db,$this->link);
  return $this->link;
  }
 
  function close($rs)
  {}
 
  function query_exec($sql)
  {
   $this->rs = mssql_query($sql,$this->link);
   return $this->rs;
  }
 
  function query_exec_new($sql)
  {
   return mssql_query($sql,$this->link);;
  }
 
  function num_rows_exec($rs)
  {
   return mssql_num_rows($rs);
  }
 
  function fetch_row_exec($rs)
  {
   return mssql_fetch_row($rs);
  }
}
怎麼程式碼這麼像?沒錯,這兩個資料庫的PHP函式就是這麼像!那這樣還需要物件導向嗎?批次字串取代就好了ㄚ!再來看看Access資料庫類別的實作方法吧,你一定會覺得還是用物件導向來做比較好了,我們把它取名叫做myaccessdb:
class myaccessdb extends mydb
{
 function myaccessdb()
  {}
 
 function connect($host,$db,$id,$password)
  {
   $this->link = new COM("ADODB.Connection") or die ("ADO連接失敗!");
  $dsn="DRIVER={Microsoft Access Driver (*.mdb)};DBQ=".realpath($db).";Uid=$id;Pwd=$password"; 
  $this->link->open($dsn);
  $this->rs = new COM("ADODB.RecordSet");
  return $this->link;
  }
 
  function close($rs)
  {
   $rs->close();
  }
 
  function query_exec($sql)
  {
   if($this->rs->state != 0)
    $this->close($this->rs);
   $this->rs->Open($sql,$this->link,1,3);
   return $this->rs;
  }
 
  function query_exec_new($sql)
  {
  $rs = new COM("ADODB.RecordSet");
   $rs->Open($sql,$this->link,1,3);
   return $rs;
  }
 
 
  function num_rows_exec($rs)
  {
   return $rs->recordcount;
  }
 
  function fetch_row_exec($rs)
  {
   if (!$rs->EOF)
   {
    $rows = array();
    for($i=0 ; $i < $rs->Fields->count ; $i++)
     array_push($rows,$rs->fields[$i]->value);
    $rs->MoveNext();
    return $rows;
   }
   else
    return NULL;
  }
}
最後我們來看看使用方式囉!
放在config.ini.php(每一支PHP程式都include的設定檔)中的宣告是有些不同,分別列出如下:
Mysql:
$mydb = new mymysqldb();
$conn = $mydb->connect("127.0.0.1","testdb","testid","testpasswd");
MSSQL:
$mydb = new mymssqldb();
$conn = $mydb->connect("127.0.0.1","testdb","testid","testpasswd");
Access:
$mydb = new myaccessdb();
$conn = $mydb->connect("","testdb","","testpasswd");
程式中的使用就完全相同了,我們來看看:
$mydb->query("select field1,field2,field3,field4 from table where field0 = '0'");
if($mydb->num_rows() > 0)
{
     list($field1,$field2,$field3,$field4)=$mydb->fetch_row();
}
所以換資料庫時不用動程式,只要改設定檔囉!

這邊我用的是Query的方式,所以必須注意的是使用的SQL必須是通用的標準SQL,例如Mysql中的limit就不能使用了!當然還有更好的改進方式,等我有空完成了會再分享給大家!

2011年6月15日 星期三

ubuntu上面安裝軟體整理

1.安裝Apache2:
sudo apt-get install apache2
2.安裝PHP5:
sudo apt-get install php5
3.安裝PHP對Apache支援的模組:
sudo apt-get install libapache2-mod-php5
4.安裝PHP5命令執行程式(/usr/bin/php):
sudo apt-get install php5-cli
PS.順帶一提,若要PHP檔可以直接執行,在檔案最前面加上:#!/usr/bin/php,並修改屬性為可執行即可!
5.安裝PHP對Mysql支援的模組:
sudo apt-get install php5-mysql
6.安裝PHP對PostgreSQL 支援的模組:
sudo apt-get install php5-pgsql

7.安裝Mysql:
sudo apt-get install mysql-server
8.安裝FTP server:
sudo apt-get install proftpd
再覆蓋proftpd.conf
在/etc/shells的最下面加上:/bin/false
使用adduser來新增使用者
再用usermod -s /bin/false [user account] 讓使用者沒有shell可以用
9.安裝Samba server:
sudo apt-get install samba smbfs
再覆蓋smb.conf
使用adduser來新增使用者
再用sudo smbpasswd -a [user account] 讓使用者可以存取分享的資料夾
如何分享,直接在資料夾上按滑鼠右鍵選分享選項即可

2011年6月14日 星期二

Ubuntu的gnome指令集

最近用一台準系統安裝ubuntu 10.04架了一台加密伺服器,加密的工具就是使用openssl,網路介面使用了準系統的無線網路,問題來了,沒有登入ubuntu無線網路居然不會連線!這會不會太扯了?我只好把自動登入打開,但是這樣的產品拿到客戶端,客戶把螢幕一接上,不就進系統了嗎?看來只好在登入後把螢幕鎖住囉!在網路上找到了gnome-screensaver-command --lock這個指令。把它放在.bashrc中就大功告成囉!當然囉,看這個指令就不難猜到一定還有一堆類似的gnome指令囉!真是一個非常棒的大發現!

2011年6月13日 星期一

Ubuntu 10 11上安裝sun jdk的方式

sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner"
sudo apt-get update
sudo apt-get install sun-java6-jdk sun-java6-plugin
sudo update-java-alternatives -s java-6-sun

2011年6月10日 星期五

Android的Script工具...(PHP,Python,Ruby)

Android的手機功能強大,你是不是不甘於只做一個使用者?
開發能夠放上Market的軟體或許不是那麼容易,
但是寫一點自己用的小工具是可以很簡單的!
要是寫過PHP,或是Python,或是Ruby,那就一定要玩玩這個:
http://code.google.com/p/android-scripting/

2011年6月9日 星期四

openssl:加解密的好工具

相信在這個講求資安的時代,大家都對資料的加解密有很大的需求,推薦各位這一個好東西,http://www.openssl.org/ ,跨平台、Open source、簡單易用、功能強大。反正非常好用啦~