只在此山中,雲深不知處


聽首歌



© 2018 by Shawn Huang
Last Updated: 2018.5.27

PHP Introduction

下載XAMPP,完成後打開XAMPP Control Panel,點選右上角config,將Editor換成Nodepad++。

點選XAMPP Control Panel中Apache之start,可在下方狀態列看到Status change detected:running。接下來到C:\xampp\htdocs建立一個新資料夾(e.g. WorkSpace),然後在NotePad++開啟新檔案,輸入程式碼。


hello.php
<?php
    echo "Hello, World";
?>	
儲存到C:\xampp\htdocs\WorkSpace,命名為hello.php。打開瀏覽器到http://localhost/WorkSpace/hello.php,看是否出現結果,顯示Hello, World表示安裝測試成功。
程式最終要放置在一個主機,我們也可以申請一個主機帳號來使用及測試。主機帳號大部分都要收費,不過還是有少部分免費的可以使用,例如:Byethost或是InfinityFree,嘗試申請了一個Byethost的帳號,先在自己電腦使用XAMPP測試及練習,然後在上傳到主機看效果。

Syntax


從例子hello.php可以看出php的語法介於<?php?>兩個符號之間。HTML的內容可以直接嵌入到php檔案之內。
php1_1.php
<head>
	<title>php1_1.php</title>
</head>
<body>
	<h1><?php 
		echo "Hello, php.";//inside php code
		#use echo to print
		/*
			multiline comment...
		*/
		?></h1>
</body>

Variables


在PHP中使用變數與JavaScript類似,屬於弱型別程式語言(Loosely Typed Language),亦即宣告變數時不需要宣告變數型態,宣告時使用$號代表變數。
php1_2_variable.php
<head>
	<title>php1_2_variable.php</title>
</head>
<body>
	<h1><?php 
		$rank = 100;
		echo "獵人等級<span style='color:blue;'>";
		echo $rank;
		echo "</span>級";
		?></h1>
</body>

Constant


在PHP中常數的宣告使用define()函數,或是使用const。
php1_2_variable.php
<head>
	<title>php1_2_constant.php</title>
</head>
<body>
    <h1>
    <?php 
        define("PI","3.14159");
        const E = 2.72;
        print "圓周率大約等於<span style='color:blue;'>".PI."</span>......";
        echo "自然底數E約等於<span style=\"color:red;\">".E."</span>......";
    ?>
    </h1>
</body>

Data Type


變數型態原則上可分:
php1_3_datatype.php
<head>
	<title>php1_3_datatype.php</title>
</head>
<body>
	<?php 
		$i = 0b111;
		var_dump($i);
		echo "<br>";
		$s = "批A去批";
		var_dump($s);
		echo "<br>";
		$f = 3.3e3;
		var_dump($f);
		echo "<br>";
		$b = true;
		var_dump($b);
		echo "<br>";
		$a = array(1,2,3);
		var_dump($a);
		echo "<br>";
		class Hunter{
			public $level = 10;
		}
		$o = new Hunter;
		var_dump($o);
		echo "<br>";
		$n = "hi";
		$n = null;
		var_dump($n);
		echo "<br>";
		$r = fopen("hello.php", "r");
		var_dump($r);
		echo "<br>";
	?>
</body>

傳值與傳址
跟其他語言(e.g. c)類似,指派變數可以有傳值與傳址兩個形式,傳址的時候,在PHP中,只要加上&符號即可。例如:
<?php
	$s1 = "Hello<br>";
	$s2 = & $s1;
	echo $s2; // Hello
	$s2 = "hi<br>";
	echo $s1; // hi
?>
函數傳址:
<?php
	function fun(&$x) { // 函數傳址
		$x = $x*2;  // 可在此修改外部變數的值
	}
	$a = 10;
	fun($a);
	echo $a;
?>	
物件變數用法也是傳值,不過實際上傳的是指位(pointer),並非本身資料。
<?php
	class One{
		public $v = 1;
		public function __toString(){
			return "value = {$this->v}<br>";
		}
	}
	function Value($obj){
		$obj->v = 2;  // 傳入的$obj指位實際為$one
		$obj = new One();  // 產生新的物件
		//echo $obj->v."<br>"; // 1
		echo $obj;
	}
	$one = new One();
	Value($one);
	//echo $one->v."<br>"; // 2
	echo $one;
?>
若是傳入的是物件本身而非僅是pointer:
<?php
	class One{
		public $v = 0;
		public function __construct($v){
			$this->v = $v;
			
		}
		public function __destruct(){
			echo __CLASS__." was destroyed.<br>";
		}
		public function __toString(){
			return "value = {$this->v}<br>";
		}
	}
	function Value(&$obj){ // 傳入的$obj為實際之$obj位址
		$obj->v = 2;  
		echo $obj; // 2
		$obj = new One(3);  // 產生新的物件取代原來物件
		echo $obj; // 3
	}
	$obj = new One(1);
	echo $obj; // 1
	Value($obj);
	echo $obj; // 3
?>

Flow Control

跟其他語言一樣可用 等作流程控制,此處先介紹計算子(Operators)。

Operators



php2_1_operator.php
<head>
	<title>php2_1_operator.php</title>
</head>
<body>
	<?php 
		$x = 0b1111;
		$y = 0x2f;
		$z = 0;
		$s1 = "abc";
		$s2 = "xyz";
		#echo $x." ".$y;
		echo ($x+$y)."<br>".($x-$y)."<br>".($x*$y)."<br>".($x/$y)."<br>".($x%$y)."<br>";
		$z = $x;
		$z += $y;
		echo "z = ".$z."<br>";
		echo ("x==y returns ");var_dump($x==$y);
		echo "<br>z++=".$z++."\t,++z=".++$z."<br>";
		var_dump ($x<$y)xor($x!=$y);
		echo "<br>".$s1.=$s2."<br>";
		echo $s1<=>$s2;
	?>
</body>

if...else...


php2_2_ifelse.php
<?php 
	$m = 0b1101011;
	$n = 0xaa;
	if($m > $n){
		echo "<b>$m</b>大於<i>$n</i>";
	}else if($m < $n){
		echo "<b>$m</b>小於<i>$n</i>";
	}else{
		echo "<b>$m</b>等於<i>$n</i>";
	}
	echo ($m > $n)?"<br><b>$m</b>大於$n":"<br><b>$m</b>小於$n";
?>

switch



php2_2_switch.php
<?php 
	$w = 55;#kg
	$h = 1.65;#m
	$bmi = $w/$h/$h;
	switch($bmi){
		case $bmi<18.5:
			echo "Too Thin";
			break;
		case $bmi>=18.5 && $bmi <22.5:
			echo "Good shape";
			break;
		case $bmi >=22.5 && $bmi <26.5:
			echo "Over-weighted";
			break;
		default:
			echo "Obese";
	}
?>

while



php2_3_while.php
<?php 
	$i = 0;
	$sum = 0;
	while($i <= 20){
		$i++;
		if($i>10)
			break;
		if($i%2)
			continue;
		echo $i."<br>";
		$sum=$sum+$i;
	}
	echo "sum = $sum<br>";
	do{#do it anyway no matter what condition it is
		echo $i;
	}while($i<0);
?>

for



php2_3_for.php
<?php 
	echo "<center>";
	for($i = 1; $i <= 50; $i++){
		for($j = 0; $j < $i; $j++){
			echo "*";
		}//for
		echo "<br>";
	}//for
	echo "</center>";
?>

foreach


Array

Function


使用關鍵字function建立函數。
php2_4_function.php
<?php 
	function sayHello(){
		echo "Hello";
	}
	function add($x, $y){
		return $x+$y;
	}
	sayHello();
	echo("<br>".add(10, 20));
	//////////////////////////////
	function sale($size, $price = 100){
		echo "<p>T-shirt #$size is $$price dollars.</p>";
	}
	sale(10);
	sale(12, 200);
	//////////////////////////////
	function square(&$x){
		$x *= $x;
		return $x;
	}
	$a = 10;
	square($a);
	echo $a;
?>

Arrow Functions
Arrow function讓我們使用一行建立函數。
<?php
	$y = 10;
	// fn
	$f1 = fn($x) => $x*$y;
	var_export($f1(9));
	echo PHP_EOL;

	// use
	$sq1 = function ($x) use ($y){ // 使用use來使用外部變數
		return $x*$y;
	};//記得加;號
	echo $sq1(5)."<br>";
	
	// Nested
	$z = 10;
	$fn1 = fn($x) => fn($y) => $x*$y*$z; // Nested
	echo $fn1(10)(5), PHP_EOL;
?>

這類的函數可以讓我們方便將函數作為輸入值。例如原本要排序陣列使用如下方式:
<?php
	function compare($x, $y){
		return $x > $y;
	}
	$arr = array("Tom", "Mary", "Jenny", "John", "Alex", "Helen");
	usort($arr, 'compare');
	print_r ($arr); // print_r()用來輸出array
?>
現在可以使用arrow function來完成。
<?php
	$arr = array("Tom", "Mary", "Jenny", "John", "Alex", "Helen", "Sam", "Mia");
	usort($arr, fn($x, $y)=>$x>$y);
	print_r ($arr); // print_r()用來輸出array
?>

Variable Scope


<?php 
	$x = 100;
	function scope(){
		echo $x;
	}
	scope();
?>

php2_4_scope.php
<?php 
	$x = 100;
	function scope(){
		global $x;
		echo $x;
	}
	scope();
	$x = 200;
	scope();
?>

recursive function



php2_5_recursive.php
<?php 
	function fibonacci($n){
		if($n == 0)
			return 0;
		if($n == 1)
			return 1;
		return fibonacci($n-1) + fibonacci($n-2);
	}
	for($i=1; $i<20; $i++){
		echo fibonacci($i)."<br>";
	}
?>

Type Declarations
自PHP 5開始加入argument type declarations,允許指定函數參數的型態。
  • 若是無法符合需要的變數型態,將會回傳fatal error。例如:
    <?php
    	function wee($s){
    		foreach ($s as $v){
    			echo $v, " ";
    		}
    	};//記得加;
    	wee(array(1,3,5,7,9,11,13,17,19,21,23,25));
    	wee("13579")
    ?>
    
    
  • callable: 始於PHP5.4。輸入函數須為callable,或是物件。如下例,就是將callable函數作用到$data上。
    <?php
    	function call(callable $callback, $data){
    		$callback($data);
    	}//toPrint
    	$wee = function($s){
    		$sum = 0;
    		foreach ($s as $v){
    			$sum += $v;
    		}
    		echo $sum;
    	};//記得加;
    	call($wee, array(1,2,3,4,5));
    ?>
  • 變數型態(bool, int, float, string):始於PHP 7,如下例。[]是空陣列,其餘可視為bool。
    <?php
    	function isTrue(bool $b){
    		if ($b){
    			echo 'true';
    		}else{
    			echo 'false';
    		}
    	}
    	isTrue(true); // true
    	isTrue(1); // true
    	isTrue('false'); // true
    	isTrue([]); // error
    ?>
  • 上例中輸入int(1)、string('false')都可正常運行,那是因為這兩者可轉換成bool,不過這不夠嚴謹,若是要嚴格執行型態檢查(strong type checking),可以加入declare(strict_types=1);這行。如下:
    <?php
    	declare(strict_types=1);
    	function isTrue(bool $b){
    		if ($b){
    			echo 'true';
    		}else{
    			echo 'false';
    		}
    	}
    	isTrue(true); // true
    	isTrue(1); // error
    	isTrue('false'); // error
    	isTrue([]); // error
    ?>

除了輸入參數之外,也可以指定傳回值的型態。
  • 指定傳回型態(使用:符號),如下例,若將結果cast成為array,傳回錯誤。(若是cast成為int, string, bool則都是可行的。)
    <?php
    	function circle(float $r): float{
    		return (pi()*$r*$r); // 若將結果cast成array: (array)(pi()*$r*$r); >> fatal error
    	}
    	echo circle(10);
    ?>
  • 若將上例之傳回型態修改為void,也會造成錯誤,此時不需傳回,可使用echo來顯示結果。
  • PHP7.1後,可以handle當輸入參數為null的情況,只要在之前加上問號(?)即可。如下例:
    <?php
    	declare(strict_types=1);
    	function nullok(?int $num){
    		echo $num === null? 'null<br>':$num;
    	}
    	nullok(null); // null
    	nullok(10); // 10
    ?>
  • PHP8之後還可以接受一個變數包含超過一個型態的參數。如下例,若是只有int型態,參數為float將傳回錯誤。
    <?php
    	declare(strict_types=1);
    	function circle(int|float $r){
    		echo pi()*$r*$r, '<br>';
    	}
    	circle(10); // 314.15926535898
    	circle(10.5); // 346.36059005827
    ?>
  • 現在class內的變數也可以直接指定變數型態。若是沒有給定型態以及初始值的變數,預設內容則為null。
  • <?php
    	declare(strict_types=1);
    	class AClass{
    		public int $age;
    		public function __construct($a){
    			$this->age = $a;
    		}
    		public function __destruct(){
    			echo __CLASS__." was destroyed.<br>";
    		}
    	}
    	$ac = new AClass(18);
    	echo $ac->age.'<br>';
    	$ac->age = 20;
    	echo $ac->age.'<br>';
    	$ac->age = 20.5; // or try '20.5' >> fatal error
    	echo $ac->age.'<br>';
    ?>
  • 使用settype()來cast或直接cast以改變變數型態。
  • <?php
    	$var = 3.14;
    	settype($var, 'int'); // 使用settype來cast
    	echo $var."<br>";
    	$var = (bool)$var; // 直接cast
    	echo $var."<br>";
    ?>
  • 使用gettype()來取得變數型態。
  • <?php
    	$var = 3.14;
    	echo gettype($var)."<br>";
    	var_dump($var);
    	echo "<br>";
    	var_export($var);
    ?>
判斷變數型態
可以使用以下方法來判斷變數是否為某型態。
  • is_array()
  • is_bool()
  • is_callable(): can it be called as a function?
  • is_float(), is_double(): is a float?
  • is_real, is_int(), is_integer(), is_long(): is an integer?
  • is_null()
  • is_numeric(): is a number or numeric string?
  • is_scalar(): is an int, float, stirng, or bool?
  • is_object()
  • is_resource()
  • is_string()
<?php
	$var = 3.14;
	echo is_float($var)? "yes<br>":"no<br>"; // yes
	echo is_bool($var)? "yes<br>":"no<br>"; // no
	echo is_numeric($var)? "yes<br>":"no<br>"; // yes
	echo is_scalar($var)? "yes<br>":"no<br>"; // yes
	echo is_int($var)? "yes<br>":"no<br>"; // no
	echo is_object($var)? "yes<br>":"no<br>"; // no
?>

BIF

內建函數(Built-in Functions)可讓我們直接使用。擇要介紹:

Math


詳細列表可見這裡
php3_1_math.php
<?php 
	echo "絕對值:".abs(-M_PI)."<br>";
	echo "天花板:".ceil(pi())."<br>";
	echo "地板:".floor(M_PI)."<br>";
	echo "根號:".sqrt(pi())."<br>";
	echo "亂數:".rand(1,100)." max:".getrandmax()."<br>";
	echo "對數底e:".log(exp(5))."<br>";
	echo "對數底10:".log10(1e5)."<br>";
	echo "次方:".pow(2,10)."<br>";
	echo "10->2:".decbin(100)."<br>";
	echo "2->10:".bindec(11111)."<br>";
	echo "10->8:".decoct(11111)."<br>";
	echo "8->10:".octdec('11111')."<br>";
	echo "10->16:".dechex(11111)."<br>";
	echo "16->10:".hexdec('11111')."<br>"; // has to be inside the quote because of a~f
	echo "任意進位轉換:".base_convert('f', 16, 8)."<br>";
?>

Array


Array的宣告方式可以使用array()函數,或是直接手動指派,index由0開始,index也可以不是指派的數字(類似python的dictionary)。
php3_2_array.php
<?php 
	$a1 = array(1,2,3,4,5);
	$a2[0] = "#ff0000";
	$a2[1] = "#00ff00";
	$a2[2] = "#0000ff";
	$a3 = array("one"=>1, "two"=>2, "three"=>3);
	$a4 = array(10=>"ten", 20=>"twenty", 30=>"thirty");
	$a5 = array(
		array("one"=>1,"two"=>2,"three"=>3), 
		array("four"=>4,"five"=>5,"six"=>6), 
		array("seven"=>7,"eight"=>8,"nine"=>9)
	);
	echo $a1[2]."<br>".$a2[2]."<br>".$a3["two"]."<br>".$a4[20]."<br>".$a5[1]["five"]."<br>";
	var_dump($a4);
	echo "<br>";
	print_r($a4);
?>

foreach



php3_2_foreach.php
<?php 
	$season = array("spring", "summer", "autumn", "winter");
	$weekday = array(1=>"Mon", 2=>"Tue", 3=>"Wed", 4=>"Thur", 5=>"Fri", 6=>"Sat", 7=>"Sun",);
	foreach($season as $value){
		echo $value . "<br>";
	}
	foreach($weekday as $key=>$value){
		echo $key."=>".$value."<br>";
	}
?>

除了使用foreach,尚可使用以下方式traverse array。
php3_2_traversal.php
<?php 
	list($x,$y,$z)=array(1,2,3);
	echo $x." ".$y." ".$z."<br>";
	
	$season = array("spring", "summer", "autumn", "winter");
	$weekday = array(1=>"Mon", 2=>"Tue", 3=>"Wed", 4=>"Thur", 5=>"Fri", 6=>"Sat", 7=>"Sun",);
	for($i = 0; $i < count($season); $i++){//alias of sizeof
		echo $season[$i]."<br>";
	}
	///////////////////////////////////////
	shuffle($weekday);
	print_r($weekday);
	echo("<br>-------------------<br>");
	reset($weekday);
	while(list($key, $value)= each($weekday)){
		echo "$key => $value<br>";
	}
	///////////////////////////////////////
	echo("<br>-------------------<br>");
	reset($weekday);
	while($value = current($weekday)){
		echo "$value<<=>>".key($weekday)."<br>";
		next($weekday);
	}
?>

operators


可使用於兩個array間的operators:
php3_2_arrayOperators.php
<?php 
	$fruit = array("a"=>"apple", "b"=>"banana", "p"=>"pear");
	$number = array(1,2,3);
	$season = array("spring", "summer", "autumn", "winter");
	$weekday = array(1=>"Mon", 2=>"Tue", 3=>"Wed", 4=>"Thur", 5=>"Fri", 6=>"Sat", 7=>"Sun",);
	$month = array(1=>"Jan", 2=>"Feb", 3=>"Mar");
	$ns = $number + $season;
	$fw = $fruit + $weekday;
	$sw = $season + $weekday;
	$wm = $weekday + $month;
	foreach($ns as $key=>$value){
		echo $key."=>".$value."<br>";
	}
	echo "<br>----------------------<br>";
	foreach($fw as $key=>$value){
		echo $key."=>".$value."<br>";
	}
	echo "<br>----------------------<br>";
	foreach($sw as $key=>$value){
		echo $key."=>".$value."<br>";
	}
	echo "<br>----------------------<br>";
	foreach($wm as $key=>$value){
		echo $key."=>".$value."<br>";
	}
	var_dump($number==$month);
	var_dump($number===$month);
	var_dump($number!=$month);
	var_dump($number<>$month);
	var_dump($number!==$month);
?>

Sorting



php3_2_arraySorting.php
<?php 
	$fruit1 = array("5"=>"waterlemon", "2"=>"apple", "1"=>"mango", "4"=>"banana", "3"=>"pear");
	$fruit2 = array("5"=>"waterlemon", "2"=>"apple", "1"=>"mango", "4"=>"banana", "3"=>"pear");
	$fruit3 = array("5"=>"waterlemon", "2"=>"apple", "1"=>"mango", "4"=>"banana", "3"=>"pear");
	for($i = 0; $i<10; $i++){
		$number[$i] = rand(1,100);
	}
	print_r($number);
	echo("<br>----------------<br>");
	sort($number);
	print_r($number);
	echo("<br>----------------<br>");
	sort($fruit1);
	print_r($fruit1);
	echo("<br>----------------<br>");
	ksort($fruit2);
	print_r($fruit2);
	echo("<br>----------------<br>");
	asort($fruit3);
	print_r($fruit3);
	echo("<br>----------------<br>");
	arsort($fruit3);
	print_r($fruit3);
?>

php3_2_arraySortingFunction.php
<?php 
	$fruit = array("5"=>"waterlemon", "2"=>"apple", "1"=>"mango", "4"=>"banana", "3"=>"pear");
	function cmp($a, $b){
		return $a<=>$b;
	}
	uasort($fruit, 'cmp');
	print_r($fruit);
?>

Array_walk


將自訂函數逐一應用到Array內的元素。
php3_2_arrayWalk.php
<?php 
	foreach(range(1,10,1) as $n){
		$numbers[$n] = $n;
	}
	function square(&$x){
		$x *= $x;
	}
	array_walk($numbers, 'square');
	print_r($numbers);
	echo("<br>");
	foreach(range('z','a',-2) as $w){
		echo $w."<br>";
	}
?>

更多關於array的函數請見官網

String



php3_3_string.php
<?php 
	$str = "The strlen() function is used to calculate the number of characters inside a string.";
	echo strlen($str)."<br>";
	echo str_word_count($str)."<br>";
	echo str_replace("strlen()","str_replace()",$str, $count)."<br>";//$count is optional
	echo "Replacements: ".$count."<br>"; // number of replace
	echo strrev($str)."<br>"; //reverse
	$stra = explode(" ", $str); // split() in Java
	$stra2 = str_split($str);
	print_r($stra);
	echo("<br>---------------------<br>");
	print_r($stra2);
	$str1 = implode(",", $stra);// alias of join()
	echo "<br>".$str1."<br>";
	echo str_shuffle($str1);
	echo("<br>---------------------<br>");
	echo strtoupper(trim($str));//strtolower()
?>

Date/Time


使用date(format)函數來得到目前日期時間,參數為日期格式。使用的符號如下:
php3_4_date.php
<?php 
	date_default_timezone_set('Asia/Taipei');
	echo date("D/d/n/Y")."<br>";
	echo date("l/d-m-Y")."<br>";
	echo date("N.d.m.Y")."<br>";
	echo date("h:i:s e T")."<br>";
	echo date("F d, Y G:i:s A P")."<br>";
	echo date("g:i:s:v a")."<br>";
?>

timestamp


timestamp指自January 1 1970 00:00:00 GMT至特定時間的秒數,可使用time()取得目前之timestamp。
php3_4_time.php
<?php 
	date_default_timezone_set('Asia/Taipei');
	$timestamp = time();
	echo($timestamp."<br>");
	echo(date("F d, Y G:i:s", $timestamp)."<br>");
	echo(date("F d, Y G:i:s", mktime(23, 59, 59, 12, 31, 1999)));
?>
更多DateTime函數可見官網

Data Transfer

在Server與Client之間需要資料傳遞,若要將資訊傳回伺服器,通常可使用get與post方式。get會將資料顯示在URL列(不安全且長度有限制),post會將資料整個包裹寄到伺服器再做後續處理。

GET



php4_1_get.php
<head>
	<title>Get method</title>
</head>
<body>
<?php 
if(isset($_GET["name"])){
	echo 'Hi, there, <strong>'.$_GET["name"].'</strong>';
}
?>

<form method="get" action="<?php echo $_SERVER["PHP_SELF"]; ?>">
	<label for="yourname">Name:</label>
	<input type="text" name="name" id="yourname">
	<input type="submit">
</form>
</body>

POST



php4_1_post.php
<head>
	<title>Post method</title>
</head>
<body>
<?php 
if(isset($_POST["name"])){
	echo 'Hi, there, <strong>'.$_POST["name"].'</strong>';
}
?>

<form method="post" action="<?php echo $_SERVER["PHP_SELF"]; ?>">
	<label for="yourname">Name:</label>
	<input type="text" name="name" id="yourname">
	<input type="submit">
</form>
</body>

PHP & HTML
我們已知可以將HTML的語法寫在echo(or print)內來顯示,也可以使用print <<<EOT ...... EOT;顯示多行。
<head>
	<title>Post method</title>
</head>
<style>
	p.bluep{
		border:1px solid blue;
	}
</style>
<body>

<?php 
$name = "";
$email = "";
if(isset($_POST["name"]) || isset($_POST["email"])){
	$name = $_POST['name'];
	$email = $_POST['email'];
	//echo "<p class=\"bluep\"><strong>Name:</strong> $name</p>";
	//echo "<p class=\"bluep\"><strong>Email:</strong> $email</p>";
}

if($name != "" || $email != "")
print <<<EOT
	<p class="bluep">Name: $name</p>
	<p class="bluep">Email: $email</p>
EOT;
// No more codes here
?>

<form method="post" action="<?php echo $_SERVER["PHP_SELF"]; ?>">
	<p>
		<label for="yourname">Name:</label>
		<input type="text" name="name" id="yourname">
	</p>
	<p>
		Email Address:
		<input type="text" id="email" name="email" size="20" maxlength="40">
	</p>

	<input type="submit" value="GO">
</form>
</body>
這個例子將php與html寫在同一個檔案內,我們也可以將其分開為兩個不同檔案,假設我們將php寫到hello.php檔案,則html檔如下:
<head>
	<title>Post method</title>
</head>
<body>

<form method="post" action="hello.php">
	<p>
		<label for="yourname">Name:</label>
		<input type="text" name="name" id="yourname">
	</p>
	<p>
		Email Address:
		<input type="text" id="email" name="email" size="20" maxlength="40">
	</p>

	<input type="submit" value="GO">
</form>
</body>
而hello.php內容則如下:
<?php 
if(isset($_POST["name"])){
	$name = $_POST['name'];
	$email = $_POST['email'];
}
echo '<h2><a href="test.html">Back to form</a></h2>';
print <<<EOT
<p>{$name}</p>
<p>Email: $email</p>
EOT;
?>
如此可以安排成兩個頁面。

FORM

使用各式表單(Form)來將資料傳遞到伺服器,還有哪些講究?

Required



php4_2_form.php
<head>
	<title>FORM</title>
</head>
<body>
<?php 
$name="";
$occupation="";
$side="";
$pets=array();
if(isset($_POST["name"])){
	$name = $_POST["name"];
}
if(isset($_POST["occupation"])){
	$occupation = $_POST["occupation"];
}
if(isset($_POST["side"])){
	$side = $_POST["side"];
}
if(isset($_POST["pets"])){
	$pets = $_POST["pets"];
}
?>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
	<label for="yourname">姓名:</label>
	<input type="text" name="name" id="yourname"><span style="color:red;"><sup>*</sup></span><br><br>
	
	<label for="occupation">職業:</label>
	<input type="text" name="occupation" id="occupation"><span style="color:red;"><sup>*</sup></span><br><br>
	
	<label>陣營:</label>
	<input type="radio" name="side" value="聯盟">聯盟
	<input type="radio" name="side" value="部落">部落<span style="color:red;"><sup>*</sup></span><br><br>
	
	<label>寵物:</label>
	<input type="checkbox" name="pets[]" value="灰皮貓">灰皮貓
	<input type="checkbox" name="pets[]" value="小耕作機器人">小耕作機器人
	<input type="checkbox" name="pets[]" value="鸚鵡">鸚鵡
	<input type="checkbox" name="pets[]" value="小座狼">小座狼
	<input type="checkbox" name="pets[]" value="聯盟氣球">聯盟氣球
	<span style="color:red;"><sup>*</sup></span><br><br>
	<input type="submit"><input type="reset" id="reset">
</form>
<?php 
echo "玩家資訊:<br>";
echo "姓名: ".$name."<br>";
echo "職業: ".$occupation."<br>";
echo "陣營: ".$side."<br>";
$allPets = "";
foreach($pets as $key=>$value){
	$allPets .= $value."  ";
}
echo "寵物: ".$allPets."<br>";
?>
</body>

php4_2_formRequired.php
<head>
	<title>FORM</title>
</head>
<body>
<?php 

$name = $occupation = $side = "";
$pets = array();
$nameErr = $occupationErr = $sideErr = $petsErr = "";

if ($_SERVER["REQUEST_METHOD"] == "POST") {
	if(empty($_POST["name"])){
		
		$nameErr = "必填";
	}else{
		$name = $_POST["name"];
	}

	if(empty($_POST["occupation"])){
		$occupationErr = "必填";
	}else{
		$occupation = $_POST["occupation"];
	}

	if(empty($_POST["side"])){
		
		$sideErr = "必填";

	}else{
		$side = $_POST["side"];
	}
	
	if(empty($_POST["pets"])){
		
		$petsErr = "必填";

	}else{
		$pets = $_POST["pets"];
	}
	
}
?>

<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
	<label for="yourname">姓名:</label>
	<input type="text" name="name" id="yourname" value="<?php echo $name; ?>">
	<span style="color:red;"><sup>*</sup><?php echo $nameErr?></span><br><br>
	
	<label for="youroccupation">職業:</label>
	<input type="text" name="occupation" id="youroccupation" value="<?php echo $occupation; ?>">
	<span style="color:red;"><sup>*</sup><?php echo $occupationErr?></span><br><br>
	
	<label>陣營:</label>
	<input type="radio" name="side" value="聯盟" <?php if(isset($side)&& $side=="聯盟") echo "checked"; ?>>聯盟
	<input type="radio" name="side" value="部落" <?php if(isset($side)&& $side=="部落") echo "checked"; ?>>部落
	<span style="color:red;"><sup>*</sup><?php echo $sideErr?></span><br><br>
	
	<label>寵物:</label>
	<input type="checkbox" name="pets[]" value="灰皮貓" <?php if(isset($pets)&& in_array("灰皮貓",$pets)) echo "checked"; ?>>灰皮貓
	<input type="checkbox" name="pets[]" value="小耕作機器人"<?php if(isset($pets)&& in_array("小耕作機器人",$pets)) echo "checked"; ?>>小耕作機器人
	<input type="checkbox" name="pets[]" value="鸚鵡"<?php if(isset($pets)&& in_array("鸚鵡",$pets)) echo "checked"; ?>>鸚鵡
	<input type="checkbox" name="pets[]" value="小座狼"<?php if(isset($pets)&& in_array("小座狼",$pets)) echo "checked"; ?>>小座狼
	<input type="checkbox" name="pets[]" value="聯盟氣球"<?php if(isset($pets)&& in_array("聯盟氣球",$pets)) echo "checked"; ?>>聯盟氣球
	<span style="color:red;"><sup>*</sup><?php echo $petsErr?></span><br><br>
	
	<input type="submit"><input type="reset" id="reset">
</form>

<?php 
echo "玩家資訊:<br>";
echo "姓名: ".$name."<br>";
echo "職業: ".$occupation."<br>";
echo "陣營: ".$side."<br>";
$allPets = implode(", ", $pets);
echo "寵物: ".$allPets."<br>";
?>

</body>

Move from one page to another

Validation


為了避免有人胡亂輸入,除了要求必填之外,尚須要確認輸入內容符合規範。
php4_3_validation.php
<head>
	<title>FORM Validation</title>
</head>
<body>
<?php 

$name = $email = "";
$nameErr = $emailErr = "";

if ($_SERVER["REQUEST_METHOD"] == "POST") {
	if(empty($_POST["name"])){
		$nameErr = "必填";
	}else{
		$tempname = $_POST["name"];
		if(!preg_match("/^[a-zA-Z]+\d*/",$tempname)){
			$nameErr = "Only letters, number and white space, cannot use number&white space as prefix.";
		}else{
			$name = $tempname;
		}
	}
	if(empty($_POST["email"])){
		$emailErr = "必填";
	}else{
		$tempemail = $_POST["email"];
		$tempemail = filter_var($tempemail, FILTER_SANITIZE_EMAIL);
		if(!filter_var($tempemail, FILTER_VALIDATE_EMAIL)){
			$emailErr = "Invalid email format";
		}else{
			$email = $tempemail;
		}
	}
}
?>

<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
	<label for="yourname">姓名:</label>
	<input type="text" name="name" id="yourname" value="<?php echo $name; ?>">
	<span style="color:red;"><sup>*</sup><?php echo $nameErr?></span><br><br>
	
	<label for="email">Email:</label>
	<input type="text" name="email" id="email" value="<?php echo $email; ?>">
	<span style="color:red;"><sup>*</sup><?php echo $emailErr?></span><br><br>
	
	<input type="submit"><input type="reset" id="reset">
</form>

<?php 
echo "輸入資訊:<br>";
echo "姓名: ".$name."<br>";
echo "Email: ".$email."<br>";
?>

</body>
  • 使用preg_match(regex, subject)函數來針對某一字串進行檢驗,第一個參數regex為Regular Expression
  • filter_var(variable, filter, options)函數可根據不同的filter來協助過濾不合格的型態,此處filter選擇FILTER_VALIDATE_EMAIL來過濾email格式。
  • 使用FILTER_VALIDATE_EMAIL之前先使用FILTER_SANITIZE_EMAIL可以幫我們先去除一些多餘的內容,例如abc@   g m a il.com,其中多了一些空白,FILTER_SANITIZE_EMAIL可以先幫我們去除。

Include File

檔案可以傳輸更多資料,而且在檔案內的內容可以被多次使用。可以使用的語法為include與require。先寫幾個要被include的檔案。
php4_4_header.php
<header style="background: gold; color: tomato;font-size:200%;font-weight:900;text-align:center;">
	PHP
</header>

php4_4_nav.php
<style>
a:hover{
	color: white;
}
nav{
	text-align:center;
	background:olive;
}
</style>
<nav><a href="http://www2.nkfust.edu.tw/~shanhuen">Home</a>|<a href="http://www2.nkfust.edu.tw/~shanhuen/">map</a>|<a href="http://www2.nkfust.edu.tw/~shanhuen/">about</a></nav>

php4_4_js.php
<head>	
	<script>
		document.body.style.background="#31a1ff";
		document.body.style.color="white";
	</script>
</head>

<body>
<?php 
$name = $email = "";
$nameErr = $emailErr = "";

if ($_SERVER["REQUEST_METHOD"] == "POST") {
	if(empty($_POST["name"])){
		$nameErr = "必填";
	}else{
		$tempname = $_POST["name"];
		if(!preg_match("/^[a-zA-Z]+\d*/",$tempname)){
			$nameErr = "Only letters, number and white space, cannot use number&white space as prefix.";
		}else{
			$name = $tempname;
		}
	}
	if(empty($_POST["email"])){
		$emailErr = "必填";
	}else{
		$tempemail = $_POST["email"];
		$tempemail = filter_var($tempemail, FILTER_SANITIZE_EMAIL);
		if(!filter_var($tempemail, FILTER_VALIDATE_EMAIL)){
			$emailErr = "Invalid email format";
		}else{
			$email = $tempemail;
		}
	}
}
?>

<form method="post" action="php4_4_include.php">
	<label for="yourname" id="namelable">姓名:</label>
	<input type="text" name="name" id="yourname">
	<span style="color:red;"><sup>*</sup></span><?php echo $nameErr?><br><br>
	
	<label for="email">Email:</label>
	<input type="text" name="email" id="email">
	<span style="color:red;"><sup>*</sup></span><?php echo $emailErr?><br><br>
	
	<input type="submit"><input type="reset" id="reset">
</form>

<?php
echo "輸入資訊:<br>";
echo "姓名: ".$name."<br>";
echo "Email: ".$email."<br>";
?>

</body>

php4_4_footer.php
<style>
footer{
	text-align:center;
	background:green;
}

</style>
<footer>&copy;2018 Department of Logistics Management@NKUST<br>Last Updated: <span id="lastModifiedTime">2018.5.27</span>
</footer>
<script>
	var d = new Date(document.lastModified);
	document.getElementById("lastModifiedTime").innerHTML = (d.getMonth()+1)+"/"+d.getDate()+"/"+d.getFullYear();
</script>

php4_4_include.php
<head>
	<title>FORM Validation</title>
	<style>
		body{
			width:85%;
			margin:auto;
		}
	</style>
</head>
<body>
<?php require "php4_4_header.php"; ?>
<?php require_once "php4_4_nav.php"; ?>
<?php include "php4_4_js.php"; ?>
<?php include_once "php4_4_footer.php"; ?>
</body>

File System

在PHP可以進行檔案操作,包含開啟關閉讀取寫入等。

Open&Close File


使用fopen($filename, $mode)函數來開啟檔案並使用fclose($handle)函數來關閉檔案。
php4_5_fopen.php
<head>
	<title>Open&Close File</title>
</head>
<body>
<?php
$filename = "abc.txt";
if(!file_exists($filename)){
	$file = fopen($filename,"r");
	fclose($file);
}else{
	die("Error: $filename does not exist.");//echo("Error: $filename does not exist.");
}
?>
</body>

Directories
Parsing Directory Paths
  • basename(string path [, string suffix])->string: return filename component of a path。在路徑中取得檔案名。例如:
    <?php
    	$path = '/nkust/www/departments/student.txt';
    	print("Filename: ".basename($path)."<br>");
    	echo "Filename without extension: ".basename($path, '.txt')."<br>";
    ?>
  • dirname(string path)->string: providing the direcory component of a path.相對於basename(),dirname()傳回檔案名之前的路徑。
    <?php
    	$path = '/nkust/www/departments/student.txt';
    	echo "Directory path: ".dirname($path)."<br>";
    ?>
  • pathinfo(string path [, options])->array: 拆解path相關資訊。
    <?php
    	$path = '/nkust/www/departments/student.html';
    	$pathinfo = pathinfo($path);
    	echo "Dir name: ".$pathinfo['dirname']."<br>"; //  /nkust/www/departments
    	echo "Base name: ".$pathinfo['basename']."<br>"; // student.html
    	echo "Extension: ".$pathinfo['extension']."<br>"; // html
    	echo "File name: ".$pathinfo['filename']."<br>"; // student
    ?>
    options可以是PATHINFO_DIRNAME、PATHINFO_BASENAME、PATHINFO_EXTENSION、PATHINFO_FILENAME任一個來取得特定的資訊。
    <?php
    	$path = '/nkust/www/departments/student.html';
    	$pathinfo = pathinfo($path, PATHINFO_BASENAME); // PATHINFO_DIRNAME、PATHINFO_BASENAME、PATHINFO_EXTENSION、PATHINFO_FILENAME
    	echo $pathinfo;
    ?>
  • realpath(string path)->string:取得檔案的絕對路徑。
    <?php
    	$path = '../../nkfust/abc.txt';
    	$absolutePath = realpath($path);
    	echo $absolutePath; // 得到絕對路徑 C:\nkfust\abc.txt
    ?>
Calculate File and Disk Sizes
Calculate Sizes:
  • filesize(string filename)->int: returns the size in bytes of a specified file.
    <?php
    	$file = '../../nkfust/Travel.exe';
    	$size = filesize($file);
    	$kilo = round($size/1024, 2);
    	echo "Size of file ".basename($file)." is ".$size." bytes or ".$kilo." KB.<br>";
    ?>
  • disk_free_space(string directory)->float:傳回可用空間。
    <?php
    	$drive = '.'; // current directory, also try C:/, D:/ and so on.
    	$space = disk_free_space($drive);
    	$mb = round($space/1048576, 2);
    	$gb = round($mb/1024, 2);
    	echo "Free space of Drive ".$drive." is ".$mb." MB or ".$gb." GB.<br>";
    ?>
  • disk_total_space(string directory)->float:計算disk size。
    <?php
    	$drive = '.'; // current directory, also try C:/, D:/ and so on.
    	$space = disk_total_space($drive);
    	$mb = round($space/1048576, 2);
    	$gb = round($mb/1024, 2);
    	echo "Total space of Drive ".$drive." is ".$mb." MB or ".$gb." GB.<br>";
    ?>

Read File


讀取檔案有多種方式,條列如下:
fread()
    使用fread(resource $handle, int $length)->string讀取文件。
<?php
	$filename = "abc.txt";
	if(file_exists($filename)){
		$file = fopen($filename, 'r');
		$content = fread($file, filesize($filename));
		echo $content;
		fclose($file);
	}else{
		echo "File does not exist.";
	}
?>
fgets()
    使用fgets(resource $handle, int $length = ?)-> string從文件中讀取一行。
<head>
	<title>Read a File</title>
</head>
<body>
<?php
$filename = "abc.txt";
if(file_exists($filename)){
	$file = fopen($filename,"r");
	//echo fread($file, filesize($filename));
	while(!feof($file)){
		echo fgets($file)."<br>";
	}
	fclose($file);
}else{
	exit("Error: $filename does not exist.");//echo("Error: $filename does not exist.");
}
?>
</body>
    若是直接讀取所有內容印出,會全部擠在一行(filesize($filename)可以得到檔案的大小)。因此使用while來一行一行讀取並換行。
    feof()可判斷是否到達end of file,fgets可在file point讀取一行。
readfile()
    使用readfile($filename)函數讀取檔案內容連open都不需要,讀取後會直接將內容印出,若想顯示換行,可使用<pre>標籤。

    php4_5_readfile.php
<head>
	<title>Read a File</title>
</head>
<body>
<?php
$filename = "abc.txt";
if(file_exists($filename)){
	echo("<pre>");
	readfile($filename);
	echo("</pre>");
}else{
	exit("Error: $filename does not exist.");
}
?>
</body>
file_get_contents()
    使用file_get_contents($filename)函數讀取檔案內容,傳回字串。可用nl2br()函數在每行之前插入<br>,或是使用字串函數str_replace()將\n換成<br>來換行。

    php4_5_fileGetContents.php
<head>
	<title>Read a File</title>
</head>
<body>
<?php
$filename = "abc.txt";
if(file_exists($filename)){
	$content = nl2br(file_get_contents($filename));
	//$content = str_replace("\n","<br>",$content);
	echo $content;
}else{
	exit("Error: $filename does not exist.");
}
?>
</body>
file()
    使用file($filename)函數讀取檔案內容,傳回Array。可用foreach來換行。

    php4_5_file.php
<head>
	<title>Read a File</title>
</head>
<body>
<?php
$filename = "abc.txt";
if(file_exists($filename)){
	$content = file($filename);
	foreach($content as $line){
		echo $line."<br>";
	}
}else{
	exit("Error: $filename does not exist.");
}
?>
</body>
fgetcsv()
    使用fgetcsv(resource handle [, int length [, string delimiter [, string enclosure]]])函數讀取csv format檔案(通常資料用逗點(,)分隔),傳回Array。

    php4_5_file.php
<?php
	$filename = "test.csv";
	$file = fopen($filename, 'r');
	while(list($name, $email, $phone) = fgetcsv($file, 1024, ',')){
		echo "<p>{$name}, {$email}, {$phone}</p>";
	}
?>
另一個方式是先使用file()讀進資料,然後再使用explode()逐行parse資料,如下:
<?php
	$filename = "test.csv";
	$data = file($filename);
	foreach($data as $value){
		list($name, $email, $phone) = explode(',', $value);
		printf("<p>%s (%s) Tel. %s</p>",$name, $email, $phone);
	}
?>
File's Time
我們可以取得檔案最後一次被使用、修改的時間。使用
  • access time: fileatime(string filename)、
  • change time: filectime(string filename)、
  • modify time: filemtime(string filename)。
<?php
	$file = "..\\..\\nkfust\\abc.txt";
	date_default_timezone_set('Asia/Taipei'); // 設定時區
	$time = date("m-d-Y g:i:sa", fileatime($file)); // 取得時間(根據指定的時區)並轉換格式
	echo "Last accessed time of ".basename($file)." is ".$time.".<br>";
?>

Write to a File


使用fwrite($file, $string)函數將$string寫入$filename。
php4_5_fwrite.php
<head>
	<title>Write to a File</title>
</head>
<body>
<?php
	$filename = "abc.txt";
	//Write to
	$openFile = fopen($filename, 'w');
	fwrite($openFile, 'Write something...'.PHP_EOL.'Write more...'.PHP_EOL.'And more'.PHP_EOL);
	fwrite($openFile, 'Write something2...'.PHP_EOL.'Write more2...'.PHP_EOL.'And more2');
	fclose($openFile);
	//Read & Print
	$file = fopen($filename,"r");
	while(!feof($file)){
		echo fgets($file)."<br>";
	}
	fclose($file);
?>
</body>
其他寫入檔案方法:

Rename&Remove File


使用rename($oldname, $newname)來將檔案改名,使用unlink($filename)來刪除檔案。

php4_5_fileRename.php
<head>
	<title>Write to a File</title>
</head>
<body>
<?php
	$filename = "abc.txt";
	$newfilename = "zzz.txt";
	//$newfilename = "E:\Temp\zzz.txt";
	if(file_exists($filename)){
		if(rename($filename, $newfilename)){
			echo("Rename successfully.<br>");
		}else{
			echo("Rename failed.");
		}
	}else{
		exit("Error: File does not exist.");
	}
	//Read & Print
	$content = nl2br(file_get_contents($newfilename));
	echo $content;
?>
</body>



php4_5_unlink.php
<head>
	<title>Write to a File</title>
</head>
<body>
<?php
	$filename = "E:\Temp\zzz.txt";
	if(file_exists($filename)){
		if(unlink($filename)){
			echo("delete file successfully.<br>");
		}else{
			echo("Delete file failed.");
		}
	}else{
		exit("Error: File does not exist.");
	}
?>
</body>

Upload & Download files

資料傳輸當然包含檔案的傳輸,可以上傳檔案到伺服器也可以自伺服器下載檔案。

Upload File



php4_6_fileUpload.php
<head>
	<title>Upload a File</title>
</head>
<body>
	<form action="fileupload.php" method="post" enctype="multipart/form-data">
	<label for="fileSelect">Filename:</label>
	<input type="file" name="uploadfile" id="fileSelect">
	<input type="submit" name="submit" value="Upload">
	</form>
</body>

fileupload.php
<?php
	if($_FILES["uploadfile"]["error"] > 0){
		echo "Error: " .$_FILES["uploadfile"]["error"]. "<br>";
	}else{
		echo "File name: ".$_FILES["uploadfile"]["name"]."<br>";
		echo "File type: ".$_FILES["uploadfile"]["type"]."<br>";
		echo "File size: ".$_FILES["uploadfile"]["size"]."<br>";
		echo "File is in: ".$_FILES["uploadfile"]["tmp_name"]."<br>";
	}
?>
將fileupload.php檔案修改如下:
fileupload.php
<?php
	if($_SERVER["REQUEST_METHOD"]=="POST"){
		if(isset($_FILES["uploadfile"]) && $_FILES["uploadfile"]["error"]==0){
			$filename=$_FILES["uploadfile"]["name"];
			$filetype=$_FILES["uploadfile"]["type"];
			$filesize=$_FILES["uploadfile"]["size"];
			
			$targetFile = "upload/".basename($filename);
			if(file_exists($targetFile))
				die("$targetFile already exists.");
				
			$maxsize = 5*1024*1024;
			if($filesize > $maxsize)
				exit("Error: File size exceeds the max size.");
			
			move_uploaded_file($_FILES["uploadfile"]["tmp_name"],"upload/".$filename);
			echo "Upload successfully.";
		}else{
			echo "Error: Something wrong. Please try again.";
		}
	}
?>

Download File


下載檔案只需要使用html的標籤a即可。
php3_4_time.php
<head>
	<title>Download a File</title>
</head>
<body>
	<a href="hello.php">Download hello.php</a>
</body>

Cookies & Sessions

Cookies是一個文字檔,允許我們儲存小量資料(約莫4KB)在使用者的電腦。Sessions則是儲存在伺服器。

Cookies


欲使用cookie,需先使用setcookie($name[, $value[, $expire[, $path[, $domain[, $secure[, $httponly]]]]]])函數設定,否則無法送出cookie。
php4_7_cookies.php
<head>
	<title>Cookies</title>
</head>
<body>
	<?php
		setcookie("username","多啦A夢", time()+5*60);
		if(isset($_COOKIE["username"])){
			echo "Welcome ".$_COOKIE["username"]."<br>";
		}else{
			echo "Hi, there.<br>";
		}
		print_r($_COOKIE);
		//setcookie("username", "", time()-5*60);
	?>
</body>

Sessions


Session會將資料儲存在伺服器,如此可以避免如cookie每次都要將資料先傳回,此外安全性也較高。要使用session需先使用session_start()函數來建立新的session,並同時為使用者產生一個唯一的id。
php3_4_time.php
<head>
	<title>Cookies</title>
</head>
<body>
	<?php
		session_start();
		$_SESSION["name"] = "Tom";
		$_SESSION["occupation"] = "Warrior";
		echo "Greeting...<span style='color:red;'>".$_SESSION["occupation"]."</span> ".$_SESSION["name"]."<br>";
		print_r($_SESSION);
		//session_destroy();
	?>
</body>

Object

設計class來產生物件。
php5_1_class.php
<head>
	<title>Create a class</title>
</head>
<body>
	<?php
		class Circle{
			public $radius; // attributes
			public function __construct($r){
				$this->radius = $r;
				echo __CLASS__." was initiated.<br>";
			}
			public function __destruct(){
				echo __CLASS__." was destroyed.<br>";
			}
			public function cArea(){
				return ($this->radius * $this->radius * pi()."<br>");
			}
		}
		$cir = new Circle(10);
		echo($cir->cArea());
		$cir->radius = 20;
		echo($cir->cArea());
	?>
</body>

Cloning an object
已知若是使用instanceB = instanceA,原則上兩者指位至同一個位址,若是要複製成一個新的物件,可以使用clone。
<?php
	class One{
		public $v;
		public $arr = [1,2,3,4,5];
		public function __construct($v){
			$this->v = $v;
		}
		public function __destruct(){
			echo __CLASS__." was destroyed.<br>";
		}
		public function __toString(){
			print_r($this->arr);
			echo "<br>";
			return "value = {$this->v}<br>";
		}
	}
	
	$one = new One("one");
	echo $one;
	
	$two = clone $one; // clone
	$two->v = "two";
	$two->arr[0] = 100; // 修改two的內容
	echo $one;
	echo $two; // 與one中的值不同
?>
我們可以在class內實作__clone()方法,當使用clone時,會直接執行此方法。
<?php
	class One{
		public $v;
		public $arr = [1,2,3,4,5];
		public function __construct($v){
			$this->v = $v;
		}
		public function __destruct(){
			echo __CLASS__." was destroyed.<br>";
		}
		public function __clone(){
			$this->v = "no name";
			$this->arr = [0,0,0,0,0];
		}
		public function __toString(){
			print_r($this->arr);
			echo "<br>";
			return "value = {$this->v}<br>";
		}
	}
	
	$one = new One("one");
	echo $one;

	$two = clone $one; // clone
	$two->arr[0] = 100; // 修改two的內容
	echo $one; // Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 ) 
	echo $two; // Array ( [0] => 100 [1] => 0 [2] => 0 [3] => 0 [4] => 0 ) 
?>

static


當變數或方法使用static關鍵字修飾時,不需要產生(new)物件(instance)便可取得變數或使用方法。
php3_4_time.php
<head>
	<title>Static variable & Method</title>
</head>
<body>
	<?php
		class Circle{
			public static $radius; // attributes

			public static function cArea(){
				return (self::$radius * self::$radius * pi()."<br>");
			}
		}
		Circle::$radius = 100;
		echo Circle::cArea();
		// initiate 
		$cir = new Circle(10);
		$cir->radius = 20;//Warning
		echo($cir->cArea());
	?>
</body>
static變數可以記憶其值即使函數結束,例如:
<?php
	function staticVar(){
		static $v = 0;
		echo $v."<br>";
		$v++;
	}
	staticVar(); // 0
	staticVar(); // 1
	staticVar(); // 2
?>

trait


trait是一組函數,可以用來加入到某物件內。
<?php
	trait someFuns{
		public function printSomething(){
			echo 'something<br>';
		}
		public function circle($r){
			return M_PI*$r*$r;
		}
	}

	class AClass{
		use someFuns;
	}

	$ac = new AClass();
	$ac->printSomething();
	echo $ac->circle(10);
?>

Inheritance

class可以繼承,使用關鍵字extends。
php5_2_inheritance.php
<head>
	<title>Static variable & Method</title>
</head>
<body>
	<?php
		class Ellipse{
			public $radiusA;
			public $radiusB;
			public function __construct($a, $b){
				$this->radiusA = $a;
				$this->radiusB = $b;
				echo __CLASS__." was initiated.<br>";
			}
			public function __destruct(){
				echo __CLASS__." was destroyed.<br>";
			}
			public function eArea(){
				return ($this->radiusA * $this->radiusB * pi()."<br>");
			}
		}
		
		class Circle extends Ellipse{
			public function isCircle(){
				if($this->radiusA == $this->radiusB)
					return true;
				else
					return false;
			}
		}
		
		$cir = new Circle(10,10);
		echo $cir->isCircle()?"圓形<br>":"橢圓形<br>";
		echo $cir->eArea();
	?>
</body>

Inheritance of static variable
如果繼承時包含static變數或方法。
<?php
	class Super{
		static $value = "super";
		public static function getValue(){
			return self::$value;
		}
	}
	class Sub extends Super{
		static $value = "sub";
	}
	echo Sub::getValue(); // super
?>
  • self用於參照目前的class($this用於參照目前的物件(instance)),而self可用於static,$this則不行(因為沒有instance)。
上例中當呼叫getValue()時,得到的是super。若是要得到sub的value,則不可使用self,應使用關鍵字static,稱為late static bindings(PHP 5.3)。
<?php
	class Super{
		protected static $value = "super";
		public static function getValue(){
			return static::$value;
		}
	}
	class Sub extends Super{
		protected static $value = "sub";
	}
	echo Sub::getValue(); // sub
?>

Visibility


php5_3_visibility.php
<head>
	<title>Visibility of variable & Method</title>
</head>
<body>
	<?php
		class Ellipse{
			private $radiusA;
			protected $radiusB;
			public function __construct($a = 1, $b = 1){
				$this->radiusA = $a;
				$this->radiusB = $b;
				echo __CLASS__." was initiated.<br>";
			}
			public function __destruct(){
				echo __CLASS__." was destroyed.<br>";
			}
			
			public function setA($a){
				$this->radiusA = $a;
			}
			
			public function getA(){
				return $this->radiusA;
			}
			
			public function setB($b){
				$this->radiusB = $b;
			}
			
			public function getB(){
				return $this->radiusB;
			}
			
			public function eArea(){
				return ($this->radiusA * $this->radiusB * pi()."<br>");
			}
		}
		
		class Circle extends Ellipse{
			public function isCircle(){
				if($this->radiusA == $this->radiusB){
					echo "radiusA = ".$this->radiusA."<br>";
					echo "radiusB = ".$this->radiusB."<br>";
					return true;
				}else{
					echo "radiusA = ".$this->radiusA."<br>";
					echo "radiusB = ".$this->radiusB."<br>";
					return false;
				}
			}
		}
		
		$ell = new Ellipse();
		$ell->setA(10);
		$ell->setB(10);
		echo $ell->eArea();
		//echo $ell->radiusB; //Fatal error
		
		$cir = new Circle(100,100);
		echo $cir->isCircle()?"圓形<br>":"橢圓形<br>";//Notice: Undefined property
		echo $cir->eArea();
	?>
</body>

Magic Constants

Magic Constants是PHP內建的常數變數,會隨著出現位置有不同的值。其前後各有兩個底線。 php5_4_magicConstants.php
<head>
	<title>Magic Constants</title>
</head>
<body>
	<?php
		echo "Line number = ".__LINE__."<br>";
		echo "File path = ".__FILE__."<br>";
		echo "Directory = ".__DIR__."<br>";
		function fun(){
			echo "Function name = ".__FUNCTION__."<br>";
		}
		fun();
		class Ellipse{
			public $radiusA;
			public $radiusB;
			function __construct($a = 1, $b = 1){
				$this->radiusA = $a;
				$this->radiusB = $b;
				echo __CLASS__." was initiated.<br>";
			}
			function __destruct(){
				echo __CLASS__." was destroyed.<br>";
			}
			function eArea(){
				echo "Class name = ".__CLASS__."<br>";
				echo "Method name = ".__METHOD__."<br>";
				echo "Name Space = ".__NAMESPACE__."<br>";
				return ("橢圓形面積 = ".$this->radiusA * $this->radiusB * pi()."<br>");
			}
		}
		$ell = new Ellipse(10,10);
		echo $ell->eArea();
	?>
</body>

Namespace example
使用{}來區分namespace範圍。
<?php
	namespace ns
	{
		class One{
			public $var;
			public function __construct($var){
				$this->var = $var;
				echo __CLASS__." was initiated.<br>";
			}
			public function __destruct(){
				echo __CLASS__." was destroyed.<br>";
			}
			public function __toString(){
				return "Value = {$this->var}<br>";
			}
		}
	}

	namespace we{
		class One{
			public $var;
			public function __construct($var){
				$this->var = $var;
				echo __CLASS__." was initiated.<br>";
			}
			public function __destruct(){
				echo __CLASS__." was destroyed.<br>";
			}
			public function __toString(){
				return "Value = {$this->var}<br>";
			}
		}
	}
	// Global namespace
	namespace{
	
		$nsone = new ns\One(1);
		echo $nsone;
		$weone = new we\One(2);
		echo $weone;

	}
?>
如果定義在不同檔案,可以使用分號(;)代替大括號,這樣還是最好一個檔案定義一個namespace。

Magic Methods

相對於magic constants,PHP還提供數個Magic methods,如下: 有些已介紹過,此處擇要介紹。

__call()表示在沒有得呼叫的情況下,呼叫__call()函數,可視為預設函數。如下例中呼叫了沒有定義的物件方法以及private method,此時都只好呼叫__call()。
<?php
	class ToCall{
		public function __call($name, $arguments){
			echo "'{$name}' is not existed.<br>";
			print_r($arguments);
			echo "<br>";
		}

		private function pri(){
			echo "A private function";
		}
	}
	$tc = new ToCall();
	$tc->onemethod(1,2,3); // 呼叫不存在的方法
	$tc->pri(123); // 呼叫private方法
?>
如果有些程式碼是每一個函數都需要執行的,那麼可以如此應用:
<?php
	class ToCall{
		public function __call($method, $arguments){
			echo "Hello<br>";
			call_user_func_array(array($this, $method), $arguments);
			echo "See ya.<br>";
		}

		private function pri(){
			echo "A private function<br>";
		}

		private function pri2(){
			echo "A private function 2<br>";
		}
	}
	$tc = new ToCall();
	$tc->pri(); // 呼叫private方法
	$tc->pri2(); // 呼叫private方法
?>


Overloading讓我們可以在執行時(run-time)增加物件成員,需要實現overloading方法,包含__get, __set, __call, 以及__callStatic等。下例中同時測試isset()、unset()、empty()等方法。
<?php
	class One{
		private $data = array();
		public $var = 1;

		public function __call($name, $args){
			$ar = "";
			if ($args <> array()){
				for($i=0; $i<count($args); $i++){
					if($i==0){
						$ar = "{$args[$i]}";
					}else{
						$ar = "{$ar}, {$args[$i]}";
					}
				}
			}
			echo "Warning: calling $name($ar)";
		}

		// __callStatic()必須為static method
		public static function __callStatic($name, $args){
			$ar = "";
			if ($args <> array()){
				for($i=0; $i<count($args); $i++){
					if($i==0){
						$ar = "{$args[$i]}";
					}else{
						$ar = "{$ar}, {$args[$i]}";
					}
				}
			}
			echo "Warning: calling static $name($ar)";
		} // __callStatic

		public function __set($name, $value){
			$this->data[$name] = $value; // 將資料加入到$data,類似dict(python)
		} // set

		public function __get($name){
			if (array_key_exists($name, $this->data)){ // check if $name in $this->data
				return $this->data[$name];
			}
		} // get

	} // One
	$one = new One();
	$one->a = 1; // call set
	echo $one->a; // call get
	$one->two(1, 2, 3);
	One::three('x', 'y', 'z');
	// 判斷變數是否存在(isset)或是否值為空(empty)
	echo isset($one->var)? "Set":"Not set";
	echo empty($one->var)? "Empty":"Not empty";
	unset($one->var); // unset() destroys the specified variables. return void.
	echo isset($one->var)? "Set":"Not set";
?>

MySQL Introduction

MySQL是一種relational資料庫,當安裝XAMPP時也同時安裝,可以直接使用。使用前先打開XAMPP Control Panel並點選MySQL的Start。


php6_1_mysqlConnection.php
<head>
	<title>MySQL Connection</title>
</head>
<body>
	<?php
		$link = mysqli_connect("localhost", "root", "");
		//$link = new mysqli("127.0.0.1", "root", "");
		if($link === false){
			die("Error: Could not connect.".mysqli_connect_error());
		}
		echo "Connect successfully.".mysqli_get_host_info($link);
		mysqli_close($link);
	?>
</body>

Database

連結資料庫後可以建立一個database,使用sql的CREATE DATABASE語法。
php3_4_time.php
<head>
	<title>MySQL Create Database</title>
</head>
<body>
	<?php
		$link = mysqli_connect("127.0.0.1", "root", "");
		if($link === false){
			die("Error: Could not connect.".mysqli_connect_error());
		}
		$sql = "CREATE DATABASE test";
		if(mysqli_query($link, $sql)){
			echo "Database created successfully.";
		}else{
			echo("Error: Could not execute $sql.".mysqli_error($link));
		}
		mysqli_close($link);
	?>
</body>

Create Table


建立了database之後,可以在其內建立table,用以儲存資料,可使用sql的CREATE TABLE語法。
php6_2_createTable.php
<head>
	<title>MySQL Create Table</title>
</head>
<body>
	<?php
		$link = mysqli_connect("127.0.0.1", "root", "", "test");
		if($link === false){
			die("Error: Could not connect.".mysqli_connect_error());
		}
		$sql = "CREATE TABLE characters(
			id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
			name VARCHAR(50) NOT NULL UNIQUE,
			race VARCHAR(50) NOT NULL,
			occupation VARCHAR(50) NOT NULL,
			level INT NOT NULL
		)";
		//$sql = "DROP TABLE characters";
		if(mysqli_query($link, $sql)){
			echo "Table created successfully.";
		}else{
			echo("Error: Could not execute $sql.".mysqli_error($link));
		}
		mysqli_close($link);
	?>
</body>

Insert

有了table之後便可以開始加入資料,使用sql的INSERT INTO語法。



php6_3_insert.php
<head>
	<title>MySQL Create Database</title>
</head>
<body>
	<?php
		$link = mysqli_connect("127.0.0.1", "root", "", "test");
		if($link === false){
			die("Error: Could not connect.".mysqli_connect_error());
		}
		$sql = "INSERT INTO characters(name, race, occupation, level) VALUES ('Tom', 'Human', 'Warrior', 1)";
		if(mysqli_query($link, $sql)){
			echo "Database created successfully.";
		}else{
			echo("Error: Could not execute $sql.".mysqli_error($link));
		}
		$sql = "INSERT INTO characters(name, race, occupation, level) VALUES ('John', 'Dwarf', 'Hunter', 2),('Mary', 'Elf', 'Mage', 5),('Lance', 'Human', 'Priest', 7)";
		if(mysqli_query($link, $sql)){
			echo "Database created successfully.";
		}else{
			echo("Error: Could not execute $sql.".mysqli_error($link));
		}
		$sql = "SELECT * FROM characters";
		if($result = mysqli_query($link, $sql)){
			if(mysqli_num_rows($result) > 0){
				echo "<table><tr>";
					echo "<th>Id</th><th>Name</th><th>Race</th><th>Occupation</th><th>Level</th>";
				echo "</tr>";
				while($row = mysqli_fetch_array($result)){
					echo "<tr>";
						echo "<td>".$row['id']."</td>";
						echo "<td>".$row['name']."</td>";
						echo "<td>".$row['race']."</td>";
						echo "<td>".$row['occupation']."</td>";
						echo "<td>".$row['level']."</td>";
					echo "</tr>";
				}
				echo "</table>";
				mysqli_free_result($result);//Free result set
			}else{
				echo "No records matched.";
			}
		}else{
			echo "Error: Could not execute $sql.".mysqli_error($link);
		}
		mysqli_close($link);
	?>
</body>

INSERT FORM


當然希望可以從網頁讓使用者輸入資料然後儲存到資料庫,所以需要設計輸入表單。
php6_3_insertForm.php
<head>
	<title>MySQL Insert Form</title>
</head>
<body>
	<form action="php6_3_formInsertion.php" method = "post">
		<p>
			<label for="name">Name:</label>
			<input type="text" name="name" id="name">
		</p>
		<p>
			<label for="race">Race:</label>
			<input type="text" name="race" id="race">
		</p>
		<p>
			<label for="name">Occupation:</label>
			<input type="text" name="occupation" id="occupation">
		</p>
		<p>
			<label for="name">Level:</label>
			<input type="text" name="level" id="level">
		</p>
		<input type="submit" value="Add">
	</form>
</body>

然後設計對應的php檔案來處理輸入。

php6_3_formInsertion.php
<?php
	$link = mysqli_connect("127.0.0.1", "root", "", "test");
	if($link === false){
		die("Error: Could not connect.".mysqli_connect_error());
	}
	$name = mysqli_real_escape_string($link, $_REQUEST['name']);
	$race = mysqli_real_escape_string($link, $_REQUEST['race']);
	$occupation = mysqli_real_escape_string($link, $_REQUEST['occupation']);
	$level = mysqli_real_escape_string($link, $_REQUEST['level']);
	//echo "$name  $race  $occupation $level<br>";
	$sql = "INSERT INTO characters(name, race, occupation, level) VALUES ('$name', '$race', '$occupation', '$level')";
	if(mysqli_query($link, $sql)){
		$last_id = mysqli_insert_id($link);
		echo "Record inserted successfully and inserted ID is ".$last_id;
	}else{
		echo("Error: Could not execute $sql.".mysqli_error($link));
	}
	
	$sql = "SELECT * FROM characters";
	if($result = mysqli_query($link, $sql)){
		if(mysqli_num_rows($result) > 0){
			echo "<table style='border:1px solid gold;'><tr>";
				echo "<th style='border:1px solid red;'>Id</th><th style='border:1px solid red;'>Name</th><th style='border:1px solid red;'>Race</th><th style='border:1px solid red;'>Occupation</th><th style='border:1px solid red;'>Level</th>";
			echo "</tr>";
			while($row = mysqli_fetch_array($result)){
				echo "<tr style='border:1px solid red;'>";
					echo "<td  style='border:1px solid blue;'>".$row['id']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['name']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['race']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['occupation']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['level']."</td>";
				echo "</tr>";
			}
			echo "</table>";
			mysqli_free_result($result);//Free result set
		}else{
			echo "No records matched.";
		}
	}else{
		echo "Error: Could not execute $sql.".mysqli_error($link);
	}
	mysqli_close($link);
?>

Prepared Statement


Prepared Statement是先將要輸入的資料格式準備好,然後再根據格式加入資料的方式。
php6_3_prepared.php
<?php
	$link = mysqli_connect("127.0.0.1", "root", "", "test");
	if($link === false){
		die("Error: Could not connect.".mysqli_connect_error());
	}
	
	//echo "$name  $race  $occupation $level<br>";
	$sql = "INSERT INTO characters(name, race, occupation, level) VALUES (?, ?, ?, ?)";
	if($stmt = mysqli_prepare($link, $sql)){
		mysqli_stmt_bind_param($stmt, "sssi", $name, $race, $occupation, $level);
		$name = $_REQUEST['name'];
		$race = $_REQUEST['race'];
		$occupation = $_REQUEST['occupation'];
		$level = $_REQUEST['level'];
		
		if(mysqli_stmt_execute($stmt)){
			echo "Insert successfully";
		}else{
			echo "Error: Could not execute query: $sql. ". mysqli_error($link);
		}
	}else{
		echo("Error: Could not prepare query: $sql. ".mysqli_error($link));
	}
	// to show all the data in the table characters
	$sql = "SELECT * FROM characters";
	if($result = mysqli_query($link, $sql)){
		if(mysqli_num_rows($result) > 0){
			echo "<table style='border:1px solid gold;'><tr>";
				echo "<th style='border:1px solid red;'>Id</th><th style='border:1px solid red;'>Name</th><th style='border:1px solid red;'>Race</th><th style='border:1px solid red;'>Occupation</th><th style='border:1px solid red;'>Level</th>";
			echo "</tr>";
			while($row = mysqli_fetch_array($result)){
				echo "<tr style='border:1px solid red;'>";
					echo "<td  style='border:1px solid blue;'>".$row['id']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['name']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['race']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['occupation']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['level']."</td>";
				echo "</tr>";
			}
			echo "</table>";
			mysqli_free_result($result);//Free result set
		}else{
			echo "No records matched.";
		}
	}else{
		echo "Error: Could not execute $sql.".mysqli_error($link);
	}
	mysqli_close($link);
?>

Select, Where, Limit & Order by

之前已經使用過SELECT * FROM characters的sql語法來選擇table characters內的所有資料,使用關鍵字SELECT選擇,*號表示所有。若是要使用其他條件來篩選資料,可使用關鍵字WHERE,若是要限制產生數量,則使用關鍵字LIMIT
php6_5_select.php
<?php
	$link = mysqli_connect("127.0.0.1", "root", "", "test");
	if($link === false){
		die("Error: Could not connect.".mysqli_connect_error());
	}
		
	$sql = "SELECT * FROM characters WHERE race='Human' ORDER BY level DESC LIMIT 1, 3 ";
	if($result = mysqli_query($link, $sql)){
		if(mysqli_num_rows($result) > 0){
			echo "<table style='border:1px solid gold;'><tr>";
				echo "<th style='border:1px solid red;'>Id</th><th style='border:1px solid red;'>Name</th><th style='border:1px solid red;'>Race</th><th style='border:1px solid red;'>Occupation</th><th style='border:1px solid red;'>Level</th>";
			echo "</tr>";
			while($row = mysqli_fetch_array($result)){
				echo "<tr style='border:1px solid red;'>";
					echo "<td  style='border:1px solid blue;'>".$row['id']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['name']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['race']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['occupation']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['level']."</td>";
				echo "</tr>";
			}
			echo "</table>";
			mysqli_free_result($result);//Free result set
		}else{
			echo "No records matched.";
		}
	}else{
		echo "Error: Could not execute $sql.".mysqli_error($link);
	}
	mysqli_close($link);
?>

And & Or



php6_5_selectAndOr.php
<?php
	$link = mysqli_connect("127.0.0.1", "root", "", "test");
	if($link === false){
		die("Error: Could not connect.".mysqli_connect_error());
	}
	//$sql = "SELECT * FROM characters WHERE race='Human' OR occupation = 'Warrior' OR level < 10" ;
	$sql = "SELECT * FROM characters WHERE occupation IN ('Warrior','Mage','Priest') AND level BETWEEN 6 AND 10" ;//name BETWEEN 'A' AND 'Z'
	if($result = mysqli_query($link, $sql)){
		if(mysqli_num_rows($result) > 0){
			echo "<table style='border:1px solid gold;'>";
				echo "<tr>";
					echo "<th style='border:1px solid red;'>Id</th>";
					echo "<th style='border:1px solid red;'>Name</th>";
					echo "<th style='border:1px solid red;'>Race</th>";
					echo "<th style='border:1px solid red;'>Occupation</th>";
					echo "<th style='border:1px solid red;'>Level</th>";
				echo "</tr>";
			while($row = mysqli_fetch_array($result)){
				echo "<tr style='border:1px solid red;'>";
					echo "<td  style='border:1px solid blue;'>".$row['id']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['name']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['race']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['occupation']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['level']."</td>";
				echo "</tr>";
			}
			echo "</table>";
			mysqli_free_result($result);//Free result set
		}else{
			echo "No records matched.";
		}
	}else{
		echo "Error: Could not execute $sql.".mysqli_error($link);
	}
	mysqli_close($link);
?>

Update & Delete

使用UPDATE關鍵字來更新資料,使用DELETE關鍵字來刪除資料。

UPDATE



php6_6_update.php
<?php
	$link = mysqli_connect("127.0.0.1", "root", "", "test");
	if($link === false){
		die("Error: Could not connect.".mysqli_connect_error());
	}
		
	$sql = "UPDATE characters SET occupation='Priest' WHERE name='Alex'";
	if(mysqli_query($link, $sql)){
		echo "Updated successfully";
	}else{
		echo "Error: Could not execute $sql. ".mysqli_error($link);
	}
	
	$sql = "SELECT * FROM characters ORDER BY occupation";
	if($result = mysqli_query($link, $sql)){
		if(mysqli_num_rows($result) > 0){
			echo "<table style='border:1px solid gold;'>";
			echo "<tr>";
				echo "<th style='border:1px solid red;'>Id</th>";
				echo "<th style='border:1px solid red;'>Name</th>";
				echo "<th style='border:1px solid red;'>Race</th>";
				echo "<th style='border:1px solid red;'>Occupation</th>";
				echo "<th style='border:1px solid red;'>Level</th>";
			echo "</tr>";
			while($row = mysqli_fetch_array($result)){
				echo "<tr style='border:1px solid red;'>";
					echo "<td  style='border:1px solid blue;'>".$row['id']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['name']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['race']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['occupation']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['level']."</td>";
				echo "</tr>";
			}
			echo "</table>";
			mysqli_free_result($result);//Free result set
		}else{
			echo "No records matched.";
		}
	}else{
		echo "Error: Could not execute $sql.".mysqli_error($link);
	}
	mysqli_close($link);
?>

DELETE



php6_6_delete.php
<?php
	$link = mysqli_connect("127.0.0.1", "root", "", "test");
	if($link === false){
		die("Error: Could not connect.".mysqli_connect_error());
	}
		
	$sql = "DELETE FROM characters WHERE id=11";
	if(mysqli_query($link, $sql)){
		echo "Delete data successfully";
	}else{
		echo "Error: Could not execute $sql. ".mysqli_error($link);
	}
	
	$sql = "SELECT * FROM characters";
	if($result = mysqli_query($link, $sql)){
		if(mysqli_num_rows($result) > 0){
			echo "<table style='border:1px solid gold;'>";
				echo "<tr>";
					echo "<th style='border:1px solid red;'>Id</th>";
					echo "<th style='border:1px solid red;'>Name</th>";
					echo "<th style='border:1px solid red;'>Race</th>";
					echo "<th style='border:1px solid red;'>Occupation</th>";
					echo "<th style='border:1px solid red;'>Level</th>";
				echo "</tr>";
			while($row = mysqli_fetch_array($result)){
				echo "<tr style='border:1px solid red;'>";
					echo "<td  style='border:1px solid blue;'>".$row['id']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['name']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['race']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['occupation']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['level']."</td>";
				echo "</tr>";
			}
			echo "</table>";
			mysqli_free_result($result);//Free result set
		}else{
			echo "No records matched.";
		}
	}else{
		echo "Error: Could not execute $sql.".mysqli_error($link);
	}
	mysqli_close($link);
?>

Alter


若是要改變欄位,可以使用關鍵字ALTER
php6_6_alter.php
<?php
	$link = mysqli_connect("127.0.0.1", "root", "", "test");
	if($link === false){
		die("Error: Could not connect.".mysqli_connect_error());
	}
	$sql = "ALTER TABLE characters ADD camp VARCHAR(30) DEFAULT 'Alliance'" ;
	if(mysqli_query($link, $sql)){
		echo "Alter successfully";
	}else{
		echo "Could not alter.";
	}
	$sql = "SELECT * FROM characters" ;
	if($result = mysqli_query($link, $sql)){
		if(mysqli_num_rows($result) > 0){
			echo "<table style='border:1px solid gold;'>";
				echo "<tr>";
					echo "<th style='border:1px solid red;'>Id</th>";
					echo "<th style='border:1px solid red;'>Name</th>";
					echo "<th style='border:1px solid red;'>Race</th>";
					echo "<th style='border:1px solid red;'>Occupation</th>";
					echo "<th style='border:1px solid red;'>Level</th>";
					echo "<th style='border:1px solid red;'>Camp</th>";
				echo "</tr>";
			while($row = mysqli_fetch_array($result)){
				echo "<tr style='border:1px solid red;'>";
					echo "<td  style='border:1px solid blue;'>".$row['id']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['name']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['race']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['occupation']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['level']."</td>";
					echo "<td  style='border:1px solid blue;'>".$row['camp']."</td>";
				echo "</tr>";
			}
			echo "</table>";
			mysqli_free_result($result);//Free result set
		}else{
			echo "No records matched.";
		}
	}else{
		echo "Error: Could not execute $sql.".mysqli_error($link);
	}
	mysqli_close($link);
?>

其他語法

假設我們已經建立了一個名為test的資料庫(Database),在hello.php其中建立一個名為players的table,並接受來自index.php中表格的數值,將資料加入到資料庫內。
hello.php
<?php
	$link = mysqli_connect("localhost", "root", "", "test");
	if($link === false){
		die("Error: Could not connect.".mysqli_connect_error());
	}
	// 建立table players
	$sql = "CREATE TABLE IF NOT EXISTS players(
		id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
		name VARCHAR(50) NOT NULL UNIQUE,
		race VARCHAR(50) NOT NULL,
		occupation VARCHAR(50) NOT NULL,
		level INT NOT NULL DEFAULT 1,
		gold INT NOT NULL DEFAULT 0
	)";
	// 查詢建立table是否成功
	if(mysqli_query($link, $sql)){
		echo "Table created successfully.<br>";
	}else{
		echo("Error: Could not execute $sql.".mysqli_error($link));
	}
	// 取得index.php中表格所輸入的資訊
	$name = mysqli_real_escape_string($link, $_REQUEST['name']);
	$race = mysqli_real_escape_string($link, $_REQUEST['race']);
	$occupation = mysqli_real_escape_string($link, $_REQUEST['occupation']);
	$level = mysqli_real_escape_string($link, $_REQUEST['level']);
	$gold = mysqli_real_escape_string($link, $_REQUEST['gold']);
	// 加入到資料庫中
	$sql = "INSERT INTO players(name, race, occupation, level, gold) VALUES ('$name', '$race', '$occupation', '$level', '$gold')";
	// 查詢是否加入成功
	if(mysqli_query($link, $sql)){
		echo "Record inserted successfully.<br>";
	}else{
		echo("Error: Could not execute $sql.".mysqli_error($link));
	}
	// 返回index.php繼續加入下一筆資料
	echo "<a href='index.php'>Login</a>";
?>
index.php
<head>
	<title>MySQL Connection</title>
</head>
<body>
<form  method="post" action="hello.php">
    <p>
        <label for="name">Name:</label>
        <input type="text" name="name" id="name">
    </p>
    <p>
        <label for="race">Race:</label>
        <input type="text" name="race" id="race">
    </p>
    <p>
        <label for="occupation">Occupation:</label>
        <input type="text" name="occupation" id="occupation">
    </p>
    <p>
        <label for="level">Level:</label>
        <input type="text" name="level" id="level">
    </p>
    <p>
        <label for="gold">Gold:</label>
        <input type="text" name="gold" id="gold">
    </p>
    
    <input type="submit" value="Add">
</form>

</body>

刪除table
用來刪除某特定的table。
<?php
    $link = mysqli_connect("127.0.0.1", "root", "", "test");
    if($link === false){
        die("Error: Could not connect.".mysqli_connect_error());
    }
    $tablename = "players";
    $sql = "DROP TABLE ".$tablename;
    if(mysqli_query($link, $sql)){
        echo "Table ".$tablename." removed successfully.";
    }else{
        echo("Error: Could not execute $sql.".mysqli_error($link));
    }
    mysqli_close($link);
?>

其他connect語法
連結資料庫,除了使用mysqli_connect()方法外,也可以使用如下方式:
<?php
$link = new mysqli();
$link->connect("localhost", "root", "", "test");
// 也可以使用如下語法:
// $link = new mysqli('localhost', 'root', '');
// $link->select_db('test');

if($link === false){
	die("Error: Could not connect.".mysqli_connect_error());
}else{
	echo("Connect to database successfully.");
}

$link->close();
?>

取得資料
fetch_row()
也可以使用以下方法取得資料庫中資料:
<head>
    <style>
        table.tabley{
            border: 5px double lime;
            outline: 3px solid blue;
            margin: 20px 0px;
            width: 100%;
        }
        table.tabley th{
            border: 1px solid Chocolate ;
            padding: 0px 0px 0px 10px;
            color: darkblue;
            font-weight: 300%;
        }
        table.tabley td{
            border: 1px solid Chocolate ;
            padding: 0px 10px 0px 10px;
            color: #ff0f0f;
            text-align: center;
        }
    </style>

</head>
<body>
<?php
    // practice for fetch_row()
    // 連結database
    $link = new mysqli();
    $link->connect("localhost", "root", "", "test");

    if($link === false){
        die("Error: Could not connect.".mysqli_connect_error());
    }else{
        echo("Connect to database successfully.<br>");
    }
    
    // SQL: 選擇資料,根據username排序
    $query = 'SELECT id, name, race, occupation, level, gold FROM players ORDER by id';
    // 查詢資料
    $result = $link->query($query, MYSQLI_STORE_RESULT);

    // 取得資料並印出
    echo "<table class='tabley'><tr><th>ID</th><th>Name</th><th>Race</th><th>Occupation</th><th>Level</th><th>Gold</th></tr>";
    while(list($id, $name, $race, $occupation, $level, $gold) = $result->fetch_row()) {
        printf("<tr><td>%d</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%d</td> <td>%d</td></tr>", 
        $id, $name, $race, $occupation, $level, $gold);
    }
    // while ($row = $result->fetch_row()) {
    //     printf("<tr><td>%d</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%d</td> <td>%d</td></tr>", $row[0], $row[1], $row[2], $row[3], $row[4], $row[5]);
    // }
    echo "</table>";
    echo "Total ".$result->num_rows." records fetched.";
    $link->close();
?>
</body>
  • MYSQLI_STORE_RESULT:傳回查詢結果於buffer,可以讓使用者使用一次。容易決定總共得到多少筆資料或是跳至某一筆特定資料。此為預設值
  • MYSQLI_USE_RESULT:傳回查詢結果,不是buffered set,表示當需要時可以自server取得資料。無法立即取得資料筆數或是跳至某特定筆資料。當會取得大量資料時,應考慮使用此選項,因為會使用較少記憶體且反應時間較快。
  • 使用$result->num_rows來取得被擷取的資料數。這只用於SELECT,若要決定被INSERT,UPDATE,或DELETE影響的資料數,使用affected_rows()
fetch_object()
<head>
    <style>
        table.tabley{
            border: 5px double lime;
            outline: 3px solid blue;
            margin: 20px 0px;
            width: 100%;
        }
        table.tabley th{
            border: 1px solid Chocolate ;
            padding: 0px 0px 0px 10px;
            color: darkblue;
            font-weight: 300%;
        }
        table.tabley td{
            border: 1px solid Chocolate ;
            padding: 0px 10px 0px 10px;
            color: #ff0f0f;
            text-align: center;
        }
    </style>

</head>
<body>
<?php
    // practice for fetch_object()
    // 連結database
    $link = new mysqli();
    $link->connect("localhost", "root", "", "test");

    if($link === false){
        die("Error: Could not connect.".mysqli_connect_error());
    }else{
        echo("Connect to database successfully.<br>");
    }
    
    // SQL: 選擇資料,根據username排序
    $query = 'SELECT id, name, race, occupation, level, gold FROM players ORDER by id';
    // 查詢資料
    $result = $link->query($query, MYSQLI_STORE_RESULT);

    // 取得資料並印出
    echo "<table class='tabley'><tr><th>ID</th><th>Name</th><th>Race</th><th>Occupation</th><th>Level</th><th>Gold</th></tr>";
    while ($row = $result->fetch_object()) {
        printf("<tr><td>%d</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%d</td> <td>%d</td></tr>", $row->id, $row->name, $row->race, $row->occupation, $row->level, $row->gold);
    }
    echo "</table>";

    $link->close();
?>
</body>
fetch_array()
<head>
    <style>
        table.tabley{
            border: 5px double lime;
            outline: 3px solid blue;
            margin: 20px 0px;
            width: 100%;
        }
        table.tabley th{
            border: 1px solid Chocolate ;
            padding: 0px 0px 0px 10px;
            color: darkblue;
            font-weight: 300%;
        }
        table.tabley td{
            border: 1px solid Chocolate ;
            padding: 0px 10px 0px 10px;
            color: #ff0f0f;
            text-align: center;
        }
    </style>

</head>
<body>
<?php
    // practice for fetch_object()
    // 連結database
    $link = new mysqli();
    $link->connect("localhost", "root", "", "test");

    if($link === false){
        die("Error: Could not connect.".mysqli_connect_error());
    }else{
        echo("Connect to database successfully.<br>");
    }
    
    // SQL: 選擇資料,根據username排序
    $query = 'SELECT id, name, race, occupation, level, gold FROM players ORDER by name';
    // 查詢資料
    $result = $link->query($query, MYSQLI_STORE_RESULT);

    // 取得資料並印出
    echo "<table class='tabley'><tr><th>ID</th><th>Name</th><th>Race</th><th>Occupation</th><th>Level</th><th>Gold</th></tr>";
    while ($row = $result->fetch_assoc()) {
        printf("<tr><td>%d</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%d</td> <td>%d</td></tr>", $row['id'], $row['name'], $row['race'], $row['occupation'], $row['level'], $row['gold']);
        //printf("<tr><td>%d</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%d</td> <td>%d</td></tr>", $row[0], $row[1], $row[2], $row[3], $row[4], $row[5]);
    }
    echo "</table>";

    $link->close();
?>
</body>
  • fetch_array()可以有輸入參數,分別為MYSQLI_ASSOC、MYSQLI_NUM、MYSQLI_BOTH。使用MYSQLI_ASSOC時,僅能使用名稱來擷取array內的值(i.e. 使用$row['id'],不能使用$row[0]),很明顯MYSQLI_NUM與之相反,而MYSQLI_BOTH則都可以(或是不給輸入參數,因為MYSQLI_BOTH為預設值)。
  • 也可以使用fetch_assoc()代替fetch_array(MYSQLI_ASSOC),效果相同。相當於fetch_row()

刪除資料
<head>
    <style>
        table.tabley{
            border: 5px double lime;
            outline: 3px solid blue;
            margin: 20px 0px;
            width: 100%;
        }
        table.tabley th{
            border: 1px solid Chocolate ;
            padding: 0px 0px 0px 10px;
            color: darkblue;
            font-weight: 300%;
        }
        table.tabley td{
            border: 1px solid Chocolate ;
            padding: 0px 10px 0px 10px;
            color: #ff0f0f;
            text-align: center;
        }
    </style>

</head>
<body>
<?php
    // practice for fetch_row()
    // 連結database
    $link = new mysqli();
    $link->connect("localhost", "root", "", "test");

    if($link === false){
        die("Error: Could not connect.".mysqli_connect_error());
    }else{
        echo("Connect to database successfully.<br>");
    }
    
    // SQL: 選擇資料,根據username排序
    $query = 'SELECT id, name, race, occupation, level, gold FROM players ORDER by id';
    // 查詢資料
    $result = $link->query($query);

    // 取得資料並印出
    echo "<table class='tabley'><tr><th>ID</th><th>Name</th><th>Race</th><th>Occupation</th><th>Level</th><th>Gold</th></tr>";
    while(list($id, $name, $race, $occupation, $level, $gold) = $result->fetch_row()) {
        printf("<tr><td>%d</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%d</td> <td>%d</td></tr>", 
        $id, $name, $race, $occupation, $level, $gold);
    }
    
    echo "</table>";
    echo "A total of ".$result->num_rows." records fetched.<br>";
    $result->free();


    // delete data
    $query = 'DELETE FROM players where level = "0"';
    $result = $link->query($query);
    echo "A total of ".$link->affected_rows." records is deleted.<br>";
    //////////// 注意此處為$link->affected_rows,而非使用$result ////////////


    // fetch data
    $query = 'SELECT id, name, race, occupation, level, gold FROM players ORDER by name';
    $result = $link->query($query);
    
    echo "<table class='tabley'><tr><th>ID</th><th>Name</th><th>Race</th><th>Occupation</th><th>Level</th><th>Gold</th></tr>";
    while ($row = $result->fetch_row()) {
        printf("<tr><td>%d</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%d</td> <td>%d</td></tr>", 
        $row[0], $row[1], $row[2], $row[3], $row[4], $row[5]);
    }
    echo "</table>";
    echo "A total of ".$result->num_rows." records fetched.<br>";
    $result->free();

    $link->close();
?>
</body>
更新資料
<head>
    <style>
        table.tabley{
            border: 5px double lime;
            outline: 3px solid blue;
            margin: 20px 0px;
            width: 100%;
        }
        table.tabley th{
            border: 1px solid Chocolate ;
            padding: 0px 0px 0px 10px;
            color: darkblue;
            font-weight: 300%;
        }
        table.tabley td{
            border: 1px solid Chocolate ;
            padding: 0px 10px 0px 10px;
            color: #ff0f0f;
            text-align: center;
        }
    </style>

</head>
<body>
<?php
    // practice for fetch_row()
    // 連結database
    $link = new mysqli();
    $link->connect("localhost", "root", "", "test");

    if($link === false){
        die("Error: Could not connect.".mysqli_connect_error());
    }else{
        echo("Connect to database successfully.<br>");
    }
    
    // SQL: 選擇資料,根據username排序
    $query = 'SELECT id, name, race, occupation, level, gold FROM players ORDER by id';
    // 查詢資料
    $result = $link->query($query);

    // 取得資料並印出
    echo "<table class='tabley'><tr><th>ID</th><th>Name</th><th>Race</th><th>Occupation</th><th>Level</th><th>Gold</th></tr>";
    while(list($id, $name, $race, $occupation, $level, $gold) = $result->fetch_row()) {
        printf("<tr><td>%d</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%d</td> <td>%d</td></tr>", 
        $id, $name, $race, $occupation, $level, $gold);
    }
    
    echo "</table>";
    echo "A total of ".$result->num_rows." records fetched.<br>";
    $result->free();


    // update data
    $query = 'UPDATE players SET level=level+2 WHERE level < 6';
    $result = $link->query($query);
    echo "A total of ".$link->affected_rows." records is updated.<br>";
    //////////// 注意此處為$link->affected_rows,而非使用$result ////////////


    // fetch data
    $query = 'SELECT id, name, race, occupation, level, gold FROM players ORDER by name';
    $result = $link->query($query);
    
    echo "<table class='tabley'><tr><th>ID</th><th>Name</th><th>Race</th><th>Occupation</th><th>Level</th><th>Gold</th></tr>";
    while ($row = $result->fetch_row()) {
        printf("<tr><td>%d</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%d</td> <td>%d</td></tr>", 
        $row[0], $row[1], $row[2], $row[3], $row[4], $row[5]);
    }
    echo "</table>";
    echo "A total of ".$result->num_rows." records fetched.<br>";
    $result->free();

    $link->close();
?>
</body>

Prepared Statement
<style>
        table.tabley{
            border: 5px double lime;
            outline: 3px solid blue;
            margin: 20px 0px;
            width: 100%;
        }
        table.tabley th{
            border: 1px solid Chocolate ;
            padding: 0px 0px 0px 10px;
            color: darkblue;
            font-weight: 300%;
        }
        table.tabley td{
            border: 1px solid Chocolate ;
            padding: 0px 10px 0px 10px;
            color: #ff0f0f;
            text-align: center;
        }
    </style>
<?php
	$link = mysqli_connect("localhost", "root", "", "test");
	if($link === false){
		die("Error: Could not connect.".mysqli_connect_error());
	}

	// 取得index.php中表格所輸入的資訊
	$name = mysqli_real_escape_string($link, $_REQUEST['name']);
	$race = mysqli_real_escape_string($link, $_REQUEST['race']);
	$occupation = mysqli_real_escape_string($link, $_REQUEST['occupation']);
	$level = mysqli_real_escape_string($link, $_REQUEST['level']);
	$gold = mysqli_real_escape_string($link, $_REQUEST['gold']);
	
	// insert record
	// 建立query跟對應的placeholders
	$query = "INSERT INTO players SET name=?, race=?, occupation=?, level=?, gold=?";
	$stmt = $link->stmt_init(); // create a statement object
	$stmt->prepare($query); // prepare the statement for execution
	$stmt->bind_param('sssii', $name, $race, $occupation, $level, $gold); // 此處使用bind_param()
	$stmt->execute();

	// show data
	$query = "SELECT id, name, race, occupation, level, gold FROM players ORDER BY id";
	$stmt->prepare($query); // prepare the statement for execution
	$stmt->execute();
	$stmt->bind_result($id, $name, $race, $occupation, $level, $gold); // 此處記得使用bind_result()

	echo "<table class='tabley'><tr><th>ID</th><th>Name</th><th>Race</th><th>Occupation</th><th>Level</th><th>Gold</th></tr>";
    while($stmt->fetch()){
        printf("<tr><td>%d</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%d</td> <td>%d</td></tr>", 
        $id, $name, $race, $occupation, $level, $gold);
    }
    echo "</table>";

	$stmt->close(); // recuperate statement resources
	$link->close(); // close connection

	echo "<a href='index.php'>Login</a>";
?>