PHPで簡易なSQLiteデータベースを実装するクラス

PHPで簡易なSQLiteデータベースを実装するクラス

PHPで簡易なSQLiteデータベースを実装するクラス

概要

データベースの実装にはいろいろと準備が必要です。しかし、あらかじめ必要な機能をまとめたクラスを用意しておけば、そのクラスを継承するだけで実装できます。

今回はPHPで簡易なSQLiteデータベースをすぐに実装できるクラスを用意しました。

コードと実装方法

コード


<?php
class DBManager{
    
    private $db; //データベース本体
    private $table_name; //テーブル名
    private $key_list; //キーリスト
    
    /**
     * データベースへのアクセス
     * @param string $file_path データベースファイルパス
     * @param string $table_name テーブル名
     * @param string[] $key_list キーリスト
     * @return void
     */     
    protected function __construct($file_path, $table_name, $key_list){
        $this->key_list = $key_list;
        $this->table_name = $table_name; 
        $sql = 'sqlite:'. $file_path;
        if($this->db = new PDO($sql)){
            $this->createTable();
            $this->checkColumns();
        }
    }

    /**
     * データベースの接続解除
     * @return void
     */
    public function __destruct(){
        $this->db = null;
    }
    /**
     * データを追加
     * @param array $data_list 登録するデータの連想配列
     * @return boolean 登録の成否
     */
    public function insert($data_list){
        $register = $this->createRegisterData($data_list);
        if(!empty($register)){
            $sql = 'insert into '. $this->table_name. ' (';
            $tmp = ') values (';
            foreach(array_keys($register) as $key){
                $sql.= $key. ', ';
                $tmp.= ':'. $key. ', ';
            }
            $sql = rtrim($sql, ', '). rtrim($tmp, ', '). ')';
            $stm = $this->bind($this->db->prepare($sql), $register);
            return $stm->execute();
        }
        return false;
    }
    /**
     * データの更新
     * @param array $data_list 更新するデータ
     * @param string $where 検索する条件
     * @return boolean 登録の成否
     */
    public function update($data_list, $where = null){
        $register = $this->createRegisterData($data_list);
        if(!empty($register)){
            $sql = 'update '. $this->table_name. ' set ';
            foreach(array_keys($register) as $key){
                $sql.= $key. ' = :'. $key. ', ';
            }
            $sql = rtrim($sql, ', ');
            if($where !== null){
                $sql.= ' where '. $where;
            }
            $stm = $this->bind($this->db->prepare($sql), $register);
            return $stm->execute();
        }
        return false;
    }
    /**
     * データの有無を確認
     * @param string $where 検索する条件
     * @return boolean データの有無
     */
    public function exists($where){
        if(!empty($this->query(null, $where))){
            return true;
        }
        return false;
    }
    /**
     * データを取得
     * @param string $select 取得するカラム 'a,b,c' 
     * @param string $where 検索する条件 'a = 1 and b >= 2'
     * @param string $order ソートするカラム 'a ASC|DESC'
     * @param int $limit 取得するデータ数
     * @param int $chunk 階層分けする場合各階層のデータ数
     * @return array データの連想配列
     */
    public function query($select=null, $where=null, $order=null, $limit=null, $chunk=null){
        $sql = 'select ';
        if($select !== null){
            $sql.= $select;
        }else{
            $sql.= '*';
        }
        $sql.= ' from '. $this->table_name;
        if($where !== null){
            $sql.= ' where '. $where;
        }
        if($order !== null){
            $sql.= ' order by '. $order;
        }
        if($limit !== null){
            $sql.= ' limit '. $limit;
        }
        $stm = $this->db->query($sql);
        $data_list = $stm->fetchAll();
        if($chunk !== null){
            $data_list = array_chunk($data_list, $chunk);
        }
        return $data_list;
    }
    
    /**
     * データの削除
     * @param string $where 検索する条件
     */
    public function delete($where = null){
        $sql = 'delete from '. $this->table_name;
        if($where !== null){
            $sql.= ' where '. $where;
        }
        $this->db->exec($sql);
    }
    /**
     * カラムリストを取得する
     * @return string[] カラムリスト
     */
    public function getColumnList(){
        $sql = 'pragma table_info("'. $this->table_name. '")';
        $column_data_list = $this->db->query($sql);
        $column_list = array();
        foreach($column_data_list as $column_data){
            if(isset($column_data['name'])){
                $column_list[] = $column_data['name'];
            }
        }
        return $column_list;
    }
    /**
     * データの数を取得
     * @param string $where 検索する条件
     * @return int データの数
     */
    public function getCount($where=null){
        $data_list = $this->query(null, $where);
        return count($data_list);
    }
    
    /**
     * 値をバインドする
     * @param object $stm statementオブジェクト
     * @param array $register 登録するデータ
     * @return object statementオブジェクト
     */
    private function bind($stm, $register){
        foreach($register as $key => $value){
            $stm->bindValue(':'. $key, $value);
        }
        return $stm;
    }
    
    /**
     * 渡されたデータとキーリストから登録するデータを作成する
     * @param array $data_list 渡されたデータの連想配列
     * @return array 登録するデータの連想配列
     */
    private function createRegisterData($data_list){
        $register = array();
        foreach($this->key_list as $key){
            if(isset($data_list[$key])){
                $register[$key] = $data_list[$key];
            }
        }
        return $register;
    }
    /**
     * テーブルの作成
     * @return void
     */
    private function createTable(){
        $sql = 'create table if not exists ';
        $sql.= $this->table_name. ' (';
        foreach ($this->key_list as $key){
            $sql.= $key. ', ';
        }
        $this->db->exec(rtrim($sql, ', '). ')');
    }
    /**
     * データベースのカラムを調整
     * @return void
     */
    private function checkColumns(){
        $check = true;
        $column_list = $this->getColumnList();
        foreach($this->key_list as $key){
            if(!in_array($key, $column_list, true)){
                $check = false;
                break;
            }
        }
        if(!$check){
            $data_list = $this->query(null, null, null, null, null);
            $sql = 'drop table '. $this->table_name;
            $this->db->exec($sql);
            $this->createTable();
            foreach($data_list as $data){
                $this->insert($data);
            }
        }
    }
}

実装方法

上記のDBManagerを継承したクラスを作成します。データベースのテーブル1つにつき1つのクラスを作成してください。テーブル名を渡すときに条件で分岐させるなどの工夫をすれば1つのクラスで複数にも対応できます。


<?php
class DBTableA extends DBManager{
    
    private const TABLE_NAME = 'table_name';
    
    public const C_ID = 'id';
    public const C_NAME = 'name';
    public const C_AGE = 'age';
    public const C_ADDRESS = 'address';
    public const C_HEIGHT = 'height';
    
    public function __construct($file_path){
        parent::__construct($file_path, self::TABLE_NAME, 
            [self::C_ID. ' integer primary key autoincrement',
                self::C_NAME,
                self::C_AGE,
                self::C_ADDRESS,
                self::C_HEIGHT,
            ]);
    }
}

コンストラクターで親クラスのDBManagerに(データベースファイルのパス, テーブル名, キーリスト)を渡します。

DBManagerの中にカラムを自動的に変更する機能を用意してあるので、ここで渡すキーリストを変更するとデータベースのカラムがすぐに書き換えられます。すでにあるカラムを削除/変更する場合はそのカラムのデータごと削除されるので注意してください。

データベースにアクセスするときはこの子クラスをインスタンス化するだけです。


<?php
//アクセス
$db = new DBTableA('./sampleDB.db');

//カラムリスト取得
$column_list = $db->getColumnList();

//データの追加
$data = [
    DBTableA::C_NAME => 'Ethan',
    DBTableA::C_AGE => 20,
];
$db->insert($data);

//データの存在確認
$db->exists(DBTableA::C_ID. ' = "5"');

//全データを取得
$data_list = $db->query();

//データを更新
$data = [DBTableA::C_NAME => 'Ethan2'];
$db->update($data, DBTableA::C_AGE. ' <= "25"');

//データを削除
$db->delete(DBTableA::C_AGE. ' >= "35"');

//終了
$db = null;

メソッド解説

データの存在確認

boolean : exists(string $where)

データが1つ以上存在する場合はtrue、データが存在しなければfalseを返します。

$whereはデータを検索する条件の文字列です。"カラム名 = 値"のように渡します。複数条件の場合は、"カラム名 = 値 and カラム名 = 値"のように渡します。

データの追加

boolean : insert(array $data_list)

データの追加が成功した場合はtrueを返します。

$data_listは追加するデータの連想配列です。array(カラム名 => 値, カラム名 => 値)のように渡します。

データの更新

boolean : update(array $data_list, string $where = null)

データの更新が成功した場合はtrueを返します。

$data_listは更新するデータの更新部分の連想配列で、array(カラム名 => 値, カラム名 => 値)のように渡します。

$whereはデータを検索する条件の文字列です。"カラム名 = 値"のように渡します。複数条件の場合は、"カラム名 = 値 and カラム名 = 値"のように渡します。

データの取得

array : query(string $select=null, string $where=null, string $order=null, int $limit=null, int $chunk=null)

データを配列として取得します。

$selectは取得するカラムを指定する文字列です。全てのカラムを取得する場合はnullを渡します。

$whereは検索する条件の文字列で、"カラム名 = 値"のように渡します。複数条件の場合は、"カラム名 = 値 and カラム名 = 値"のように渡します。全てのデータを取得する場合はnullを渡します。

$orderはソートするカラム名です。"カラム名 ASC"のように渡します。ASC(昇順)、DESC(降順)。

$limitは取得するデータ数の限界値です。例えば、3を渡した場合、3つまでデータを取得します。

$chunkは階層分けするデータ数です。例えば、3を渡した場合、3つずつでデータを区切った多次元配列になります。

データの削除

void : delete(string $where=null)

$whereは検索する条件の文字列で、"カラム名 = 値"のように渡します。複数条件の場合は、"カラム名 = 値 and カラム名 = 値"のように渡します。全てのデータを削除する場合はnullを渡します。

カラム一覧の取得

string[] : getColumnList()

カラムリストの配列を取得します。

データ数取得

int : getCount(string $where=null)

条件に当てはまったデータの数を取得します。

$whereは検索する条件の文字列で、"カラム名 = 値"のように渡します。複数条件の場合は、"カラム名 = 値 and カラム名 = 値"のように渡します。全てのデータをカウントする場合はnullを渡します。

投稿されたコメント一覧

コメント投稿フォーム

必須項目
任意項目

ウェブサービス一覧