用於PHP的文檔存儲,該存儲允許倍數並發。它是MongoDB或CouchDB的簡約替代品,而沒有安裝新服務的開銷。
它還可以充當一個小的足跡數據庫。
平均而言,SMB每月產生100張發票。因此,假設SMB每十年生成12000個發票。
測試與客戶一起生成12000個發票,詳細信息(每個詳細信息約1-5行),以及i7/ssd/16GB/Windows 64bits上的日期。

進行100次並發測試的測試(寫和閱讀)10次。
| n° | 閱讀 | (多發性硬化症) | 閱讀 | 錯誤 |
|---|---|---|---|---|
| 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 ' )); 它創建文檔storeone實例。
| 戰略 | 類型 | 伺服器 | 基準 |
|---|---|---|---|
| DSO_AUTO | 它設定了最佳可用策略(默認) | 取決於 | - |
| DSO_FOLDER | 它使用文件夾來鎖定/解鎖文檔 | - | 0.3247 |
| DSO_APCU | 它使用apcu鎖定/解鎖文檔 | - | 0.1480 |
| dso_redis | 它使用redis鎖定/解鎖文檔 | Localhost:6379 | 2.5403(最壞) |
| dso_none | 它無需鎖定/解鎖文檔。這是最快的方法,但對於用戶而言,它是不安全的 | 0 |
| 戰略 | 類型 |
|---|---|
| php | 它使用serialize()函數序列化 |
| php_array | 它使用include()/var_export()函數序列化。結果可以在OPCACHE上緩存,因為結果是PHP代碼文件。 |
| json_object | 它是使用JSON(作為對象)序列化的 |
| JSON_ARRAY | 它使用JSON(作為數組)序列化 |
| CSV | 它使用CSV文件序列化。 |
| igbinary | 它使用igbinary文件序列化。 |
| 無(默認值) | 它不是序列化的。信息必須手動序列化/除外序列化 |
示例:
$ 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_array基準添加100個插入物需要多少時間(以秒為單位)。
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 ());
}如果收集有效(子文件夾),則返回為true。
$ ok = $ flatcon -> isCollection ( ' tmp ' );它設置了當前集合
$ flatcon -> collection ( ' newcollection ' ); // it sets a collection.該命令可以嵌套。
$ flatcon -> collection ( ' newcollection ' )-> select (); // it sets and return a query請注意,它無法驗證該集合是否正確或存在。您必須使用ISCollection()來驗證是否正確。
如果我們想自動序列化信息,它將設置它,並將其設置如何序列化。您也可以使用構造函數設置。
| 戰略 | 類型 |
|---|---|
| php | 它使用serialize()函數序列化。 |
| php_array | 它使用include()/var_export()函數序列化。結果可以在OPCACHE上緩存,因為結果是PHP文件 |
| json_object | 它是使用JSON(作為對象)序列化的 |
| JSON_ARRAY | 它使用JSON(作為數組)序列化 |
| CSV | 它使用CSV文件序列化。 |
| igbinary | 它使用igbinary文件序列化。 |
| 無(默認值) | 它不是序列化的。信息必須手動序列化/除外序列化 |
它創建一個集合(基本文件夾內的新文件夾)。如果操作失敗,它將返回false;否則它將返回真實
$ flatcon -> createCollection ( ' newcollection ' );
$ flatcon -> createCollection ( ' /folder1/folder2 ' ); 將新文檔(字符串)插入指定的$ ID中。如果文檔存在,則已更新。
$嘗試表示嘗試的數量。默認值為-1(默認嘗試數)。
// 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 ' ]);如果該文檔已鎖定,則將其重新驗證直到可用或在“ nth”嘗試之後(默認情況下,它的100次嘗試相當於10秒)
它比插入或更新快。
將新文檔(字符串)插入指定的$ ID中。如果文檔存在,則返回false。
$嘗試表示嘗試的數量。默認值為-1(默認嘗試數)。
// 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 ' ]);如果該文檔已鎖定,則將其重新驗證直到可用或在“ nth”嘗試之後(默認情況下,它的100次嘗試相當於10秒)
在指定的$ ID中更新文檔(字符串)。如果文檔不存在,則返回false
$嘗試表示嘗試的數量。默認值為-1(默認嘗試數)。
// 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 ' ]);如果文檔已鎖定,則將其重新驗證直至可用或在“ nth”數量之後進行(默認情況下,它的100次嘗試等於10秒)
它讀取文檔$ id 。如果文檔不存在,或者無法讀取文檔,則它將返回false。
$嘗試表示嘗試的數量。默認值為-1(默認嘗試數)。
$ doc = $ flatcon -> get ( " 1 " ); // the default value is false
$ doc = $ flatcon -> get ( " 1 " ,- 1 , ' empty ' );如果該文檔已鎖定,則將其重新驗證直到可用或在“ nth”嘗試之後(默認情況下,它的100次嘗試相當於10秒)
它讀取已過濾的文檔$ id 。如果文檔不存在,或者無法讀取文檔,則它將返回false。
$嘗試表示嘗試的數量。默認值為-1(默認嘗試數)。
// 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']]如果該文檔已鎖定,則將其重新驗證直到可用或在“ nth”嘗試之後(默認情況下,它的100次嘗試相當於10秒)
它為具有名稱$名稱的文檔添加了一個值。添加了新值,因此可以避免創建整個文檔。例如,對於日誌文件很有用。
a)如果值不存在,則使用$ addValue創建。否則,它將返回真實
b)如果存在該值,則添加$ addValue ,它將返回true
c)否則,它將返回false
$ seq = $ flatcon -> appendValue ( " log " , date ( ' c ' ). " new log " );它讀取或生成一個新序列。
a)如果序列存在,則會通過$ Interval遞增,並返回該值。
b)如果序列不存在,則使用$ init創建,然後返回該值。 c)如果庫無法創建序列,無法鎖定或序列存在
$ seq = $ flatcon -> getNextSequence ();您可以窺視使用$ id = get('genseq_')的序列,但是不建議這樣做。
如果序列損壞,則將其重置為$ init
如果您需要保留序列列表,則可以使用$ reserveaditional
$ 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.它根據時間,隨機值和服務器返回唯一的序列(64位整數)。
碰撞的機會(相同值的產生)為1/4095(每兩個操作每0.0001秒執行一次)。
$ this -> nodeId = 1 ; // if it is not set then it uses a random value each time.
$ unique = $ flatcon -> getSequencePHP (); 它檢查文檔$ id是否存在。如果文檔存在,它將返回true。否則,它返回false。
$嘗試表示嘗試的數量。默認值為-1(默認的嘗試號)。
僅當文檔被完全解鎖時,才會發生驗證。
$ found = $ flatcon -> ifExist ( " 1 " );如果文檔已鎖定,則將其重新驗證直至可用或在“ nth”數量之後進行(默認情況下,它的100次嘗試等於10秒)
它刪除文檔$ id 。如果文檔不存在,或者無法刪除,則它將返回false。
$嘗試表示嘗試的數量。默認值為-1(默認的嘗試號)。
$ doc = $ flatcon -> delete ( " 1 " );如果文檔已鎖定,則將其重新驗證直至可用或在“ nth”數量之後進行(默認情況下,它的100次嘗試等於10秒)
它返回存儲在集合上的所有ID。
$ listKeys = $ flatcon -> select ();
$ listKeys = $ flatcon -> select ( " invoice_* " );它包括鎖定文件。
在$ iDdestination中復製文檔$ idorigin
$ bool = $ flatcon -> copy ( 20 , 30 );如果文檔目的地存在,則更換了
將文檔$ IDORIGIN重命名為$ IDDESTINATION
$ bool = $ flatcon -> rename ( 20 , 30 );如果文檔目標存在,則操作失敗。
它將stdclass轉換為特定類。
$ inv = new Invoice ();
$ invTmp = $ doc -> get ( ' someid ' ); //$invTmp is a stdClass();
DocumentStoreOne:: fixCast ( $ inv , $ invTmp ); 它與對像數組的成員無效。陣列保存為stdclass。
下一個字段是公開的,可以在運行時更改
| 場地 | 類型 |
|---|---|
| $數據庫 | 數據庫的字符串根文件夾 |
| $收集 | 數據庫的字符串電流集合(子文件夾) |
| $ MAXLOCKTIME = 120 | 鎖的最大持續時間(以秒為單位)。默認情況下是2分鐘 |
| $ defaultNumRetry = 100 | int默認的重試號碼。默認情況下,它嘗試100x0.1sec = 10秒 |
| $ Intervalbetweentry = 100000 | int間隔(以微秒為單位)。 100000表示0.1秒 |
| $ docext =“。dson” | 文檔的字符串默認擴展名(帶有點) |
| $ keyCencryption =“” | 字符串指示鍵在存儲時是否加密(文件名)。空的手段,沒有加密。您可以使用MD5,SHA1,SHA256,.. |
例子:
$ 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 可以手動完成。該系統允許存儲一個可以輕鬆訪問的預計值(而不是讀取所有值)。
假設下一個練習,我們有購買的清單
| ID | 顧客 | 年齡 | 性別 | 產品購買 | 數量 |
|---|---|---|---|---|---|
| 14 | 約翰 | 33 | m | 33 | 3 |
| 25 | 安娜 | 22 | f | 32 | 1 |
| productCode | Unitprice |
|---|---|
| 32 | 23.3 |
| 33 | 30 |
約翰以33號代碼購買了3種產品。每單位33產品的價格為$ 23.3。
問題,每個客戶支付了多少錢?
這是一個簡單的練習,更適合關係數據庫(從購買內聯接產品中選擇 *)。但是,如果文檔很長或很複雜,可以存儲在數據庫中,則在這裡存儲在此處。
// 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.| 顧客 | 價值 |
|---|---|
| 約翰 | 69.9 |
| 安娜 | 30 |
由於它是在代碼上完成的,因此可以創建一個混合系統(關係數據庫+商店+內存緩存)
假設我們要序列化下一個信息:
$ input =[[ ' a1 ' => 1 , ' a2 ' => ' a ' ],[ ' a1 ' => 2 , ' a2 ' => ' b ' ]];值未序列化,因此不可能序列化對象,數組或其他結構。它只能與字符串一起使用。
如何存儲值
helloworld
如何返回值
" helloworld " PHP的序列化是序列化和去序列化的更快方法之一,它總是以相同的結構(類,數組,字段)返回相同的值
但是,存儲的值可能很長。
如何存儲值:
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";}}
如何返回值:
[['a1'=>1,'a2'=>'a'],['a1'=>2,'a2'=>'b']]
此序列化生成了PHP代碼。該代碼是冗長的,但是它具有一些不錯的功能:
如何存儲值:
<?php /** @generated */
return array (
0 =>
array (
' a1 ' => 1 ,
' a2 ' => ' a ' ,
),
1 =>
array (
' a1 ' => 2 ,
' a2 ' => ' b ' ,
),
);如何返回值:
[['a1'=>1,'a2'=>'a'],['a1'=>2,'a2'=>'b']]
這兩種方法都與JSON一起用於序列化和除外序列化,但是返回的第一個始終是一個關聯數組,而另一個可以返回對象(stdclass)
Pro:
缺點:
如何存儲值:
[{"a1":1,"a2":"a"},{"a1":2,"a2":"b"}]
如何返回值:
[[ ' a1 ' => 1 , ' a2 ' => ' a ' ],[ ' a1 ' => 2 , ' a2 ' => ' b ' ]] // array
[stdClass{ ' a1 ' => 1 ,'a2'=>'a'},stdClass{ ' a1 ' => 2 ,'a2'=>'b'}] // object默認情況下,當發生錯誤或異常時,此庫會引發錯誤。某些方法允許避免丟棄錯誤,但大多數方法可能會丟棄錯誤。
錯誤是嘗試/捕獲捕獲物。
// 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 ();或者,您也可以用來避免拋出例外:
// not throw an error:
$ this ->-> noThrowOnError ()-> insert ( ' id1 ' , ' values ' );
// but you can still see the latest error:
if ( $ this -> latestError ) {
var_dump ( $ this -> latestError );
}您可以與CSV合作如下:
$ 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]無法在repo.packagist.org中加載軟件包eftec/documentStoreOne:[InfirartValueException]無法解析版本約束 ^5.6。 :無效版本字符串“^5.6”。