Object Relational Mapping
ClearPress comes with a built-in, basic ORM layer in the ClearPress::model superclass. Like views, data model objects should be systematically named to avoid adding complexity (though it is possible to override everything if you really want to!). Usually a class maps to a table and an instance of a class (yes, an object) usually maps to an individual row. Tables are usually named in the singular form (e.g. 'child' rather than 'children') and the class name-suffix has the same name as the table, e.g. application::model::child.
Table fields / data members
Data model objects at the bare minimum carry the following information - the package name and an array of fields which map to the database table the class represents.
Fields can be reflected in automatic get/set accessors courtesy of Class::Accessor. Most data models come with this near their head: which uses the array from sub fields() { } to construct the accessors.
The ClearPress ORM does not (currently) perform database inspection to build attributes and relationships automatically (at run- or compile- time). It relies on the list of fields always reflecting what's in the database. For example:
Creating stuff
Here's our data model: which represents a database table: and here's how we could use it to add a new entry in the database: Using accessors to set all the values is unwieldy so we can also do it during construction: Notice that we didn't add an id_kid to either of these, because we want our database to allocate them for us. id_kid is the first field in sub fields and as such it's recognised by ClearPress::model as the primary key for this class. If we did add an id_kid, the new entry would be created with that id unless it already exists, in which case an error would be raised.
Reading stuff
Read access from the database comes in a couple of flavours - lists and individuals. The latter (read) requires an entity's id. Listings are fractionally simpler as the basics are implemented in the superclass.
List
To activate the basic list method (list everything) we add this to the top of the class which adds a pluralised accessor (in this case kids) returning an array reference of all kid objects from the database. This can now be used like so:
Read
To read a specific entity given its id (primary key) we can specify it in the constructor:
Updating stuff
To modify an existing entity we load it with its primary key, add the value to change then ask it to update: If the row in the database is heavy (e.g. contains a large text field or blob) you don't need to worry. ClearPress::model tries to be lazy by default - as we don't ask it for anything we didn't give it, it won't try to fetch the row from the database. It will just save the values it has.
Deleting stuff
Deleting entries from the database is easy. Read with an entity's primary key, then call delete:
Secondary Keys
ClearPress::model supports the use of a unique secondary key (not compound). If, say, a user has a unique username, the primary id would be id_user or similar, and the secondary key would be username. ClearPress::model::init will check for a non-numeric scalar value in the constructor, and attempt to load on that when the primary key is not present. Similarly it will also attempt to load against a named field.
The named-field method is particularly useful when you wish to load based on a numeric secondary key.