Stairtower is a database server for schema-free, JSON documents, that provides a restful API and is entirely written in PHP.
The server runtime is built on React and utilizes PHP's native JSON de- and encoding facilities to transform data. Where applicable the Standard PHP Library (SPL) is used to build on a solid foundation and increase performance.
The aim was to create a database system that is
- portable
- flexible
- offers database seeding
- does not require additional configuration
- does not require additional software or languages
- stores data in a human readable format
- fits into the PHP environment
- and is written in the language that we now and love
Additionally it should simply show that this is possible in the language that sometimes seems to be derided by followers of 'modern' programming languages.
While creating such applications one may hit the wall of PHP. Managing memory and fine tuning performance in PHP has its limitations. The control over memory usage, allocation and freeing in a long running PHP application is complicated, if not even impossible (please correct me). So the performance and efficiency of other document stores may be a lot better.
An attempt to memory management is done with the Memory Manager which holds the only reference to memory intense object's (especially Database instances) and allows them to be freed (calling unset()
followed by gc_collect_cycles()
).
The whole system is written in a language that powers more than 80% of the web (https://w3techs.com/technologies/details/pl-php/all/all) and is used by some of the internet's biggest players. Writing the server in PHP opens the source code to be understood by a huge community and empowers them to adapt it to their needs. Furthermore parts of Stairtower may be reused in other projects (e.g. the server's backend could be used as data provider without using the REST interface).
The software is in alpha state. The biggest parts of the API are defined and most parts are covered by unit tests. Nevertheless their is much to improve.
PHP 5.4 or higher
git clone https://github.com/cundd/pos.git stairtower
cd stairtower
2. Install requirements with Composer
Get Composer:
curl -sS https://getcomposer.org/installer | php
Install the libraries:
php composer.phar update
curl will be used to interact with the database. But first the server has to be started.
cd /path/to/stairtower/root/
bin/server
curl https://127.0.0.1:1338/
curl https://127.0.0.1:1338/_stats
curl https://127.0.0.1:1338/_all_dbs
Create a database with name 'myDb'. The empty body will let curl set the Content-Length
header which Stairtower requires for PUT
and POST
requests
curl -X PUT https://127.0.0.1:1338/myDb -d ""
# Listing all databases should contain 'myDb'
curl https://127.0.0.1:1338/_all_dbs
# Listing the Documents of 'myDb' should return
# an empty array
curl https://127.0.0.1:1338/myDb
If the Document body is a JSON string it is important to tell curl to send the appropriate header (--header "Content-Type:application/json"
)
curl --header "Content-Type:application/json" \
-X POST https://127.0.0.1:1338/myDb \
-d '{
"name": "T-Shirt - Stairtower",
"type": "clothes",
"category": "merchandise",
"price": 12.50,
"options": {
"colors": ["green", "red", "blue"],
"size": ["xs", "s", "m", "l"]
}
}'
Adding two more example Documents:
curl --header "Content-Type:application/json" -X POST https://127.0.0.1:1338/myDb -d '{ "name": "Hoodie - Stairtower", "type": "clothes", "category": "merchandise", "price": 19.50, "options": { "colors": ["black", "blue"], "size": ["s", "m", "l"] }}';
curl --header "Content-Type:application/json" -X POST https://127.0.0.1:1338/myDb -d '{ "name": "USB stick", "type": "electronics", "category": "merchandise", "price": 10.50, "options": { "memory": ["8GB", "32GB", "64GB"] }}';
And check if they exist in the database:
curl https://127.0.0.1:1338/myDb
You may have recognized that the Documents have been assigned an _id
property. This defines a unique identifier inside the Database. This property is indexed by default and allows fast lookups.
To retrieve a single Document you can use it's resource URI, which is built from the Database identifier and the Document identifier (e.g. myDb/stairtower_0.0.1_1920_document_1415440762
).
curl https://127.0.0.1:1338/myDb/document_identifier
You can search by adding a property value pair as query string to the request. This example should return the hoodie and the t-shirt we added above.
curl "https://127.0.0.1:1338/myDb/?type=clothes"
Documents are updated by sending a PUT
request to the Documents resource URI. Please keep in mind that those updates do NOT patch a Document but will replace it completely.
curl --header "Content-Type:application/json" \
-X PUT https://127.0.0.1:1338/myDb/document_identifier \
-d '{
"name": "T-Shirt - Stairtower",
"type": "clothes",
"category": "merchandise",
"price": 13.50,
"options": {
"colors": ["green", "red", "blue"],
"size": ["xs", "s", "m", "l"]
}
}'
Documents are deleted by sending a DELETE
request to the Documents resource URI.
curl -X DELETE https://127.0.0.1:1338/myDb/document_identifier
Deletion of a whole Database is similar to removing a single Document. You simply omit the Document identifier when sending a DELETE
request.
curl -X DELETE https://127.0.0.1:1338/myDb/
curl -X POST https://127.0.0.1:1338/_restart
curl -X POST https://127.0.0.1:1338/_shutdown
This section lists some planed features.
- Intelligent database writes (currently all loaded databases will be written to the filesystem, even without modifications)
- Improved memory usage assumptions (before loading databases)
- Implement a queue to schedule tasks (like database updates or reindexing)
- Additional indexes and index types
- Update and delete collision prevention (like in CouchDB)
- Authentication (via Basic Auth and header)
- Request caching
- MapReduce/Views to customize data aggregation
The MIT License (MIT)
Copyright (c) 2014 Daniel Corn
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.