Aquí podría ser tu PUBLICIDAD


Bases de datos planas

votos
101

¿Cuáles son las mejores prácticas para crear estructuras de bases de datos de archivos planos en PHP?

Muchos de los frameworks de archivos planos PHP más maduros que veo intentan implementar una sintaxis de consulta similar a SQL, que en la mayoría de los casos es exagerada para mis propósitos (yo solo usaría una base de datos en ese momento).

¿Hay algún truco elegante para obtener un buen rendimiento y características con un pequeño costo de código?

Publicado el 01/08/2008 a las 15:19
fuente por usuario saint_groceon
En otros idiomas...        العربية       

12 respuestas

votos
68

Bueno, ¿cuál es la naturaleza de las bases de datos planas. ¿Son grandes o pequeños? ¿Es simple arrays con matrices en ellos? si es algo simple, diga userprofiles construidos como tales:

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

y para guardar o actualizar el registro db para ese usuario.

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

y cargar el registro para el usuario

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

pero nuevamente esta implementación variará en la aplicación y naturaleza de la base de datos que necesita.

Respondida el 01/08/2008 a las 06:45
fuente por usuario w-ll


Aquí podría ser tu PUBLICIDAD


votos
46

Puede considerar SQLite . Es casi tan simple como archivos planos, pero obtienes un motor SQL para consultas. Se trabaja bien con PHP también.

Respondida el 09/08/2008 a las 12:00
fuente por usuario yukondude

votos
20

En mi opinión, usar una "base de datos de archivos planos" en el sentido que usted está dando sentido (y la respuesta que ha aceptado) no es necesariamente la mejor manera de hacer las cosas. Primero que nada, usar serialize()y unserialize()puede causar dolores de cabeza MAYORES si alguien entra y edita el archivo (de hecho, puede poner el código de arbritrary en su "base de datos" para que se ejecute cada vez).

Personalmente, yo diría: ¿por qué no mirar hacia el futuro? Ha habido tantas veces que tuve problemas porque he estado creando mis propios archivos "propietarios", y el proyecto se ha disparado hasta el punto en que necesita una base de datos, y estoy pensando "ya sabes, deseo". Lo escribí para una base de datos para comenzar con "- porque la refacturación del código requiere mucho tiempo y esfuerzo.

De esto aprendí que mi aplicación se verificará en el futuro de modo que cuando se haga más grande no tenga que ir y pasar días refabricando es la manera de seguir adelante. ¿Cómo hago esto?

SQLite. Funciona como una base de datos, usa SQL, y es bastante fácil cambiar a mySQL (especialmente si está usando clases abstractas para la manipulación de la base de datos como lo hago yo).

De hecho, especialmente con el método de la "respuesta aceptada", puede reducir drásticamente el uso de memoria de su aplicación (no tiene que cargar todos los "REGISTROS" en PHP)

Respondida el 21/09/2008 a las 07:21
fuente por usuario Mez

votos
15

Es verdad. serialize()puede ser bastante útil para eso también.

Creo que el truco para crear un sistema viable es encontrar una forma de indexar los nodos de datos sin matarte con la complejidad.

Respondida el 01/08/2008 a las 03:58
fuente por usuario saint_groceon

votos
11

Un marco que estoy considerando sería para una plataforma de blogs. Dado que casi cualquier vista posible de datos que desearía estaría ordenada por fecha, estaba pensando en esta estructura:

Un directorio por nodo de contenido:

./content/YYYYMMDDHHMMSS/

Subdirectorios de cada nodo incluyendo

/tags  
/authors  
/comments  

Además de archivos de texto simples en el directorio de nodos para contenidos pre y post-renderizados y similares.

Esto permitiría una simple glob()llamada PHP (y probablemente una inversión de la matriz de resultados) para consultar casi cualquier cosa dentro de la estructura de contenido:

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

Devolvería rutas incluyendo todos los artículos etiquetados como "gracioso".

Respondida el 01/08/2008 a las 03:26
fuente por usuario saint_groceon

votos
8

Aquí está el 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);
    }
}

?>

Almacena cada entrada como un archivo separado, que encontramos que es lo suficientemente eficiente para su uso (no se cargan datos innecesarios y es más rápido de guardar).

Respondida el 28/10/2008 a las 11:45
fuente por usuario Ryan McCue

votos
8

Si va a utilizar un archivo plano para conservar los datos, utilice XML para estructurar los datos. PHP tiene un analizador XML integrado .

Respondida el 18/09/2008 a las 07:40
fuente por usuario Jason

votos
7

He escrito dos funciones simples diseñadas para almacenar datos en un archivo. Se puede juzgar por sí mismo si es útil en este caso. El punto es salvar una variable php (si es o una matriz de una cadena o un objeto) en un archivo.

<?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;
}
Respondida el 19/12/2012 a las 09:48
fuente por usuario jpcrevoisier

votos
6

Éste es inspirador como una solución práctica:
https://github.com/mhgolkar/FlatFire
Utiliza múltiples estrategias para el manejo de datos ...
[Copiado de archivos Léame]

Libre o estructurado o mixto

- 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
Respondida el 02/05/2013 a las 02:57
fuente por usuario omran

votos
6

En mi humilde opinión, tiene dos opciones si se quiere evitar algo elaboración de cerveza casera:

  1. SQLite

    Si está familiarizado con DOP, se puede instalar un driver PDO que soporta SQLite. Nunca lo usaron, pero he utilizado DOP una tonelada con MySQL. Voy a dar a este un tiro en un proyecto actual.

  2. XML

    Hecho esto muchas veces para cantidades relativamente pequeñas de datos. XMLReader es una lectura hacia adelante, clase de peso ligero, el cursor de estilo. SimpleXML hace que sea fácil de leer un documento XML en un objeto que se puede acceder como cualquier otra instancia de clase.

Respondida el 02/12/2012 a las 04:49
fuente por usuario siliconrockstar

votos
6

Si desea un resultado legible para las personas, también puede usar este tipo de archivo:

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

De esta forma, solo tiene un archivo, puede depurarlo (y arreglarlo manualmente) fácilmente, puede agregar campos más adelante (al final de cada línea) y el código PHP es simple (para cada línea, divida según |).

Sin embargo, los inconvenientes son que debe analizar todo el archivo para buscar algo (si tiene millones de entradas, no está bien) y debe manejar el separador en los datos (por ejemplo, si el nick es WaR | ordz).

Respondida el 18/09/2008 a las 08:51
fuente por usuario ofaurax

votos
4

Simplemente señalando un posible problema con una base de datos de archivos planos con este tipo de sistema:

data|some text|more data

row 2 data|bla hbalh|more data

etc ...

El problema es que los datos de celda contiene un "|" o un "\ n", entonces se perderán los datos. A veces sería más fácil de dividir por combinaciones de letras que la mayoría de la gente no utilizar.

Por ejemplo:

Columna divisor: #$% (Shift+345)

Fila divisor: ^&* (Shift+678)

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

A continuación, utilice: explode("#$%", $data); use foreach, the explode again to separate columns

O cualquier cosa a lo largo de estas líneas. Además, debo añadir que las bases de datos de archivos planos son buenos para los sistemas con pequeñas cantidades de datos (es decir. A menos de 20 filas), pero se convierten en enormes cerdos de memoria para las bases de datos más grandes.

Respondida el 04/01/2013 a las 01:14
fuente por usuario Michael Burt


Aquí podría ser tu PUBLICIDAD