Structr
, (*1)
With the advent of document based stores like CouchDB and MongoDB complex data structures are a lot more common within web applications. You no longer have a separate array containing a blog post and another containing all comments but a single document containing most, if not all data. The schema-less design most of these document stores use can lead to huge mess if one doesn't exercise sufficient discipline., (*2)
With Structr you can define the format of these documents within your application so you can validate and/or transform documents. Furthermore Structr can change variable types or run custom code on parts of the document., (*3)
Besides complex documents Structr can be used to parse most PHP data such as request parameters, for example you can use it to define valid values for a paging GET parameter., (*4)
Example
``` php
<?php, (*5)
use Structr\Structr;, (*6)
$value = array(
"id" => 23,
"author" => "John",
"title" => "Foo",
"text" => "The quick brown fox jumps over the lazy dog's back",
"tags" => array("foo", "bar", "baz"),
"comments" => array(
array(
"author" => "Mike",
"text" => "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
)
)
);, (*7)
Structr::define("comment") // Define the 'comment' subdocument
->isMap() // A map is an associative array
->strict() // A strict map doesn't allow any extra keys in the input document and will fail validation if any
// are present
->key("author")
->defaultValue("Anonymous") // The default value is used if the key is not present in the input document
->isString()->end()
->endKey()
->key("text")
->isString()->end()
->endKey()
->end()
;, (*8)
$document = Structr::ize($value)
->isMap()
->key("id")
->isInteger()->coerce()->end() // Scalar values such as integers are parsed strictly by default, if the
// type is not the same it will raise an exception. The 'coerce' option
// will tell the parser to allow Structr to cast the value to the desired
// type.
->endKey()
->key("author")
->defaultValue("No Author")
->isString()->end()
->endKey()
->key("title")
->isString()->end()
->endKey()
->key("text")
->isString()->end()
->endKey()
->key("tags")
->isList()
->item()
->isString()->end()
->endItem()
->end()
->post(function($v) { sort($v); return $v; }) // Any node in the Structr tree can define a
// postprocessing function to be called on the resulting
// value for that node.
->endKey()
->key("comments")
->isList()
->item()
->is("comment")->end()
->endItem()
->end()
->endKey()
->end()
->run();, (*9)
```, (*10)
This definition is very verbose, but also very flexible. More examples are forthcoming, but for now you can take a look at the tests directory., (*11)