PDOのラッパー関数＋クラスの例

**思いつきで**PDOのラッパーを作ってみたのでコードラクガキ。
メリットはコードが完結になるとこかな・・・。

関数を接続の軸として、ラッパークラスを呼び出してる。
ラッパークラスは、**基本的に [PDOクラス](http://php.net/manual/ja/class.pdo.php) を `__call()` で呼び出してるだけ**だけど、いくつかサンプルで独自のメソッドを入れてみた。

## 本体ファイル

```php:db.php
<?php
// 接続情報
$GLOBALS['db'] = array(
    'host' => 'localhost',
    'user' => 'root',
    'pass' => 'pass',
    'name' => 'mydb',
    'charset' => 'utf8',
);

// 接続用関数
function db($dbname = null)
{
    static $connect = null, $default = null, $current = null;

    if (is_object($connect)) {
        if (!empty($dbname) && is_string($dbname)) {
            $current = $dbname;
            try {
                $connect->exec("USE `{$dbname}`;");
            } catch (PDOException $e) {
                trigger_error($e->getMessage(), E_USER_WARNING);
                return $connect;
            } catch (Exception $e) {
                trigger_error($e->getMessage(), E_USER_WARNING);
                return $connect;
            }
        } elseif($default != $current) {
            try {
                if($connect->exec("USE `{$default}`;")) {
                    $current = $default;
                }
            } catch (PDOException $e) {
                trigger_error($e->getMessage(), E_USER_WARNING);
                return $connect;
            } catch (Exception $e) {
                trigger_error($e->getMessage(), E_USER_WARNING);
                return $connect;
            }
        }
        return $connect;
    }

    if (empty($GLOBALS['db'])) {
        trigger_error('DB setting required');
        return false;
    }

    $config = $GLOBALS['db'];

    if (array_key_exists('dbname', $config)) {
        $config['name'] = $config['dbname'];
    }

    $default = $config['name'];

    if (!empty($dbname) && is_string($dbname)) {
        $config['name'] = $dbname;
    }

    if (
        empty($config) || !is_array($config)
        || empty($config['host']) || !is_string($config['host'])
        || empty($config['user']) || !is_string($config['user'])
        || empty($config['pass']) || !is_string($config['pass'])
        || empty($config['name']) || !is_string($config['name'])
    ) {
        trigger_error('DB setting is not correct', E_USER_WARNING);
        return false;
    }

    $config['charset'] = (empty($config['charset']) ? 'utf8' : $config['charset']);

    $dsn = 'mysql:';
    $dsn .= 'dbname='.$config['name'].';';
    $dsn .= 'host='.$config['host'].';';
    $dsn .= 'charset='.$config['charset'];
    
    $pdo = null;
    try {
        $pdo = new PDO($dsn, $config['user'], $config['pass'], array(
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES => false,
        ));
    } catch (PDOException $e) {
        trigger_error($e->getMessage(), E_USER_WARNING);
        return false;
    } catch (Exception $e) {
        trigger_error($e->getMessage(), E_USER_WARNING);
        return false;
    }

    if (is_object($pdo)) {
        $current = $config['name'];
        return $connect = new db($pdo);
    }
}

// ラッパークラス
class db
{
    public $connect = null;

    public function __construct($connect = null)
    {
        $this->connect = $connect;
    }

    public function __call($name = null, $args = null)
    {
        if (!is_object($this->connect)) {
            return false;
        }

        if (method_exists($this->connect, $name)) {
            return call_user_func_array(array($this->connect, $name), $args);
        }
    }

    // テーブル一覧を取得するメソッド
    public function tables($dbname = null)
    {

        static $buffer = array();

        try {
            if (empty($dbname)) {
                $dbname = $this->connect->query("SELECT DATABASE();")->fetchColumn();
            }

            if (!empty($buffer[$dbname])) {
                return $buffer[$dbname];
            }

            if ($query = $this->connect->query("SHOW TABLES FROM `{$dbname}`;")) {
                $datas = array();
                foreach($query->fetchAll(PDO::FETCH_NUM) as $val) {
                    $datas[] = $val[0];
                }
                return $buffer[$dbname] = $datas;
            }
        } catch (PDOException $e) {
            trigger_error($e->getMessage(), E_USER_WARNING);
            return false;
        }
    }

    // テーブルの情報を取得するメソッド
    public function status($table = null)
    {
        if (empty($table) || !is_string($table)) {
            trigger_error('Table name required', E_USER_WARNING);
            return false;
        }

        static $buffer = array();
        if (!empty($buffer[$table])) {
            return $buffer[$table];
            
        }

        try {
            if ($query = $this->connect->query("SHOW TABLE STATUS LIKE '{$table}';")) {
                return $buffer[$table] = $query->fetch(PDO::FETCH_ASSOC);
            }
        } catch (PDOException $e) {
            trigger_error($e->getMessage(), E_USER_WARNING);
            return false;
        }
    }

    // テーブルのカラムの詳細一覧を取得するメソッド
    public function columns($table = null, $column = null)
    {
        if (empty($table) || !is_string($table)) {
            trigger_error('Table name required', E_USER_WARNING);
            return false;
        }

        static $buffer = array();
        if (!empty($buffer[$table])) {
            if (!empty($column)) {
                if (!empty($buffer[$table][$column])) {
                    return $buffer[$table][$column];
                } else {
                    return null;
                }
            } else {
                return $buffer[$table];
            }
            
        }

        try {
            if ($query = $this->connect->query("SHOW FULL COLUMNS FROM `{$table}`;")) {
                $datas = array();
                while($val = $query->fetch(PDO::FETCH_ASSOC)) {
                    $datas[$val['Field']] = $val;
                }
                $buffer[$table] = $datas;
                
                if (!empty($column)) {
                    if (!empty($datas[$column])) {
                        return $datas[$column];
                    }
                } else {
                    return $datas;
                }
            }
        } catch (PDOException $e) {
            trigger_error($e->getMessage(), E_USER_WARNING);
            return false;
        }
    }

    // テーブルのカラム名のみ取得するメソッド
    public function colnames($table = null)
    {
        if (!$datas = $this->columns($table)) {
            return false;
        }

        return $buffer = array_keys($datas);
    }
}
```

## 実行例

```php:実行例
// 例）普通にデータ取得
$data = db()->query("SELECT * FROM `mytable` LIMIT 10;")->fetchAll();

// 例）上と違うDB（ここでは「mydb2」）からデータ取得
$data = db("mydb2")->query("SELECT `id` FROM `other` LIMIT 1;")->fetchColumn();

// 例）[拡張メソッド] テーブル一覧の取得
$data = db()->tables(); // 現DBのテーブル一覧
$data = db("mydb2")->tables();// データベース「mydb2」のテーブル一覧

// 例）[拡張メソッド] 特定テーブルの情報を取得
$data = db()->status("mytable"); // テーブル「mytable」の情報取得

// 例）[拡張メソッド] 特定テーブルのカラム情報を取得
$data = db()->columns("mytable"); // テーブル「mytable」のカラム情報取得

// 例）[拡張メソッド] 特定テーブルのカラム名のみを取得
$data = db()->colnames("mytable");
```

エラー処理とかは激甘だけどわりと動いたw