Bazy plików płaskich [zamknięte]
Jakie są najlepsze praktyki tworzenia płaskich struktur bazy danych w PHP?
Wiele bardziej dojrzałych frameworków plików php, które widzę, próbuje zaimplementować składnię zapytań podobną do SQL, która w większości przypadków jest ponadprzeciętna dla moich celów (w tym momencie użyłbym tylko bazy danych).
Czy są jakieś eleganckie sztuczki, aby uzyskać dobrą wydajność i funkcje z małym kodem na wierzchu?
12 answers
Jaka jest natura płaskich baz danych? Są duże czy małe. Czy to proste tablice z tablicami w nich? jeśli jego coś prostego powiedzieć USERPROFILE zbudowane jako takie:
$user = array("name" => "dubayou",
"age" => 20,
"websites" => array("dubayou.com","willwharton.com","codecream.com"),
"and_one" => "more");
I aby zapisać lub zaktualizować rekord db dla tego użytkownika.
$dir = "../userdata/"; //make sure to put it bellow what the server can reach.
file_put_contents($dir.$user['name'],serialize($user));
I załadować rekord dla użytkownika
function &get_user($name){
return unserialize(file_get_contents("../userdata/".$name));
}
Ale znowu ta implementacja będzie się różnić w zależności od aplikacji i charakteru potrzebnej bazy danych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-14 12:26:34
Możesz rozważyć SQLite . To prawie tak proste, jak płaskie pliki, ale masz silnik SQL do zapytań. To działa również dobrze z PHP .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-08 23:00:54
Moim zdaniem korzystanie z "bazy plików płaskich" w sensie, w jakim masz na myśli (i odpowiedź, którą zaakceptowałeś), nie jest najlepszym sposobem, aby przejść do rzeczy. Po pierwsze, użycie serialize()
i unserialize()
może powodować poważne bóle głowy, jeśli ktoś wejdzie i edytuje plik (w rzeczywistości może umieścić kod arbritrary w "bazie danych", aby być uruchamianym za każdym razem.)
Z tego nauczyłem się, że przyszłościowe sprawdzanie mojej aplikacji, aby kiedy robi się większa, nie muszę iść i spędzać dni na refaktoryzacji jest drogą do przodu. Jak to zrobić?
SQLite. Działa jako baza danych, używa SQL i jest dość łatwy do zmiany na mySQL (espescially jeśli używasz abstrakcyjnych klas do manipulacji bazami danych, jak ja!)
W rzeczywistości, espescially z metodą "accepted answer", może drastycznie zmniejszyć zużycie pamięci aplikacji (nie musisz ładować wszystkich "rekordów" do PHP)Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-31 13:23:52
To prawda. serialize()
może być do tego całkiem przydatna.
Myślę, że sztuczka, aby wymyślić sprawny system, polega na znalezieniu sposobu na indeksowanie węzłów danych bez zabijania się złożonością.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-14 12:28:29
Jeden framework, który rozważam, byłby dla platformy blogowej. Ponieważ prawie każdy możliwy widok danych, który chciałbyś, byłby posortowany według daty, myślałem o tej strukturze:
Jeden katalog na węzeł treści:
./content/YYYYMMDDHHMMSS/
Podkatalogi każdego węzła wraz z
/tags
/authors
/comments
Oraz proste pliki tekstowe w katalogu node dla zawartości przed-i po renderowaniu i tym podobnych.
To pozwoli na proste PHP glob()
wywołanie (i prawdopodobnie odwrócenie z tablicy wyników) do zapytań o prawie wszystko w strukturze treści:
glob("content/*/tags/funny");
Zwróci ścieżki zawierające wszystkie artykuły oznaczone tagiem "Śmieszne".
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-24 17:19:04
Oto kod, którego używamy dla Liliny:
<?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) != '/')
$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);
}
}
?>
Przechowuje każdy wpis jako osobny plik, który okazał się wystarczająco wydajny do użycia (żadne niepotrzebne dane nie są ładowane i jest szybszy do zapisania).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-03 13:29:02
Jeśli chcesz użyć płaskiego pliku do utrwalania danych, użyj XML do uporządkowania danych. PHP posiada wbudowany parser XML .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-28 07:03:01
Napisałem dwie proste funkcje przeznaczone do przechowywania danych w pliku. Możesz sam ocenić, czy jest to przydatne w tym przypadku. Chodzi o to, aby zapisać zmienną php (jeśli jest to tablica, łańcuch lub obiekt) do pliku.
<?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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-19 21:17:45
Jeśli chcesz uzyskać wynik czytelny dla człowieka, możesz również użyć tego typu pliku:
ofaurax|27|male|something|
another|24|unknown||
...
W ten sposób Masz tylko jeden plik, możesz go łatwo debugować (i ręcznie naprawić), możesz dodać pola później (na końcu każdej linii), A kod PHP jest prosty (dla każdej linii, podziel według|).
Jednak wadą jest to, że powinieneś parsować cały plik, aby coś wyszukać (jeśli masz miliony wpisów, to nie jest w porządku) i powinieneś obsługiwać separator w danych (na przykład jeśli nick to WaR|ordz).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-18 07:51:30
Ten jest inspirujący jako praktyczne rozwiązanie:
https://github.com/mhgolkar/FlatFire
Wykorzystuje wiele strategii do obsługi danych...
[Skopiowane z pliku Readme]
Wolne, strukturyzowane lub mieszane
- 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-02 13:57:13
IMHO, masz dwie opcje, jeśli chcesz uniknąć homebrewing czegoś:
-
SQLite
Jeśli znasz PDO, możesz zainstalować sterownik PDO, który obsługuje SQLite. Nigdy go nie używałem, ale używałem PDO a ton z MySQL. Zamierzam dać temu szansę na obecny projekt.
-
XML
Zrobiłem to wiele razy dla stosunkowo małych ilości danych. XMLReader jest lekką klasą w stylu kursora. SimpleXML ułatwia odczyt dokumentu XML do obiektu, do którego można uzyskać dostęp, tak jak każda inna instancja klasy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-24 17:50:22
Po prostu wskazując na potencjalny problem z bazą plików płaskich z tego typu systemem:
data|some text|more data
row 2 data|bla hbalh|more data
...etc
Problem polega na tym, że dane komórki zawierają " / "lub" \n", a następnie dane zostaną utracone. Czasami łatwiej byłoby podzielić na kombinacje liter, których większość ludzi nie użyłaby.
Na przykład:
Rozdzielacz kolumn: #$% (Shift+345)
Row splitter: ^&* (Shift+678)
Plik tekstowy: test data#$%blah blah#$%^&*new row#$%new row data 2
Następnie użyj: explode("#$%", $data); use foreach, the explode again to separate columns
Lub cokolwiek z tych linie. Dodam też, że bazy danych plików płaskich są dobre dla Systemów z niewielkimi ilościami danych(np. mniej niż 20 wierszy), ale stają się ogromnymi wieprzami pamięci dla większych baz danych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-04 00:39:53