# :-: 一、傳統的錯誤處理方式
```php
namespace jiangshi\ouyangke;
// 傳統方式的錯誤處理
class Calculator{
protected $defaultOperators = ['+', '-', '*', '/', '%'];
protected $result;
public function __construct(...$operators){
// 判斷操作是否在有效范圍內
foreach ($operators as $operator) {
if (in_array($operator, $this->defaultOperators)) {
continue;
} else {
die('操作符錯誤');
}
}
// 更新操作符類型
$this->defaultOperators = $operators;
}
// 運算方法
public function operation($type,...$args){
// 判斷操作符合法性
if (in_array($type, $this->defaultOperators)) {
$num = count($args);
switch ($num) {
case 0:
die('參數不能為空');
break;
case ($num < 2):
die('參數不能少于2個');
break;
default:
// 用參數數組的第一個值初始化$this->result屬性,該屬性保存著返回值
// 同時, $this->>result 也做為所有運算的第一個操作數
$this->result = array_shift($args);
if (is_numeric($this->result)) {
$this->execute($type, ...$args);
} else {
die('第一個參數必須數值型');
}
}
} else {
die('操作類型錯誤');
}
// 運算結果四舍五入(保留小數點后2位)
return round($this->result, 2);
}
// 運算執行器方法
protected function execute($type, ...$args){
foreach ($args as $arg) {
// 判斷當前操作數是否數字/可轉為數字的字符串
if (is_numeric($arg)) {
switch ($type) {
case '+': // 加法
$this->result += $arg;
break;
case '-': // 減法
$this->result -= $arg;
break;
case '*': // 乘法
$this->result *= $arg;
break;
case '/': // 除法
if ($arg !== 0) {
$this->result /= $arg;
break;
} else {
die('除數不能為0');
}
case '%': // 取模
$this->result %= $arg;
break;
}
} else {
die('操作數類型錯誤');
}
}
}
}
// 實例化, 并自定義允許進行的操作類型
//$calculator = new Calculator('+','-','*','/');
//$calculator = new Calculator('+','-','*','888');
$calculator = new Calculator('+','-');
echo '<per>';
//echo $calculator->operation('+'); // 參數不能為空
//echo $calculator->operation('+', 100); // 參數不能少于2個
//echo $calculator->operation('+', 'abc',888); // 第一個參數必須是可計算的數值或數值型字符串
echo $calculator->operation('+', '100',888); // 988
echo '<hr>';
echo $calculator->operation('-', '100',888); // -788
echo '<hr>';
// 添加運算符: 乘法與除法
$calculator = new Calculator('+','-','*', '/');
echo $calculator->operation('*', '100',888); // 88800
echo '<hr>';
echo $calculator->operation('/', '100',888); // 0.11
```
*****
# :-: 二、系統異常類常規處理
* Exception 類是可以進行擴展的
* Exception 中只有__construct()和__toString()允許擴展,其它都是最終方法final,不允許擴展
```php
// 異常類: Exception
namespace jiangshi\ouyangke;
use Exception;
// 用戶代碼應該全部放在try 塊中
try {
class Calculator{
protected $defaultOperators = ['+', '-', '*', '/', '%'];
protected $result;
public function __construct(...$operators){
// 判斷操作是否在有效范圍內
foreach ($operators as $operator) {
if (in_array($operator, $this->defaultOperators)) {
continue;
} else {
// die('操作符錯誤');
throw new Exception('操作符錯誤', 101);
}
}
// 更新操作符類型
$this->defaultOperators = $operators;
}
// 運算方法
public function operation($type,...$args){
// 判斷操作符合法性
if (in_array($type, $this->defaultOperators)) {
$num = count($args);
switch ($num) {
case 0:
throw new Exception('參數不能為空', 102);
// die('參數不能為空');
break;
case ($num < 2):
// die('參數不能少于2個');
throw new Exception('參數不能少于2個', 103);
break;
default:
// 用參數數組的第一個值初始化$this->result屬性,該屬性保存著返回值
// 同時, $this->>result 也做為所有運算的第一個操作數
$this->result = array_shift($args);
if (is_numeric($this->result)) {
$this->execute($type, ...$args);
} else {
// die('第一個參數必須數值型');
throw new Exception('第一個參數必須數值型', 104);
}
}
} else {
// die('操作類型錯誤');
throw new Exception('操作類型錯誤', 105);
}
// 運算結果四舍五入(保留小數點后2位)
return round($this->result, 2);
}
// 運算執行器方法
protected function execute($type, ...$args){
foreach ($args as $arg) {
// 判斷當前操作數是否數字/可轉為數字的字符串
if (is_numeric($arg)) {
switch ($type) {
case '+': // 加法
$this->result += $arg;
break;
case '-': // 減法
$this->result -= $arg;
break;
case '*': // 乘法
$this->result *= $arg;
break;
case '/': // 除法
if ($arg !== 0) {
$this->result /= $arg;
break;
} else {
// die('除數不能為0');
throw new Exception('除數不能為0', 106);
}
case '%': // 取模
$this->result %= $arg;
break;
}
} else {
// die('操作數類型錯誤');
throw new Exception('操作數類型錯誤', 107);
}
}
}
}
// 實例化, 并自定義允許進行的操作類型
$calculator = new Calculator('+','-','*', '/');
echo '<per>';
// echo $calculator->operation('*');
// echo $calculator->operation('*',30);
// echo $calculator->operation('*','abc',999);
echo $calculator->operation('*','379',200);
echo '<hr>';
echo $calculator->operation('/', 678,234);
} catch (Exception $e) {
// 使用異常,將執行過程中可能出現的錯誤進行統一管理,更加優雅高效
// getCode(): 獲取自定義錯誤代碼, getMessage(): 獲取自定義錯誤信息
echo $e->getCode(). ': ' .$e->getMessage();
}
```
*****
# :-: 三、自定義異常類處理
* 下面我們來創建一個自己的異常類, 專用于處理算術運算中可能出現的錯誤
* 基本要求是: 錯誤代碼加粗, 提示文本描紅, 并要求換行顯示
```php
// 異常類: Exception
namespace jiangshi\ouyangke;
use Exception;
// 自定義異常類
class CalException extends Exception{
public function __construct($message = "", $code = 0){
parent::__construct($message, $code);
}
public function errorInfo(){
return
<<< ERROR
<h2>
<strong>{$this->getCode()}: </strong>
<span style="color: red">{$this->getMessage()}</span>
</h2>
ERROR;
}
}
// 以try 塊中,所有的 Exception 類全部替換成 CalException 類即可
try {
class Calculator{
protected $defaultOperators = ['+', '-', '*', '/', '%'];
protected $result;
public function __construct(...$operators){
// 判斷操作是否在有效范圍內
foreach ($operators as $operator) {
if (in_array($operator, $this->defaultOperators)) {
continue;
} else {
// die('操作符錯誤');
throw new CalException('操作符錯誤', 101);
}
}
// 更新操作符類型
$this->defaultOperators = $operators;
}
// 運算方法
public function operation($type,...$args){
// 判斷操作符合法性
if (in_array($type, $this->defaultOperators)) {
$num = count($args);
switch ($num) {
case 0:
throw new CalException('參數不能為空', 102);
// die('參數不能為空');
break;
case ($num < 2):
// die('參數不能少于2個');
throw new Exception('參數不能少于2個', 103);
break;
default:
// 用參數數組的第一個值初始化$this->result屬性,該屬性保存著返回值
// 同時, $this->>result 也做為所有運算的第一個操作數
$this->result = array_shift($args);
if (is_numeric($this->result)) {
$this->execute($type, ...$args);
} else {
// die('第一個參數必須數值型');
throw new CalException('第一個參數必須數值型', 104);
}
}
} else {
// die('操作類型錯誤');
throw new CalException('操作類型錯誤', 105);
}
// 運算結果四舍五入(保留小數點后2位)
return round($this->result, 2);
}
// 運算執行器方法
protected function execute($type, ...$args){
foreach ($args as $arg) {
// 判斷當前操作數是否數字/可轉為數字的字符串
if (is_numeric($arg)) {
switch ($type) {
case '+': // 加法
$this->result += $arg;
break;
case '-': // 減法
$this->result -= $arg;
break;
case '*': // 乘法
$this->result *= $arg;
break;
case '/': // 除法
if ($arg !== 0) {
$this->result /= $arg;
break;
} else {
// die('除數不能為0');
throw new CalException('除數不能為0', 106);
}
case '%': // 取模
$this->result %= $arg;
break;
}
} else {
// die('操作數類型錯誤');
throw new CalException('操作數類型錯誤', 107);
}
}
}
}
// 實例化, 并自定義允許進行的操作類型
$calculator = new Calculator('+','-','*', '/');
echo '<per>';
// echo $calculator->operation('*');
// echo $calculator->operation('*',30);
// echo $calculator->operation('*','abc',999);
// echo '<hr>';
echo $calculator->operation('*','379',200);
echo '<hr>';
echo $calculator->operation('/', 678,234);
} catch (CalException $e) {
// 使用異常,將執行過程中可能出現的錯誤進行統一管理,更加優雅高效
// getCode(): 獲取自定義錯誤代碼, getMessage(): 獲取自定義錯誤信息
// echo $e->getCode(). ': ' .$e->getMessage();
echo $e->errorInfo();
}
```
*****
# :-: 四、框架中的模型的實現原理
* 框架中的模型, 通常會與一張數據表對應, 而模型對象,則與數據表中的一條記錄對應
* 這種數據表到類的映射關系, 對于面向對象的方式管理數據庫極其重要
```php
namespace jiangshi\ouyangke;
use PDO;
class User{
private $uid;
private $phone;
private $name;
private $age;
private $sex;
private $last_time;
// 屬性重載
public function __get($name){
return $this->$name;
}
public function __set($name, $value){
$this->$name = $value;
}
// 構造方法: 用于初始化或設置默認值
public function __construct(){
// 設置屬性值的自動轉換
// 將時間戳轉為日期字符串
$this->last_time = date('Y/m/d', $this->last_time);
// 將性別轉為可識別的字符
$this->sex = $this->sex ? '男' : '女';
}
}
$pdo = new PDO('mysql:host=localhost;dbname=ouyangke','root','root');
$stmt = $pdo->prepare('SELECT * FROM `user`');
$stmt->setFetchMode(PDO::FETCH_CLASS,User::class);
$stmt->execute();
//$obj = $stmt->fetch();
// 返回的每一條記錄都是User類的實例對象
//var_dump($obj);
while ($user = $stmt->fetch()) {
// 測試
// echo '<pre>' . print_r($user, true);
// 屬性重載的應用
echo "<li>{$user->uid}: {$user->name}--{$user->sex}--{$user->phone}--{$user->last_time}</li>";
}
```
*****
# :-: 五、文件上傳的完整流程
>[info] index.html文件
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--請求類型必須是POST, 數據編碼類型必須是: 復合表單數據,讓服務器知道上傳的是文件-->
<form action="demo5.php" method="post" enctype="multipart/form-data">
<input type="file" name="my_file" id="">
<!--隱藏域:限制上傳文件大小, 不超過php.ini: upload_max_filesize值-->
<!--1M=1024k=1048576字節, 3M = 3145728字節-->
<input type="hidden" name="MAX_FILE_SIZE" value="3145728">
<button>上傳</button>
</form>
</body>
</html>
```
>[info] upload.php文件
* 前單表單中進行一些必要的設置, 以支持文件上傳
* 后端PHP主要使用超全局變量: $_FILES 來處理上傳的文件
```php
// 1. 配置上傳參數
// 設置允許上傳的文件類型
$fileType = ['jpg', 'jpeg', 'png', 'gif'];
// 設置允許上傳的最大文件長度
$fileSize = 3145728;
// 上傳到服務器上指定的目錄
$filePath = '/uploads/';
// 上傳的原始文件名
$fileName = $_FILES['my_file']['name'];
// 上傳保存在服務器上的臨時文件名
$tempFile = $_FILES['my_file']['tmp_name'];
// 2. 判斷上傳是否成功?
// 主要是通過$_FILES['my_file']['error']值, 等于0成或,大于1出錯,出錯類型用switch分析
$uploadError = $_FILES['my_file']['error'];
if ($uploadError > 0) {
switch ($uploadError) {
case 1:
case 2: die('上傳文件不允許超過3M');
case 3: die('上傳文件不完整');
case 4: die('沒有文件被上傳');
default: die('未知錯誤');
}
}
// 3. 判斷文件擴展名是否正確?
$extension = explode('.',$fileName)[1];
if (!in_array($extension, $fileType)) {
die('不允許上傳' . $extension . '文件類型');
}
// 4. 為了防止同名文件相互覆蓋, 應該將上傳到指定目錄的文件重命名,例如用md5+時間戳
$fileName = date('YmdHis',time()).md5(mt_rand(1,99)) . '.' . $extension;
// 5. 判斷文件是否上傳成功?
// 判斷是否是通過post上傳的
if (is_uploaded_file($tempFile)) {
if (move_uploaded_file($tempFile, __DIR__ . $filePath.$fileName)) {
// 提示用戶上成功,并返回上一個頁面,再強行刷新當前頁面
echo '<script>alert("上傳成功");history.back();</script>';
} else {
die('文件無法移動到指定目錄,請檢查目錄權限');
}
} else {
die('非法操作');
}
exit();
```
- 序言
- PHP基礎
- 認識PHP
- 環境安裝
- PHP語法
- 流程控制
- PHP數組
- PHP函數
- PHP類與對象
- PHP命名空間
- PHP7新特性
- PHP方法庫
- PHP交互
- 前后端交互
- 項目常規開發流程
- MySQL數據庫
- 會話控制
- Ajax分頁技術
- 細說函數
- 類與對象
- 對象進階
- 類與對象進階
- OOP面向對象
- 設計模式
- 路由與模板引擎
- 異常類
- PHP爬蟲
- PHP抓取函數
- PHP匹配函數
- 正則表達式
- PHP字符串函數
- 抓取實戰
- PHP接口
- 了解接口
- PHP插件
- PHPSpreadsheet
- ThinkPHP6
- 安裝
- 架構
- 數據庫
- 數據庫操作
- 視圖
- 模版
- 模型
- 雜項
- 命令行
- 交互
- 微信小程序
- 介紹
- 配置
- 組件
- 交互
- API
- 其他知識
- 百度小程序
- 介紹
- 配置
- 組件
- 交互
- API
- 其他知識
- Linux
- 服務器上線流程
- 安裝svn
- MySQL
- 認識MySQL
- MySQL函數
- 雜項
- composer依賴管理工具