平面文件数据库

saint_groceon 108 php sql database flat-file

在PHP中创建平面文件数据库结构的最佳实践是什么?

我看到很多比较成熟的PHP平面文件框架试图实现类似SQL的查询语法,这在大多数情况下都是我的目的(我只会在那时使用数据库).

是否有任何优雅的技巧,以获得良好的性能和功能与小代码开销?

w-ll.. 73

那么,平面数据库的本质是什么.它们是大还是小.它是带有数组的简单数组吗?如果它的简单说明userprofiles如此构建:

$user = array("name" => "dubayou", 
              "age" => 20,
              "websites" => array("dubayou.com","willwharton.com","codecream.com"),
              "and_one" => "more");

并保存或更新该用户的db记录.

$dir = "../userdata/";  //make sure to put it bellow what the server can reach.
file_put_contents($dir.$user['name'],serialize($user));

并为用户加载记录

function &get_user($name){
    return unserialize(file_get_contents("../userdata/".$name));
}

但是,此实现将根据您所需的数据库的应用程序和性质而有所不同.


yukondude.. 47

你可能会考虑SQLite.它几乎和平面文件一样简单,但你确实得到了一个用于查询的SQL引擎.它也适用于PHP.

  • SQLite默认情况下构建为5.0+,但是从PHP 5.4+开始折扣(!)!正如我在2012年7月所写的那样,SQLite默认情况下不再使用最新的系统.官方声明[此处](http://www.php.net/manual/en/sqlite.requirements.php) (6认同)
  • 对@Sliq的评论作出反应,声明"SQLite已......停止"是正确的:名为"SQLite"的扩展名已停止,默认情况下"SQLite3"现已启用.http://php.net/manual/en/sqlite.installation.php"从PHP 5.0开始,这个扩展与PHP捆绑在一起.从PHP 5.4开始,这个扩展只能通过PECL获得." http://php.net/manual/en/sqlite3.installation.php"自PHP 5.3.0起,默认启用SQLite3扩展." "这个扩展简要地是PECL扩展,但该版本仅推荐用于实验用途." (4认同)

Mez.. 20

在我看来,使用"平面文件数据库"就意味着你的意思(以及你接受的答案)并不是最好的方法.首先,如果有人进入并编辑文件,使用serialize()unserialize()可能导致严重的头痛(事实上,他们可以在每次运行的"数据库"中放置arbritrary代码.)

就个人而言,我会说 - 为什么不展望未来?有很多次我遇到过问题,因为我一直在创建自己的"专有"文件,而且项目已爆炸到需要数据库的地步,我想"你知道,我希望我为数据库编写了这个" - 因为代码的重构需要花费太多的时间和精力.

从这一点我已经了解到我的应用程序的未来证明,以便当它变得更大时,我不必花费数天时间进行重构是前进的方法.我该怎么做呢?

SQLite的.它作为一个数据库工作,使用SQL,很容易转换到mySQL(特别是如果你像我一样使用抽象类进行数据库操作!)

事实上,特别是"接受的答案"的方法,它可以大大减少你的应用程序的内存使用(你不必将所有"记录"加载到PHP)


saint_groceo.. 12

我正在考虑的一个框架是博客平台.由于几乎任何可能的数据视图都会按日期排序,我正在考虑这个结构:

每个内容节点一个目录:

./content/YYYYMMDDHHMMSS/

每个节点的子目录包括

/tags  
/authors  
/comments  

以及节点目录中的简单文本文件,用于预呈现和后呈现内容等.

这将允许简单的PHP glob()调用(可能是结果数组的反转)来查询内容结构中的任何内容:

glob("content/*/tags/funny");  

返回路径包括标记为"有趣"的所有文章.


Ryan McCue.. 9

这是我们为Lilina使用的代码:

<?php
/**
 * Handler for persistent data files
 *
 * @author Ryan McCue <cubegames@gmail.com>
 * @package Lilina
 * @version 1.0
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 */

/**
 * Handler for persistent data files
 *
 * @package Lilina
 */
class DataHandler {
    /**
     * Directory to store data.
     *
     * @since 1.0
     *
     * @var string
     */
    protected $directory;

    /**
     * Constructor, duh.
     *
     * @since 1.0
     * @uses $directory Holds the data directory, which the constructor sets.
     *
     * @param string $directory 
     */
    public function __construct($directory = null) {
        if ($directory === null)
            $directory = get_data_dir();

        if (substr($directory, -1) != '/')
            $directory .= '/';

        $this->directory = (string) $directory;
    }

    /**
     * Prepares filename and content for saving
     *
     * @since 1.0
     * @uses $directory
     * @uses put()
     *
     * @param string $filename Filename to save to
     * @param string $content Content to save to cache
     */
    public function save($filename, $content) {
        $file = $this->directory . $filename;

        if(!$this->put($file, $content)) {
            trigger_error(get_class($this) . " error: Couldn't write to $file", E_USER_WARNING);
            return false;
        }

        return true;
    }

    /**
     * Saves data to file
     *
     * @since 1.0
     * @uses $directory
     *
     * @param string $file Filename to save to
     * @param string $data Data to save into $file
     */
    protected function put($file, $data, $mode = false) {
        if(file_exists($file) && file_get_contents($file) === $data) {
            touch($file);
            return true;
        }

        if(!$fp = @fopen($file, 'wb')) {
            return false;
        }

        fwrite($fp, $data);
        fclose($fp);

        $this->chmod($file, $mode);
        return true;

    }

    /**
     * Change the file permissions
     *
     * @since 1.0
     *
     * @param string $file Absolute path to file
     * @param integer $mode Octal mode
     */
    protected function chmod($file, $mode = false){
        if(!$mode)
            $mode = 0644;
        return @chmod($file, $mode);
    }

    /**
     * Returns the content of the cached file if it is still valid
     *
     * @since 1.0
     * @uses $directory
     * @uses check() Check if cache file is still valid
     *
     * @param string $id Unique ID for content type, used to distinguish between different caches
     * @return null|string Content of the cached file if valid, otherwise null
     */
    public function load($filename) {
        return $this->get($this->directory . $filename);
    }

    /**
     * Returns the content of the file
     *
     * @since 1.0
     * @uses $directory
     * @uses check() Check if file is valid
     *
     * @param string $id Filename to load data from
     * @return bool|string Content of the file if valid, otherwise null
     */
    protected function get($filename) {
        if(!$this->check($filename))
            return null;

        return file_get_contents($filename);
    }

    /**
     * Check a file for validity
     *
     * Basically just a fancy alias for file_exists(), made primarily to be
     * overriden.
     *
     * @since 1.0
     * @uses $directory
     *
     * @param string $id Unique ID for content type, used to distinguish between different caches
     * @return bool False if the cache doesn't exist or is invalid, otherwise true
     */
    protected function check($filename){
        return file_exists($filename);
    }

    /**
     * Delete a file
     *
     * @param string $filename Unique ID
     */
    public function delete($filename) {
        return unlink($this->directory . $filename);
    }
}

?>

它将每个条目存储为一个单独的文件,我们发现它的使用效率足够高(没有加载不需要的数据,保存起来更快).


Jason.. 8

如果您要使用平面文件来保存数据,请使用XML来构建数据.PHP有一个内置的XML解析器.


用户甲.. 7

我写了两个简单的函数,用于将数据存储在一个文件中.如果它在这种情况下有用,你可以自己判断.重点是将php变量(如果它是一个字符串或一个对象的数组)保存到文件中.

<?php
function varname(&$var) {
    $oldvalue=$var;
    $var='AAAAB3NzaC1yc2EAAAABIwAAAQEAqytmUAQKMOj24lAjqKJC2Gyqhbhb+DmB9eDDb8+QcFI+QOySUpYDn884rgKB6EAtoFyOZVMA6HlNj0VxMKAGE+sLTJ40rLTcieGRCeHJ/TI37e66OrjxgB+7tngKdvoG5EF9hnoGc4eTMpVUDdpAK3ykqR1FIclgk0whV7cEn/6K4697zgwwb5R2yva/zuTX+xKRqcZvyaF3Ur0Q8T+gvrAX8ktmpE18MjnA5JuGuZFZGFzQbvzCVdN52nu8i003GEFmzp0Ny57pWClKkAy3Q5P5AR2BCUwk8V0iEX3iu7J+b9pv4LRZBQkDujaAtSiAaeG2cjfzL9xIgWPf+J05IQ==';
    foreach($GLOBALS as $var_name => $value) {
        if ($value === 'AAAAB3NzaC1yc2EAAAABIwAAAQEAqytmUAQKMOj24lAjqKJC2Gyqhbhb+DmB9eDDb8+QcFI+QOySUpYDn884rgKB6EAtoFyOZVMA6HlNj0VxMKAGE+sLTJ40rLTcieGRCeHJ/TI37e66OrjxgB+7tngKdvoG5EF9hnoGc4eTMpVUDdpAK3ykqR1FIclgk0whV7cEn/6K4697zgwwb5R2yva/zuTX+xKRqcZvyaF3Ur0Q8T+gvrAX8ktmpE18MjnA5JuGuZFZGFzQbvzCVdN52nu8i003GEFmzp0Ny57pWClKkAy3Q5P5AR2BCUwk8V0iEX3iu7J+b9pv4LRZBQkDujaAtSiAaeG2cjfzL9xIgWPf+J05IQ==')
        {
            $var=$oldvalue;
            return $var_name;
        }
    }
    $var=$oldvalue;
    return false;
}

function putphp(&$var, $file=false)
    {
    $varname=varname($var);
    if(!$file)
    {
        $file=$varname.'.php';
    }
    $pathinfo=pathinfo($file);
    if(file_exists($file))
    {
        if(is_dir($file))
        {
            $file=$pathinfo['dirname'].'/'.$pathinfo['basename'].'/'.$varname.'.php';
        }
    }
    file_put_contents($file,'<?php'."\n\$".$varname.'='.var_export($var, true).";\n");
    return true;
}


ofaurax.. 6

如果您想要一个人类可读的结果,您也可以使用这种类型的文件:

ofaurax|27|male|something|
another|24|unknown||
...

这样,您只有一个文件,您可以轻松地调试它(并手动修复),您可以稍后添加字段(在每行的末尾),PHP代码很简单(对于每一行,根据|分割).

但是,缺点是您应该解析整个文件以搜索某些内容(如果您有数百万条目,那就没有问题)并且您应该处理数据中的分隔符(例如,如果缺口是WaR | ordz).


siliconrocks.. 6

恕我直言,如果你想避免自制东西,你有两个选择:

  1. SQLite的

    如果您熟悉PDO,则可以安装支持SQLite的PDO驱动程序.从未使用它,但我使用了PDO和MySQL.我打算对当前项目进行一次研究.

  2. XML

    对于相对少量的数据,这样做了很多次. XMLReader是一个轻量级,前瞻性的游标样式类. SimpleXML使得将XML文档读取到可以像任何其他类实例一样访问的对象中变得简单.


用户甲.. 6

这是一个鼓舞人心的实用解决方案:
https://github.com/mhgolkar/FlatFire
它使用多种策略来处理数据...
[从自述文件复制]

自由或结构或混合

- STRUCTURED
Regular (table, row, column) format.
[DATABASE]
/   \
TX  TableY
    \_____________________________
    |ROW_0 Colum_0 Colum_1 Colum_2|
    |ROW_1 Colum_0 Colum_1 Colum_2|
    |_____________________________|
- FREE
More creative data storing. You can store data in any structure you want for each (free) element, its similar to storing an array with a unique "Id".
[DATABASE]
/   \
EX  ElementY (ID)
    \________________
    |Field_0 Value_0 |
    |Field_1 Value_1 |
    |Field_2 Value_2 |
    |________________|
recall [ID]: get_free("ElementY") --> array([Field_0]=>Value_0,[Field_1]=>Value_1...
- MIXD (Mixed)
Mixed databases can store both free elements and tables.If you add a table to a free db or a free element to a structured db, flat fire will automatically convert FREE or SRCT to MIXD database.
[DATABASE]
/   \
EX  TY