本地開發環境
使用本地apache和mysql,配置www.api.com虛擬主機。
接口項目需求
- 用戶登錄
- 用戶注冊
確認項目需求要素
- 資源路徑(/users)
- HTTP動詞(POST)
- 狀態碼(200,204,400,401,403,404,405,500)
- 錯誤處理(輸出JSON格式錯誤信息)
- 返回結果(輸出JSON數組或JSON對象)
數據庫設計
用戶登錄和注冊業務邏輯設計
lib/db.php(連接數據庫)
1 <?php 2 // 鏈接數據庫 3 $pdo=new PDO("mysql:host=localhost;dbname=api","root",""); 4 // 設置字符集編碼 5 $pdo->exec("set names utf8"); 6 return $pdo; 7 ?>
lib/ErrorCode.php
1 <?php 2 /** 3 * 錯誤碼 4 */ 5 class ErrorCode 6 { 7 const USERNAME_CANNOT_EMPTY=1;//用戶名不能為空 8 const PASSWORD_CANNOT_EMPTY=2;//密碼不能為空 9 const USERNAME_EXISTS=3;//用戶名已存在 10 const REGISTER_FAIL=4;//注冊失敗 11 const LOGIN_USERNAME_CANNOT_EMPTY=5;//登錄用戶名為空 12 const LOGIN_PASSWORD_CANNOT_EMPTY=6;//登錄密碼不能為空 13 const LOGIN_FAIL=7;//登錄失敗 14 } 15 ?>
lib/User.php
1 <?php 2 // 導入錯誤碼類 3 require_once __DIR__."/ErrorCode.php"; 4 /** 5 * 實現用戶注冊的業務邏輯設計 6 */ 7 class User 8 { 9 //屬性 10 private $_db;//存儲pdo 11 /** 12 * 屬性賦值 13 * @param [type] $_db [description] 14 */ 15 public function __construct($_db) 16 { 17 $this->_db=$_db; 18 } 19 /** 20 * 登錄的方法 21 * @param [type] $username 登錄用戶名 22 * @param [type] $password 登錄密碼 23 * @return array [description] 24 */ 25 public function login($username,$password) 26 { 27 // 1.檢測是否能接收到數據 28 // echo $username.$password; 29 // 判斷登錄的用戶名是否為空 30 if (empty($username)) { 31 throw new Exception("用戶名為空",ErrorCode::LOGIN_USERNAME_CANNOT_EMPTY); 32 } 33 // 判斷登錄密碼是否為空 34 if (empty($password)) { 35 throw new Exception("密碼為空",ErrorCode::LOGIN_PASSWORD_CANNOT_EMPTY); 36 } 37 $sql="select * from users where username=:username and password=:password"; 38 // 密碼加密 39 $password=$this->_md5($password); 40 // 預處理 41 $list1=$this->_db->prepare($sql); 42 // 綁定參數 43 $list1->bindParam("username",$username); 44 $list1->bindParam("password",$password); 45 // 執行 46 $list1->execute(); 47 // 獲取結果集 48 $user=$list1->fetch(PDO::FETCH_ASSOC); 49 if (empty($user)) { 50 throw new Exception("登錄的用戶名或密碼有誤",ErrorCode::LOGIN_FAIL); 51 } 52 return $user; 53 } 54 /** 55 * 注冊方法 56 * @param [type] $username [注冊用戶名] 57 * @param [type] $password 注冊密碼 58 * @return array 返回注冊成功后的數據 59 */ 60 public function register($username,$password) 61 { 62 // 1.測試是否調用成功 63 // echo "this is register"; 64 // 2.測試$_db屬性是否賦值成功 65 // echo "<pre>"; 66 // var_dump($this->_db); 67 // 3.測試是否接收到$username和$password 68 // echo $username.$password; 69 // 4.把接收到的$username和$password寫入到users庫 70 // 判斷注冊的用戶名是否為空 71 if (empty($username)) { 72 // 如果用戶名為空拋出異常, 第一個參數返回信息,第二個參數為狀態碼(ErrorCode類里的USERNAME_CONNOT_EMPTY靜態屬性) 73 throw new Exception("用戶名不能為空",ErrorCode::USERNAME_CANNOT_EMPTY); 74 } 75 // 判斷密碼是否為空 76 if (empty($password)) { 77 throw new Exception("密碼不能為空",ErrorCode::PASSWORD_CANNOT_EMPTY); 78 } 79 // 判斷注冊的用戶名是否已存在 80 if ($this->isUsernameExists($username)) { 81 throw new Exception("用戶名已經注冊",ErrorCode::USERNAME_EXISTS); 82 } 83 // 入庫 84 $sql="insert into users (username,password,created_at)values(:username,:password,:created_at)"; 85 // 處理接收到的數據 86 $created_at=time(); 87 $password=$this->_md5($password); 88 // 返回預處理 89 $list=$this->_db->prepare($sql); 90 // 綁定參數 91 $list->bindParam("username",$username); 92 $list->bindParam("password",$password); 93 $list->bindParam("created_at",$created_at); 94 // 判斷執行是否成功 95 if (!$list->execute()) { 96 throw new Exception("注冊失敗",ErrorCode::REGISTER_FAIL); 97 } 98 // 返回數據 99 return [ 100 'user_id'=>$this->_db->lastInsertId(), 101 'username'=>$username, 102 'created_at'=>$created_at 103 ]; 104 105 } 106 /** 107 * 檢測用戶名是否已存在的方法 108 * @param [type] $username [description] 109 * @return boolean [description] 110 */ 111 public function isUsernameExists($username) 112 { 113 $extists=false; 114 115 $sql="select * from users where username=:username"; 116 // 返回預處理 117 $sm=$this->_db->prepare($sql); 118 //綁定參數 119 $sm->bindParam("username",$username); 120 //執行 121 $sm->execute(); 122 // 獲取結果 123 $res=$sm->fetch(PDO::FETCH_ASSOC); 124 return !empty($res); 125 } 126 /** 127 * md5加密密碼 128 * @param [type] $string [description] 129 * @return [type] [description] 130 */ 131 public function _md5($string) 132 { 133 return md5($string); 134 } 135 } 136 137 ?>
index.php
1 <?php 2 // 導入User.php 3 require __DIR__."/lib/User.php"; 4 // 導入db.php 5 require __DIR__."/lib/db.php"; 6 7 // 實例化User類 $pdo傳入連接庫 8 $user=new User($pdo); 9 // 調用注冊方法 實現注冊業務邏輯操作 10 // echo "<pre>"; 11 // print_r($user->register("admin6","1213")); 12 13 // 調用登錄的方法 實現登錄的業務邏輯操作 14 // $user->login("admin3","1213"); 15 // 檢測是否實現登錄業務邏輯操作 16 echo "<pre>"; 17 // print_r($user->login("admin4","1213")); 18 ?>
初始化參數和完善用戶登錄及注冊API
restful/.htaccess(用於重寫index.php)
RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php/$1 [L]
restful/index.php
1 <?php 2 //restful的入口文件里導入用戶注冊的業務邏輯類 3 require __DIR__."/../lib/User.php"; 4 //導入鏈接數據庫的業務類 5 require __DIR__."/../lib/db.php"; 6 7 /** 8 * 實現用戶注冊API 接口參數完善 9 */ 10 class Restful 11 { 12 // 設置私有成員屬性 13 private $_user;//User類的對象 14 private $_requestMethod;//接口的請求方法 http動詞集合 15 private $_resourceName;//接口的請求資源路徑 請求資源路徑集合 16 private $_allowResource=['users'];//接口允許的請求資源路徑 17 private $_allowRequestMethod=['GET','POST','PUT','DELETE'];//接口允許請求方法 18 //狀態碼 19 private $_statusCode=[ 20 200=>'OK', 21 204=>'NO CONTENT', 22 400=>'Bad Request',//請求出了問題 23 401=>'request auth is valid',//請求沒有授權 24 403=>'forbiden',//服務器禁止訪問 25 404=>"Not Fond",//找不到服務器 26 405=>'methis is not allowed',//請求方式不允許 27 500=>'server Interval error',//服務器未知錯誤 28 ]; 29 /** 30 * 屬性賦值 31 * @param User $_user User類約束 user實例化的對象 32 */ 33 public function __construct(User $_user) 34 { 35 $this->_user=$_user; 36 } 37 /** 38 * run 方法 完善用戶注冊的參數 39 * 資源路徑 http動詞 返回碼 返回錯誤碼 返回的響應數據 40 * @return [type] [description] 41 */ 42 public function run() 43 { 44 try { 45 // 調用初始化請求方法 46 $this->_setupRequestMethod(); 47 // 初始化請求資源路徑 48 $this->_setupResource(); 49 //規定請求資源路徑 返回響應數據 50 if ($this->_resourceName=="users") { 51 return $this->_json($this->_headerUser()); 52 } 53 } catch (Exception $e) { 54 // getMessage()獲取錯誤信息 getCode() 獲取錯誤碼 55 $this->_json(['error'=>$e->getMessage()],$e->getCode()); 56 } 57 } 58 /** 59 * 初始化請求方法 60 * @return [type] [description] 61 */ 62 public function _setupRequestMethod() 63 { 64 // echo "<pre>"; 65 // print_r($_SERVER); 66 // 賦值請求方式 67 $this->_requestMethod=$_SERVER['REQUEST_METHOD']; 68 // 判斷接口的請求方法是否存在於允許的請求方法內 69 if (!in_array($this->_requestMethod,$this->_allowRequestMethod)) { 70 throw new Exception("請求方法不允許",405); 71 } 72 } 73 /** 74 * 初始化請求資源路徑 75 * @return [type] [description] 76 */ 77 public function _setupResource() 78 { 79 // echo "<pre>"; 80 // print_r($_SERVER); 81 // 獲取請求資源路徑 82 $path=$_SERVER['PATH_INFO']; 83 // echo $path; 84 //轉換為數組 85 $param=explode("/",$path); 86 // print_r($param); 87 // 請求資源路徑 88 $this->_resourceName=$param[1]; 89 if (!in_array($this->_resourceName, $this->_allowResource)) { 90 throw new Exception("請求資源路徑不允許", 400); 91 } 92 } 93 /** 94 * 返回調用接口的數據(獲取客戶端提交的數據) 95 * @return json 返回調用接口的json格式數據 96 */ 97 public function _headerUser() 98 { 99 //判斷請求的方式是否為post 100 if ($this->_requestMethod!="POST") { 101 throw new Exception("請求方式不允許",405); 102 } 103 //獲取客戶端提交的數據 104 $body=$this->_getBodyParams(); 105 106 // 獲取請求資源路徑 107 $path=$_SERVER['PATH_INFO']; 108 //轉換為數組 109 $param=explode("/",$path); 110 // 判斷是登錄還是注冊 111 if ($param[2]=="register") { 112 // 判斷用戶名不能為空 113 if (empty($body['username'])) { 114 throw new Exception("用戶名不能為空",400); 115 } 116 // 判斷密碼不能為空 117 if (empty($body['password'])) { 118 throw new Exception("密碼不能為空",400); 119 } 120 121 //返回調用接口的json數據 122 return $this->_user->register($body['username'],$body['password']); 123 }elseif ($param[2]=="login") { 124 // 判斷用戶名為空 125 if (empty($body['username'])) { 126 throw new Exception("用戶名為空",400); 127 } 128 // 判斷密碼為空 129 if (empty($body['password'])) { 130 throw new Exception("密碼為空",400); 131 } 132 //返回登錄調用接口的json數據 133 return $this->_user->login($body['username'],$body['password']); 134 }else{ 135 throw new Exception("請求資源路徑不允許",400); 136 } 137 138 139 } 140 /** 141 * 獲取客戶端提交的數據 142 * @return array 獲取客戶端提交的數據(username,password) 143 */ 144 public function _getBodyParams() 145 { 146 $raw=file_get_contents('php://input'); 147 if (empty($raw)) { 148 throw new Exception("請求參數有誤",400); 149 } 150 // 把客戶端傳遞的json格式數據轉換為數組格式 151 return json_decode($raw,true); 152 } 153 /** 154 * 轉換響應數據(響應的狀態碼)的格式 155 * @param array $array 具體錯誤信息 156 * @param integer $code 具體的相應狀態碼 157 * @return [type] [description] 158 */ 159 public function _json($array,$code=0) 160 { 161 if ($code >0 && $code !== 200 && $code != 204) { 162 //把狀態碼寫入到響應頭里 163 header("HTTP/1.1 $code"); 164 } 165 header("Content-type:application/json;charset=utf-8"); 166 //把響應體轉換為json格式輸出 JSON_UNESCAPED_UNICODE 轉義參數 防止有特殊字符和空格出現 167 echo json_encode($array,JSON_UNESCAPED_UNICODE); 168 } 169 } 170 171 // 實例化USer 172 $user=new User($pdo); 173 // 調用Restful類的run方法 174 $Restful=new Restful($user); 175 $Restful->run(); 176 177 ?>
注:if語句也可以換成switch語句
2020-04-07