上次寫過了微型專案 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,就留給大家啦(燦笑