廣告廣告
  加入我的最愛 設為首頁 風格修改
首頁 首尾
 手機版   訂閱   地圖  簡體 
您是第 10221 個閱讀者
 
發表文章 發表投票 回覆文章
  可列印版   加為IE收藏   收藏主題   上一主題 | 下一主題   
abac
個人文章 個人相簿 個人日記 個人地圖
小人物
級別: 小人物 該用戶目前不上站
推文 x0 鮮花 x10
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片
推文 x0
[PHP][教學] PHP新手上路
一、PHP簡介

PHP是一種易於學習和使用的伺服器端腳本語言。只需要很少的編程知識你就能使用PHP建立一個真正交互的WEB站點。本教程並不想讓你完全瞭解這種語言,只是能使你儘快加入開發動態web站點的行列。我假定你有一些HTML(或者HTML編輯器)的基本知識和一些編程思想。

1.簡介

PHP是能讓你生成動態網頁的工具之一。PHP網頁檔被當作一般HTML網頁檔來處理並且在編輯時你可以用編輯HTML的常規方法編寫PHP。

PHP代表:超文本預處理器(PHP: Hypertext Preprocessor)。PHP是完全免費的,不用花錢,你可以從PHP官方站點(http://www....net)自由下載。PHP遵守GNU公共許可(GPL),在這一許可下誕生了許多流行的軟體諸如Linux和Emacs。你可以不受限制的獲得源碼,甚至可以從中加進你自己需要的特色。PHP在大多數Unix平臺,GUN/Linux和微軟Windows平臺上均可以運行。怎樣在Windows環境的PC機器或Unix機器上安裝PHP的資料可以在PHP官方站點上找到。安裝過程很簡單。


如果你的機器解決了2000問題,那麼PHP也一樣沒有千年蟲問題!

1.1 歷史

三年前,Rasmus Lerdorf為了創建他的線上簡歷而創造了"個人主頁工具"(Personal Home Page Tools)。這是一種非常簡單的語言。其後越來越多的人們注意到了這種語言並對其擴展提出了各種建議。在許多人的無私奉獻下以及這種語言本身的源代碼自由性質,它演變成為一種特點豐富的語言,而且現在還在成長中。

PHP雖然很容易學習,但是速度上比mod_perl(植入web伺服器的perl模組)慢。現在有了可以與mod_perl速度想媲美的被稱作Zend的新引擎,而PHP4就可以充分利用這個引擎。PHP4還處在BETA測試階段。Andy Gutmans和Zeev Suraki是Zend的主要作者。可以去Zend站點(http://www.z...com)瞭解更多。

PHP的應用在個人性質的web工程中增長顯著。根據Netcraft在1999年10月的報告,有931122個域和321128個IP位址利用PHP技術。

1.2 PHP的先進之處

應用PHP有許多好處。當然已知的不利之處在於PHP由於是開放源碼項目,沒有什麼商業支持,並且由此而帶來的執行速度緩慢(直到PHP4之前)。但是PHP的郵件列表很是有用而且除非你正在運行像Yahoo!或者Amazon.com這樣的極受歡迎的站點,你不會感覺出PHP的速度與其他的有什麼不同。最起碼我就沒有感覺出來!好了,讓我們來看看PHP有那些優點:

- 學習過程


我個人更喜歡PHP的非常簡單的學習過程。與Java和Perl不同,你不必把頭埋進100多頁的文檔中努力學習才可以寫出一個像樣的程式。只要瞭解一些基本的語法和語言特色,你就可以開始你的PHP編碼之旅了。之後你在編碼過程中如果遇到了什麼麻煩,還可以再去翻閱相關文檔。

PHP的語法與C,Perl,ASP或者JSP。對於那些對上述之一的語言較熟悉的人來說,PHP太簡單了。相反的,如果你對PHP瞭解較多,那麼你對於其他幾種語言的學習都很簡單了。

你只需要30分鐘就可以將PHP的核心語言特點全部掌握,你可能已經非常瞭解HTML,甚至你已經知道怎樣用編輯設計軟體或者手工來製作好看的WEB站點。由於PHP代碼能夠無障礙的添加進你的站點,在你設計和維護站點的同時,你可以很輕鬆的加入PHP使得你的站點更加具有動態特性。

- 資料庫連接

PHP可以編譯成具有與許多資料庫相連接的函數。PHP與MySQL是現在絕佳的組合。你還可以自己編寫週邊的函數取間接存取資料庫。通過這樣的途徑當你更換使用的資料庫時,可以輕鬆的更改編碼以適應這樣的變化。PHPLIB就是最常用的可以提供一般事務需要的一系列基庫。

- 可擴展性

就像前面說的那樣,PHP已經進入了一個高速發展的時期。對於一個非程式師來說為PHP擴展附加功能可能會比較難,但是對於一個PHP程式師來說並不困難。

- 面向物件編程

PHP提供了類和物件。基於web的編程工作非常需要面向物件編程能力。PHP支持構造器、提取類等。

- 可伸縮性

傳統上網頁的交互作用是通過CGI來實現的。CGI程式的伸縮性不很理想,因為它為每一個正在運行的CGI程式開一個獨立進程。解決方法就是將經常用來編寫CGI程式的語言的解釋器編譯進你的web伺服器(比如mod_perl,JSP)。PHP就可以以這種方式安裝,雖然很少有人願意這樣以CGI方式安裝它。內嵌的PHP可以具有更高的可伸縮性。

- 更多特點

PHP的開發者們為了更適合web編程,開發了許多週邊的流行基庫,這些庫包含了更易用的層。你可以利用PHP連接包括Oracle,MS-Access,Mysql在內的大部分資料庫。你可以在蒼蠅上畫圖,編寫程式下載或者顯示e-mail。你甚至可以完成網路相關的功能。最好的是,你可以選擇你的PHP安裝版本需要哪些功能。引用Nissan的Xterra的話來說就是PHP可以做到你想讓它做到的一切而且無所不能!

1.3 競爭對手:ASP,mod_perl,JSP

我當然不清楚ASP/JSP能做些什麼。不過明確的是編寫那樣的代碼有多簡單,購買它們會有多昂貴以及它們需要多麼昂貴和強大的硬體。如果你有什麼中立的觀點(比如說沒有被SUN和Microsoft的百萬美金所影響),請順便通知我。

據我所知,JSP基於Java,因此Java程式師可以輕鬆開始編碼。ASP只是一個一般的引擎,具有支援多種語言的能力,不過默認的並且是最常用的還是VBScript。

mod_perl與Perl一樣強大,只是更快一些。

二、PHP入門

PHP站點的線上教程已經很棒了。在那裏還有一些其他教程的鏈結。而本文的該部分將讓你對PHP熟悉一點。我不可能做到沒有任何遺漏,我的目的只在於能讓你迅速開始你的PHP編程。

2.1 首要條件

你首先必須要有一個正在工作著的支援PHP的web伺服器。我假定在你的伺服器上所有PHP檔的副檔名為.php3。

2.2 PHP的安裝

生成一個名為test.php3的檔,含有以下內容:
<? phpinfo(); ?>
然後在你的流覽器中打開此文件。看看這個頁面你就知道你的PHP安裝使用的選項了。

2.3 語法

就像前面提到的一樣,你可以混合編寫你的PHP代碼和HTML代碼。因此你必須有辦法將兩者區別開來。以下就是你可以採用的幾種方法。你可以選用其中一種你最適應的並且就這樣堅持這種方法!

從HTML中分離

以下是可以使用的方法:
<? . . . ?>
<?php . . . ?>
<script language="php"> . . . </script>
<% . . . %>

語句

與Perl和C一樣,在PHP中用(;)來分隔語句。那些從HTML中分離出來的標誌也表示語句的結束。

注釋

PHP支援C,C++和Unix風格的注釋方式:

/* C,C++風格多行注釋 */
// C++風格單行注釋
# Unix風格單行注釋

Hello,World!

通過我們已經學過的知識,你可以編寫一個最簡單的程式輸出一個也許是程式世界中最有名的詞語:
<HTML>
<HEAD>
<TITLE>
<?
echo "Hello World!";
?>
</TITLE>
</HEAD>
<BODY>
<H1>
First PHP page
</H1>
<HR>
<?
// Single line C++ style comment
/*
printing the message
*/
echo "Hello World!";
# Unix style single line comment
?>
</BODY>
</HTML>

2.4 資料類型

PHP支援整數、浮點數、字串、陣列和物件。變數類型通常不由程式師決定而由PHP運行過程決定(真是好的解脫!)。但是類型也可以被函數cast或者settype()明確的設定。

數值

數值類型可以是整數或是浮點數。你可以用以下的語句來為一個數值賦值:
$a = 1234; # 十進位數字
$a = -123; # 負數
$a = 0123; # 八進位數 (等於十進位數字的83)
$a = 0x12; # 十六進位數(等於十進位數字的18)
$a = 1.234; # 浮點數"雙精度數"
$a = 1.2e3; # 雙精度數的指數形式

字串

字串可以由單引號或雙引號引出的欄位定義。注意不同的是被單引號引出的字串是以字面定義的,而雙引號引出的字串可以被擴展。反斜杠(\)可以被用來分割某些特殊字元。舉例如下:
$first = 'Hello'
$second = "World";
$full1 = "$first $second"; # 產生 Hello World
$full2 = '$first $second'# 產生 $first $second

可以將字元和數位利用運算符號連接起來。字元被轉化成數位,利用其最初位置。在PHP手冊中有詳細的例子。

陣列與哈希表

陣列與哈希表以同樣的方法被支援。怎樣運用取決於你怎樣定義它們。你可以用list()或者array()來定義它們,也可以直接為陣列賦值。陣列的索引從0開始。雖然我在這裏沒有說明,但是你一樣可以輕易的使用多維陣列。

// 一個包含兩個元素的陣列
$a[0] = "first";
$a[1] = "second";
$a[] = "third"; // 添加陣列元素的簡單方法
// 現在$a[2]被賦值為"third"
echo count($a); // 列印出3,因為該是陣列有3個元素
// 用一個語句定義一個陣列並賦值
$myphonebook = array (
"sbabu" => "5348",
"keith" => "4829",
"carole" => "4533"
);
// 噢,忘了教長吧,讓我們添加一個元素
$myphonebook["dean"] = "5397";
// 你定義的carale元素錯了,讓我們更正它
$myphonebook["carole"] => "4522"
// 我還沒有告訴你怎樣使用陣列的相似支援方式嗎?讓我們看一看
echo "$myphonebook[0]"; // sbabu
echo "$myphonebook[1]"; // 5348

其他一些對陣列或哈希表有用的函數包括sort(),next(),prev()和each()。

對象

使用new語句產生一個物件:
class foo
{
function do_foo ()
{
echo "Doing foo.";
}
}
$bar = new foo;
$bar->do_foo();

改變變數類型

在PHP手冊中提到:"PHP不支援(也不需要)直接在聲明變數時定義變數類型;變數類型將根據其被應用的情況決定。如果你為變數var賦值為一個字串,那麼它變成了一個字串。如果你又為它賦了整數值,那麼它就變成了整數。"
$foo = "0"; // $foo是字串(ASCII 48)
$foo++; // $foo是字串"1" (ASCII 49)
$foo += 1; // $foo現在是整數(2)
$foo = $foo + 1.3; // $foo是一個雙精度數(3.3)
$foo = 5 + "10 Little Piggies"; // $foo是一個整數(15)
$foo = 5 + "10 Small Pigs"; // $foo是一個整數(15)

如果想要強行轉換變數類型,可以使用與C語言相同的函數settype()。

2.5 變數與常量

可能你已經注意到,變數都有一個美元符號($)的首碼。所有變數都是局部變數,為了使得定義的函數中可以使用外部變數,使用global語句。而你要將該變數的作用範圍限制在該函數之內,使用static語句。
$g_var = 1 ; // 全局範圍
function test()
{
global $g_var; // 這樣就可以聲明總體變數了
}

更先進一些的是變數的變數表示。請參考PHP手冊。這在有時會顯得很有用。

PHP內置了許多已定義的變數。你也可以用define函數定義你自己的常量,比如define("CONSTANT","value")。

2.6 運算符

PHP具有C,C++和Java中的通常見到的運算符。這些運算符的優先權也是一致的。賦值同樣使用"="。

算術和字元

以下只有一種運算符是有關字元的:
$a + $b :加
$a - $b :減
$a * $b :乘
$a / $b :除
$a % $b :取模(餘數)
$a . $b :字元串連接

邏輯和比較

邏輯運算符有:
$a || $b :或
$a or $b :或
$a && $b :與
$a and $b :與
$a xor $b :異或 (當$a或$b為true時為true,兩者一樣時為false)
! $a :非
比較運算符有:
$a == $b :相等
$a != $b :不等
$a < $b :小於
$a <= $b :小於等於
$a > $b :大於
$a >= $b :大於等於
與C一樣PHP也有三重運算符(?:)。位操作符在PHP同樣存在。

優先權

就和C以及Java一樣!

2.7 控制流程結構

PHP有著與C一樣的流程控制。我將在下面大概介紹。

if, else, elseif, if(): endif

if (運算式一)
{
. . .
}
elseif (運算式二)
{
. . .
}
else
{
. . .
}
// 或者像Python一樣
if (運算式一) :
. . .
. . .
elseif (運算式二) :
. . .
else :
. . .
endif ;

Loops. while, do..while, for

while (運算式)
{
. . .
}
do
{
. . .
}
while (運算式);
for (運算式一; 運算式二; 運算式三)
{
. . .
}
//或者像Python一樣
while (expr) :
. . .
endwhile ;

switch

switch是對多重if-elseif-else結構的最好的替換:
switch ($i)
{
case 0:
print "i equals 0";
case 1:
print "i equals 1";
case 2:
print "i equals 2";
}

break, continue

break中斷當前的迴圈控制結構。
continue被用來跳出剩下的當前迴圈並繼續執行下一次迴圈。

require, include

就像C中的#include預處理一樣。你在require中指定的那個檔將替代其在主文件中的位置。在有條件的引用檔時,可以使用include()。這樣就使得你可以將複雜的PHP檔分割成多個檔並且在不同需要時分別引用它們。

2.8 函數

你可以像以下的例子一樣定義自己的函數。函數的返回值可以是任何資料類型:
function foo (變數名一, 變數名二, . . . , 變數名n)
{
echo "Example function.\n";
return $retval;
}
所有PHP代碼都可以出現在函數定義中,甚至包括對其他函數和類的定義。函數必須在引用之前定義。

2.9 類

利用類模型建立類。可以參考PHP手冊中對類的詳細解釋。
class Employee
{
var $empno; // 員工人數
var $empnm; // 員工姓名

function add_employee($in_num, $in_name)
{
$this->empno = $in_num;
$this->empnm = $in_name;
}

function show()
{
echo "$this->empno, $this->empnm";
return;
}

function changenm($in_name)
{
$this->empnm = $in_name;
}
}

$sbabu = new Employee;
$sbabu->add_employee(10,"sbabu");
$sbabu->changenm("babu");

$sbabu->show();

三、從實例入手 

PHP的許多特點與其他軟體或者工具有關。利用迄今為止我們所學到的PHP知識,我們可以試著建立一個簡單交互的網站。利用這一過程我們又可以學到不少東西。好吧,我們現在開始專注於一個典型個人網站的建設。

3.1 計畫一個站點
一般一個個人站點包括一個歡迎頁面、一個留言本頁面、一個書簽鏈結頁面、一個計數器、聯繫資訊,甚至還有照片集和一些音樂檔等等。讓我們從一個標題頁面、一個聯繫資訊頁面和一個簡歷頁面開始。我們同樣需要標準的通用的頁面頭部和底部。

標題頁面--front.html


這裏我們有一個非常簡單的html檔:
<HTML>
<HEAD>
<TITLE>
我的個人主頁--歡迎
</TITLE>
</HEAD>
<BODY>
<H1>
我的個人主頁
</H1>
<H2>
歡迎
</H2>
<HR>
<P>
歡迎來我的寒舍,雖然這裏現在暫時還沒有什麼。
</P>
<P>
不過我希望馬上就可以多起來。
</P>
<HR>
<P ALIGN="CENTER">
<SMALL> <I>
Copyright ? 我自己,1999
</I> </SMALL>
</P>
</BODY>
</HTML>

聯繫資訊頁面--count.html

同樣我們又有了一個簡單頁面:
<HTML>
<HEAD>
<TITLE>
我的個人主頁--聯繫資訊
</TITLE>
</HEAD>
<BODY>
<H1>
我的個人主頁
</H1>
<H2>
聯繫資訊
</H2>
<HR>
<P>
你可以通過1-800-PHP-INFO聯繫我
</P>
<HR>
<P ALIGN="CENTER">
<SMALL> <I>
Copyright ? 我自己,1999
</I> </SMALL>
</P>
</BODY>
</HTML>


3.2 HTML到PHP

從上面你可以看出,每個頁面有相同的頭部和底部。像上面那樣每個頁面都寫入相同的資訊在工作量少的時候還可以,但是想像一下當有100多頁面且你需要全部更改其頭部或底部時你要花費多大精力?一頁一頁的手工更改是一件多麼冗長無趣的事情啊!所以我們應該為這些頁面編寫PHP的頭部和底部檔,之後我們只要在每個HTML頁面中引用它們就行了。我們將把這些include檔放在一個叫include的子目錄下。下面我們就把這些站點的通用內容寫進檔中。

全站通用變數設定:common.inc
<?
// 全站通用變數
$MyEmail = "phptalk@tnc.org";
$MyEmailLink = "<a href=\"mailto:$MyEmail\">$MyEmail</a>";
$MyName = "PHP Talk";
$MySiteName = $MyName."'s Home Page";
?>

通用頁面頭部:header.inc
<?
// 定義通用頁面頭部
?>
<HTML>
<HEAD>
<TITLE>
<? echo "$MySiteName - $title"; ?>
</TITLE>
</HEAD>
<BODY>
<H1>
<? echo "$MySiteName"; ?>
</H1>
<H2>
<? echo "$title"; ?>
</H2>
<HR>

通用頁面底部:footer.inc
<?
// 通用頁面底部
?>
<HR>
<P ALIGN="CENTER">
<SMALL> <I>
Copyright ? by
<? echo "$MyName ($MyEmailLink)"; ?>
, 1999
</I> </SMALL>
</P>
</BODY>
</HTML>

新的頁面front.php3:
<?
include("include/common.inc");
$title = "Welcome";
include("include/header.inc");
?>
<P>
歡迎來我的寒舍,雖然這裏現在暫時還沒有什麼。
</P>
<P>
不過我希望馬上就可以多起來。
</P>
<?
include("include/footer.inc");
?>

新的cont.php3:
<?
include("include/common.inc");
$title = "Contact Information";
include("include/header.inc");
?>
<P>
你可以通過1-800-PHP-INFO聯繫我
</P>
<?
include("include/footer.inc");
?>

現在你就可以猜出這樣安排的好處了。如果你想改動頁面的頭部或者底部,你只需要改動相應的檔就可以了。如果你要修改你的e-mail位址甚至你的名字,只要修改common.inc文件就行了。另外值得注意的是你可以把具有任何檔案名或者檔副檔名的檔包含進你的檔中,你甚至可以包含其他站點上的檔。

3.3 計數器

讓我們在首頁上加上一個計數器。這個例子已經被講過多次了,但是還是有利於演示怎樣讀寫檔以及創建自己的函數。counter.inc包含以下代碼:
<?
/*
|| 一個簡單的計數器
*/
function get_hitcount($counter_file)
{
/* 將計數器歸零
這樣如果計數器還未被使用,初始值將是1
你當然也可以把初始值設成20000來騙人咯
*/
$count=0;
// 如果存放計數器檔已經存在,讀取其中的內容
if ( file_exists($counter_file) )
{
$fp=fopen($counter_file,"r");
// 我們只取了前20位,希望你的站點不要太受歡迎啊
$count=0+fgets($fp,20);
// 由於函數fgets()返回字串,我們可以通過加0的方法將其自動轉換為整數
fclose($fp);
// 對檔操作完畢
}
// 增加一次計數值
$count++;
// 將新的計數值寫入檔
$fp=fopen($counter_file,"w");
fputs($fp,$count);
fclose($fp);
# 返回計數值
return ($count);
}
?>
然後我們更改front.php3檔以顯示這個計數器:
<?
include("include/counter.inc");
// 我把計數值放在文件counter.txt中,讀出並輸出
printf ("<CENTER><B>%06d</B></CENTER> <BR> \n",
get_hitcount("counter.txt"));
include("include/footer.inc");
?>
看看我們的新front.php3

3.4 回饋表單

讓我們再添加一個回饋表單以便你的流覽者填寫並e-mail給你。舉例來說我們用一種很簡單的方法實現它,我們只需要兩個頁面:一個為流覽者提供輸入表單;一個獲得表單數據並處理、mail給你。

PHP中獲取表單數據是很簡單的。當一個表單被發送後,表單中所包含的各個元素被賦上了相應的值,而這樣就可以像引用一般變數一樣使用了。
<FORM name="myform" ACTION="process_form.php3" METHOD="POST">
<INPUT TYPE="TEXT" NAME="mytext" VALUE="Some Value">
</FORM>

在process_form.php3中,變數$mytext就被賦予了輸入的值--非常簡單!同樣的,你可以從列表框、多選框、單選框、按鈕等表單元素中取得變數值。你唯一要做的就是為表單中的每一個元素取名以便將來可以引用。

根據這個方法,我們可以生成一個簡單的包含三個元素的表單:姓名、e-mail地址和留言。當流覽者發送表單後,處理該表單的PHP頁面(sendfdbk.php3)讀取資料,檢查姓名是否為空,最後將資料mail給你。

表單:form.php3
<?
include("include/common.inc");
$title = "Feedback";
include("include/header.inc");
?>
<P>
<FORM ACTION="sendfdbk.php3" METHOD="POST">
<INPUT TYPE="text" NAME="name" value="Your name" SIZE="20" MAXLENGTH="30">
<INPUT TYPE="text" MAXLENGTH="40" WIDTH="20" value="Your Email" NAME="email">
<BR>
<TEXTAREA ROWS="7" COLS="40" NAME="comment">
Your feedback on my home page.
</TEXTAREA>
<BR>
<INPUT TYPE="submit" VALUE="Send Feedback!">
</FORM>
</P>
<?
include("include/footer.inc");
?>

處理表單:sendfdbk.php3
<?
include("include/common.inc");
$title = "Feedback";
include("include/header.inc");
if ( $name == "" )
{
// 現在我很討厭匿名的留言!
echo "Duh ? How come you are anonymous?";
}
elseif ($name == "Your name")
{
// 這個流覽者真是不想透露姓名啊!
echo "Hello ? <B>Your name</B> is supposed to be replaced with
your actual name!</B>";
}
else
{
// 輸出一段禮貌的感謝語
echo "
Hello, $name.
<BR>
Thank you for your feedback. It is greatly appreciated.
<BR>
Thanking you
<BR>
$MyName <BR>
$MyEmailLink
";
// 最後mail出去
mail($MyEmail, "Feedback.","
Name : $name
E-mail : $email
Comment : $comment
");
}
include("include/footer.inc");
?>

3.5 簡單的站內搜索引擎

PHP可以調用外部程式。在Unix環境下我們可以利用程式grep實現一個簡單的搜索引擎。我們可以做的稍微複雜一些:使用一個頁面既輸出一個表單供用戶輸入搜索字串又輸出查詢結果。
<?
include("include/common.inc");
$title = "Search";
include("include/header.inc");
?>
<P>
<FORM ACTION="<? echo "$PHP_SELF"; ?>" METHOD="POST">
<INPUT TYPE="text" NAME="searchstr" value="<? echo "$searchstr"; ?>"
SIZE="20" MAXLENGTH="30">
<INPUT TYPE="submit" VALUE="Search!">
</FORM>
</P>
<?
if ( ! empty($searchstr) )
{
// empty()用來檢查查詢字串是否為空
// 如果不為空,調用grep查詢
echo "<HR>\n";
// 調用grep對所有檔進行大小寫非敏感模式的查詢
$cmdstr = "grep -i $searchstr *";
$fp = popen( $cmdstr, "r" ); // 執行命令並輸出管道
$myresult = array(); // 存儲查詢結果
while( $buffer = fgetss ($fp, 4096))
{
// grep返回這樣格式: 檔案名:匹配字串出現行數
// 因此我們利用函數split()分離處理資料
list($fname, $fline) = split(":",$buffer, 2);
// 我們只輸出第一次匹配的結果
if ( !defined($myresult[$fname]))
$myresult[$fname] = $fline;
}
// 現在我們將結果存儲在陣列中,下面就可以處理並輸出了
if ( count($myresult) )
{
echo "<OL>\n";
while(list($fname,$fline) = each($myresult))
echo "<LI>
<A HREF=\"$fname\">$fname</A> : $fline </LI>\n";
echo "</OL>\n";
}
else
{
// 如果沒有查詢結果
echo "Sorry. Search on <B>$searchstr</B>
returned no results.<BR>\n";
}
pclose($fp);
}
?>
<?
include("include/footer.inc");
?>


注釋:

PHP_SELF是PHP內建的變數。包含當前檔案名。
fgets()按行讀取文件,最多4096(指定)字元長度。
fgetss()與fgets()相似,只是解析輸出的HTML標記。
split()有一個參數是2,因為我們只需要把輸出分成兩部分。另外需要省略":"。
each()是一個陣列操作函數,用來更方便的遍曆整個陣列。
popen()、pclose()與fopen()、fclose()的功能很相似,只是增加了管道處理。
請注意以上的代碼並不是實現一個搜索引擎的好辦法。這只是有助於我們更好學習PHP而舉出的一個例子而已。理想的情況是你應該建立一個包含關鍵字的資料庫然後進行搜索。



四、與資料庫鏈結

通過PHP你可以輕鬆的連接到資料庫,請求資料並將其顯示在你的web站點中,甚至修改資料庫中的資料。MySQL是一種很流行的資料庫,並且在互聯網中有許多有關PHP與MySQL的教程。MySQL是免費的,這一點也許就吸引了不少人。由於其廣泛應用,我就不想在這裏贅述MySQL的使用方法了。Oracle被大量在企業應用中採用,因此我們就利用Oracle來介紹PHP與資料庫的連接。我們當然不會提及Oracle資料庫的設計原理,原因是這已經超出了我們的討論範圍。
PHP提供了兩套函數與Oracle連接,分別是ORA_和OCI函數。其中ORA_函數略顯陳舊。OCI函數更新據說更好一些。兩者的使用語法幾乎相差無幾。如前所述,你的PHP安裝選項應該可以支援兩者的使用。
想獲得更多有關在Microsoft Windows平臺上安裝支持PHP3的Apache伺服器的知識以及更多有關Oracle資料庫的知識,請查閱以下URL:www.csoft.net/~vsbabu/articles/oraphp.html。

4.1 連接

<?
if ($conn=Ora_Logon("user@TNSNAME","password"))
{
echo "<B>SUCCESS ! Connected to database<B>\n";
}
else
{
echo "<B>Failed :-( Could not connect to database<B>\n";
}
Ora_Logoff($conn);
phpinfo();
?>
以上代碼使用TNSNAME(在你的tnsnames.ora檔中指明)定義的Oracle資料庫名稱、用戶名稱和密碼連接資料庫。在成功連接的基礎上,ora_logon函數返回一個非零的連接ID並儲存在變數$conn中。

4.2 查詢

假設與資料庫已經連接就緒,下面我們就來實際的應用對資料庫的查詢。下面的代碼演示了一個連接並查詢的典型例子:
<?
/*
* 連接資料庫並執行查詢
*/
function printoraerr($in_cur)
{
// 檢查Oracle是否出錯
// 如果存在錯誤則顯示
// 當指標被啟動時每次請求Oracle後調用該函數
if(ora_errorcode($in_cur))
echo "Oracle code - ".ora_error($in_cur)."\n";
return;
}
/** 主程序 */
if (!($conn=ora_logon("user@TNSNAME","password")))
{
echo "Connection to database failed\n";
exit;
}
echo "Connected as connection - <b>$conn</b><br>\n";
echo "Opening cursor ...<br>\n";
$cursor=ora_open($conn); printoraerr($cursor);
echo "Opened cursor - <b>$cursor</b><br>\n";
$qry="select user,sysdate from dual";
echo "Parsing the query <b>$qry</b> ...<br>\n";
ora_parse($cursor,$qry,0); printoraerr($cursor);
echo "Query parsed <br>\n";
echo "Executing cursor ...<br>\n";
ora_exec($cursor); printoraerr($cursor);
echo "Executed cursor<br>\n";
echo "Fetching cursor ...<br>\n";
while(ora_fetch($cursor))
{
$user=ora_getcolumn($cursor,0); printoraerr($cursor);
$sysdate=ora_getcolumn($cursor,1); printoraerr($cursor);
echo " row = <B>$user, $sysdate </B><br>\n";
}
echo "Fetched all records<br>\n";
echo "Closing cursor ...<br>\n";
ora_close($cursor);
echo "Closed cursor<br>\n";
echo "Logging off from oracle... <br>\n";
ora_logoff($conn);
echo "Logged off from oracle <br>\n";
?>
(譯者注:以上代碼段缺少注釋,請讀者參考PHP Manual的Oracle資料庫函數部分)

4.3 顯示結果

以下代碼演示了怎樣查詢資料庫並將結果輸出:
<?
function printoraerr($in_cur, $conn)
{
// 檢查Oracle是否出錯
// 如果存在錯誤則顯示
// 當指標被啟動時每次請求Oracle後調用該函數
// If it encountered an error, we exit immediately
if(ora_errorcode($in_cur))
{
echo "Oracle code - ".ora_error($in_cur)."<br>n";
ora_logoff($conn);
exit;
}
return;
}

function exequery($w_qry,$conn)
{
$cursor=ora_open($conn); printoraerr($cursor,$conn);
ora_parse($cursor,$w_qry,0); printoraerr($cursor,$conn);
ora_exec($cursor); printoraerr($cursor,$conn);
$numrows=0;
$w_numcols=ora_numcols($cursor);
// 顯示頭部
echo "
<TABLE WIDTH=\"100%\" BORDER=\"0\" CELLSPACING=\"1\" CELLPADDING=\"2\">
<TR>\n";
for ($i=0;$i<$w_numcols;$i++)
{
$align=(ora_columntype($cursor,$i)=="NUMBER")?"RIGHT":"LEFT";
echo "\t<TH VALIGN=TOP ALIGN=$align>".ora_columnname($cursor,$i)."</TH>\n";
}
echo "</TR>\n";
while(ora_fetch($cursor))
{
echo "<TR>\n";
for ($i=0;$i<$w_numcols;$i++)
{
$align=(ora_columntype($cursor,$i)=="NUMBER")?"RIGHT":"LEFT";
if(ora_columntype($cursor,$i)=="LONG")
echo "<TD VALIGN=TOP ALIGN=$align><PRE>".
ora_getcolumn($cursor,$i)."</PRE></TD>\n";
else
echo "<TD VALIGN=TOP ALIGN=$align>".ora_getcolumn($cursor,$i)."</TD>\n";
printoraerr($cursor,$conn);
}
$numrows++;
echo "</TR>\n";
}
if ($numrows==0)
echo "<TR><TD COLSPAN=\"$w_numcols\"><B>Query returned no records
</B></TD></TR>\n";
else
{
echo "<TR>\n";
echo "<TH COLSPAN=\"".($w_numcols-1)."\" ALIGN=RIGHT>Count</TH>\n";
echo "<TH ALIGN=RIGHT>$numrows</TH>\n";
echo "</TR>\n";
}
echo "</TABLE>\n";
ora_close($cursor);
return;
}

// 主程序
if(!($conn=ora_logon("user@SID","password")))
{
echo "Error: Cannot connect to database\n";
exit;
}
$qry="SELECT
deptno \"Dept\"
,empno \"Emp\"
,empnm \"Name\"
,salary \"Salary\"
FROM
employee
ORDER BY 1,2";
exequery($qry);
ora_logoff($conn);
?>
(譯者注:以上代碼段缺少注釋,請讀者參考PHP Manual的Oracle資料庫函數部分)

4.4 基於HTTP的Oracle登錄

將以下代碼加在PHP頁面代碼之前以確認Oracle登錄。注意你必須正確設定$ SID。
<?
if(!isset($PHP_AUTH_USER))
{
Header("WWW-authenticate: basic realm=\"$SID\"");
Header("HTTP/1.0 401 Unauthorized");
$title="Login Instructions";
echo "<blockquote>
You are not authorized to enter the site
</blockquote> \n";
exit;
}
else
{
if (!($conn=ora_logon("$PHP_AUTH_USER@$SID",$PHP_AUTH_PW)))
{
Header("WWW-authenticate: basic realm=\"$SID\"");
Header("HTTP/1.0 401 Unauthorized");
$title="Login Instructions";
echo "<blockquote>
You are not authorised to enter the site
</blockquote> \n";
exit;
}
}
?>

五、其他功能\

5.1 生成圖像

PHP可以操作處理圖像。如果你已經安裝了GD庫,你甚至可以利用PHP生成圖像。
<?
Header("Content-type: image/gif");
$string=implode($argv," ");
$im = imagecreatefromgif("images/button1.gif");
$orange = ImageColorAllocate($im, 220, 210, 60);
$px = (imagesx($im)-7.5*strlen($string))/2;
ImageString($im,3,$px,9,$string,$orange);
ImageGif($im);
ImageDestroy($im);
?>
(譯者注:以上代碼段缺少注釋,請讀者參考PHP Manual的圖像處理函數部分)
這段代碼在其他頁面中通過以下標記<img src="button.php3?text">調用,然後以上的那段button.php3代碼取得text值並在另外取得的圖像檔中加上該值--在以上的代碼中該圖像檔是images/button1.gif--最後輸出到流覽器。假如你想在表單域中使用圖像按鈕,但是又不希望在每次按鈕上的文字改變後不得不重新生成新的圖像,就可以利用這樣簡單的方法動態生成圖像檔。

5.2 Cookies

PHP支援基於HTTP的cookies。在需要時你可以像使用一般變數一樣方便的使用cookie。Cookies是流覽器保存於用戶端的一些資訊片段,由此你可以知道是否一台特定PC上的任何人都訪問過你的站點,流覽者者在你的站點上的蹤跡等等。使用cookies的典型例子就是對流覽者偏好的甄別。Cookies由函數setcookie()設定。與輸出HTTP標頭的函數header()一樣,setcookie()必須在任何實際內容杯輸出到流覽器之前調用。以下是一個簡單例子:
<?
if (empty($VisitedBefore))
{
// 如果沒有設定cookie,為cookie賦上當前時間值
// 函數中的最後一個參數聲明了該cookie保存的時間
// 在這個例子中是1年
// time()函數返回自1970年1月1日以來的以秒數計的時間
SetCookie("VisitedBefore",time(), time()+(60*60*24*365));
}
else
{
// 歡迎流覽者再次光臨
echo "Hello there, welcome back<BR>";
// 讀取cookie並判斷
if ( (time() - $VisitedBefore) >= "(60*60*24*7)" )
echo "Why did you take a week to come back. You should be here more often!? ";
}
?>

5.3 基於HTTP驗證

基於HTTP驗證當PHP以CGI模式運行時不能實現。我們可以使用函數header()發送HTTP標頭強制驗證,用戶端流覽器則彈出供輸入用戶名和密碼的對話方塊。這兩個變數被儲存在$PHP_AUTH_USER和$PHP_AUTH_PW中,你可以使用這兩個變數驗證合法並允許進入。以下的例子通過用戶名稱/密碼對為tnc/nature的驗證一名用戶的登錄:
<?
if(!isset($PHP_AUTH_USER))
{
Header("WWW-Authenticate: Basic realm=\"My Realm\"");
Header("HTTP/1.0 401 Unauthorized");
echo "Text to send if user hits Cancel button\n";
exit;
}
else
{
if ( !($PHP_AUTH_USER=="tnc" && $PHP_AUTH_PW=="nature") )
{
// 如果是錯誤的用戶名稱/密碼對,強制再驗證
Header("WWW-Authenticate: Basic realm=\"My Realm\"");
Header("HTTP/1.0 401 Unauthorized");
echo "ERROR : $PHP_AUTH_USER/$PHP_AUTH_PW is invalid.";
exit;
}
else
{
echo "Welcome tnc!";
}
?>
事實上再實際引用中不大可能如上面使用代碼段明顯的用戶名稱/密碼對,而是利用資料庫或者加密的密碼檔存取它們。

5.4 文件上傳

你可以利用PHP實現檔的功能,注意用戶端的流覽器應該是Netscape3以上或者IE3以上。以下就是該功能的簡單演示:
( upload.html ):
<HTML>
<HEAD>
<TITLE>Upload Your File</TITLE>
</HEAD>
<BODY>
<FORM ACTION="receiver.php3"
ENCTYPE="multipart/form-data" METHOD=POST>
<INPUT TYPE="HIDDEN"
NAME="MAX_FILE_SIZE" VALUE="2000000">
<INPUT TYPE="FILE"
NAME="uploadfile" SIZE="24" MAXLENGTH="80">
<BR><BR>
<INPUT TYPE="SUBMIT" VALUE="Upload File!"
NAME="sendit">
<INPUT TYPE="SUBMIT" VALUE="Cancel"
NAME="cancelit"><BR>
</FORM>
<I><FONT SIZE="2">(You may notice a slight
delay while we upload your file.)</FONT></I>
</BODY>
</HTML>

下面是處理上傳的文件:
( receiver.php3 ):
<?
function do_upload ()
{
global $uploadfile, $uploadfile_size;
global $local_file, $error_msg;
if ( $uploadfile == "none" )
{
$error_msg = "You did not specify a file for uploading.";
return;
}
if ( $uploadfile_size > 2000000 )
{
$error_msg = "Sorry, your file is too large.";
return;
}
$the_time = time ();
// 你需要對以下目錄有寫許可權
$upload_dir = "/local/uploads";
$local_file = "$upload_dir/$the_time";
if ( file_exists ( '$local_file' ) )
{
$seq = 1;
while ( file_exists ( "$upload_dir/$the_time$seq" ) ) { $seq++; }
$local_file = "$upload_dir/$the_time$seq";
};
rename ( $uploadfile, $local_file );
display_page ();
}
function display_page ()
{
// 這裏是你的頁面內容
}
<HTML>
<HEAD>
<TITLE>php3 Receiving Script</TITLE>
</HEAD>
<BODY>
<?
if ( $error_msg ) { echo "<B>$error_msg</B><BR><BR>"; }
if ( $sendit )
{
do_upload ();
}
elseif ( $cancelit )
{
header ( "Location: $some_other_script" );
exit;
}
else
{
some_other_func ();
}
?>
</BODY>
</HTML>

5.5 常用函數

我們簡單來看看一些常用的函數。

陣列


array - 生成陣列
count - 陣列元素個數
sort - 陣列排序,另有其他幾種排序函數可供使用
list - 列出陣列元素
each - 返回下一個key/value對
current - 返回當前陣列元素
next,prev - 傳回當前陣列元素前後指標



日期和時間

checkdate - 驗證日期/時間格式
date - 生成日期/時間格式
time - 當前時間資訊
strftime - 格式化日期/時間

目錄、檔系統

chdir - 改變目錄
dir - 目錄類別
opendir, readdir, closedir - 開啟、讀取、關閉目錄
fopen, fclose - 開啟、關閉文件
fgets, fgetss - 逐行讀取內容
file - 將整個檔讀入一個陣列變數中

正則運算式

ereg - 匹配正則運算式
eregi - 大小寫非敏感匹配正則運算式
ereg_replace -匹配正則運算式並替換
eregi_replace -大小寫非敏感匹配正則運算式並替換
split - 依規則切開字串並以陣列形勢存儲



字串

AddSlashes - 加上斜杠後使用字串
echo - 輸出一個或多個字串
join, implode - 將陣列元素合併為字串
htmlentities, htmlspecialchars - 將HTML特殊字元轉換為HTML標記形式
split - 依規則切開字串並以陣列形勢存儲
5.6 擴展我們的範例主頁

我們將使用以上提到的一些函數和思想為我們的範例主頁添加更多的動態內容。我們可以在每個頁面的頂部加上導航欄,同時使得當前頁自動的不被鏈結顯示;同時還可以添加一個用戶驗證表單以便上傳音樂、圖像等檔並自動更新頁面。

導航欄

實際上就是在footer.inc檔中加上一段代碼。假設你的web站點中所有尾碼為.php3的檔都會出現在導航欄中,以下就是被存為include/navbar.inc的代碼:
<?
/* 輸出該導航欄,鏈結所有除當前頁的站內.php3文件 */
# 讀取目錄
$d = dir("./");
echo "<P ALIGN=\"CENTER\"> | \n";
while($entry = $d->read())
{
// 忽略無檔情況
if ( !is_file($entry) )
continue;
/* 將檔案名與副檔名分開。由於.是正則運算式特殊字元,應該用\引出 */
list($filenm, $fileext) = split("\.",$entry, 2);
// 忽略非.php3檔情況
if( $fileext != "php3" )
continue;
/* 現在我們已經把.php3文件都選出,下面搜尋文件中的第一行(標題)
類似$title="something";
並將以上標題內容分開,用作鏈結文字 */
$linknm = "";
$fp=fopen($entry,"r");
while($buffer=fgets($fp, 4096))
{
$buffer = trim($buffer);
// 我們已經把每個檔的標題放在檔的第一行以便搜索
// 但是當你改變變數名稱時可能會帶來大麻煩
if (ereg("title *= *\"", $buffer))
{
/* 我們已經取得了標題內容並可以在此基礎上
進行去除空格等處理。
必須以PHP代碼方式處理,比如$title = "blah blah" */
eval($buffer);
// 然後將鏈結文字顯示為標題文字
$linknm = $title;
break;
}
}
fclose($fp);
if ( $entry == basename($PHP_SELF) )
echo "$linknm";
else
echo "<A HREF=\"$entry\">$linknm</A>";
echo " | ";
}
$d->close();
echo " </P>\n";
?>

照片收藏夾

我們將引用基於HTTP的驗證、檔系統函數和檔上傳功能維護放置圖像檔的目錄。
同時我們需要建立一個可以列出在該目錄下所有照片的頁面。

文件上傳
<?
include("include/common.inc");
// 我們在這裏再做一次用戶驗證
if(!isset($PHP_AUTH_USER))
{
Header("WWW-Authenticate: Basic realm=\"$MySiteName\"");
Header("HTTP/1.0 401 Unauthorized");
echo "Sorry, you are not authorized to upload files\n";
exit;
}
else
{
if ( !($PHP_AUTH_USER==$MyName && $PHP_AUTH_PW==$MyPassword ) )
{
// 如果是錯誤的用戶名稱/密碼對,強制再次認證
Header("WWW-Authenticate: Basic realm=\"My Realm\"");
Header("HTTP/1.0 401 Unauthorized");
echo "ERROR : $PHP_AUTH_USER/$PHP_AUTH_PW is invalid.<P>";
exit;
}
}
if ( $cancelit )
{
// 當流覽者按下"取消"按鈕則轉向首頁面
header ( "Location: front_2.php3" );
exit;
}
function do_upload () {
global $userfile, $userfile_size, $userfile_name, $userfile_type;
global $local_file, $error_msg;
global $HTTP_REFERER;
if ( $userfile == "none" ) {
$error_msg = "You did not specify a file for uploading.";
return;
}
if ( $userfile_size > 2000000 )
{
$error_msg = "Sorry, your file is too large.";
return;
}
// Wherever you have write permission below...
$upload_dir = "photos";
$local_file = "$upload_dir/$userfile_name";
if ( file_exists ( $local_file ) ) {
$error_msg = "Sorry, a file with that name already exists";
return;
};
// 你還可以由此檢查檔案名稱/類型對以確定是何種檔:gif,jpg,mp3…
rename($userfile, $local_file);
echo "The file is uploaded<BR>\n";
echo "<A HREF=\"$HTTP_REFERER\">Go Back</A><BR>\n";
}
$title = "Upload File";
include("include/header.inc");
if (empty($userfile) || $userfile=="none")
{
// 輸出以下表單
?>
<FORM ACTION="<? echo "$PHP_SELF"; ?>" ENCTYPE="multipart/form-data" METHOD=POST>
<INPUT TYPE="HIDDEN" NAME="MAX_FILE_SIZE" VALUE="2000000">
<INPUT TYPE="FILE" NAME="userfile" SIZE="24" MAXLENGTH="80">
<BR><BR>
<INPUT TYPE="SUBMIT" VALUE="Upload File!" NAME="sendit">
<INPUT TYPE="SUBMIT" VALUE="Cancel" NAME="cancelit"><BR>
</FORM>
<I><FONT SIZE="2">(You may notice a slight delay while we upload your file.)</FONT></I>
<?
} else {
if ( $error_msg ) { echo "<B>$error_msg</B><BR><BR>"; }
if ( $sendit ) {
do_upload ();
}
}
include("include/footer.inc");
?>

照片圖庫


<?
include("include/common.inc");
$title = "Gallery";
include("include/header.inc");
?>
<P>
Here are some of our family photos. This PHP script can really
be made better, by splitting into multiple pages.
</P>
<?
$d = dir("photos");
while($entry = $d->read())
{
if (is_file("photos/$entry"))
echo "<IMG SRC=\"photos/$entry\">\n";
}
$d->close();
?>
<?
include("include/footer.inc");
?>

另外,你可以在檔上傳的表單中加上一個輸入元素去描述該上傳的檔。這個元素將被存儲在檔中,然後被以上的照片圖庫的那段代碼所讀出並顯示出來。

六、網路資源

你可以通過web上的眾多資源更多的瞭解PHP3。許多郵件列表和書籍對你都非常有用。

6.1 站點

PHP的爆炸性流行使得一夜之間出現了很多基於PHP的站點,其中不少站點有線上教程、範例代碼、技巧和提示等內容。


國內
http://www.ph....com - PHP中文用戶,也就是這裏了
http://www.p...com - 中國PHP聯盟
http://www.ph....net - PHP專門站
http://www.php....com - PHP CHINA
http://www.cpcw.com/nets...page/cgi/ - 電腦報網頁陶吧
國外
http://www.p...et/ - PHP官方站點
http://www.dev...com/ - 極好的教程
http://px.sk...com - 代碼交換
http://www.phpb....com/ - 教程、專欄和郵件列表檔案
http://www.web....com/ - 文章和代碼
http://www.phpw....net/ - 提示與技巧
http://www.iometrics.co...ist.php3/ - IOMetrics scripts的檔案
http://www.e-gine...phpkb/ - PHP知識庫

6.2 郵件列表

你可以在PHP官方站點的"支援"欄目內登記獲得以下的郵件列表。值得注意的是這些都是高流量流表,一般每天會有100份e-mail。


php3@lists.php.net - 主要的列表
php-dev@lists.php.net - 主要針對開發者
php-list@exp.com.cn - 本站的郵件列表,與論壇相通

6.3 引人注目的工程

一些基於PHP的工程已經發展得比較完善。其中一些更出色更引人注目的是:

http:// phplib.netuse.de - PHPLib,一整套PHP函數庫
http://www.ph....org - Phorum是一個很完善的BBS系統
http://www.fish...l.org - FishCartSQL是一個電子商務解決方案
http://www.midgar...ct.org - Midgard是一個網路應用開發平臺


[ 此文章被andyz在2005-05-18 20:27重新編輯 ]



獻花 x0 回到頂端 [樓 主] From:台灣數位聯合 | Posted:2005-01-04 05:01 |

首頁  發表文章 發表投票 回覆文章
Powered by PHPWind v1.3.6
Copyright © 2003-04 PHPWind
Processed in 0.027469 second(s),query:15 Gzip disabled
本站由 瀛睿律師事務所 擔任常年法律顧問 | 免責聲明 | 本網站已依台灣網站內容分級規定處理 | 連絡我們 | 訪客留言