Um armazenamento de documentos para PHP que permite múltiplos simultaneses. É uma alternativa minimalista ao MongoDB ou CouchDB sem a sobrecarga de instalar um novo serviço.
Ele também funciona como um pequeno banco de dados de pegada.
Em média, um SMB gera 100 faturas por mês. Então, digamos que um SMB gera 12000 faturas por década.
Teste de geração de 12000 faturas com cliente, detalhes (cerca de 1-5 linhas por detalhe) e data em um i7/ssd/16gb/windows 64bits.

Um teste com 100 testes simultâneos (gravar e ler), 10 vezes.
| N ° | Lê | (EM) | Lê | Erro |
|---|---|---|---|---|
| 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 ' )); Ele cria a instância DocumentStoreOne.
| estratégia | tipo | servidor | benchmark |
|---|---|---|---|
| Dso_auto | Ele define a melhor estratégia disponível (padrão) | depende | - |
| Dso_folder | Ele usa uma pasta para bloquear/desbloquear um documento | - | 0,3247 |
| DSO_APCU | Ele usa a APCU para bloquear/desbloquear um documento | - | 0,1480 |
| Dso_redis | Ele usa redis para bloquear/desbloquear um documento | Localhost: 6379 | 2.5403 (pior) |
| Dso_none | Ele não usa nada para bloquear/desbloquear um documento. É o método mais rápido, mas não é seguro para os usuários múltiplos | 0 |
| estratégia | tipo |
|---|---|
| php | Ele serializa usando a função Serialize () |
| php_array | Ele serializa usando a função incluir ()/var_export (). O resultado pode ser armazenado em cache no Opcache porque o resultado é um arquivo de código PHP. |
| json_object | é serializado usando JSON (como objeto) |
| json_array | é serializado usando JSON (como matriz) |
| CSV | Ele serializa usando um arquivo CSV. |
| Igbinário | Ele serializa usando um arquivo igbinary. |
| Nenhum (valor padrão) | não é serializado. As informações devem ser serializadas/despertalizadas manualmente |
Exemplos:
$ 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_arrayReferência de quanta tempo (em segundos) leva para adicionar 100 inserções.
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 ());
}Retorna true se a coleção for válida (um subpasso).
$ ok = $ flatcon -> isCollection ( ' tmp ' );Ele define a coleção atual
$ flatcon -> collection ( ' newcollection ' ); // it sets a collection.Este comando pode ser aninhado.
$ flatcon -> collection ( ' newcollection ' )-> select (); // it sets and return a queryObserve que ele não valida se a coleção estiver correta ou existir. Você deve usar o iSCollection () para verificar se está certo.
Ele define se queremos serializar automaticamente as informações e definimos como elas são serializadas. Você também pode definir usando o construtor.
| estratégia | tipo |
|---|---|
| php | Ele serializa usando a função Serialize (). |
| php_array | Ele serializa usando a função incluir ()/var_export (). O resultado pode ser armazenado em cache no opcache porque o resultado é um arquivo php |
| json_object | é serializado usando JSON (como objeto) |
| json_array | é serializado usando JSON (como matriz) |
| CSV | Ele serializa usando um arquivo CSV. |
| Igbinário | Ele serializa usando um arquivo igbinary. |
| Nenhum (valor padrão) | não é serializado. As informações devem ser serializadas/despertalizadas manualmente |
Ele cria uma coleção (uma nova pasta dentro da pasta base). Retorna falsa se a operação falhar; Caso contrário, retorna verdadeiro
$ flatcon -> createCollection ( ' newcollection ' );
$ flatcon -> createCollection ( ' /folder1/folder2 ' ); Insira um novo documento (string) no $ ID indicado. Se o documento existir, ele será atualizado.
$ tenta indica o número de tentativas. O valor padrão é -1 (número padrão de tentativas).
// 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 ' ]);Se o documento estiver bloqueado, ele serião até que esteja disponível ou após um número "Nth" de tentativas (por padrão, são 100 tentativas tão equivalentes a 10 segundos)
É mais rápido que inserir ou atualizar.
Insira um novo documento (string) no $ ID indicado. Se o documento existir, ele retornará falso.
$ tenta indica o número de tentativas. O valor padrão é -1 (número padrão de tentativas).
// 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 ' ]);Se o documento estiver bloqueado, ele serião até que esteja disponível ou após um número "Nth" de tentativas (por padrão, são 100 tentativas tão equivalentes a 10 segundos)
Atualize um documento (string) no $ ID indicado. Se o documento não existir, ele retornará falso
$ tenta indica o número de tentativas. O valor padrão é -1 (número padrão de tentativas).
// 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 ' ]);Se o documento estiver bloqueado, ele serião até que esteja disponível ou após um número "Nth" de tentativas (por padrão, são 100 tentativas que equivale a 10 segundos)
Ele lê o documento $ id . Se o documento não existir, ou não conseguir lê -lo, ele retornará false.
$ tenta indica o número de tentativas. O valor padrão é -1 (número padrão de tentativas).
$ doc = $ flatcon -> get ( " 1 " ); // the default value is false
$ doc = $ flatcon -> get ( " 1 " ,- 1 , ' empty ' );Se o documento estiver bloqueado, ele serião até que esteja disponível ou após um número "Nth" de tentativas (por padrão, são 100 tentativas tão equivalentes a 10 segundos)
Ele lê o documento $ ID filtrado. Se o documento não existir, ou não conseguir lê -lo, ele retornará false.
$ tenta indica o número de tentativas. O valor padrão é -1 (número padrão de tentativas).
// 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']]Se o documento estiver bloqueado, ele serião até que esteja disponível ou após um número "Nth" de tentativas (por padrão, são 100 tentativas tão equivalentes a 10 segundos)
Ele agrega um valor a um documento com nome $ nome . O novo valor é agregado, por isso evita criar o documento inteiro. É útil, por exemplo, para um arquivo de log.
a) Se o valor não existir, será criado com $ addValue. Caso contrário, ele retornará verdadeiro
b) Se o valor existir, então $ addValue será adicionado e retornará verdadeiro
c) Caso contrário, ele retornará falso
$ seq = $ flatcon -> appendValue ( " log " , date ( ' c ' ). " new log " );Ele lê ou gera uma nova sequência.
a) Se a sequência existir, ela será incrementada pelo intervalo $ e esse valor será retornado.
b) Se a sequência não existir, é criada com $ init e esse valor será retornado. c) Se a biblioteca não conseguir criar uma sequência, não é possível travar ou a sequência existe, mas não é possível ler, ela retorna falsa
$ seq = $ flatcon -> getNextSequence ();Você pode espiar uma sequência com $ id = get ('genseq_'), no entanto, não é recomendado.
Se a sequência estiver corrompida, será redefinido para $ init
Se você precisar reservar uma lista de seqüências, você pode usar $ Reserveaddicional
$ 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.Ele retorna uma sequência única (número inteiro de 64 bits) com base no tempo, um valor aleatório e um serverID.
As chances de colisão (uma geração do mesmo valor) são 1/4095 (por duas operações executadas a cada 0,0001 segundo).
$ this -> nodeId = 1 ; // if it is not set then it uses a random value each time.
$ unique = $ flatcon -> getSequencePHP (); Ele verifica se o documento $ id existe. Ele retorna true se o documento existir. Caso contrário, ele retorna falsa.
$ tenta indica o número de tentativas. O valor padrão é -1 (número padrão de tentativas).
A validação só ocorre se o documento estiver totalmente desbloqueado.
$ found = $ flatcon -> ifExist ( " 1 " );Se o documento estiver bloqueado, ele serião até que esteja disponível ou após um número "Nth" de tentativas (por padrão, são 100 tentativas que equivale a 10 segundos)
Ele exclui o documento $ id . Se o documento não existir, ou não conseguir excluir, ele retornará false.
$ tenta indica o número de tentativas. O valor padrão é -1 (número padrão de tentativas).
$ doc = $ flatcon -> delete ( " 1 " );Se o documento estiver bloqueado, ele serião até que esteja disponível ou após um número "Nth" de tentativas (por padrão, são 100 tentativas que equivale a 10 segundos)
Ele retorna todos os IDs armazenados em uma coleção.
$ listKeys = $ flatcon -> select ();
$ listKeys = $ flatcon -> select ( " invoice_* " );Inclui documentos bloqueados.
Copie o documento $ odorigin em $ idDestination
$ bool = $ flatcon -> copy ( 20 , 30 );Se o destino do documento existir, então será substituído
Renomeie o documento $ idorigin como $ idDestination
$ bool = $ flatcon -> rename ( 20 , 30 );Se o destino do documento existir, a operação falhará.
Ele converte um stdclass em uma classe específica.
$ inv = new Invoice ();
$ invTmp = $ doc -> get ( ' someid ' ); //$invTmp is a stdClass();
DocumentStoreOne:: fixCast ( $ inv , $ invTmp ); Não funciona com membros que são uma variedade de objetos. A matriz é mantida como Stdclass.
Os próximos campos são públicos e eles podem ser alterados durante o tempo de execução
| campo | Tipo |
|---|---|
| $ banco de dados | pasta raiz string do banco de dados |
| Coleção $ | Coleção atual da string (subpasta) do banco de dados |
| $ maxlocktime = 120 | Int Duração do máximo do bloqueio (em segundos). Por padrão, são 2 minutos |
| $ defaultNumRetry = 100 | INT Número padrão de tentativas. Por padrão, ele tenta 100x0.1seg = 10 segundos |
| $ intervalbetweenRetry = 100000 | INT intervalo (em microssegundos) entre as tentativas. 100000 significa 0,1 segundos |
| $ DOCEXT = ". DSON" | Extensão padrão de string (com ponto) do documento |
| $ keyencryption = "" | String indica se a chave é criptografada ou não quando é armazenada (o nome do arquivo). Vazio significa, sem criptografia. Você pode usar o MD5, SHA1, SHA256, .. |
Exemplo:
$ 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 Pode ser feito manualmente. O sistema permite armazenar um valor pré-calculado que pode ser facilmente acessado (em vez de ler todos os valores).
Digamos o próximo exercício, temos uma lista de compras
| eu ia | cliente | idade | sexo | ProductPurchase | quantia |
|---|---|---|---|---|---|
| 14 | John | 33 | m | 33 | 3 |
| 25 | Anna | 22 | f | 32 | 1 |
| código de produto | UnitPrice |
|---|---|
| 32 | 23.3 |
| 33 | 30 |
John comprou 3 produtos com o código 33. Os produtos 33 custam US $ 23,3 por unidade.
Pergunta, quanto todo cliente pagou?.
É um exercício simples, é mais adequado para um banco de dados relacional (selecione * FROM PRODUSTOS PRODUTOS DE COMPRAS INTERNO). No entanto, se o documento for longo ou complexo para armazenar no banco de dados, será aqui onde uma loja de documentos brilha.
// 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.| cliente | valor |
|---|---|
| John | 69.9 |
| Anna | 30 |
Como é feito no código, é possível criar um sistema híbrido (banco de dados relacional+armazenamento+cache de memória)
Digamos que queremos serializar as próximas informações:
$ input =[[ ' a1 ' => 1 , ' a2 ' => ' a ' ],[ ' a1 ' => 2 , ' a2 ' => ' b ' ]];Os valores não são serializados, portanto, não é possível serializar um objeto, matriz ou outra estrutura. Funciona apenas com cordas.
Como os valores são armazenados
helloworld
Como os valores são retornados
" helloworld " A serialização do PHP é uma das maneiras mais rápidas de serializar e desarrializar, e sempre retorna o mesmo valor com a mesma estrutura (classes, matriz, campos)
No entanto, o valor armazenado pode ser longo.
Como os valores são armazenados:
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";}}
Como os valores são retornados:
[['a1'=>1,'a2'=>'a'],['a1'=>2,'a2'=>'b']]
Essa serialização gera um código PHP. Este código é detalhado, no entanto, possui alguns bons recursos:
Como os valores são armazenados:
<?php /** @generated */
return array (
0 =>
array (
' a1 ' => 1 ,
' a2 ' => ' a ' ,
),
1 =>
array (
' a1 ' => 2 ,
' a2 ' => ' b ' ,
),
);Como os valores são retornados:
[['a1'=>1,'a2'=>'a'],['a1'=>2,'a2'=>'b']]
Ambos os métodos funcionam com o JSON para a serialização e desperalização, mas os primeiros em retornos sempre uma matriz associativa, enquanto o outro poderia devolver um objeto (stdclass)
Pró:
Contras:
Como os valores são armazenados:
[{"a1":1,"a2":"a"},{"a1":2,"a2":"b"}]
Como os valores são retornados:
[[ ' a1 ' => 1 , ' a2 ' => ' a ' ],[ ' a1 ' => 2 , ' a2 ' => ' b ' ]] // array
[stdClass{ ' a1 ' => 1 ,'a2'=>'a'},stdClass{ ' a1 ' => 2 ,'a2'=>'b'}] // objectPor padrão, essa biblioteca lança erros quando ocorre um erro ou exceção. Alguns métodos permitem evitar erros de lançamento, mas a maioria deles pode causar um erro.
Os erros são tentativas/capturas de captura.
// 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 ();Ou você também pode usar para evitar jogar uma exceção:
// not throw an error:
$ this ->-> noThrowOnError ()-> insert ( ' id1 ' , ' values ' );
// but you can still see the latest error:
if ( $ this -> latestError ) {
var_dump ( $ this -> latestError );
}Você pode trabalhar com o CSV da seguinte maneira:
$ 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] não foi possível carregar o pacote eftec/documentStoreOne em repo.packagist.org: [inesperedValueException] não pôde analisar a restrição da versão ^5.6. : String de versão inválida "^5.6. "