Vă mulțumim pentru susținere

Baze de date bazate pe fișiere

Care sunt cele mai bune practici în ceea ce privește crearea de structuri baze de date cu fișiere plate în PHP? O mulțime de cadre de fișiere PHP mai mature văd acolo încercarea de a implementa sintaxa de interogare asemănătoare SQL, care este în topul scopurilor mele în cele mai multe cazuri (aș folosi doar o bază de date la acel moment).

Există trucuri elegante acolo pentru a obține performanțe bune și caracteristici cu un mic cod deasupra capului pe care ar dori-o să luați această problemă în primul rând?

0
adăugat editat
Aș dori să adaug că există un pachet aici pentru baza de date a fișierelor plate github.com/tmarois/Filebase Știu că aceasta este o întrebare veche, dar acest pachet este cea mai recentă construită și menținută, plus cele mai multe neglijente care trebuie incluse.
adăugat autor timothymarois

12 răspunsuri

Un cadru pe care-l iau în considerare ar fi pentru o platformă de blogging. Deoarece aproape orice vizualizare posibilă a datelor pe care le-ați dori ar fi sortată după dată, m-am gândit la această structură:

Un director pe nod de conținut:

./content/YYYYMMDDHHMMSS/

Subdirectoarele fiecărui nod, inclusiv

/tags  
/authors  
/comments  

Pe lângă fișierele text simple din directorul nod pentru conținut pre-și post-redat și altele asemenea.

Acest lucru ar permite un simplu apel glob () în PHP (și probabil o inversare a matricea de rezultate) pentru a interoga doar despre orice din structura conținutului:

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

S-ar întoarce căi, inclusiv toate articolele etichetate "amuzant".

0
adăugat

Este adevărat. serialize () poate fi destul de util pentru asta.

Cred că trucul pentru a veni cu un sistem viabil este găsirea unui mod de a indexa nodurile de date fără a vă ucide cu complexitate.

0
adăugat

Care este natura bazelor de date plate? Sunt mari sau mici. Sunt simple mese cu matrice în ele? dacă ceva simplu spune userprofiles construit ca atare:

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

și să salvați sau să actualizați înregistrarea db pentru acel utilizator.

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

și pentru a încărca înregistrarea pentru utilizator

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

dar din nou această implementare va varia în funcție de aplicația și natura bazei de date de care aveți nevoie.

0
adăugat

Puteți lua în considerare SQLite . Este aproape la fel de simplu ca fișierele plate, dar obțineți un motor SQL pentru interogare. funcționează bine și cu PHP .

0
adăugat
SQLite a fost construit în 5.0+ în mod implicit, dar cu discount (!) De la PHP 5.4+ pe !!! Pe măsură ce scriu acest lucru în iulie 2012, SQLite nu va mai funcționa la sistemele actualizate în mod implicit. Declarație oficială aici
adăugat autor Sliq
Instalarea driverului SQLite PDO este destul de banală dacă aveți acces la server. În Ubuntu / Debian care rulează Apache2 trebuie doar să faceți instalarea apt-get install php5-sqlite apache2 restart
adăugat autor siliconrockstar
Ca răspuns la comentariul de la @Sliq, afirmând că "SQLite a fost ... întrerupt" este un fel de adevărat: extensia numită "SQLite" a fost întreruptă și "SQLite3" este acum activată în mod implicit. php.net/manual/en/sqlite.installation.php "Din moment ce PHP 5.0 această extensie a fost asociată cu PHP. Începând cu PHP 5.4, această extensie este disponibilă numai prin PECL. "
adăugat autor Paul van Leeuwen

IMHO, aveți două opțiuni dacă vreți să evitați ceva inițial:

  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. XMLReader is a lightweight, read-forward, cursor-style class. SimpleXML makes it simple to read an XML document into an object that you can access just like any other class instance.

0
adăugat

Dacă doriți un rezultat care poate fi citit-uman, puteți utiliza, de asemenea, acest tip de fișier:

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

În acest fel, aveți un singur fișier, îl puteți depana (și remediați manual) ușor, puteți adăuga mai târziu câmpuri (la sfârșitul fiecărei linii), iar codul PHP este simplu (pentru fiecare rând, împărțit în funcție de |).

Cu toate acestea, dezavantajele sunt că ar trebui să parse întregul fișier pentru a căuta ceva (dacă aveți milioane de intrări, nu este bine) și ar trebui să se ocupe de separator în date (de exemplu, dacă porecla este WaR | ordz).

0
adăugat

Dacă intenționați să utilizați un fișier plat pentru a persista datele, utilizați XML pentru a structura datele. PHP are un parser XML încorporat .

0
adăugat
Și urmați regulile xml ale lizibilității umane sau puteți folosi serializarea sau json-ul sau ceva asemănător.
adăugat autor Ben

După părerea mea, folosirea unei "baze de date de fișiere plate" în sensul în care înțelegeți (și răspunsul pe care l-ați acceptat) nu este în mod necesar cel mai bun mod de a face lucrurile. Mai întâi de toate, folosirea serialize () și unserialize () poate cauza dureri majore dacă cineva intră și editează fișierul "baza de date" care trebuie rulată de fiecare dată.)

Personal, aș spune - de ce nu te uiți în viitor? Au fost atâtea ori că am avut probleme pentru că mi-am creat propriile fișiere "proprietare", iar proiectul a explodat până la un punct în care are nevoie de o bază de date și mă gândesc "știi tu, doresc Am scris acest lucru pentru ca o bază de date să înceapă cu "- pentru că refactorizarea codului durează prea mult timp și efort.

Din aceasta am invatat ca viitoarele probe de aplicare mea, astfel incat atunci cand devine mai mare nu trebuie sa merg si sa petreaca zile refactoring este calea de a merge mai departe. Cum pot face acest lucru?

SQLite. Funcționează ca o bază de date, utilizează SQL și este destul de ușor să se schimbe în MySQL (espescially dacă folosiți clase abstracte pentru manipularea bazei de date ca mine!)

De fapt, espescially cu metoda "acceptat răspuns", poate reduce drastic utilizarea memoriei aplicației dvs. (nu trebuie să încărcați toate "RECORDS" în PHP)

0
adăugat

Iată codul pe care îl folosim pentru Lilina:


 * @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);
    }
}

?>

Se stochează fiecare intrare ca fișier separat, pe care am descoperit că este suficient de eficient pentru utilizare (nu se încarcă date care nu sunt necesare și este mai rapid de salvat).

0
adăugat

Am scris două funcții simple concepute pentru a stoca date într-un fișier. Puteți judeca singur dacă este util în acest caz. Ideea este să salvați o variabilă php (dacă este vorba de un șir sau de un obiect) într-un fișier.

0
adăugat
Am descoperit acest lucru interesant și aceasta este metoda BETTER, pentru că am aruncat doar matricea formatată într-un fișier. Nu avem nevoie să o construim din nou, ci doar citiți-o. De asemenea, modificați variabilele este puțin ușor. Nu voi folosi niciodată acest lucru pentru a stoca date mari, dar mi-am dat seama că este practic să stocați modulele programului fără bază de date. Mulțumesc.
adăugat autor erm3nda
Aceasta este o întrebare de patru ani, cu un răspuns acceptat și multe răspunsuri suplimentare. Luați în considerare concentrarea asupra întrebărilor mai noi, cu excepția cazului în care răspunsul acceptat aici este clar greșit sau inadecvat.
adăugat autor mcknz

Doar subliniind o problemă potențială cu o bază de date cu fișiere plate cu acest tip de sistem:

data|some text|more data

row 2 data|bla hbalh|more data

... etc

Problema este că datele de celule conțin un "|" sau "\ n" atunci datele vor fi pierdute. Uneori ar fi mai ușor să se împartă prin combinații de scrisori pe care majoritatea oamenilor nu le-ar folosi.

De exemplu:

Column splitter: #$% (Shift+345)

Row splitter: ^&* (Shift+678)

Text file: test data#$%blah blah#$%^&*new row#$%new row data 2

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

Sau ceva în acest sens. De asemenea, aș putea adăuga că bazele de date cu fișiere plate sunt bune pentru sistemele cu cantități mici de date (adică, mai puțin de 20 de rânduri), dar devin grave de memorie pentru bazele de date mai mari.

0
adăugat
Puncte bune. Cu un pas mai departe, PHP poate serializa serios JSON. Escaping de intrare este mult mai simplu, astfel încât să nu aveți nevoie pentru a utiliza combinații de șir amuzant, astfel încât fișierul este mai ușor de citit.
adăugat autor Cypher

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

Gratuit sau structurat sau mixt

- 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
0
adăugat