博客园  :: 首页  :: 新随笔  :: 订阅 订阅  :: 管理

PHP 简易文件数据库

Posted on 2020-08-22 10:37  PHP-张工  阅读(550)  评论(0编辑  收藏  举报
<?php

// 文件数据库
class ZFileDB
{
    // 选择表
    public static function table($_table, $_db = 'db01')
    {
        $db = new ZFileDB($_table, $_db);

        return $db;
    }

    private $table = '';
    private $db_file = '';
    private $head_file = '';
    private $where = [];
    private $info = null;
    private $sort = '';

    // 构造函数
    public function ZFileDB($_table, $_db = 'db01')
    {
        $this -> table = $_table;
        if (strpos($_db, '/') === false)
        {
            $this -> db_file = './' . $_db . '/' . $_table . '.zdb';
            $this -> head_file = './' . $_db . '/' . $_table . '.zdbh';
        }
        else
        {
            $this -> db_file = $_db . '/' . $_table . '.zdb';
            $this -> head_file = $_db . '/' . $_table . '.zdbh';
        }

        if (!file_exists($this -> db_file))
        {
            $this -> init();
        }

        // 获取信息
        $content = @file_get_contents($this -> head_file);
        $this -> info = json_decode($content, true);
    }

    // 初始化
    private function init()
    {
        $content = [
            'version'     => 'ZFileDB v1.0',
            'table'       => $this -> table,
            'last_id'     => 0,
            'count'       => 0,
            'create_time' => date('Y-m-d H:i:s'),
            'last_time'   => date('Y-m-d H:i:s'),
        ];

        file_put_contents($this -> head_file, json_encode($content));
        file_put_contents($this -> db_file, '');
    }

    // 获取信息
    public function info()
    {
        return $this -> info;
    }
    
    // 保存信息
    private function info_save()
    {
        return file_put_contents($this -> head_file, json_encode($this -> info));
    }

    // 获取列表
    public function select()
    {
        $list = [];

        $handle = @fopen($this -> db_file, 'r');
        while (($buffer = fgets($handle)) !== false)
        {
            $item = $this -> parseWhere($buffer);
            if ($item !== null)
            {
                $list[] = $item;
            }
        }
        fclose($handle);

        // 处理排序
        if ($this -> sort != '')
        {
            $sort_key = $sort = trim($this -> sort);
            $sort_attr = SORT_REGULAR;

            if (strtolower(substr($sort, -5)) == ' desc')
            {
                $sort_attr = $sort_attr|SORT_DESC;
                $sort_key = substr($sort, 0, -5);
            }

            $sort_data = [];

            foreach ($list as $key => $arr)
            {
                $sort_data[$key] = $arr[$sort_key];
            }
  
            array_multisort($sort_data, $sort_attr, $list);
        }

        return $list;
    }

    public function order($sort)
    {
        $this -> sort = $sort;

        return $this;
    }

    // 获取单条值
    public function find($id)
    {
        if (empty($id))
        {
            return null;
        }

        $item = null;

        $id = intval($id);
        $index = 0;
        $handle = @fopen($this -> db_file, 'r');
        while (($buffer = fgets($handle)) !== false)
        {
            $index++;
            if ($index == $id)
            {
                $item = trim($buffer);
                $item = json_decode($item, true);
                break;
            }
        }
        fclose($handle);

        return $item;
    }

    // 条件过滤
    public function where($key, $op, $val = null)
    {
        if ($val === null)
        {
            return $this -> where($key, '=', $op);
        }

        $this -> where[] = [$key, $op, $val];

        return $this;
    }

    // 解析条件过滤
    private function parseWhere($str)
    {
        $str = trim($str);
        if (empty($str))
        {
            return null;
        }

        $item = json_decode($str, true);

        if ($item === false)
        {
            return null;
        }

        if (!empty($this -> where))
        {
            $bo = true;
            foreach ($this -> where as $r)
            {
                $k = $r[0];
                $v = $r[2];
                if (!isset($item[$k]))
                {
                    return null;
                }
                switch ($r[1])
                {
                    case '=':
                        if ($item[$k] != $v)
                        {
                            return null;
                        }
                        break;
                    case '>':
                        if ($item[$k] <= $v)
                        {
                            return null;
                        }
                        break;
                    case '<':
                        if ($item[$k] >= $v)
                        {
                            return null;
                        }
                        break;
                }
            }
        }

        return $item;
    }

    // 数量限制
    public function selectLimit($start, $length = 0)
    {
        if ($length === 0)
        {
            $length = $start;
            $start = 0;
        }

        if ($length <= 0)
        {
            return [];
        }

        $list = [];

        $index = 0;
        $count = 0;
        $handle = @fopen($this -> db_file, 'r');
        while (($buffer = fgets($handle)) !== false)
        {
            $item = $this -> parseWhere($buffer);
            if ($item !== null)
            {
                $index++;
                if ($index > $start)
                {
                    $count++;
                    $list[] = $item;
                }

                if ($count >= $length)
                {
                    break;
                }
            }
        }
        fclose($handle);

        return $list;
    }

    // 数量查询
    public function count()
    {
        $count = 0;

        $handle = @fopen($this -> db_file, 'r');
        while (($buffer = fgets($handle)) !== false)
        {
            $item = $this -> parseWhere($buffer);
            if ($item !== null)
            {
                $count++;
            }
        }
        fclose($handle);

        return $count;
    }

    // 插入单条数据
    public function insert($item)
    {
        $this -> info['last_id']++;
        $this -> info['count']++;

        $item['id'] = $this -> info['last_id'];

        file_put_contents($this -> db_file, json_encode($item) . PHP_EOL, FILE_APPEND|LOCK_EX);

        $this -> info_save();

        return $item['id'];
    }

    // 批量插入
    public function insertAll($list)
    {
        $content = '';
        foreach ($list as $r)
        {
            $this -> info['last_id']++;
            $this -> info['count']++;
    
            $r['id'] = $this -> info['last_id'];

            $content .= json_encode($r) . PHP_EOL;
        }
        
        file_put_contents($this -> db_file, $content, FILE_APPEND|LOCK_EX);

        $this -> info_save();

        return count($list);
    }

    // 条件更新
    private function updateWhere($update)
    {
        $bo = false;
        
        $handle_writer = @fopen($this -> db_file . 'w', 'w');
        $handle_reader = @fopen($this -> db_file, 'r');
        while (($buffer = fgets($handle_reader)) !== false)
        {
            $item = $this -> parseWhere($buffer);
            if ($item !== null)
            {
                $new = array_merge($item, $update);
                fputs($handle_writer, json_encode($new) . PHP_EOL);
                $bo = true;
            }
            else
            {
                fputs($handle_writer, $buffer);
            }
        }
        fclose($handle_reader);
        fclose($handle_writer);

        if ($bo)
        {
            rename($this -> db_file . 'w', $this -> db_file);
        }
        else
        {
            unlink($this -> db_file . 'w');
        }
    }

    // 单条更新
    public function update($item)
    {
        if (!empty($this -> where))
        {
            if (isset($item['id']))
            {
                return false;
            }

            $this -> updateWhere($item);

            return true;
        }

        if (empty($item['id']))
        {
            return false;
        }

        $bo = false;
        $id = $item['id'];
        $index = 0;
        $handle_writer = @fopen($this -> db_file . 'w', 'w');
        $handle_reader = @fopen($this -> db_file, 'r');
        while (($buffer = fgets($handle_reader)) !== false)
        {
            $index++;
            if ($index == $id)
            {
                $old = trim($buffer);
                $old = json_decode($old, true);
                if (!empty($old))
                {
                    $new = array_merge($old, $item);
                    fputs($handle_writer, json_encode($new) . PHP_EOL);
                    $bo = true;
                }
                else
                {
                    fputs($handle_writer, $buffer);
                }
            }
            else
            {
                fputs($handle_writer, $buffer);
            }
        }
        fclose($handle_reader);
        fclose($handle_writer);

        if ($bo)
        {
            rename($this -> db_file . 'w', $this -> db_file);
        }
        else
        {
            unlink($this -> db_file . 'w');
        }

        return $bo;
    }

    // 批量更新
    public function updateAll($list)
    {
        $arr = array_column($list, null, 'id');
        
        $count = 0;
        $index = 0;
        $handle_writer = @fopen($this -> db_file . 'w', 'w');
        $handle_reader = @fopen($this -> db_file, 'r');
        while (($buffer = fgets($handle_reader)) !== false)
        {
            $index++;
            if (isset($arr[$index]))
            {
                $old = trim($buffer);
                $old = json_decode($old, true);
                if (!empty($old))
                {
                    $new = array_merge($old, $arr[$index]);
                    fputs($handle_writer, json_encode($new) . PHP_EOL);
                    $count++;
                }
                else
                {
                    fputs($handle_writer, $buffer);
                }
            }
            else
            {
                fputs($handle_writer, $buffer);
            }
        }
        fclose($handle_reader);
        fclose($handle_writer);

        if ($count > 0)
        {
            rename($this -> db_file . 'w', $this -> db_file);
        }
        else
        {
            unlink($this -> db_file . 'w');
        }

        return $count;
    }

    // 条件删除
    private function deleteWhere()
    {
        $bo = false;
        
        $handle_writer = @fopen($this -> db_file . 'w', 'w');
        $handle_reader = @fopen($this -> db_file, 'r');
        while (($buffer = fgets($handle_reader)) !== false)
        {
            $item = $this -> parseWhere($buffer);
            if ($item !== null)
            {
                fputs($handle_writer, PHP_EOL);
                $bo = true;
                $this -> info['count']--;
            }
            else
            {
                fputs($handle_writer, $buffer);
            }
        }
        fclose($handle_reader);
        fclose($handle_writer);

        if ($bo)
        {
            rename($this -> db_file . 'w', $this -> db_file);
            $this -> info_save();
        }
        else
        {
            unlink($this -> db_file . 'w');
        }
    }

    // 删除
    public function delete($id = null)
    {
        if (!empty($this -> where))
        {
            $this -> deleteWhere();

            return true;
        }

        if (empty($id))
        {
            return false;
        }

        $bo = false;
        $index = 0;
        $handle_writer = @fopen($this -> db_file . 'w', 'w');
        $handle_reader = @fopen($this -> db_file, 'r');
        while (($buffer = fgets($handle_reader)) !== false)
        {
            $index++;
            if ($index == $id)
            {
                $old = trim($buffer);
                $old = json_decode($old, true);
                if (!empty($old))
                {
                    fputs($handle_writer, PHP_EOL);
                    $bo = true;
                }
                else
                {
                    fputs($handle_writer, $buffer);
                }
            }
            else
            {
                fputs($handle_writer, $buffer);
            }
        }
        fclose($handle_reader);
        fclose($handle_writer);

        if ($bo)
        {
            rename($this -> db_file . 'w', $this -> db_file);
            $this -> info['count']--;
            $this -> info_save();
        }
        else
        {
            unlink($this -> db_file . 'w');
        }

        return $bo;
    }

    // 清空表
    public function deleteAll($where = null)
    {
        if ($where === null)
        {
            $this -> init();
        }

        return true;
    }
}


// 示例代码
date_default_timezone_set("PRC");
header('Content-type: text/plain; charset=utf-8');

//ZFileDB::table('t1') -> deleteAll();
ZFileDB::table('t1') -> insert(['a' => 123, 'dt' => date('Y-m-d H:i:s'), 'rand' => rand(1, 100)]);
ZFileDB::table('t1') -> insertAll([
    ['a' => 123, 'dt' => date('Y-m-d H:i:s'), 'rand' => rand(1, 100)],
    ['a' => 124, 'dt' => date('Y-m-d H:i:s'), 'rand' => rand(1, 100)],
]);
ZFileDB::table('t1') -> where('id', '<', '100') -> update(['c' => 2]);
ZFileDB::table('t1') 
    -> where('id', '>', '100')
    -> delete();
$res = ZFileDB::table('t1') 
    -> find(1);
$res = ZFileDB::table('t1') 
    -> order('rand DESC')
    -> select();

var_dump($res);