/ PHP

[PHP note.] 微型專案 Part 2

上次寫過了微型專案 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 所以大抵上我只能收GETPOST會比較正常。至於PUTDELETE什麼時候能處理呢?我也不知道(聳肩

至於我剛剛埋了什麼 Bug,就留給大家啦(燦笑