1. 程式人生 > >《Head First PHP & MySQL》學習總結

《Head First PHP & MySQL》學習總結

第1章  為靜態頁面賦予生命

1 通過引入PHP,web伺服器能夠動態地生成HTML web頁面

2 表單使用HTML<form>標籤建立,每個<form>標籤都有一個action屬性,不論為action屬性設定什麼檔名,表單提交時Web伺服器都會用設定的這個檔案來處理表單。如

                  <form  method="post"  action="report.php"> </form>

3 php變數可以直接寫在雙引號字串中

$msg = "$name was abducted $when_it_happened and was gone for $how_long.\n".
    "Number of aliens: $how_many\n".
    "Alien description: $alien_description\n".
    "What they did: $what_they_did\n".
    "Fang spotted: $fang_spotted\n".
    "Other comments: $other";

4 php是一種程式語言,需要一個允許它允許的環境。

5 <?php ...... ?>  為php程式碼區

6 php的一些規則

  • 每個php語句都必須以一個分號( ; )結束,如 echo "hello " ;
  • 如果web頁面有php程式碼,一個好的想法是將web伺服器上的副檔名命名為.php而不是.html 
  • php變數總是以一個美元符號( $ ) 開頭,如 $email
  • php變數美元符號後第一個字元可以是一個字母或下劃線( _ )。變數名只能由字母,數字或下劃線組成

7 php的字串可以用雙引號或單引號

引起

8 $_POST是一個特殊的變數,稱為超級全域性變數。是php內建。直接繫結到HTML表單使用的表單post提交方法

9 echo命令用於將字串作為html內容輸出到瀏覽器上

10 點號( . ) 用於將字串和變數連結在一起

11 換行符(\n)只能在雙引號串中轉義,才會生效。單引號字串被認為是原始文字,而php處理雙引號串時會尋找變數。在一個雙引號中遇到變數時,php會在串中插入該變數的值。

              $t  = 123;    

              echo "hello , $t \n";      // 輸出 hello , 123 ,並另起一行
              echo 'hello , $t\n';       //  輸出hello , $t\n       

 

 

 

第2章  連線MySQL

1 操作MySQL的三個函式

// mysqli_connect()連線資料庫
$dbc = mysqli_connect("127.0.0.1","root","root","aliendatabase") or die("Error connecting to MySQL server.");
	
$query = "INSERT INTO aliens_abduction (first_name, last_name, when_it_happened, how_long, " .
    "how_many, alien_description, what_they_did, fang_spotted, other, email) " .
    "VALUES ('$first_name', '$last_name', '$when_it_happened', '$how_long', '$how_many', " .
    "'$alien_description', '$what_they_did', '$fang_spotted', '$other', '$email')";

//操作查詢語句
$result = mysqli_query($dbc,$query) or die("Error querying database.");
   
//斷開與資料庫的連線
mysqli_close($dbc);

2 用mysqli_connect( host,username,password,dbname,port,socket) 建立連線,引數都是可選項

$dbc  = mysqli_connect(

               "127.0.0.1",       // 資料庫所在的位置

               "yang",                       // 資料庫的帳號

               "123456",                  // 密碼

               "aliendatabase" ) ;    // 資料庫名

3 也可以使用mysqli_select_db( ) 選擇資料庫

$dbc = mysqli_connect("localhost" , "root" , "root") or die("Error");   // 如果失敗會直接呼叫die()

mysqli_select_db($dbc , "aliendatabase");     // 此處選擇資料庫

4 使用mysqli_query(database_connection , query) 函式操作MySQL資料庫。

$result = mysqli_query($dbc , $query) or die("Error querying database");

5 用mysqli_close(database_connection) 關閉連線,用完MySQL資料庫連線進行關閉是個好習慣。

6 資料庫伺服器同時只允許有一定數目的可用連線,所以要儘可能地節省。關閉一個連線會釋放掉這個連線。

 

 

 

 

第3章 建立與填充資料庫

1 如果知道某個欄位最多有n個字元,使用varchar比char要好。char比varchar效率高,它不必維護可變長度。如果明確的 知道欄位的固定長度更適合用char。

2 查詢結果,用mysqli_fetch_array()獲取查詢結果,呼叫一次讀一行

$query = "SELECT * FROM elvis_database" ; 

$result = mysqli_query($dbc , $query) ;

while( $row = mysqli_fetch_array($result)){   // $row是一個數組

         echo $row['first_name']." ".$row["last_name"]." ".$row["email"];

}

 

 

 

第4章  現實的實際應用

1 isset()判斷一個變數是否存在,empty()函式判斷變數是否包含一個空值。當一個變數已被賦值,isset()返回true。當一個變數設定為0,空串,false或NULL時empty()返回true。

2 isset()無法顯示出空表單域與已填充表單域之間有何區別。

3 php中,與操作符(&&)和或操作符(||)都是短路操作符

4 php巢狀html程式碼

<?php
	$t = 1;
	if($t == 1){	
?>
		<h>hello</h>
<?php
	} else {
?>
		<h>ok</h>
<?php
	}
?>

5 將表單動作指向指令碼,指令碼URL可以用$_SERVER["PHP_SELF"],如下

                   <form  action="<?php echo $_SERVER['PHP_SELF'];?>" method="post"> . . . </form>

6 如果表單form定義了提交控制元件<input type="submit" name="submit">,則可以用isset($_POST["submit"])判斷是否已經點選過提交

<form action = "<?php echo $_SERVER['PHP_SELF'];?>" method="post">
   <input type="submit" name="submit" value="ok">
</form>
<?php
	if(isset($_POST['submit']))
		echo "submit";
	else 
		echo "none";
?>

7 MySQL插入欄位

mysql> alter table email_list ADD id int not null auto_increment FIRST , add primary key(id);   ### FIRST表示插入到第一列

8 複選框的name屬性帶方括號([ ])會自動將複選框值放入該name值的陣列中,如下

<input type="checkbox" value="1" name="school[ ]">         

9 php可以利用foreach迴圈處理陣列,如下

foreach($colors as $color) {

        echo $color ;  

}

 

 

 

 

第5章 使用儲存在檔案中的資料

1 MySQL的alter語句

  • alter table xxtable add column age tinyint    //  新增一列
  • alter table xxtable drop column age             //  刪除一列
  • alter table xxtable change column score high_score int     // 修改列,列名改為high_score,型別改為int
  • alter table xxtable modify column date datetime after age   // 修改列的資料型別或位置

2 表單上傳檔案

<form enctype="multipart/form-data" method="post" action="<?php echo $_SERVER['PHP_SELF'];?>">
<input type="hidden" name="MAX_FILE_SIZE" value="32768"/>
<label for="name">Name:</label><input type="text" id="name" name="name" value="<?php if(!empty($name)) echo $name;?>"/><br />
<label for="score">Score:</label><input type="text" id="score" name="score" value="<?php if(!empty($score)) echo $score;?>"/><br />
<label for="screenshot">Screen shot:</label>
<input type="file" id="screenshot" name="screenshot"/>
<hr />
<input type="submit" name="submit" value="Add"/>
</form>

echo $_FILES['screenshot']['name'].": ".$_FILES['screenshot']['type'].": ".$_FILES['screenshot']['size'].": ".$_FILES['screenshot']['tmp_name'].": ".$_FILES['screenshot']['error'];

if(is_file($row['screenshot']) && filesize($row['screenshot'])>0)
  • <form enctype="multipart/form-data" ... > 中的enctype屬性告訴表單要使用檔案上傳所需的一種特殊型別編碼
  • <input type="file" ... >   type屬性表示檔案
  • 表單上傳的檔案要用 $_FILES這個PHP內建的超級全域性變數,而不是$_POST。$_FILES['screenshot']['name']為檔名,$_FILES['screenshot']['type']為檔案的MIME型別,$_FILES['screenshot']['size']為檔案大小,$_FILES['screenshot']['tmp_name']為檔案在伺服器上的臨時儲存位置,$_FILES['screenshot']['error']為上傳結果,0表示成功
  • is_file() 判斷是否為檔案,filesize()獲取檔案大小
  • <input type="hidden" name="MAX_FILE_SIZE" value="32768"/> 這樣的設定可以限制form上傳的檔案大小隻能為32k

3 php函式move_uploaded_file()接受一個檔案的源位置和目標位置,然後負責完成檔案移動。如下

define('GW_UPLOADPATH','images/');
$screenshot = $_FILES['screenshot']['name'];
$target = GW_UPLOADPATH.$screenshot;
move_uploaded_file($_FILES['screenshot']['tmp_name'], $target); // 將檔案從臨時儲存位置移動到目標位置

4 define()定義常量,如下

             define( 'DW' , 123) ;      // 定義常量DW的值為123

5 共享指令碼資料

1) 在指令碼appvars.php先定義變數

<?php
define('GW_UPLOADPATH','images/');
?>

2)   在其他的檔案用require_once()來包含這個指令碼,這個檔案就可以使用這個變數

<?php
require_once('appvars.php');
?>

6 require_once()和include()的區別在於如果未找到包含檔案,require_once()會產生一個錯誤,而include()不會顯示任何錯誤。require_once也保證檔案不會被包含多次。php還有include_once()和require()。

7 MySQL的結果排序

select * from guitarwars order by score asc;
select * from guitarwars order by score desc,date asc;

8 unlink()函式用於刪除一個檔案,如下所示,符號@為了避免檔案刪除失敗報錯

@unlink($_FILES['screenshot']['tmp_name'];

9 POST請求只能從表單發出,而GET請求可以打包成URL

 

 

 

第6章  保證應用安全

1 http認證提供了一種使用PHP保護頁面的簡單方法,$_SERVER['PHP_AUTH_USER']儲存了使用者名稱,$_SERVER['PHP_AUTH_PW']儲存了密碼。

2 HTTP認證的基本思想是,伺服器會“扣留”一個受保護的web頁面,然後要求瀏覽器向用戶詢問一個使用者名稱和口令。瀏覽器和伺服器之間是通過首部完成,首部是一個短小的文字訊息,包含所請求或傳送的特定指令。首部如下

3 瀏覽器鍵入一個URL或點選Web頁面一個連結時,瀏覽器會組裝一個GET請求,併發送到伺服器。這個請求會打包成一系列的首部,每個首部包含有關請求的一些資訊。

4 利用php控制首部,header()函式允許從php指令碼建立和傳送首部,header()函式會立即從伺服器向瀏覽器傳送一個首部,而且這個函式必須在向瀏覽器傳送任何具體內容之前呼叫。header()函式呼叫應當放在php指令碼的所有html程式碼之前。如下所示

<?php
header("Content-Type:text/html");
?>

注:在首部之前即使傳送一個空格或字元瀏覽器都會拒絕。使用即使是<?php標記前面多一個隨意的空格都會導致這個指令碼失效

5 首部可以做很多事

  • 位置首部重定向到其他頁面
<?php
// 重定向到百度
header('Location:http://www.baidu.com');
?>
  • 重新整理首部,設定時間重新整理頁面 
<?php
// 5秒後重新整理頁面,到百度
header("Refresh:5;url=http://www.baidu.com");
echo "In 5 seconds you'll be taken to baidu";
?>
  • 內容首部,控制由伺服器傳送的內容型別
<?php
// 瀏覽器會根據text/plain只作為文字顯示
header('Content-Type:text/plain');
echo "This <strong>text</strong> won't actually be bold";
?>

6 http的認證,會自動有彈窗提示要求輸入使用者名稱和密碼

<?php
$username = 'rock';
$password = 'roll';
if(!isset($_SERVER['PHP_AUTH_USER'])||!isset($_SERVER['PHP_AUTH_PW'])||($_SERVER['PHP_AUTH_USER']!=$username||$_SERVER['PHP_AUTH_PW']!=$password)){
	header('HTTP/1.1401 Unauthorized');
	header('WWW-Authenticate:Basic realm="Guitar Wars"');
	exit('<h2>Guitar Wars</h2>Sorry, you must enter a valid user name and password to access this page.');
}
?>

7 保護資料避免SQL注入

  • 可以採用trim()去掉字串前面和後面多餘的空格
  • 內建函式mysqli_real_escape_string( )將有危險的字元進行轉義。
$score = "1000','1v1.jpg',1);";
$score = mysqli_real_escape_string($dbc,trim($score));  //$score 變成"1000\',\'1v1.jpg\',1);"
  • MySQL裡某些欄位可以宣告為預設值,不需要insert該欄位值
  • 表單驗證安全後再插入資料

 

 

 

 

第7章 構建個性化Web應用

1 MySQL有個SHA()的函式,SHA(Secure Hash Algorithm )會對文字串應用一個加密演算法,結果是一個唯一加密串,長度固定為40個十六進位制字元,如下

insert into mismatch_user(username , password , join_date) values( 'Yang' , SHA('123456') , NOW())

注:SHA()函式提供的是單向加密,即無法對已經加密的資料解密。

2 MySQL提供了另一個與SHA()類似的函式,名為MD5(),一般認為SHA()會更安全些。

3 可以使用mysqli_num_rows()函式檢視搜尋結果個數

$dbc = mysqli_connect(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME) or die("Fail to connect");
$user_name = mysqli_real_escape_string($dbc,trim($_SERVER["PHP_AUTH_USER"]));
$user_password = mysqli_real_escape_string($dbc,trim($_SERVER["PHP_AUTH_PW"]));
$query = "select user_id,username from mismatch_user where username='$user_name' and password=sha('$user_password')";
$data = mysqli_query($dbc,$query);
if(mysqli_num_rows($data) == 1){
	$row = mysqli_fetch_array($data);
	$user_id = $row['user_id'];
	$username = $row['username'];
}

注:sql語句如果是字串變數記得一定要在包圍在引號裡,不如sql語句執行時會異常

4 HTTP認證只有在瀏覽器關閉時才會重置,或人工手動清除。

5 PHP通過一個名為setcookie()函式和一個$_COOKIE的超級全域性變數提供對cookie的訪問。如下

// 將"sidneyk"存在名為username的cookie中
setcookie("username","sidneyk");

// 通過$_COOKIE['username']取到"sidneyk"值
$username = $_COOKIE['username'];

6 setcookie()還接受可選的第三個引數,即設定cookie的到期日期。到了這個日期時cookie會自動刪除。如果沒有指定日期,cookie會在瀏覽器關閉時自動到期。

<?php
require_once('connectvars.php');

$error_msg = "";

if(!isset($_COOKIE['user_id'])){
	if(isset($_POST['submit'])){
		$dbc = mysqli_connect(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME) or die("Fail to connect");
		$user_name = mysqli_real_escape_string($dbc,trim($_POST['username']));
		$user_password = mysqli_real_escape_string($dbc,trim($_POST['password']));
		if(!empty($user_name) && !empty($user_password)){
			$query = "select user_id,username from mismatch_user where username='$user_name' and password=sha('$user_password')";
			error_log($query);
			$data = mysqli_query($dbc,$query);
			error_log(mysqli_num_rows($data));
			if(mysqli_num_rows($data) == 1){
				$row = mysqli_fetch_array($data);
				setcookie("user_id",$row['user_id']);
				setcookie("username",$row['username']);
				$home_url = "http://".$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF'])."/index.php";
				header("Location: ".$home_url);
			}else{
				$error_msg = "Sorry, you must enter a valid username and password to log in.";
			}
		}else{
			$error_msg = "Sorry, you must enter your username and password to log in.";
		}
	}
}

?>
<html>
<head>
<title>Mismatch - Log In</title>
<link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>
<h3>Mismatch - Log In</h3>
<?php
if(empty($_COOKIE["user_id"])){
	echo "<p class='error'>$error_msg</p>";

?>
<form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>">
<fieldset>
<legend>Log In</legend>
<label for="username">Username: </label>
<input type="text" id="username" name="username" value="<?php if(!empty($user_name)) echo $user_name;?>"/><br />
<label for="password">Password: </label>
<input type="password" id="password" name="password"/>
</fieldset>
<input type="submit" name="submit" value="Log In"/>
</form>
<?php
}else{
	echo "<p class='login'>You are logged in as ".$_COOKIE['username'].".</p>";
}
?>
</body>
</html>

7 刪除cookie要通過呼叫setcookie()設定過期的時間,如下

setcookie("username","sidneyk",time()-3600);

8 會話允許將小段資料持久地儲存在伺服器上,而不依賴於客戶端。它比cookie更安全和可靠。但不同於cookie,會話無法對一個會話變數將資料儲存多久做太多控制。會話一結束就會自動銷燬會話變數。關閉瀏覽器,會話也會結束。

會話有非常明確的開始和結束。session_start()函式開始一個會話,並允許在會話變數中儲存資料。session_start()不會設定任何資料,而只是建立會話並開始執行。會話在內部由一個唯一的會話識別符號標識。一旦會話開始,就可以用超級變數$_SESSION來設定會話變數。瀏覽器關閉或呼叫session_destroy()時會話會結束

session_start();  // 開始會話

$_SESSION['username'] = 'sidneyk';   // 設定會話變數

$username = $_SESSION['username'] ;  // 獲取會話變數

session_destroy();  // 結束會話

注:session_destroy()只是結束會話,但不會銷燬會話變數。所以一般在結束之前要手動刪除會話變數。有一個快捷方法即把$_SESSION設定為空陣列,$_SESSION = array()。

9 會話在後臺實際上會使用cookie,如果瀏覽器支援cookie,會話可能會設定一個cookie臨時儲存會話ID。PHP還必須刪除可能在瀏覽器上自動建立來儲存會話ID的所有cookie。如下

if(isset($_COOKIE[session_name()])){
    setcookie(session_name(),"",time()-3600);
}

10 使用會話完成登出的必要步驟

  • 刪除會話變數,$_SESSION = array()
  • 檢視會話cookie是否存在,存在則將其刪除   if(isset($_COOKIE[session_name()]))
  • 銷燬會話   session_destroy()
  • 將使用者重定向到主頁 header()

11 不同的地方呼叫session_start(),即session_start()多次被呼叫,但不會建立多個會話,還是隻有一個會話。

12 cookie的生命期並不與瀏覽器例項繫結,即使關閉瀏覽器,cookie也不會消失。cookie可以永存,至少在它的到期日期來到之前。會話session可以比cookie儲存更大的資料。

13 為了避免程式碼重複,將重複的程式碼可以獨立出來做一個檔案,如下

  • header.php   頁首
  • navmenu.php  導航選單
  • startsession.php  會話啟動指令碼
  • footer.php   頁尾

 

 

 

第8章  收穫資料

1 外來鍵(foreign key)將一個表中的一行連結到另一個表中的一行。一個表中的外來鍵引用另一個表的主鍵,從而建立這兩個表間的一個聯絡用於查詢。

2 php支援三元操作符( ? : )   ,   condition ? A : B

 

 

 

 

第9章  通過函式改善生活

1 預設情況下MySQL的where子句是不區分大小寫

2 在SQL中,百分號(%)可以代表0或多個字元,下劃線(_)表示一個字元,如下

select * from xxx like '_ _ _ hello' ;     // 表示匹配xxxhello

3 explode()可以將一個字串拆分為多個單獨的子字串陣列,如下

$search_words = explode( '  ' , 'Tipper Cow') ;     // 第一個引數是定界符,即根據什麼拆分,可以是一個字元或多個字元。

4 implode()可以將多個子字串組合成一個字串,如下

$where_clause = implode(' or ' , $where_list) ;   // 第一個引數是定界符,即子字串間加入該引數組合

5 str_replace()替換字串或單個字元,如下

$clean_search = str_replace("thousands" , "hundreds" , "Make thousands of dollars your very first month");  // 在第三個引數裡找出第一個引數的字串,用第二個字串替換

注:explode()和implode(),str_replace()都是準確使用定界符,如定界符為一個空格,源字串的連續三個空格會被當成三個定界符,如下

$user_search = "bull matador   cape";
$search_words = explode(" ",$user_search);
var_dump($search_words);

輸出:
array(5) {
  [0]=>
  string(4) "bull"
  [1]=>
  string(7) "matador"
  [2]=>
  string(0) ""
  [3]=>
  string(0) ""
  [4]=>
  string(4) "cape"
}

6 陣列增加

$user_search = "bull matador cape ok";
$search_words = explode(" ",$user_search);
$temp = array();
foreach($search_words as $word){
    $temp[] = $word;     // 可以不用填寫陣列下標
}

7 substr( string , start , length) 擷取字串的一部分,第一個引數string是源字串,第二個引數是擷取起點,第三個引數是擷取的長度,這個是可選引數。

$job_desc = "Are you a practioner of the lost art of cat juggling?";
echo substr($job_desc,4,3) ;   // 輸出 you
echo substr($job_desc,49) ;    // 輸出ing?
echo substr($job_desc,-53,7) ;  // 輸出 Are you
echo substr($job_desc,-9) ;      // 輸出juggling?

8 定義函式,使用關鍵詞function

function replace_commas($str){
    $new_str = str_replace(',',' ',$str);
    return $new_str;
}

 

 

 

第10章 正則表示式