##Brine ORM
[logo]:https://github.com/theorchard/brine/raw/master/docs/brine.png "Brine"
![Brine](https://github.com/theorchard/brine/raw/master/docs/brine.png "Brine")
Brine is a tiny ORM used to access [Redis](http://redis.io) data. It is can be used to serve data that has been imported into redis using a number of command line tools found in [Redis Api](https://github.com/theorchard/redis-api)


* [Namespaces](#namespaces)
* [File System](#file-system)
* [Models](#models)
    * [Saving Data](#saving-data)
    * [Getting Data](#getting-data)
    * [Deleting Models](#deleting-models)
    * [Resetting Data](#resetting-data)
    * [Additional Methods](#additional-methods)
    * [Chaining](#chaining)
* [Associations](#associations)
    * [BelongsTo/Parent](#belongstoparent)
    * [HasMany/Children](#hasmanychildren)
    * [Cascading Deletes](#cascading-deletes)
* [Zsets](#zsets)
    * [Overview](#overview)
    * [Using Zsets](#using-zsets)

###NAMESPACES 

Brine is namespaced to `Brine\Brine.` All examples assume:

```php
use Brine\Brine as Brine;
```

###FILE SYSTEM

Although Brine was originally designed to be used as a core framework to be extended in many different circumstances, at the moment developers can only use Brine for Orchard data. The core library is located at `/src/Brine/Data` and the extensions of the core (i.e. your models, zsets, etc.) are located at `/src/Brine/App`.

All files should be capitalized and camel cased. So for a model named 'Example' your model file should be named 'Example.php'. Models are in `/src/Brine/App/Models` and Zsets are `/src/Brine/App/Zsets`

###MODELS
Models are classes that describe Redis [hash](http://redis.io/commands#hash) data types. All models extend the base `Brine::Model` class. 

```php
Brine::lib('Model/Model');
class Example extends Model {
    //model code here
}
```

_Note:_ As shown in the example, before defining your class you must include the Model class from the brine library. 

At minimum, a model needs `_defaults` and `_idField` properties:

```php
Brine::lib('Model/Model');
class Example extends Model {

    protected $_defaults = array(
            'exampleId' => '',
            'exampleName' => ''
        );
    protected $_idField = 'exampleId';

}
```

The `_defaults` property is an associative array listing all hash fields used to store data in Redis. The `_idField` must be a field listed in the `_defaults` array, and must be a unique ID used to access the model.

####SETTING AND GETTING MODEL DATA
A model can be retrieved through the `Brine::model` factory:

```php
$example = Brine::model('Example');
```

This will return an Example model object with no data.

If you wish to create a model with some data, pass a plain vanilla object as the second argument to the model method with specific data:

```php
$data = new \stdClass();
$data->exampleId = 123;
$data->exampleName = 'Foo';
$example = Brine::model('Example', $data);
```

To access any of these properties you can use:

```php
$example->getExampleId(); //Returns '123'
$example->getExampleName(); //Returns 'Foo'
```

To set data, you can use the following setters:

```php
$example->setExampleId('12345'); //Is now '12345'
$example->setExampleName('Bar'); //Is now 'Bar'
```

Alternatively you can access a model's ID by using the `Model::id()` method. This will return the value of the field you set as `Model::_idField`

```php
$example->id(); //Returns the value of exampleId
```

The full list of data can be returned with the `Model::full()` method.

```php
$data = $example->full();
echo $data->exampleId; //'123'
echo $data->exampleName; //'Bar'
```

You can also get the above data as a JSON string:

```php
$example->toJSON(); //{"exampleId":"123","exampleName":"Foo"}
```

####SAVING DATA

In the above examples, data was set to the model, but was not saved to Redis. In order to do so, you must explicitly save the data. So, to start again from the beginning:

```php
$data = new \stdClass();
$data->exampleId = 123;
$data->exampleName = 'Foo';
$example = Brine::model('Example', $data);
$example->save();
```

####GETTING DATA

If a model already exists in Redis, it can be retrieved with the following method. 

```php
$example = Brine::model('Example');
$data = $example->find(123)->full(); //finds an example model with an exampleId 123
```
You may also retrieve a range of models. Model ranges are an ordered list of model keys. For example, say there are 100 Example models saved to the database, and we want the first thirty:

```php
$example = Brine::model('Example');
$examples = $examples->range(0, 29); //returns: array(brine:Example:1, brine:Example:2 ...)
```

The `range` method returns keys. If you want a full object, use `rangeFull`

####ALPHABETICAL SORT

In the above example, the sort order of the models is the model ID. Out of the box, however, Brine provides a second sort option: alphabetically by a selected field. In order to use this we need to add the following to the model's class *before* data is imported to redis:

```php
class Example extends Model {
    
    protected $_alphaField = 'exampleName'; //The name of a string field to sort on
    protected $_defaults = array(
            'exampleId' => '',
            'exampleName' => ''
        );
    protected $_idField = 'exampleId';

}
```

To retrieve example models listed in alphabetical order, add a `true` flag to the range method:

```php
$examples = $examples->range(0, 29, true); //now the keys will be sorted alphabetically
```


####DELETING MODELS

In order to delete a model from the database, you can use the `Model::del()` method.

```php
$example = Brine::model('Example');
$example->find(123)->del();
```
There is, for reasons related to data importing, a `Model::deleteAll()` method. This method does exactly what it describes: it deletes all models of the type you are currently using.

```php
$example = Brine::model('Example');
$example->count(); //Returns 5, the number of example models in the database
$example->deleteAll();
$example->count(); //Returns 0
```

Obviously this is a powerful method and should only be used rarely.

####RESETTING DATA

If you need a new model you should use the `Brine::model()` factory method to produce a new model; however, if you need to reset a model back to its defaults, you may use `Model::reset()`. For example:

```php
$example = Brine::model('Example');
$example->find(123);
echo $example->id(); //123
$example->reset();
echo $example->id(); //""
```

*Note: This technique should be rarely used. Again: use the factory to create a new model, rather than using `reset`.*

####ADDITIONAL METHODS

The following methods are also available:

* `Model::key()`: Retrieve a model's internal key. This is the key that used by redis to store relevant data. (brine:Example:123)
* `Model::modified()`: Returns the timestamp for the last time the data was modified (i.e saved to the server).
* `Model::name()`: Get the name of a model. In the above examples, 'Example' would be returned.
* `Model::count()`: Get a count of all models.
* `Model::lastSave()`: Get the response of the last save. Will be an array returned by Redis::exec()
* `Model::getModelFromKey()` Get a model name from a key. Given brine:Example:123, this method will return 'Example'
* `Model::exists()`: Does a record exist?


####CHAINING

Some model methods are chainable: all setters and `find.` So, for example, the following is possible:

```php
$example = Brine::model('Example');
$example->setExampleId(123)
        ->setExampleName('test')
        ->save();
```

As is:

```php
$example = Brine::model('Example');
$example->find(123)->full()
```

The examples in this document rarely use chaining in order to be more explicit.

###ASSOCIATIONS

Models can have two associations: a parent ('belongsTo') and/or children ('hasMany'). A parent is another model, and children are represented by a Zset (see below).

####BelongsTo/Parent

In order to define a parent, use the `Model::_associations()` method in your model:

```php
Brine::lib('Model/Model');
class Example extends Model {

    protected $_defaults = array(
            'exampleId' => '',
            'exampleName' => '',
            'developerId' => '',
        );
    protected $_idField = 'exampleId';

    public function _associations() {
        $this->_belongsTo('Developer', 'developerId');
    }

}
```

In the above example, a separate model, 'Developer,' owns the example. The `_belongsTo` method in the `_associations` method sets this relation. The first argument passed to `_belongsTo` is the name of the model, and the second argument is the field on which the 'join' is made. In this case it is `Example::developerId`.

In order to access a model's parent, you can do the following:

```php
$example = Brine::model('Example');
$example->find(123);
$developer = $example->parent('Developer');
$data = $developer->full();
```

The `$data` variable will now contain the parent's data. Parent models can be used for several things, but mainly can be used to test record ownership. In the previous example, we can now test the developer data to see if the user can view the data.

####HasMany/Children

Unlike model parents, which reference other models, model children references a Zset. In the following case, 'Examples' is a Zset we have explicitly created using `Brine::Zset()`. 

```php
Brine::lib('Model/Model');
class Developer extends Model {

    protected $_defaults = array(
            'developerId' => '',
            'developerName' => ''
        );
    protected $_idField = 'developrId';

    protected function _associations() {
        $this->_hasMany('Examples');        
    }
    
}
```

To access children, use the `Model::children()` method;

```php
$developer = Brine::model('Developer');
$developer->find(123);
$examples = $developer->children('Example');
```

`$examples` is a Zset object, explained in the following section.

####CASCADING DELETES

A delete on a parent class can cascade to children. So, to continue the above examples, if a Developer is deleted all of that Developer's Examples will also be deleted (if you wish). To do so, add the following to the Developer model:

```php
Brine::lib('Model/Model');
class Developer extends Model {

    protected $_defaults = array(
            'developerId' => '',
            'developerName' => ''
        );
    protected $_idField = 'developrId';

    protected function _associations() {
        $this->_hasMany('Examples', array('cascade' =>true)); //Set cascade to true 
    }
    
}
```

###ZSETS

####OVERVIEW

All lists of models in Brine are controlled by Redis's sorted set data type. A sorted set is, according to the [docs](http://redis.io/topics/data-types): "non repeating collections of Strings... every member of a Sorted Set is associated with score that is used in order to take the sorted set ordered, from the smallest to the greatest score. While members are unique, scores may be repeated."

So, for a key named 'my_key' you can set a string ('my_value') with a score of 0.

```
zset my_key 0 my_value
```

This is useful for data such as top downloads, where the score is the number of downloads and the string is the unique identifier for the artist:

```
my_top_downloads 345 tricky
my_top_downloads 321 manson
my_top_downloads 666 aleister
```

Now, the 'my_top_downloads' key will return:

```
aleister, tricky, manson
```

####USING ZSETS

In Brine, Zsets control:

* lists of models by ID (and possibly alphabetically by a select field)
* lists of children
* other more specific lists, such as number of downloads, clicks, page views, etc.

The first two items were covered above, and are handled internally by Brine. However, if you need a more specific kind of zset (the third item), you can extend the `Brine::Zset` class.

As of this writing, it's important to note that unlike models, zsets must have a owner model. The owner model is used to access set of data.

To continue with the previous examples, if we want a list of the most read Examples from a particular developer, we can make the following class:

```php
use Brine\Brine;
Brine::lib('Zset/Zset');
class MostRead extends Zset {
    
    protected $_name = 'mostread';

}
```

To add keys to this class we do the following:

```php
//get model data
$example = Brine::model('Example'); //get example object
$example->find(123); //find record 123, already saved to db
$key = $example->key(); //returns the key, brine:Example:123

//get the owner
$developer = Brine::model('Developer');
$developer->find(456);

//create a zset object
$mostRead = Brine::zset('MostRead', $developer); //pass the developer model object as the second item
$mostRead->setScore($key, 789);

```

The Example 123 belonging to Developer 456 has a score of 789 (789 views).

In the database a zset record has been stored with the following key: zset:mostread:Developer:456. The first part of the key is the type (zset); the second part is the name of the zset (set in the class above); the third part is the owner model name; and the last is the owner model ID.
