A first look at Atomik Models

Update: Things have completely change since then. While annotations will be used, their syntax and the way to define models have changed.

It's been quite a long time since I blogged anything. I merely touch at a computer for the past two weeks but I hope to resume the work on Atomik as soon as possible for the 2.2 release.

Meanwhile, I want to present you the new Model plugin that will come with this version. A quick reminder to begin. Putting it simply, models are a way to map database tables to classes. This allow to manipulate data from the database as objects in our application. An ORM (Object Relational Mapper) is the library/tool that allows you to do such a thing. The Model plugin brings the Atomik_Model library which is an ORM.

I tried to create an ORM which is not full of big enterprisy features (there are already some very good ones) but one that is more suited to the everyday developer. Models are defined as classes and annotations are used to configure it. By annotations I mean using PHP's doc comment and @ keywords (like php documentor documentation).
A big feature of Atomik_Model is that the data do not have to come from the database. Each model is bound to one adapter where it will fetch its data. This can be an xml file or a web service for example. Relations between models (like foreign keys in an RDBMS) are also supported. Finally, you can also generate forms for each model (this uses Atomik_Form / Form plugin).

So, how to define a model ? Assuming that our default adapter (the data source) is the database:

class User extends Atomik_Model 
{
  public $username;
  }

This will be mapped to the User table. The primary key is automatically generated (and named id, this can be changed). You can change the table name using the @table annotation:

/**
 * @table users
 */
class User extends Atomik_Model
{ /* ... */ }

The Model plugin creates some console commands to automatically generate tables associated to the models (the Console plugin is needed). You won't have to write a line of sql!

php indexp.php db-create

Now let's create another model named Article and add a relation between the two (a user has many articles).

/**
 * @has many Article as articles
 */
class User extends Atomik_Model
{
  public $name;
}  
/**
 * @has parent User as author 
 */ 
class Article extends Atomik_Model 
{
  public $title;
  public $text;
}

As you can see, the @has annotation is used. It follows this schema: @has [relation type] [model name] as [property]. The relation type can be one, many or parent. The property will be the object property used to access the associated model.

Now let's query these models! There are three static methods of Atomik_Model to do so: find(), findOne() and findAll(). All takes as first argument the model name. find() takes as second a model id. findOne() and findAll() works the same way except that findOne() returns the first record only. They take as parameter an array of fields/value for conditions.

$users = Atomik_Model::findAll('User');
echo '<ul>';
foreach ($users as $user) {
  echo '<li>' . $user->name . '<ul>';
  foreach ($user->articles as $article) {
    echo '<li>' . $article->title . '</li>';
  }
  echo '</ul></li>'; 
} 
echo '</ul>';

As you can see, we're getting the user's articles by simply using its articles property. This was a quick look at what's coming up. There's much more to discover in Atomik_Model as well as in the new Atomik Library. I hope you'll like it!



comments powered by Disqus

16/06/2009