The Streams platform leans heavily on domain-driven design (DDD). We call these domain abstractions streams
, hence our namesake.
An example could be configuring a domain model (a stream) for a website's pages, users of an application, or feedback submissions from a form.
You can define stream configurations in the streams/
directory using JSON files. The filenames serve as a handle
, which you can use to reference the stream later.
It is highly encouraged to use the plural form of a noun when naming Streams—for example, contacts and people. You may also use naming conventions like business_contacts
or neat-people
.
To get started, you need only specify the handle
, which is the filename itself, and some fields
to describe the domain object's structure.
Let's create a little stream to hold information for a simple CRM.
// streams/contacts.json
{
"name": "Contacts",
"source": {
"type": "filebase",
"filename": "streams/data/contacts",
"format": "json"
},
"config": {
"prototype": "Streams\\Core\\Entry\\Entry",
"collection": "Illuminate\\Support\\Collection"
},
"fields": {
"name": "string",
"email": "email",
"company": {
"type": "relationship",
"config": {
"related": "companies"
}
}
}
}
Fields are an essential descriptor of the domain object. They describe what properties the domain object will have available and how the property data works. Things like accessors, data mutation, and casting can be controlled by the field's type.
The fieldsconfiguration keys serve as a handle
, which you can use to reference the field later. For example, the above contact fields can be accessed later like this:
$entry->email; // The email value.
$entry->company->email; // The related company's email value.
Streams can streamline routing by defining routes in their configuration.
// streams/contacts.json
{
"routes": {
"index": "contacts",
"view": "contacts/{id}"
}
}
You can also use an array to include other route options.
// streams/contacts.json
{
"routes": {
"contact": {
"csrf": false,
"uri": "form/{entry.email}"
}
}
}
Streams simplify validation by defining validation in their configuration.
// streams/contacts.json
{
"rules": {
"name": [
"required",
"max:100"
],
"email": [
"required",
"email:rfc,dns"
],
"company": "required|unique"
}
}
Streams provides a touch-free caching system you can define in the configuration.
// streams/contacts.json
{
"cache": false,
"ttl": 1800 // 30 minutes
}
Sources define the source information for entry data which you can define in the configuration.
// streams/contacts.json
{
"source": {
"type": "filebase",
"format": "md",
"prototype": "Streams\\Core\\Entry\\Entry"
}
}
Domain entities are called entries
within the Streams platform. A stream defines entry attributes, or fields
, that dictate the entry's properties, data-casting, and more.
You can use JSON file references within stream configurations to point to other JSON files using the @
symbol followed by a relative path to the file. In this way, you can reuse various configuration information or tidy up larger files. The referenced file's JSON data directly replaces the reference.
// streams/contacts.json
{
"name": "Contacts",
"fields": "@streams/fields/contacts.json"
}
// streams/fields/contacts.json
{
"name": "string",
"email": "email",
"company": {
"type": "relationship",
"stream": "company"
}
}
A stream can extend
another stream, which works like a recursive merge.
// streams/family.json
{
"name": "Family Members",
"extend": "contacts",
"fields": {
"relation": {
"type": "selection",
"config": {
"options": {
"mother": "Mother",
"father": "Father",
"brother": "Brother",
"sister": "Sister"
}
}
}
}
}
In the above example, all contacts
fields are available to you, as well as the new relation
field.
$entry->email; // The email value.
$entry->relation; // The relation value.
You can configure the flat-file database as well as other sources for storing data including any Laravel database. No code changes required.