NoSQL Data Access API
Table of contents:, (*1)
About
This API is a ultra light weight Data Access Layer that acts like an equivalent of PDO for NoSQL key-value databases (aka key-value stores). As a data access layer, its purpose is to to shield complexity of working with different NoSQL vendors and provide a simple as well as elegant interface for connecting and querying. At this time, following vendors are supported:, (*2)
-
APC: an extremely fast database without persistence abilities, handled directly by PHP that uses opcode cache and data store
-
APCu: an extremely fast database without persistence abilities, handled directly by PHP that uses only data store
-
Memcache: a very fast database with persistence abilities, requiring you to have MemCache server installed on your machine
-
Memcached: a very fast database with persistence abilities, requiring you to have MemCache server installed on your machine
-
Redis: a slightly slower database with persistence abilities and many extra features, requiring you to have Redis server installed on your machine
-
Couchbase: a slower database with persistence abilities and many extra features, requiring you to have Couchbase server installed on your machine
, (*3)
The whole idea of working with NoSQL databases (vendors) is reduced to following steps:, (*4)
API is fully PSR-4 compliant, only requiring PHP8.1+ interpreter, SimpleXML extension and official extension for each vendor. To quickly see how it works, check:, (*5)
-
installation: describes how to install API on your computer, in light of steps above
-
unit tests: API has 100% Unit Test coverage, using UnitTest API instead of PHPUnit for greater flexibility
-
examples: shows a deep example of API functionality
Configuration
To configure this API you must have a XML with a nosql tag inside:, (*6)
<nosql>
<{ENVIRONMENT}>
<server name="..." driver="..." {OPTIONS}/>
...
</{ENVIRONMENT}>
...
</nosql>
Where:, (*7)
-
nosql: holds global connection information for NoSQL vendors used
- {ENVIRONMENT}: name of development environment (to be replaced with "local", "dev", "live", etc)
-
server: stores connection information about a single vendor via attributes:
-
name: (optional) unique identifier. Required if multiple nosql vendors are used for same environment!
-
driver: (mandatory) NoSQL vendor name. Supported values: apc, apcu, memcache, memcached, redis, couchbase
- {OPTIONS}: a list of extra attributes necessary to configure respective vendor identified by driver above:
-
host: server host name (eg: 127.0.0.1), host name and port (eg: 127.0.0.1:1234) or list of host names and ports separated by commas (eg: 192.168.1.9:1234,192.168.1.10:4567). Required unless driver is APC/APCu!
-
timeout: (not recommended) time in seconds by which idle connection is automatically closed. Not supported if driver is APC/APCu/Couchbase!
-
persistent: (not recommended) whether or not connections should be persisted across sections (value can be: 0 or 1). Not supported if driver is APC/APCu/Couchbase!
-
username: user name to use in connection. Required if driver is Couchbase, ignored otherwise!
-
password: password to use in connection. Required if driver is Couchbase, ignored otherwise!
-
bucket_name: name of bucket (equivalent of SQL schema) where key-value pairs are stored. Required if driver is Couchbase, ignored otherwise!
-
bucket_password: (optional) bucket password. Optional if driver is Couchbase, ignored otherwise!
Example:, (*8)
<nosql>
<local>
<server driver="memcached" host="127.0.0.1"/>
</local>
<live>
<server driver="redis" host="127.0.0.1"/>
</live>
</nosql>
Execution
Once you have completed step above, you need to run this in order to be able to connect and query database(s) later on:, (*9)
new Lucinda\NoSQL\Wrapper(simplexml_load_file(XML_FILE_NAME), DEVELOPMENT_ENVIRONMENT);
This will wrap each server tag found for current development environment into Lucinda\NoSQL\DataSource objects and inject them statically into Lucinda\NoSQL\ConnectionFactory class., (*10)
Class above insures a single Lucinda\NoSQL\Driver is reused per server throughout session (input-output request flow) duration when . If vendor associated is not embedded (APC/APCu) and requires a server, same object also implements Lucinda\NoSQL\Server, which can be used in connection management., (*11)
There may be situations when abstraction provided by Lucinda\NoSQL\Driver is not enough and you need to run specific operations known only to respective vendor. You can do so by extra getDriver method, available unless vendor is APC/APCu:, (*12)
Method |
Arguments |
Returns |
Description |
getDriver |
void |
Redis |
Gets access to redis native driver if data source is redis. |
getDriver |
void |
Memcache |
Gets access to memcache native driver if data source is memcache. |
getDriver |
void |
Memcached |
Gets access to memcached native driver if data source is memcached. |
getDriver |
void |
CouchbaseBucket |
Gets access to couchbase native driver if data source is couchbase. |
Installation
First choose a folder where API will be installed then write this command there using console:, (*13)
composer require lucinda/nosql-data-access
Then create a configuration.xml file holding configuration settings (see configuration above) and a index.php file (see initialization above) in project root with following code:, (*14)
require(__DIR__."/vendor/autoload.php");
new Lucinda\NoSQL\Wrapper(simplexml_load_file("configuration.xml"), "local");
Then you are able to query server, as in below example:, (*15)
$driver = Lucinda\NoSQL\ConnectionFactory::getInstance("");
$driver->set("hello", "world");
Unit Tests
For tests and examples, check following files/folders in API sources:, (*16)
Examples
Working With Shared Driver
Usage example:, (*17)
$driver = Lucinda\NoSQL\ConnectionFactory::getInstance("");
$driver->set("i", 1, 10); // sets key i as 1 for 10 seconds
$driver->get("i"); // returns 1
$driver->contains("i"); // returns true
$driver->increment("i"); // returns 2
$driver->decrement("i"); // returns 1
$driver->delete("i"); // deletes key i from store
$driver->flush(); // clears all value in store
Working With Native Driver
Usage example (assumes driver was redis):, (*18)
$driver = Lucinda\NoSQL\ConnectionFactory::getInstance("");
$redisDriver = $driver->getDriver();
if ($redisDriver->ping()) {
echo "Success!";
}
Reference Guide
Class ConnectionFactory
Lucinda\NoSQL\ConnectionFactory class insures a single Lucinda\NoSQL\Driver is used per session and server name. Has following public static methods:, (*19)
Method |
Arguments |
Returns |
Description |
static setDataSource |
string $serverName, Lucinda\NoSQL\DataSource
|
void |
Sets data source detected beforehand per value of name attribute @ server tag. Done automatically by API! |
static getInstance |
string $serverName |
Lucinda\NoSQL\Driver |
Gets driver from data source based on value of name attribute @ server tag, opens connection in case object implements Lucinda\NoSQL\Server and returns it for later querying. Throws Lucinda\NoSQL\ConnectionException if connection fails! |
^ if your application uses a single database server per environment and name attribute @ server XML tag isn't set, empty string must be used as server name!, (*20)
Usage example:, (*21)
$driver = Lucinda\NoSQL\ConnectionFactory::getInstance("myServer");
$driver->get("hello"); // gets value of "hello" key from store
Interface Server
Lucinda\NoSQL\Server interface defines operations to manage connection to key-value store servers via following methods:, (*22)
Above methods HANDLED BY API AUTOMATICALLY, so to be used only in niche situations!, (*23)
Interface Driver
Lucinda\NoSQL\Driver interface defines operations to perform on key-value stores via following methods:, (*24)
Method |
Arguments |
Returns |
Description |
set |
string $key, $value, int $expiration=0 |
void |
Sets value in store by key, available for seconds defined by expiration (unless later is zero). |
get |
string $key |
mixed |
Gets value from store by key. |
contains |
string $key |
bool |
Checks if key exists in store. |
increment |
string $key, int $offset = 1 |
int |
Increments value in store by existing key and offset, then returns it. Throws Lucinda\NoSQL\KeyNotFoundException if key doesn't exist in store! |
decrement |
string $key, int $offset = 1 |
int |
Decrements value in store by existing key and offset, then returns it. Throws Lucinda\NoSQL\KeyNotFoundException if key doesn't exist in store! |
delete |
string $key |
void |
Deletes value from store by existing key. Throws Lucinda\NoSQL\KeyNotFoundException if key doesn't exist in store! |
flush |
void |
void |
Clears all values in store. |
If any of above operations fails due to server issues, a Lucinda\NoSQL\OperationFailedException is thrown!, (*25)