上次寫過了微型專案 Part 1,所以今天就繼續寫 Part 2,一樣是嘴砲文居多,所以如果有大神路過可以直接按 Alt+F4
跳過這樣(無誤。
那我們就繼續了。
錯誤控制
通常我們是會用簡單的if...else
來作一些例外的控制,這是最直觀也最方便的模式。然後,我們就會需要一個容器來幫我做這些錯誤的判斷、顯示、控制輸出等等。
所以,我可以在原先的 bootstrap.php 裡面加入一個叫做 Error 的靜態類別來幫我們做這件事情。
<?php
class Error {
public $error_codes;
public static function bind() {
$this->error_codes = array(
'5000' => '這是一個錯誤訊息喔~'
);
}
public static response($codes = 5000) {
return $this->error_codes[$codes];
}
}
?>
這樣就是簡易的錯誤輸出了,不過好像有奇怪的東西混進來某些地方怪怪的?是的,這只是輸出錯誤訊息而已,如果我們要連同header
一起送出的話,我們就需要在多一個東西來幫我們做輸出。
<?php
public static response($codes = 5000) {
header('HTTP/1.0 400 BAD REQUEST');
echo '<h1>'.$this->error_cdes[$codes].'</h1>';
exit;
}
?>
這樣就直接以HTTP 400 BAD REQUEST
的狀態把資料送出了。如果,你要做紀錄的話,就在exit
之前作掉就可以了。所以我在 Api 這個 Controller 要做錯誤輸出,就使用Error::response(5000)
就可以了。
紀錄檔
當然,我們要把錯誤記錄下來,所以也可以寫一個靜態類別來幫我們做這件事情。其實只是很單純的檔案操作,所以要怎麼操作就見仁見智。這裡給個簡單的範例,大概描述一下紀錄操作。
<?php
class Log {
public function write($content, $filename = 'debug', $dir = '') {
if (is_array($dir)) {
$check_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'logs';
foreach($dir as d) {
if (!is_dir($check_path . $d)) {
@mkdir ($check_path . $d);
@chmod ($check_path . $d, 0777);
}
$check_path .= $d . DIRECTORY_SEPARATOR;
}
$dir = implode(DIRECTORY_SEPARATOR, $dir);
} elseif (is_string($dir) && !empty($dir)) {
$check_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'logs' . DIRECTORY_SEPARATOR;
if (!is_dir($check_path . $dir)) {
@mkdir ($check_path . $dir);
@chmod ($check_path . $dir, 0777);
}
}
$filename .= ".log";
$real_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'logs' . DIRECTORY_SEPARATOR . $filename;
if (is_string($content)) {
$content = '['.date("Y-m-d H:i:s).']'.$content."\n";
file_put_contents($real_path, $content, FILE_APPEND);
} else {
ob_start();
echo '['.date("Y-m-d H:i:s).']';
print_r($content);
echo "\n";
$raw = ob_get_contents();
ob_end_clean();
file_put_contents($real_path, $raw, FILE_APPEND);
}
}
}
?>
寫得有點紊亂,而且我埋了一個 bug 在裡面,所以拷貝貼上記得要改喔(啾咪
Idiorm 資料庫操作
這是一套很輕量化的資料庫操作套件,基本上有點類似Doctrine,但是他沒有 Doctrine 那麼複雜。然後,由於我們是使用 UTF-8,所以我必須要多做一行設定。
ORM::configure('mysql:host=localhost;dbname=api');
ORM::configure('username', 'hinablue');
ORM::configure('password', 'calineILoveYou');
// 這一行,如果你的資料庫都是英文資料,就沒差。
// 但是由於我是台灣人,所以加上這一行也是很合理的。
ORM::configure('driver_options', array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
畢竟他是 ORM,所以請在資料結構上下一點功夫,不然資料庫跑起 Query 可能會是很難看的數據。這是 ORM 的優點,也是缺點。雖然我們可以很直觀的去下一組 MySQL Query 來取資料,但是萬一被中出了,可能就笑不出來了。
<?php
$oops = "SELECT * FROM `users` WHERE `username`='".$_POST['username']."' AND `password` ='".$_POST['password']."'";
// 要爆了!
?>
關於中出的文章,問問咕狗大神可以問到很多,你可以參考 appleboy 寫得這一篇PHP+MySQL 環境下 SQL Injection 攻防戰,希望大家不要常常被中出。
RESTful 是什麼?
石頭寫了兩篇非常棒的文章,我也是由這裡開始做我的 RESTful 的介面的。
擴充元件
Components 很好用,怎麼用呢?我們下次見(喂
設定檔案
控制元件內,我們會定義很多固定的數值,通常會是常數或是魔術數字等等。那,下次再說(喂喂
小結
對於 RESTful 來說,我們有四種方法可以使用GET
,POST
,PUT
,DELETE
,但是,因為我們後端是 PHP 所以大抵上我只能收GET
和POST
會比較正常。至於PUT
跟DELETE
什麼時候能處理呢?我也不知道(聳肩
至於我剛剛埋了什麼 Bug,就留給大家啦(燦笑