Ein Dokumentengeschäft für PHP, der mehrfach Paralluren ermöglicht. Es handelt sich um eine minimalistische Alternative zu MongoDB oder CouchDB, ohne dass ein neuer Service überzogen ist.
Es funktioniert auch als kleine Fußabdruckdatenbank.
Im Durchschnitt erzeugt ein SMB 100 Rechnungen pro Monat. Nehmen wir also an, ein SMB erzeugt 12000 Rechnungen pro Jahrzehnt.
Testen Sie das Generieren von 12000 Rechnungen mit Kunden, Details (ca. 1 bis 5 Zeilen pro Detail) und datieren Sie auf einem i7/ssd/16 GB/Windows 64bit.

Ein Test mit 100 gleichzeitiger Test (Schreiben und Lesen), 10 Mal.
| N ° | Liest | (MS) | Liest | Fehler |
|---|---|---|---|---|
| 1 | 100 | 7471 | 100 | 0 |
| 2 | 100 | 7751 | 100 | 0 |
| 3 | 100 | 7490 | 100 | 0 |
| 4 | 100 | 7480 | 100 | 0 |
| 5 | 100 | 8199 | 100 | 0 |
| 6 | 100 | 7451 | 100 | 0 |
| 7 | 100 | 7476 | 100 | 0 |
| 8 | 100 | 7244 | 100 | 0 |
| 9 | 100 | 7573 | 100 | 0 |
| 10 | 100 | 7818 | 100 | 0 |
include " lib/DocumentStoreOne.php " ;
use eftec DocumentStoreOne DocumentStoreOne ;
try {
$ flatcon = new DocumentStoreOne ( " base " , ' tmp ' );
// or you could use:
// $flatcon = new DocumentStoreOne(__DIR__ . "/base", 'tmp');
} catch ( Exception $ e ) {
die ( " Unable to create document store. Please, check the folder " );
}
$ flatcon -> insertOrUpdate ( " somekey1 " , json_encode ( array ( " a1 " => ' hello ' , " a2 " => ' world ' ))); // or you could use serialize/igbinary_serialize
$ doc = $ flatcon -> get ( " somekey1 " );
$ listKeys = $ flatcon -> select ();
$ flatcon -> delete ( " somekey1 " ); include " lib/DocumentStoreOne.php " ;
use eftec DocumentStoreOne DocumentStoreOne ;
$ doc = new DocumentStoreOne ( " base " , " task " , ' folder ' );
//also: $doc=new DocumentStoreOne(__DIR__."/base","task",'folder');
$ doc -> serializeStrategy = ' php ' ; // it sets the strategy of serialization to php
$ doc -> autoSerialize ( true ); // autoserialize
$ flatcon -> insertOrUpdate ( " somekey1 " , array ( " a1 " => ' hello ' , " a2 " => ' world ' )); Es erstellt die DokumentstoreOne -Instanz.
| Strategie | Typ | Server | Benchmark |
|---|---|---|---|
| DSO_AUTO | Es setzt die beste verfügbare Strategie (Standard) | kommt darauf an | - - |
| DSO_FOLDER | Es verwendet einen Ordner zum Sperren/Entsperren eines Dokuments | - - | 0,3247 |
| DSO_APCU | Es verwendet APCU zum Sperren/Entsperren eines Dokuments | - - | 0,1480 |
| DSO_REDIS | Es verwendet Redis zum Sperren/Entsperren eines Dokuments | Localhost: 6379 | 2.5403 (schlimmste) |
| Dso_none | Es wird nichts verwendet, um ein Dokument zu sperren/freizuschalten. Es ist die schnellste Methode, ist aber für Mehrfachbenutzer unsicher | 0 |
| Strategie | Typ |
|---|---|
| Php | Es serialisiert mit der Serialize () -Funktion |
| PHP_Array | Es serialisiert mit incluse ()/var_export () Funktion. Das Ergebnis könnte auf Opcache zwischengespeichert werden, da das Ergebnis eine PHP -Codedatei ist. |
| JSON_Object | Es wird mit JSON (als Objekt) serialisiert |
| JSON_Array | Es wird mit JSON (als Array) serialisiert |
| CSV | Es serialisiert mithilfe einer CSV -Datei. |
| Igbinary | Es serialisiert mithilfe einer iGBINY -Datei. |
| Keine (Standardwert) | Es ist nicht serialisiert. Informationen müssen manuell serialisiert/deserialisiert werden |
Beispiele:
$ flatcon = new DocumentStoreOne ( __DIR__ . " /base " ); // new instance, using the folder /base, without serialization and with the default data
$ flatcon = new DocumentStoreOne ( __DIR__ . " /base " , '' , ' auto ' , '' , ' php_array ' ); // new instance and serializing using php_arrayBenchmark Wie viel Zeit (in Sekunden) benötigt, um 100 Einsätze hinzuzufügen.
use eftec DocumentStoreOne DocumentStoreOne ;
include " lib/DocumentStoreOne.php " ;
try {
$ flatcon = new DocumentStoreOne ( __DIR__ . " /base " , ' tmp ' );
} catch ( Exception $ e ) {
die ( " Unable to create document store. " . $ e -> getMessage ());
} use eftec DocumentStoreOne DocumentStoreOne ;
include " lib/DocumentStoreOne.php " ;
try {
$ flatcon = new DocumentStoreOne ( " /base " , ' tmp ' ,DocumentStoreOne:: DSO_APCU );
} catch ( Exception $ e ) {
die ( " Unable to create document store. " . $ e -> getMessage ());
}Gibt true zurück, wenn die Sammlung gültig ist (ein Unterordner).
$ ok = $ flatcon -> isCollection ( ' tmp ' );Es setzt die aktuelle Sammlung
$ flatcon -> collection ( ' newcollection ' ); // it sets a collection.Dieser Befehl könnte verschachtelt werden.
$ flatcon -> collection ( ' newcollection ' )-> select (); // it sets and return a queryBeachten Sie, dass es nicht bestätigt wird, ob die Sammlung korrekt ist oder existiert. Sie müssen isCollection () verwenden, um zu überprüfen, ob es richtig ist.
Es wird festgelegt, wenn wir die Informationen automatisch serialisieren möchten, und wir legen fest, wie sie serialisiert werden. Sie können auch mit dem Konstruktor einstellen.
| Strategie | Typ |
|---|---|
| Php | Es serialisiert mit der Serialize () -Funktion. |
| PHP_Array | Es serialisiert mit incluse ()/var_export () Funktion. Das Ergebnis kann auf Opcache zwischengespeichert werden, da das Ergebnis eine PHP -Datei ist |
| JSON_Object | Es wird mit JSON (als Objekt) serialisiert |
| JSON_Array | Es wird mit JSON (als Array) serialisiert |
| CSV | Es serialisiert mithilfe einer CSV -Datei. |
| Igbinary | Es serialisiert mithilfe einer iGBINY -Datei. |
| Keine (Standardwert) | Es ist nicht serialisiert. Informationen müssen manuell serialisiert/deserialisiert werden |
Es erstellt eine Sammlung (einen neuen Ordner im Basisordner). Es gibt falsch zurück, wenn die Operation fehlschlägt. Ansonsten kehrt es wahr zurück
$ flatcon -> createCollection ( ' newcollection ' );
$ flatcon -> createCollection ( ' /folder1/folder2 ' ); Fügt ein neues Dokument (Zeichenfolge) in die angegebene ID ein. Wenn das Dokument vorhanden ist, wird es aktualisiert.
$ tries zeigt die Anzahl der Versuche an. Der Standardwert beträgt -1 (Standardzahl der Versuche).
// if we are not using auto serialization
$ doc = json_encode ([ " a1 " => ' hello ' , " a2 " => ' world ' ]);
$ flatcon -> insertOrUpdate ( " 1 " , $ doc ); // it will create a document called 1.dson in the base folder.
// if we are using auto serialization
$ flatcon -> insertOrUpdate ( " 1 " ,[ " a1 " => ' hello ' , " a2 " => ' world ' ]);Wenn das Dokument gesperrt ist, wird es bis zum verfügbaren oder nach einer "N -ten" Anzahl von Versuchen wiederholt (standardmäßig sind es 100 Versuche, die 10 Sekunden entsprechen)
Es ist schneller als einfügen oder aktualisieren.
Fügt ein neues Dokument (Zeichenfolge) in die angegebene ID ein. Wenn das Dokument existiert, gibt es false zurück.
$ tries zeigt die Anzahl der Versuche an. Der Standardwert beträgt -1 (Standardzahl der Versuche).
// if we are not using auto serialization
$ doc = json_encode ( array ( " a1 " => ' hello ' , " a2 " => ' world ' ));
$ flatcon -> insert ( " 1 " , $ doc );
// if we are using auto serialization
$ flatcon -> insert ( " 1 " ,[ " a1 " => ' hello ' , " a2 " => ' world ' ]);Wenn das Dokument gesperrt ist, wird es bis zum verfügbaren oder nach einer "N -ten" Anzahl von Versuchen wiederholt (standardmäßig sind es 100 Versuche, die 10 Sekunden entsprechen)
Aktualisieren Sie ein Dokument (Zeichenfolge) in der angegebenen ID . Wenn das Dokument nicht vorhanden ist, gibt es falsche zurück
$ tries zeigt die Anzahl der Versuche an. Der Standardwert beträgt -1 (Standardzahl der Versuche).
// if we are not using auto serialization
$ doc = json_encode ([ " a1 " => ' hello ' , " a2 " => ' world ' ]);
$ flatcon -> update ( " 1 " , $ doc );
// if we are using auto serialization
$ flatcon -> update ( " 1 " ,[ " a1 " => ' hello ' , " a2 " => ' world ' ]);Wenn das Dokument gesperrt ist, wird es bis zum verfügbaren oder nach einer "N -ten" Anzahl von Versuchen wiederholt (standardmäßig sind es 100 Versuche, die zu 10 Sekunden entsprechen)
Es liest das Dokument $ id . Wenn das Dokument nicht vorhanden ist oder es nicht lesen kann, gibt es falsch zurück.
$ tries zeigt die Anzahl der Versuche an. Der Standardwert beträgt -1 (Standardzahl der Versuche).
$ doc = $ flatcon -> get ( " 1 " ); // the default value is false
$ doc = $ flatcon -> get ( " 1 " ,- 1 , ' empty ' );Wenn das Dokument gesperrt ist, wird es bis zum verfügbaren oder nach einer "N -ten" Anzahl von Versuchen wiederholt (standardmäßig sind es 100 Versuche, die 10 Sekunden entsprechen)
Es liest das Dokument $ id gefiltert. Wenn das Dokument nicht vorhanden ist oder es nicht lesen kann, gibt es falsch zurück.
$ tries zeigt die Anzahl der Versuche an. Der Standardwert beträgt -1 (Standardzahl der Versuche).
// data in rows [['id'=>1,'cat'=>'vip'],['id'=>2,'cat'=>'vip'],['id'=>3,'cat'=>'normal']];
$ data = $ this -> getFiltered ( ' rows ' ,- 1 , false ,[ ' cat ' => ' normal ' ]); // [['id'=>3,'cat'=>'normal']]
$ data = $ this -> getFiltered ( ' rows ' ,- 1 , false ,[ ' type ' => ' busy ' ], false ); // [2=>['id'=>3,'cat'=>'normal']]Wenn das Dokument gesperrt ist, wird es bis zum verfügbaren oder nach einer "N -ten" Anzahl von Versuchen wiederholt (standardmäßig sind es 100 Versuche, die 10 Sekunden entsprechen)
Es fügt einem Dokument mit Name $ $ einen Wert hinzu. Der neue Wert wird hinzugefügt, sodass das gesamte Dokument erstellt wird. Es ist beispielsweise für eine Protokolldatei nützlich.
a) Wenn der Wert nicht vorhanden ist, wird er mit $ addValue erstellt. Andernfalls wird es wahr zurückkehren
b) Wenn der Wert existiert, wird $ addValue hinzugefügt und er wird wahr zurückgegeben
c) Ansonsten wird es falsch zurückgegeben
$ seq = $ flatcon -> appendValue ( " log " , date ( ' c ' ). " new log " );Es liest oder generiert eine neue Sequenz.
a) Wenn die Sequenz existiert, wird sie durch $ Intervall erhöht und dieser Wert wird zurückgegeben.
b) Wenn die Sequenz nicht vorhanden ist, wird sie mit $ init erstellt und dieser Wert wird zurückgegeben. c) Wenn die Bibliothek keine Sequenz erstellen kann, nicht in der Lage ist, zu sperren oder die Sequenz zu existieren, aber sie nicht lesen kann, gibt sie falsch zurück
$ seq = $ flatcon -> getNextSequence ();Sie können eine Sequenz mit $ id = get ('genSeq_') ansehen, es wird jedoch nicht empfohlen.
Wenn die Sequenz beschädigt ist, wird sie auf $ init zurückgesetzt
Wenn Sie eine Liste von Sequenzen reservieren müssen, können Sie $ $ reseveladditional verwenden
$ seq = $ flatcon -> getNextSequence ( " seq " ,- 1 , 1 , 1 , 100 ); // if $seq=1, then it's reserved up to the 101. The next value will be 102.Es gibt eine eindeutige Sequenz (64 -Bit -Integer) zurück, die auf der Zeit, einem zufälligen Wert und einer Serverid basiert.
Die Kollisionschancen (eine Generation desselben Werts) betragen 1/4095 (pro zwei Operationen, die alle 0,0001 Sekunden ausgeführt werden).
$ this -> nodeId = 1 ; // if it is not set then it uses a random value each time.
$ unique = $ flatcon -> getSequencePHP (); Es prüft, ob das Dokument $ id vorhanden ist. Es gibt wahr zurück, wenn das Dokument existiert. Ansonsten kehrt es falsch zurück.
$ tries zeigt die Anzahl der Versuche an. Der Standardwert beträgt -1 (Standardzahl der Versuche).
Die Validierung erfolgt nur, wenn das Dokument vollständig freigeschaltet ist.
$ found = $ flatcon -> ifExist ( " 1 " );Wenn das Dokument gesperrt ist, wird es bis zum verfügbaren oder nach einer "N -ten" Anzahl von Versuchen wiederholt (standardmäßig sind es 100 Versuche, die zu 10 Sekunden entsprechen)
Es löscht das Dokument $ id . Wenn das Dokument nicht vorhanden ist oder es nicht löschen kann, gibt es falsch zurück.
$ tries zeigt die Anzahl der Versuche an. Der Standardwert beträgt -1 (Standardzahl der Versuche).
$ doc = $ flatcon -> delete ( " 1 " );Wenn das Dokument gesperrt ist, wird es bis zum verfügbaren oder nach einer "N -ten" Anzahl von Versuchen wiederholt (standardmäßig sind es 100 Versuche, die zu 10 Sekunden entsprechen)
Es gibt alle in einer Sammlung gespeicherten IDs zurück.
$ listKeys = $ flatcon -> select ();
$ listKeys = $ flatcon -> select ( " invoice_* " );Es enthält gesperrte Dokumente.
Kopieren Sie das Dokument $ idoriginin in $ iddestination
$ bool = $ flatcon -> copy ( 20 , 30 );Wenn das Dokumentziel existiert, wird es ersetzt
Benennen Sie das Dokument $ idorigin als $ iddestination um
$ bool = $ flatcon -> rename ( 20 , 30 );Wenn das Dokumentziel existiert, schlägt der Vorgang fehl.
Es wandelt eine STD -Klasse in eine bestimmte Klasse um.
$ inv = new Invoice ();
$ invTmp = $ doc -> get ( ' someid ' ); //$invTmp is a stdClass();
DocumentStoreOne:: fixCast ( $ inv , $ invTmp ); Es funktioniert nicht mit Mitgliedern, die eine Reihe von Objekten sind. Das Array wird als STD -Klasse gehalten.
Die nächsten Felder sind öffentlich und können während der Laufzeit geändert werden
| Feld | Typ |
|---|---|
| $ Datenbank | String Root -Ordner der Datenbank |
| $ kollektion | String Current Collection (Unterordner) der Datenbank |
| $ maxlocktime = 120 | int Maximiumdauer des Schlosses (in Sekunden). Standardmäßig sind es 2 Minuten |
| $ defaultnumretry = 100 | int Standardnummer der Wiederholungen. Standardmäßig versucht es 100x0.1sec = 10 Sekunden |
| $ intervalbetweenretry = 100000 | INT -Intervall (in Mikrosekunden) zwischen Wiederholungen. 100000 bedeutet 0,1 Sekunden |
| $ decext = ". Dson" | String Standardweiterung (mit Punkt) des Dokuments |
| $ keyencryption = "" | Die String gibt an, ob der Schlüssel verschlüsselt ist oder nicht, wenn er gespeichert ist (der Dateiname). Leere Mittel, keine Verschlüsselung. Sie könnten MD5, SHA1, SHA256, .. |
Beispiel:
$ ds = new DocumentStoreOne ();
$ ds -> maxLockTime = 300 ; $ ds = new DocumentStoreOne ();
$ ds -> insert ( ' 1 ' , ' hello ' ); // it stores the document 1.dson
$ ds -> keyEncryption = ' SHA256 ' ;
$ ds -> insert ( ' 1 ' , ' hello ' ); // it stores the document 6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b.dson Es könnte manuell gemacht werden. Das System ermöglicht es, einen vorkalkulierten Wert zu speichern, auf den leicht zugegriffen werden kann (anstatt alle Werte zu lesen).
Nehmen wir an, wir haben eine Liste von Einkäufen
| Ausweis | Kunde | Alter | Sex | Produktpurchase | Menge |
|---|---|---|---|---|---|
| 14 | John | 33 | M | 33 | 3 |
| 25 | Anna | 22 | F | 32 | 1 |
| Produktcode | Unitprice |
|---|---|
| 32 | 23.3 |
| 33 | 30 |
John kaufte 3 Produkte mit dem Code 33. Die Produkte 33 kosten 23,3 USD pro Einheit.
Frage: Wie viel hat jeder Kunde bezahlt?
Es ist eine einfache Übung, die für eine relationale Datenbank besser geeignet ist (aus Einkäufen Inner -Join -Produkte auswählen). Wenn das Dokument jedoch lang oder komplex in der Datenbank gespeichert ist, ist es hier, wo ein Dokumentgeschäft leuchtet.
// 1) open the store
$ ds = new DocumentStoreOne ( ' base ' , ' purchases ' ); // we open the document store and selected the collection purchase.
$ ds -> autoSerialize ( true , ' auto ' );
// 2) reading all products
// if the list of products holds in memory then, we could store the whole list in a single document (listproducts key)
$ products = $ ds -> collection ( ' products ' )-> get ( ' listproducts ' );
// 3) we read the keys of every purchases. It could be slow and it should be a limited set (<100k rows)
$ purchases = $ ds -> collection ( ' purchases ' )-> select (); // they are keys such as 14,15...
$ customerXPurchase =[];
// 4) We read every purchase. It is also slow. Then we merge the result and obtained the final result
foreach ( $ purchases as $ k ) {
$ purchase = $ ds -> get ( $ k );
@ $ customerXPurchase [ $ purchase -> customer ]+=( $ purchase -> amount * @ $ products [ $ purchase -> productpurchase ]); // we add the amount
}
// 5) Finally, we store the result.
$ ds -> collection ( ' total ' )-> insertOrUpdate ( $ customerXPurchase , ' customerXPurchase ' ); // we store the result.| Kunde | Wert |
|---|---|
| John | 69.9 |
| Anna | 30 |
Da es auf Code durchgeführt wird, ist es möglich, ein Hybridsystem (relationale Datenbank+Store+Speichercache) zu erstellen.
Nehmen wir an, wir möchten die nächsten Informationen serialisieren:
$ input =[[ ' a1 ' => 1 , ' a2 ' => ' a ' ],[ ' a1 ' => 2 , ' a2 ' => ' b ' ]];Die Werte sind nicht serialisiert, daher ist es nicht möglich, ein Objekt, ein Array oder eine andere Struktur zu serialisieren. Es funktioniert nur mit Saiten.
Wie Werte gespeichert werden
helloworld
Wie Werte zurückgegeben werden
" helloworld " Die Serialisierung von PHP ist eine der schnelleren Möglichkeiten, um zu serialisieren und zu serialisieren, und gibt immer den gleichen Wert mit derselben Struktur zurück (Klassen, Array, Felder)
Der gespeicherte Wert könnte jedoch lang sein.
Wie die Werte gespeichert werden:
a:2:{i:0;a:2:{s:2:"a1";i:1;s:2:"a2";s:1:"a";}i:1;a:2:{s:2:"a1";i:2;s:2:"a2";s:1:"b";}}
Wie die Werte zurückgegeben werden:
[['a1'=>1,'a2'=>'a'],['a1'=>2,'a2'=>'b']]
Diese Serialisierung generiert einen PHP -Code. Dieser Code ist ausführlich, er hat jedoch einige nette Funktionen:
Wie die Werte gespeichert werden:
<?php /** @generated */
return array (
0 =>
array (
' a1 ' => 1 ,
' a2 ' => ' a ' ,
),
1 =>
array (
' a1 ' => 2 ,
' a2 ' => ' b ' ,
),
);Wie die Werte zurückgegeben werden:
[['a1'=>1,'a2'=>'a'],['a1'=>2,'a2'=>'b']]
Beide Methoden arbeiten mit JSON für die Serialisierung und De-Serialisierung mit JSON, aber der erste bei Renditen immer ein assoziatives Array, während das andere ein Objekt zurückgeben könnte (STDCLASS)
Pro:
Nachteile:
Wie die Werte gespeichert werden:
[{"a1":1,"a2":"a"},{"a1":2,"a2":"b"}]
Wie die Werte zurückgegeben werden:
[[ ' a1 ' => 1 , ' a2 ' => ' a ' ],[ ' a1 ' => 2 , ' a2 ' => ' b ' ]] // array
[stdClass{ ' a1 ' => 1 ,'a2'=>'a'},stdClass{ ' a1 ' => 2 ,'a2'=>'b'}] // objectStandardmäßig löst diese Bibliothek Fehler aus, wenn ein Fehler oder eine Ausnahme auftritt. Einige Methoden ermöglichen es, Fehler zu vermeiden, aber die meisten von ihnen könnten einen Fehler machen.
Die Fehler sind Versuch/Catch-Fang.
// throw an error:
$ this -> throwable = true ; // (default value is true) If false, then the errors are stored in $this->latestError
try {
$ this -> insert ( ' id1 ' , ' values ' );
} catch ( $ ex ) {
var_dump ( $ ex );
} // not throw an error:
$ this -> throwable = false ;
$ this -> insert ( ' id1 ' , ' values ' );
if ( $ this -> latestError ) {
var_dump ( $ this -> latestError );
}
$ this -> resetError ();Oder Sie können auch nicht eine Ausnahme ausgelöst haben:
// not throw an error:
$ this ->-> noThrowOnError ()-> insert ( ' id1 ' , ' values ' );
// but you can still see the latest error:
if ( $ this -> latestError ) {
var_dump ( $ this -> latestError );
}Sie können wie folgt mit CSV arbeiten:
$ doc = new DocumentStoreOne ( __DIR__ . " /base " , '' , ' none ' , '' , ' csv ' ); // set your strategy to csv.
$ doc -> docExt = ' .csv ' ; // (optional), you can set the extension of the document
$ doc -> csvPrefixColumn = ' col_ ' ; // (optional), you can set the name of the columns (if the csv doesn't have columns)
$ doc -> csvStyle (); // (optional) not needing, but you can use to set your own specifications of csv, for example tab-separated, etc.
$ doc -> regionalStyle (); // (optional) not needing, but you can use to set your own regional settings.
$ values =[
[ ' name ' => ' john1 ' , ' age ' => 22 ],
[ ' name ' => ' john2 ' , ' age ' => 22 ],
[ ' name ' => ' john3 ' , ' age ' => 22 ],
];
$ doc -> delete ( ' csv1 ' );
$ doc -> insert ( ' csv1 ' , $ values );[RunTimeException] konnte Paket EFTEC/DocumentStoreOne in repo.packagist.org nicht laden: [UnerwartworpEdValueException] konnte die Versionsbeschränkung nicht analysieren ^5.6. : Ungültige Versionszeichenfolge "^5.6. "