bancos de dados de arquivo simples

votos
101

Quais são as melhores práticas em torno de criar estruturas de banco de dados de arquivo simples em PHP?

Um monte de PHP plana estruturas mais maduros arquivo que vejo lá fora, tentar implementar a sintaxe de consulta SQL-like, que é mais alto para os meus propósitos na maioria dos casos (eu iria usar apenas um banco de dados nesse ponto).

Há algum elegantes truques lá fora, para obter um bom desempenho e recursos com uma pequena sobrecarga código?

Publicado 01/08/2008 em 15:19
fonte usuário
Em outras línguas...                            


12 respostas

votos
68

Bem, qual é a natureza das bases de dados planas. eles são grandes ou pequenos. É matrizes simples com matrizes neles? se é algo simples dizer UserProfiles construído como tal:

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

e para salvar ou atualizar o registro de db para esse usuário.

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

e para carregar o registro para o usuário

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

mas novamente esta implementação irá variar sobre a aplicação ea natureza da base de dados que você precisa.

Respondeu 01/08/2008 em 18:45
fonte usuário

votos
46

Você pode considerar SQLite . É quase tão simples como arquivos simples, mas você começa um motor de SQL para consultar. Ele funciona bem com PHP também.

Respondeu 09/08/2008 em 00:00
fonte usuário

votos
20

Na minha opinião, usando um "banco de dados de arquivo simples", no sentido que você está significando (e a resposta que você aceita) não é neccesarily a melhor maneira de fazer as coisas. Primeiro de tudo, usando serialize()e unserialize()pode causar dores de cabeça PRINCIPAIS se alguém entra e edita o arquivo (que pode, de fato, colocar o código arbritrary no seu "banco de dados" para ser executado a cada vez.)

Pessoalmente, eu diria que - por que não olhar para o futuro? Houve tantas vezes que eu tive problemas porque eu tenho vindo a criar meus próprios arquivos de "propriedade", eo projeto tem explodiu a um ponto onde ele precisa de um banco de dados, e eu estou pensando "você sabe, eu desejo eu tinha escrito isso para um banco de dados para começar" - porque a refatoração do código leva maneira muito tempo e esforço.

Deste Eu aprendi que o futuro à prova a minha candidatura para que quando ele se torna maior eu não tenho que ir e passar dias refatoração é o caminho a percorrer para a frente. Como eu faço isso?

SQLite. Ele funciona como um banco de dados, usa SQL, e é muito fácil de mudar para mySQL (espescially se você estiver usando as classes abstratas para a manipulação de banco de dados como eu!)

Na verdade, espescially com o método "resposta aceito" 's, pode reduzir drasticamente o uso de memória do seu aplicativo (você não tem que carregar todos os 'registros' em PHP)

Respondeu 21/09/2008 em 19:21
fonte usuário

votos
15

Isso é verdade. serialize()pode ser muito útil para isso também.

Eu acho que o truque para chegar com um sistema viável é encontrar alguma maneira de indexar os nós de dados sem se matar com a complexidade.

Respondeu 01/08/2008 em 15:58
fonte usuário

votos
11

Um quadro que eu estou considerando seria para uma plataforma de blogging. Desde apenas sobre qualquer ponto de vista possível de dados que você gostaria que seria classificados por data, eu estava pensando sobre essa estrutura:

Um diretório por nó de conteúdo:

./content/YYYYMMDDHHMMSS/

Subdiretórios de cada nó, incluindo

/tags  
/authors  
/comments  

Bem como arquivos de texto simples no diretório do nó de conteúdo pré e tornado-post e similares.

Isso permitiria que um simples PHP glob()chamada (e, provavelmente, uma inversão da matriz resultado) para consultar sobre praticamente qualquer coisa dentro da estrutura de conteúdo:

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

Retornaria caminhos incluindo todos os artigos com a tag "engraçado".

Respondeu 01/08/2008 em 15:26
fonte usuário

votos
8

Aqui está o código que usamos para 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);
    }
}

?>

Ele armazena cada entrada como um arquivo separado, o que encontramos é eficiente o suficiente para uso (sem dados desnecessários é carregado e é mais rápido para salvar).

Respondeu 28/10/2008 em 11:45
fonte usuário

votos
8

Se você estiver indo para usar um arquivo simples para persistir dados, use XML para estruturar os dados. PHP tem um parser XML embutido .

Respondeu 18/09/2008 em 07:40
fonte usuário

votos
7

Eu escrevi duas funções simples projetados para armazenar dados em um arquivo. Você pode julgar por si mesmo se é útil neste caso. O ponto é para salvar uma variável php (se é um array uma string ou um objeto) para um arquivo.

<?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;
}
Respondeu 19/12/2012 em 21:48
fonte usuário

votos
6

Este é inspirador como uma solução prática:
https://github.com/mhgolkar/FlatFire
Ele usa várias estratégias para lidar com dados ...
[Copiado do Arquivo Leia-me]

Grátis ou Structured ou mista

- 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
Respondeu 02/05/2013 em 14:57
fonte usuário

votos
6

IMHO, você tem duas opções se você quer evitar homebrewing algo:

  1. SQLite

    Se você estiver familiarizado com DOP, você pode instalar um driver PDO que suporta SQLite. Nunca usei, mas eu usei PDO uma tonelada com o MySQL. Vou dar a este um tiro em um projeto atual.

  2. XML

    Feito isso muitas vezes para quantidades relativamente pequenas de dados. XMLReader é uma leve leitura para a frente, classe, cursor de estilo. SimpleXML torna simples para ler um documento XML em um objeto que você pode acessar tal como qualquer outra instância de classe.

Respondeu 02/12/2012 em 16:49
fonte usuário

votos
6

Se você quer um resultado legível, você também pode usar esse tipo de arquivo:

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

Desta forma, você tem apenas um arquivo, você pode depurá-lo (e corrigir manualmente) facilmente, você pode adicionar campos mais tarde (no final de cada linha) eo código PHP é simples (para cada linha, divididos de acordo com |).

No entanto, as desvantagens é que você deve analisar o arquivo inteiro para procurar alguma coisa (se você tem milhões de entrada, não é muito bem) e você deve lidar com o separador em dados (por exemplo, se o nick é a guerra | ordz).

Respondeu 18/09/2008 em 08:51
fonte usuário

votos
4

Apenas indicando um potencial problema com um banco de dados de arquivo simples com este tipo de sistema:

data|some text|more data

row 2 data|bla hbalh|more data

... etc

O problema é que os dados célula contém um "|" ou um "\ n", em seguida, os dados serão perdidos. Às vezes, seria mais fácil para dividir por combinações de letras que a maioria das pessoas não usam.

Por exemplo:

divisor de coluna: #$% (Shift+345)

divisor Row: ^&* (Shift+678)

Arquivo de texto: test data#$%blah blah#$%^&*new row#$%new row data 2

Em seguida, use: explode("#$%", $data); use foreach, the explode again to separate columns

Ou qualquer coisa nesse sentido. Além disso, eu poderia acrescentar que os bancos de dados de arquivos planos são bons para sistemas com pequenas quantidades de dados (ie. A menos de 20 linhas), mas tornam-se grandes devoradores de memória para bancos de dados maiores.

Respondeu 04/01/2013 em 01:14
fonte usuário

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