Bases de datos de archivos planos [closed]

9 minutos de lectura

avatar de usuario
san_groceon

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

Existe una gran cantidad de marcos de trabajo de archivos planos de PHP más maduros que intento implementar sintaxis de consulta similar a SQL, que es exagerada para mis propósitos en la mayoría de los casos. (Solo usaría una base de datos en ese punto).

¿Existen trucos elegantes para obtener un buen rendimiento y funciones con una pequeña sobrecarga de código?

  • Me gustaría agregar que hay un paquete aquí para Base de datos de archivos planos github.com/tmarois/Filebase Sé que esta es una vieja pregunta, pero este paquete es la compilación y el mantenimiento más recientes, además lleno de características la mayoría se olvidan de incluir.

    – tmarois

    6 de septiembre de 2017 a las 13:24


  • Estoy desarrollando un CMS y uso una base de datos de texto de archivo de texto plano. Ha llevado muchas horas hacerlo y muchas horas refractarlo pero funciona perfectamente. Las consultas se realizarán mucho más rápido con una base de datos completamente indexada y optimizada. Sin embargo, evito la necesidad de consultas almacenando metadatos y con una organización y estructura cuidadosas. Cuando necesito datos, los obtengo sin for loop (a menos que esté usando todos los datos en la carpeta), por lo tanto, funciona mucho más rápido que una base de datos. Entraría en detalles y daría una muy buena respuesta, pero desafortunadamente esta pregunta está cerrada.

    – Dan Bray

    21 oct 2018 a las 17:01

avatar de usuario
ll-ll

Bueno, cuál es la naturaleza de las bases de datos planas. ¿Son grandes o pequeños? ¿Son matrices simples con matrices en ellas? si es algo simple, diga perfiles de usuario creados como tales:

$user = array("name" => "bob", 
              "age" => 20,
              "websites" => array("example.com","bob.example.com","bob2.example.com"),
              "and_one" => "more");

y para guardar o actualizar el registro de base de datos 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 para cargar el registro para el usuario

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

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

podrías considerar SQLite. Es casi tan simple como los archivos planos, pero obtiene un motor SQL para realizar consultas. Eso funciona bien con PHP también.

  • SQLite se incorporó a 5.0+ de forma predeterminada, ¡pero se descontó (!) de PHP 5.4+ en !!! Mientras escribo esto en julio de 2012, SQLite ya no funcionará en sistemas actualizados de manera predeterminada. Declaración oficial aquí

    – Sliq

    26 de julio de 2012 a las 21:59


  • La instalación del controlador SQLite PDO es bastante trivial si tiene acceso al servidor. En Ubuntu/Debian ejecutando Apache2 simplemente haga apt-get install php5-sqlite service apache2 restart

    – estrella de rock de silicio

    2 de diciembre de 2012 a las 15:39

  • En reacción al comentario de @Sliq, afirmar que “SQLite fue… descontinuado” es cierto: la extensión llamada “SQLite” se descontinuó y “SQLite3” ahora está habilitado de manera predeterminada. php.net/manual/en/sqlite.installation.php “Desde PHP 5.0, esta extensión se incluyó con PHP. A partir de PHP 5.4, esta extensión solo está disponible a través de PECL”. php.net/manual/en/sqlite3.installation.php “La extensión SQLite3 está habilitada de forma predeterminada a partir de PHP 5.3.0”. “Esta extensión fue brevemente una extensión PECL, pero esa versión solo se recomienda para uso experimental”.

    –Paul van Leeuwen

    04/12/2016 a las 20:25


  • No respondiste la pregunta

    – JG Estiot

    18 de julio de 2019 a las 15:08

avatar de usuario
Mez

En mi opinión, usar una “Base de datos de archivos planos” en el sentido que quiere decir (y la respuesta que ha aceptado) no es necesariamente la mejor manera de hacer las cosas. En primer lugar, usando serialize() y unserialize() puede causar GRANDES dolores de cabeza si alguien ingresa y edita el archivo (pueden, de hecho, poner código arbitrario en su “base de datos” para que se ejecute cada vez).

Personalmente, diría: ¿por qué no mirar hacia el futuro? Ha habido tantas veces que he tenido 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 “sabes, me gustaría Escribí esto para comenzar con una base de datos”, porque la refactorización del código requiere demasiado tiempo y esfuerzo.

A partir de esto, aprendí que preparar mi aplicación para el futuro, de modo que cuando sea más grande, no tenga que ir y pasar días refactorizando es el camino a seguir. ¿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 manipular la base de datos como yo!)

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

  • Eso es cierto. serialize() puede ser muy útil para eso también. Creo que el truco para crear un sistema viable es encontrar alguna forma de indexar los nodos de datos sin matarte con la complejidad.

    – san_groceon

    1 de agosto de 2008 a las 14:58


  • Le doy un escenario en el que no desea usar SQLite o, de hecho, ninguna base de datos e ir directamente al sistema de archivos. tiene 80 millones de registros de transacciones en su sistema, la longitud de cada registro de transacción es de solo 126 caracteres, está agregando 1800 transacciones en un segundo y solo lee estos datos una vez al día después de la medianoche.

    – Aaaa

    14 de agosto de 2020 a las 9:16

  • ¿Tienes un ejemplo de uso?

    – compañero

    4 de septiembre de 2020 a las 4:44

avatar de usuario
san_groceon

Un marco que estoy considerando sería para una plataforma de blogs. Dado que casi cualquier vista posible de los datos que desee se ordenará 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 contenido renderizado anterior y posterior y similares.

Esto permitiría un PHP simple glob() llamada (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 que incluyen todos los artículos etiquetados como “gracioso”.

avatar de usuario
Ryan McCue

Aquí está el código que usamos para 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) != "https://stackoverflow.com/")
            $directory .= "https://stackoverflow.com/";

        $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 guardar).

En mi humilde opinión, tienes dos… er, tres opciones si quieres evitar hacer algo casero:

  1. SQLite

Si está familiarizado con PDO, puede instalar un controlador de PDO que admita SQLite. Nunca lo usé, pero he usado PDO mucho con MySQL. Voy a darle una oportunidad a esto en un proyecto actual.

  1. XML

Hecho esto muchas veces para cantidades relativamente pequeñas de datos. Lector XML es una clase liviana, de lectura hacia adelante, estilo cursor. SimpleXML simplifica la lectura de un documento XML en un objeto al que puede acceder como cualquier otra instancia de clase.

  1. JSON (actualizar)

Buena opción para pequeñas cantidades de datos, solo lea/escriba el archivo y json_decode/json_encode. Sin embargo, no estoy seguro de si PHP ofrece una estructura para navegar por un árbol JSON sin cargarlo todo en la memoria.

avatar de usuario
Pedro Mortensen

Si va a usar un archivo sin formato para conservar los datos, use XML para estructurar los datos. PHP tiene un analizador XML incorporado.

  • Y siga las reglas xml de legibilidad humana o también podría usar serialización o json o algo así.

    – ben

    23 de junio de 2016 a las 7:10

  • Muy mal consejo. Nunca se debe utilizar XML. Es una aberración gorda.

    – JG Estiot

    18 de julio de 2019 a las 15:10

  • @JGEstiot ¿Le importa explicar más?

    – UncaughtTypeError

    26 de julio de 2019 a las 13:27

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad