張凱迪(KD Chang)
台灣大學,主修經濟學,臺大資管所。服務過上市電子公司、人工智慧新創公司、全球前三大瀏覽器製造商和電子商務平台,也曾參與數個組織的創辦。夢想是做出人們想用的產品和辦一所心目中理想的學校。
講師:張凱迪(KD.Chang)
Copyright © 2014 All rights reserved
Flow Control
Function
Error Handle
一般而言,PHP 的程式是由上往下一直執行下去,但我們往往在功能上需要依條件不同而改變執行順序,這時候流程控制就扮演關鍵角色
1. 循序結構(Sequential)
預設的程式執行方式,亦即一個程式一行程式執行下來
2. 選擇結構(Selection)
是一種條件控制,可分為是非或二選一或多選等情況
3. 重複結構(Iteration)
亦即迴圈控制,可以重複執行程式區塊,直到符合結束條件
http://docs.oracle.com/
條件敘述
迴圈結構
PHP 條件敘述可分為:是非題、二選一或多選一等情況,而三元運算子( ? : ) 可以建立更簡潔的條件判斷
http://www.geocities.ws/paylook/Module6_files/image012.png
if 條件敘述是一種是否執行的是非題,如果符合條件運算結果為true則執行程式區塊(括號內程式碼)
<?php
$grades = 70;
if($grades > 60) {
echo '真假,你竟然及格了!?!';
}
//若區塊內只有一行敘述可以不用大括號,但建議使用方便閱讀
?>
若有兩個區塊,則可以變成二選一的選擇題。符合條件執行第一個區塊,不符合則執行第二個區塊
<?php
$age = 20;
if(age >= 20){
echo '你可以投票了!';
}
else {
echo '小朋友,你還未成年喔~';
}
?>
若需要有多選一的情況,則可以運用if/if elseif/else建立多選一的條件選擇
<?php
$time = 11;
if ($time < 10 && $time > 5) {
echo 'Good morning';
} elseif ($time > 20 && $time < 24) {
echo 'Good Night';
} else {
echo 'Good Evening';
}
?>
建立多選一的另一種方式為使用switch條件敘述,若是條件非邏輯判斷且選擇很多,建議使用switch,避免過多的if else判斷導致程式閱讀不易。請注意break敘述為必須,才會在符合條件執行完該區塊後跳出迴圈,否則會依序一直執行下去,至於最後的default值為選擇性,主要是提供都不符合條件執行的區塊
<?php
$country = '台灣';
switch($country){
case '台灣':
echo '台灣好!';
break;
case '米國':
echo '米國米多';
break;
case '日本':
echo '大和艦隊';
break;
default:
echo '地球人';
}
?>
三元運算為簡化的條件判斷,其中 ? 代表" if "," : "代表else
<?php
$age = 30;
$vote = (age >= 20) ? "成年" : "未成年";
echo $vote;
?>
透過上述所講的流程控制的方法製作一個藉由月份判斷季節的程式(3-5春, 6-8夏, 9-11秋, 12-2冬)
<form action="season.php" method="get">
<input name="month" type="text" placeholder="請輸入月份">
<input type="submit">
</form>
PHP 支持多種迴圈結構,一般可分為前測和後測。係指於迴圈前判斷條件還是迴圈後判斷
http://cdn2-b.examiner.com/
http://www.twivs.tnc.edu.tw/testnew/vbtest/VBPIC/loop1.gif
for迴圈可以透過計數器的增加減少執行固定次數的程式區塊,由於是在迴圈開始前檢查條件,故稱前測迴圈
<?php
// for (起始值; 條件式; 更新值) {
// 指令;
// }
for($i = 0; $i < 10; $i++){
echo $i;
}
for($i = 10; $i < 0; $i--){
echo $i;
}
?>
while迴圈同樣也是前測迴圈,但和 for 迴圈不同的地方是,while需要自行在程式區塊內處理計數器的增減,若符合條件(true)才進入迴圈內,否則(false)則離開迴圈 *請注意不要讓while變成無窮迴圈(1.忘記加計數器 2.讓條件永遠成立 EX. while(1) or while(true) )避免系統耗盡當機
$sum = 0;
$i = 1;
while($i <= 10){
$sum += $i;
$i++;
}
echo $sum;
http://www.twivs.tnc.edu.tw/testnew/vbtest/VBPIC/loop2.gif
do/while 迴圈和 while 類似,只是do/while迴圈是在迴圈結尾才檢查條件是否符合,亦即迴圈區塊至少會執行一次
<?php
$i = 11;
$sum = 0;
do {
$sum += $i;
$i++;
} while($i <= 10);
echo $sum;
?>
除了依照條件控制程式的流程外,我們也可以使用break和continue來控制程式的流程。注意的是兩者只能在程式區塊中使用
1. break
當某些條件成立時,強迫迴圈終止,跳出迴圈(程式區塊),如同我們之前看到 switch 在條件符合時整個跳出迴圈
2. continue
與 break 不同的是 continue 不會完全跳出程式區塊,只會結束這次迴圈,直接開始下次的迴圈
<?php
for($i = 0; $i < 10; $i++){
if($i === 1)
continue;
echo $i;
}
for($j = 0; $j < 10; $j++){
if($j === 1)
break;
echo $j;
}
?>
巢狀迴圈亦即在迴圈中擁有其他迴圈,EX. while中有for,for中有while迴圈
<?php
echo '<table>';
for($i = 1; $i <=9; $i++){
echo '<tr>';
$j = 1;
while($j <= 9){
echo '<td>' . $i * $j . '</td>';
$j++;
}
echo '</tr>';
}
echo '</table>';
?>
運用迴圈方法印出 1 - 100 的數值,但只印出奇數
隨著軟體開發的功能越來越複雜,我們必須把工作切成一個又一個的模組,方便同事間分工合作。而透過將大程式切割成一個個小程式,再將小程式一一完成,就是模組化程式設計的基本過程(在 PHP 中即為將問題分割成一個個函數)
http://captivatedev.com/
當我們程式越寫越大就會碰到程式碼重複的問題,而函數就是要解決這個問題,將一些共用的程式碼集合成一個區塊,可以傳入參數(Parameter)和回傳執行結果。也可以想成數學上的函數,將參數傳入後,會產生結果,而那個回傳結果就是函數的return值
執行函數稱為"Call Function",呼叫函數時不一定要傳入參數(傳入實際值為argument),但函數一定會有回傳值,若沒有設置則回傳NULL
Syntax : 需要傳入參數的資料型別
Semantics : 函數的功能
當我們呼叫函式時可以只知道需要傳入的參數並在傳入後取的傳回值,通常我們不需要知道內部的實作過程,但要達到這個目標,使用函數的人必須了解一些規則:
1. 函數的對外的介面接口需要定義良好、完整
2. 使用函數時,我們通常不需要知道背後的實作過程,但要知道如何使用介面
3. 在實作函數時專心於處理傳入的參數和傳回值,並確實完成函數功能的實作
函數的內容是程式區塊,最簡單的函數不含回傳值和傳入參數,僅有關鍵字function 後面接函數名稱和函數內程式區塊,使用時呼叫函數名稱
<?php
function printHeader() {
echo '<h1>新手的網站</h1>';
echo '<hr>';
}
function printContent() {
echo '<p>我是內容呦~</p>';
}
function printFooter() {
echo '<hr>';
echo '<h5>Copyright © 新手上路,請多包含:)</h5>';
}
printHeader();
printContent();
printFooter();
?>
函數可以透過傳入不同參數而有不同的執行結果,而結果可以透過 return 回傳
<?php
function discount($price) {
if($price > 500) {
return $price * 0.9;
} else {
return $price;
}
}
echo discount(1000);
?>
運用函數設計一個台幣兌換美元的程式 1 : 30.1
函數在傳遞時,可以指定參數的傳遞方式。一般在 PHP 中提供兩種參數傳遞方式:
1. 傳值呼叫 (變數傳入函數不改變原變數值)
2. 傳址呼叫 (將原變數儲存的記憶體位址傳入,在程式區塊中改變變數值,會改變原變數)
<?php
$a = 12;
$b = 12;
function byValue($a){
$a += 1;
}
function byRef(&$b){
$b += 1;
}
byValue($a);
byRef($b);
echo $a;
echo '<br>';
echo $b;
?>
函數變數為函數名稱使用變數呼叫,預設參數值為函數參數事先設定預設值,若沒有傳入參數則使用預設值
<?php
function area($width, $height=7){
return $width * $height;
}
echo area(10);
$name = 'area';
echo $name(7);
?>
變數在宣告後都有其可以被存取的有效範圍,稱為 scope,為程式設計中非常重要的觀念。變數範圍主要為以下三種:
1. 區域變數(Local Variable):在函數內指定的變數只能在函數內使用,函數外程式碼無法存取此變數(請特別注意函數參數也是一種區域變數)
2. 全域變數(Global Variable):在函數外指定變數,則整個PHP 檔案都可以使用。若全域變數在函數中使用,在使用前需先宣告成 global
3. 靜態變數(Static Variable):一種特殊區域變數,執行函數完變數值不會消失
<?php
$a = 7;
$b = 13;
function fnA(){
$a = 4;
$b = 5;
}
function fnB(){
global $a, $b;
$a = 4;
$b = 5;
}
fnA();
echo $a, $b;
echo '<br>';
fnB();
echo $a, $b;
?>
在 PHP 函數宣告的靜態變數,不同於其他區域變數在離開函數後就會消失。靜態變數由於有配置固定的記憶體位置,所以重複呼叫函數靜態變數值都會保留。其宣告方法是在變數前加上 static 關鍵字
<?php
function staticFn(){
static $count = 0;
$count += 1;
return $count;
}
echo staticFn();
echo '<br>';
echo staticFn();
?>
PHP 中的 require() 和 include() 和 echo() 和 print() 一樣並非函數,而是語言建構子,可以將外部檔案引入目前的 PHP 檔案中,引入位置為 require() 和 include() 敘述位置,引入檔名可以為 .php 或 .txt,同常會使用 .inc
注意:兩者差別在於 require() 通常用於程式檔案的一開頭(如果是在條件區塊,不管是否符合條件都一定會引入)且如果引入檔不存在則產生執行錯誤。而 include 通常使用在程式中的流程敘述中,如果引入檔不存在只會產生警告訊息,程式一樣會繼續執行
<?php
require 'main.inc';
require ('main.inc');
$file_name = 'main.inc';
require $file_name;
include_once('main.inc');
?>
如果只希望引入一次可使用,require_once() / include_once(),如已經引入則不會再次引入檔案
PHP 內部已經有許多好用的內建函數可以使用,讓開發者不用再重新造輪子自己撰寫,以下列出常用的內建函數:
1. 取得時間刻記與日期時間
2. 日期時間格式與處理函數
3. 檢查資料型態函數
PHP 日期 / 時間函數是以時間刻記(Timestamps)作為計算依據,時間刻記是從 1/1/1970 年到指定日期/時間的秒數,在取得timestamp後就可以使用函數轉換成日期/時間
1. time() 傳回現在伺服器的 timestamp
2. mktime(int, int, int, int, int, int) 傳回指定日期/時間的timestamp,參數有六個,依序為時、分、秒、越、日和年
3. getdate(int) 傳回 timestamp 轉換成的伺服器日期/時間陣列
4. checkdate(int, int, int) 檢查參數日期是否是正確日期
<?php
$timestamp = time();
$now_time_is = getdate($timestamp);
echo $timestamp;
echo '<br>';
print_r($now_time_is);
?>
當取得 timestamp 後可以利用內建日期時間格式函數轉換格式和調整日期/時間
<?php
$timestamp = time();
$dates = date("l F j Y h:i:s A", $timestamp);
echo $dates;
echo '<br>';
echo strtotime("+10 days", $timestamp);
?>
PHP 檢查資料型態函數可以檢查變數儲存的資料型態,或檢查是否有指定變數值,還數回傳值是布林值,如果真為 true,偽是 false,另有 gettype() 和 get_resource_type() 取得型別
<?php
$a = 10;
echo empty($a);
echo isset($a);
unset($a);
echo is_null($a);
?>
運用函數製作一個可以輸入身高體重計算 BMI 的程式 (W/H*H)
請試著運用 include() 或 require() 將範例中的 printHeader() 獨立成另一個檔案,並在 index.php 中引入
<?php
function printHeader() {
echo '<h1>新手的網站</h1>';
echo '<hr>';
}
printHeader();
?>
PHP 程式錯誤主要有分為兩種:
1. 環境錯誤(Environmental Errors):環境錯誤亦稱外部錯誤,這是指程式執行環境導致的錯誤,非程式設計問題。例如:檔案不存在、寫入權限不足等
2. 程式錯誤(Programming Errors):指程式中有 bug,可能是語法錯誤、語意錯誤或程式邏輯有錯誤
其中語意和語法錯誤會在直譯過程中產生錯誤訊息,為程式設計者產生的錯誤,可以在執行程式前除錯。環境錯誤和邏輯錯誤為執行時(Runtime)產生的錯誤
Error Handling 是一種錯誤處理的機制,可以處理直譯過程中的錯誤或是執行過程的錯誤,PHP 內建錯誤處理機制,當錯誤發生時可以產生各種不同的錯誤訊息:
1. Parse Errors:剖析錯誤是指 PHP 語法和語意錯誤,這是執行前,直譯過程找出的錯誤
2. Fatal Errors:嚴重的執行時錯誤,會導致程式終止
3. Warnings:可以補救的非致命錯誤,會試圖繼續執行程式
4. Notices:很小的錯誤,只是用來提醒程式碼可能有錯誤
PHP 基本錯誤處理方式有:不理會、終止程式顯示錯誤訊息、寫入記錄檔,使用自定錯誤處理進行補救。一般可以使用 die()、exit() 進行簡單錯誤處理,亦可以透過 error_reporting() 指定需要回到的錯誤等級,並用 set_error_handler() 制定錯誤處理函數。若需要則透過 error_log() 將錯誤訊息寫入檔案或是產生使用者自定錯誤 trigger_error()
<?php
$file = @fopen($filename, "r") or exit('檔案開啟錯誤!');
$file = @fopen($filename, "r") or die('檔案開啟錯誤!');
?>
請回想過去寫的練習程式中所發現的錯誤訊息是屬於哪一類?
By 張凱迪(KD Chang)
本課程分為 前端網頁程式設計基礎班 和 PHP 網站程式設計與資料庫基礎班 兩個班,希望藉由這次課程能讓對於網頁程式設計有興趣的同學可以有一個入門的管道,在上完課程後可以有足夠的自學能力能夠持續學習進修,進而將自己的點子付諸實踐。課程網站:http://kdchang.cc/web-programming-course/ Email:web.programming.course@gmail.com FB 粉絲專頁:https://fb.com/Web.Programming.Course
台灣大學,主修經濟學,臺大資管所。服務過上市電子公司、人工智慧新創公司、全球前三大瀏覽器製造商和電子商務平台,也曾參與數個組織的創辦。夢想是做出人們想用的產品和辦一所心目中理想的學校。