Плоские базы данных файлов

голоса
101

Каковы лучшие практики вокруг создания плоских структур баз данных файлов в PHP?

Многие из более зрелых PHP плоских рамок файлов я вижу там пытаются внедрить SQL-подобный синтаксис запросов, который поверх для моих целей в большинстве случаев (я бы просто использовать базу данных в этой точке).

Есть ли какие-либо изящные трюки вне там, чтобы получить хорошую производительность и функциональные возможности с небольшим кодом накладные расходы?

Задан 01/08/2008 в 15:19
источник пользователем
На других языках...                            


12 ответов

голоса
11

Один из рамок я рассматриваю бы для ведения блога платформы. Так как только о любой возможной связи с данными вы хотите бы быть отсортированы по дате, я думал об этой структуре:

Один каталог на узел контента:

./content/YYYYMMDDHHMMSS/

Поддиректории каждого узла, включая

/tags  
/authors  
/comments  

Так же, как простые текстовые файлы в каталоге узла для предварительного и последующего рендеренного содержания и тому подобного.

Это позволило бы простой PHP glob()вызов (и , возможно, разворот результирующего массива) для запроса на что угодно в структуре содержания:

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

вернуться бы путями, включая все статьи, помеченные «смешно».

Ответил 01/08/2008 в 15:26
источник пользователем

голоса
15

Это правда. serialize()может быть очень полезно для того , как хорошо.

Я думаю, что трюк, чтобы придумать жизнеспособную систему найти какой-то способ для индексирования узлов данных, не убивая себя со сложностью.

Ответил 01/08/2008 в 15:58
источник пользователем

голоса
68

Ну, какова природа плоских баз данных. Являются ли они большими или маленькими. Это простые массивы с массивами в них? если его что-то просто сказать userprofiles, построенные как таковой:

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

и сохранить или обновить запись дб для этого пользователя.

$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));
}

но опять же эта реализация будет зависеть от применения и природы базы данных вам нужно.

Ответил 01/08/2008 в 18:45
источник пользователем

голоса
46

Вы могли бы рассмотреть SQLite . Это почти так же просто , как плоские файлы, но вы получите SQL двигатель для запроса. Это хорошо работает с PHP тоже.

Ответил 09/08/2008 в 00:00
источник пользователем

голоса
8

Если вы собираетесь использовать плоский файл для сохранения данных, использовать XML для структурирования данных. PHP имеет встроенный XML - анализатор .

Ответил 18/09/2008 в 07:40
источник пользователем

голоса
6

Если вы хотите результат удобочитаемый, вы можете также использовать этот тип файла:

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

Таким образом, у вас есть только один файл, вы можете отлаживать его (и вручную исправить) легко, вы можете добавить поля позже (в конце каждой строки) и код PHP прост (для каждой строки, разделить в соответствии с |).

Однако, недостатки в том, что вы должны разобрать весь файл, чтобы искать что-то (если у вас есть миллионы записи, это не хорошо), и вы должны обрабатывать разделитель в данных (например, если ник WaR | ordz).

Ответил 18/09/2008 в 08:51
источник пользователем

голоса
20

На мой взгляд, используя «плоский файл базы данных» в том смысле , что вы означающего (и ответ вы приняли) не neccesarily лучший способ идти о вещах. Прежде всего, использование serialize()и unserialize()может вызвать серьезные головные боли , если кто - то входит и редактирует файл (они могут, на самом деле, положить arbritrary код в «базе данных» , который будет запускаться каждый раз.)

Лично я бы сказал, - почему бы не смотреть в будущее? Там было так много раз, что я имел проблемы, потому что я создавал свои собственные «фирменные» файлы, и проект разобранный до точки, где она нуждается в базе данных, и я имею в вид «Вы знаете, я хочу Я написал это для базы данных, чтобы начать с»- потому, что рефакторинг кода занимает слишком много времени и усилий.

Из этого я узнал, что будущую корректуру моего приложения таким образом, что, когда она становится больше не придется идти и тратить дни рефакторинга это путь вперед. Как мне это сделать?

SQLite. Он работает в качестве базы данных использует SQL, и довольно легко перейти к MySql (espescially, если вы используете абстрагированные классы для манипулирования базами данных, как я!)

На самом деле, espescially с «принят ответом» 'ы метода, он может значительно сократить использование памяти вашего приложения (вам не придется загружать все „ЗАПИСЬ“ в PHP)

Ответил 21/09/2008 в 19:21
источник пользователем

голоса
8

Вот код, который мы используем для Лилина:

<?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);
    }
}

?>

Он хранит каждую запись в отдельный файл, который мы нашли достаточно эффективным для использования (без ненужных данных не будет загружен, и это быстрее, чтобы сэкономить).

Ответил 28/10/2008 в 11:45
источник пользователем

голоса
6

ИМХО, у вас есть два варианта, если вы хотите, чтобы избежать домашнего пивоварения что-то:

  1. SQLite

    Если вы знакомы с PDO, вы можете установить драйвер PDO, который поддерживает SQLite. Никогда не использовал его, но я использовал PDO тонну с MySQL. Я собираюсь дать этому выстрел на текущем проекте.

  2. XML

    Совершено много раз для относительно небольших объемов данных. XMLReader представляет собой легкий для чтения вперед, курсор класса стиля. SimpleXML делает его простым для чтения документа XML в объект , который вы можете получить доступ к так же , как и любому другому экземпляру класса.

Ответил 02/12/2012 в 16:49
источник пользователем

голоса
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;
}
Ответил 19/12/2012 в 21:48
источник пользователем

голоса
4

Просто указывая на возможную проблему с плоской базой данных файла с этим типом системы:

data|some text|more data

row 2 data|bla hbalh|more data

...и т.д

Проблема заключается в том, что данные клетки содержит «|» или «\ п», то данные будут потеряны. Иногда легче было бы разделить комбинациями букв, которые большинство людей не будут использовать.

Например:

разветвитель Колонка: #$% (Shift+345)

Ряд разветвитель: ^&* (Shift+678)

Текстовый файл: test data#$%blah blah#$%^&*new row#$%new row data 2

Затем с помощью: explode("#$%", $data); use foreach, the explode again to separate columns

Или что-нибудь вдоль этих линий. Кроме того, я мог бы добавить, что плоские базы данных файлов хороши для систем с небольшими объемами данных (то есть. Менее 20 строк), но становлюсь огромными боров памяти для больших баз данных.

Ответил 04/01/2013 в 01:14
источник пользователем

голоса
6

Это один вдохновляет как практическое решение:
https://github.com/mhgolkar/FlatFire
Он использует несколько стратегий для обработки данных ...
[Скопировано из Readme File]

Свободный или Структурированная или смешанный

- 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
Ответил 02/05/2013 в 14:57
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more