php 平面文件数据库

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/85/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 21:06:42  来源:igfitidea点击:

Flat file databases

phpsqldatabaseflat-file

提问by saint_groceon

What are the best practices around creating flat file database structures in PHP?

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

A lot of more matured PHP flat file frameworks out there which I attempt to implement SQL-like query syntax which is over the top for my purposes in most cases. (I would just use a database at that point).

有很多更成熟的 PHP 平面文件框架,我试图实现类似 SQL 的查询语法,在大多数情况下,这对于我的目的来说是最重要的。(那时我只会使用数据库)。

Are there any elegant tricks out there to get good performance and features with a small code overhead?

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

采纳答案by w-ll

Well, what is the nature of the flat databases. Are they large or small. Is it simple arrays with arrays in them? if its something simple say userprofiles built as such:

那么,平面数据库的本质是什么。它们是大的还是小的。它是带有数组的简单数组吗?如果它的一些简单的说用户配置文件是这样构建的:

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

and to save or update the db recordfor that user.

并保存或更新该用户的数据库记录

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

and to load the recordfor the user

并为用户加载记录

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

but again this implementation will vary on the application and nature of the database you need.

但同样,此实现将因您需要的数据库的应用程序和性质而异。

回答by yukondude

You might consider SQLite. It's almost as simple as flat files, but you do get a SQL engine for querying. It works well with PHPtoo.

您可能会考虑SQLite。它几乎和平面文件一样简单,但您确实可以获得用于查询的 SQL 引擎。它也适用于 PHP

回答by Mez

In my opinion, using a "Flat File Database" in the sense you're meaning (and the answer you've accepted) isn't neccesarily the best way to go about things. First of all, using serialize()and unserialize()can cause MAJOR headaches if someone gets in and edits the file (they can, in fact, put arbritrary code in your "database" to be run each time.)

在我看来,在您的意思(以及您已接受的答案)的意义上使用“平面文件数据库”不一定是处理事情的最佳方式。首先,如果有人进入并编辑文件,使用serialize()unserialize()可能会导致严重的头痛(实际上,他们可以将任意代码放入您的“数据库”中,以便每次运行。)

Personally, I'd say - why not look to the future? There have been so many times that I've had issues because I've been creating my own "proprietary" files, and the project has exploded to a point where it needs a database, and I'm thinking "you know, I wish I'd written this for a database to start with" - because the refactoring of the code takes way too much time and effort.

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

From this I've learnt that future proofing my application so that when it gets bigger I don't have to go and spend days refactoring is the way to go forward. How do I do this?

从中我了解到,对我的应用程序进行未来验证,以便当它变得更大时,我不必花费数天时间进行重构,这是前进的道路。我该怎么做呢?

SQLite. It works as a database, uses SQL, and is pretty easy to change over to mySQL (espescially if you're using abstracted classes for database manipulation like I do!)

SQLite。它用作数据库,使用 SQL,并且很容易转换到 mySQL(特别是如果您像我一样使用抽象类进行数据库操作!)

In fact, espescially with the "accepted answer"'s method, it can drastically cut the memory usage of your app (you don't have to load all the "RECORDS" into PHP)

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

回答by saint_groceon

One framework I'm considering would be for a blogging platform. Since just about any possible view of data you would want would be sorted by date, I was thinking about this structure:

我正在考虑的一个框架是博客平台。由于您想要的几乎任何可能的数据视图都将按日期排序,因此我正在考虑这种结构:

One directory per content node:

每个内容节点一个目录:

./content/YYYYMMDDHHMMSS/

Subdirectories of each node including

每个节点的子目录包括

/tags  
/authors  
/comments  

As well as simple text files in the node directory for pre- and post-rendered content and the like.

以及节点目录中用于渲染前和渲染后内容等的简单文本文件。

This would allow a simple PHP glob()call (and probably a reversal of the result array) to query on just about anything within the content structure:

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

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

Would return paths including all articles tagged "funny".

将返回包括所有标记为“有趣”的文章的路径。

回答by Ryan McCue

Here's the code we use for Lilina:

这是我们用于 Lilina 的代码:

<?php
/**
 * Handler for persistent data files
 *
 * @author Ryan McCue <[email protected]>
 * @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);
    }
}

?>

It stores each entry as a separate file, which we found is efficient enough for use (no unneeded data is loaded and it's faster to save).

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

回答by Jason

If you're going to use a flat file to persist data, use XML to structure the data. PHP has a built-in XML parser.

如果您打算使用平面文件来持久化数据,请使用 XML 来构建数据。PHP 有一个内置的 XML 解析器

回答by ofaurax

If you want a human-readable result, you can also use this type of file :

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

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

This way, you have only one file, you can debug it (and manually fix) easily, you can add fields later (at the end of each line) and the PHP code is simple (for each line, split according to |).

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

However, the drawbacks is that you should parse the entire file to search something (if you have millions of entry, it's not fine) and you should handle the separator in data (for example if the nick is WaR|ordz).

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

回答by siliconrockstar

IMHO, you have two options if you want to avoid homebrewing something:

恕我直言,如果您想避免自制某些东西,您有两种选择:

  1. SQLite

    If you're familiar with PDO, you can install a PDO driver that supports SQLite. Never used it, but I have used PDO a ton with MySQL. I'm going to give this a shot on a current project.

  2. XML

    Done this many times for relatively small amounts of data. XMLReaderis a lightweight, read-forward, cursor-style class. SimpleXMLmakes it simple to read an XML document into an object that you can access just like any other class instance.

  1. SQLite

    如果您熟悉 PDO,则可以安装支持 SQLite 的 PDO 驱动程序。从未使用过它,但我在 MySQL 中大量使用了 PDO。我将在当前项目中试一试。

  2. XML

    对于相对少量的数据,多次执行此操作。 XMLReader是一个轻量级的、向前读的、游标样式的类。 SimpleXML使将 XML 文档读入对象中变得简单,您可以像访问任何其他类实例一样访问该对象。

回答by jpcrevoisier

I have written two simple functions designed to store data in a file. You can judge for yourself if it's useful in this case. The point is to save a php variable (if it's either an array a string or an object) to a file.

我编写了两个简单的函数,旨在将数据存储在文件中。你可以自己判断它在这种情况下是否有用。关键是将一个 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;
}

回答by omran

This one is inspiring as a practical solution:
https://github.com/mhgolkar/FlatFire
It uses multiple strategies to handling data...
[Copied from Readme File]

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

Free or Structured or Mixed

自由或结构化或混合

- 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