Abstract Class Misago\ActiveRecord\Base

Database object abstraction.

Permits to handle database entries like objects. It supports CRUD operations (create, read, update and delete).

Extends:

CRUD

All the examples will use this single model:

class Post extends Misago\ActiveRecord\Base
{
} 

Create

You can create a new record, then save it:

$post = new Post(array('title' => 'aaa', 'body' => 'bbb'));
$post->save(); 

Or you can create it directly:

$new_post = Post::create(array('title' => 'aaa', 'body' => 'bbb')); 

Read

Find one

All the following methods will return a single post. As a matter of fact, they all return the same post (in these examples):

$post = new Post(1);
$post = Post::find(1);
$post = Post::find(':first', array('conditions' => array('id' => 1)));
$post = Post::find(':first', array('conditions' => 'id = 1'));
$post = Post::find_by_id(1); 

If no post is found, returns null.

Find all

The following methods will return a collection of posts:

$posts = Post::find();
$posts = Post::find(':all');
$posts = Post::find(':all', array('order' => 'created_at desc', 'limit' => 25));
$posts = Post::find_all_by_category('aaa');
$posts = Post::find_all_by_category('aaa', array('order' => 'title asc')); 

If no posts are found, returns an empty ActiveArray.

Find values

Data won't be processed into objects, and it shall return a simple hash of key => value pairs. It's especially useful for collecting data for a HTML select. for instance

$values = Post::find(':first', array('select' => 'id, title'));
# => array('id' => '1', 'title' => 'my post') 

Scopes

Scopes are predefined options for find requests.

Default scope

You may define a default scope for all finds. In the following example, all find requests to Comment will be returned ordered by creation date:

class Comment extends Misago\ActiveRecord\Base
{
  protected static $default_scope = array('order' => 'created_at asc');
} 

Attention:

Named scopes

[TODO]

Update

There are several ways to update a record.

$updated_post = Post::update(3, array('category' => 'ccc'));

$post = new Post(2);
$post->title = 'abcd';
$post->save();

$post = new Post(4);
$post->update_attributes(array('category' => 'ddd')); 

Check update, update_attribute and update_attributes for more examples.

Delete

There are two ways to delete records: delete and destroy.

The difference is that destroy always instanciates the record before deletion, permitting to interact with it. To delete an uploaded photo when deleting an image from a web gallery for instance.

On the contrary, delete will delete all records at once in the database throught a SQL DELETE statement. There is no way to interact with the deletion of a particular entry.

The advantage of destroy is the ability to interact with the deletion; while the advantage of delete is it should be faster, especially when deleting many records.

Implementation detail: there is actually no delete and destroy methods, since PHP 5 disallows $this in a static method, which disallows to use the same method for a static and an instance call. The actual methods are _delete, _static_delete, _destroy and _static_destroy. You must never call them directly.

delete

Post::delete(5);

$post = new Post();
$post->delete(3);

Post::delete_all(array('category' => 'aaa'));
Post::delete_all(array('category' => 'bbb', array('limit' => 5, 'order' => 'created_at desc')); 

destroy

Post::destroy(5);

$post = new Post();
$post->destroy(3);

$post = new Post();
Post::destroy_all(array('category' => 'aaa'));
Post::destroy_all(array('category' => 'bbb', array('limit' => 5, 'order' => 'created_at desc')); 

Callbacks

Callbacks are hooks inside the lifecycle of an action to the record.

For instance when saving a new record:

As you can see, there are a lot of callbacks, which permits you to interact with the creation process at every step of it. Same goes for update, which has the same lifecycle, but uses particular *_on_update callbacks instead of *_on_create.

destroy has callbacks too, but the lifecycle is simplier:

Remember that only destroy has callbacks, delete has no such handlers.

IMPROVE: Check if columns do not conflict with object class attributes. TEST: Test callbacks.

Inheritence

Extends:
Calculations

Protected static attributes

Protected instance attributes

Methods

Public static methods

_static_delete($id)

Deletes the record from database using a SQL DELETE statement. The record isn't instanciated, and callbacks aren't runned. This is faster than the destroy method.

Post::delete(1);
Post::delete(array(1, 2, 3)); 

_static_destroy($id)

Deletes the record from database. The record is instanciated and callbacks are processed. This is slower than the delete method.

Post::destroy(1); 

all($options=null)

Shortcut for find(:all).

build_sql_from_options($options)

Returns full SQL string from given options.

columns()

Returns the list of columns with definitions.

connection()

count_by_sql($sql)

Counts columns. SQL Request is supposed to return a single column and a single row (returns a single int).

$count = $post->count_by_sql("select count(*) from posts where created_at > now()"); 

Use count instead, unless you need special features. Be aware that custom SQL requests may brake whenever you switch between connection adapters.

create(array $attributes)

Creates a new record.

$user  = User::create(array('name' => 'John'));
$users = User::create(array('name' => 'Jane'), array('name' => 'Billy')); 

decrement_counter($counter_name, $id)

Decrements a counter.

Post::decrement_counter('comment_count', 13);

default_scope()

delete_all($conditions=null, $options=null)

Deletes many records at once using a single SQL DELETE statement. Records aren't instanciated and deletion callbacks aren't runned. This is faster than the destroy_all method.

Available options: limit, order

destroy_all($conditions=null, $options=null)

Destroys many records at once. Each matching record is instanciated, and deletion callbacks (before_destroy, after_destroy)are run. This is slower than the delete_all method, but it permits to clean up things.

Available options: limit, order

do_create(array $attributes)

Same as create but throws an exception on failure.

do_update($id, $attributes)

Same as update but throws an exception on failure.

exists($id)

Checks wether a given record exists or not.

find($method_or_id=':all', $options=null)

Finds records in database.

Methods:

  • :all - Returns all found records.
  • :first - Returns the first found record (null if nothing is found).
  • :values - Returns bare values (uninstanciated).

Options:

  • select - (collection)
  • conditions - (string, array or hash)
  • group - (collection)
  • order - (collection)
  • limit - (integer)
  • page - (integer)
  • include - (collection)

Eager Loading:

See Misago\ActiveRecord\Associations.

TEST: Test option 'group'.

find_by_sql($sql)

Returns an array of ActiveRecords, using results as attributes.

Use find instead, unless you need special features. Be aware that custom SQL requests may brake whenever you switch between connection adapters.

first($options=null)

Shortcut for find(:first).

increment_counter($counter_name, $id)

Increments a counter.

Post::increment_counter('comment_count', 23);

merge_conditions($a, $b)

merge_options($a, $b)

paginate($options=array())

Finds paginated results.

Accepts all find options, plus:

  • page - current page (defaults to 1)
  • per_page - how many results per page (defaults to 30)
  • count - particular options for count()

Returns a Misago\ActiveSupport\ActiveArray object with the following properties, useful for adding paginated links in views:

  • current_page
  • per_page
  • total_entries
  • total_pages

primary_key()

table_name()

transaction($callback, array $args=array())

Executes a function inside a database transaction.

Whenever an exception is raised, transacted queries will be rollbacked and it returns false.

If no exception is raised, transacted queries will be commited to the database, and it returns the executed function's result.

update($id, $attributes)

Updates one or many records.

# update one row
$user = $user->update(1, array('name' => 'Joe'));

# update many rows
$people = array(
  1 => array('name' => 'Polly'),
  2 => array('name' => 'Jean')
);
$users = User::update(array_keys($people), array_values($people)); 

update_all($updates, $conditions=null, $options=null)

Updates many records at once, and returns the number of affected rows.

Available options: limit, order.

update_counters($id, $counters)

Updates multiple counters at once.

Post::update_counters(5, array('comment_count' => 1, 'tag_count' => -1));

values($options=null)

Shortcut for find(:values).

Public instance methods

__construct($arg=null)

_delete()

Deletes the record from database using a SQL DELETE statement. The record isn't instanciated, and callbacks aren't runned. This is faster than the destroy method.

$post = new Post(456);
$post->delete();       # => delete from posts where id = 456; 

_destroy()

Deletes the record from database. The record is instanciated, and callbacks (before_destroy, after_destroy) are processed. This is slower than the delete method, but it permits to interact with the deletion (ie. do some cleanup).

$post = new Post(456);
$post->destroy(); 

cache_key()

Generates a cache key for this record.

Produces class_name/id-updated_at if update_at exists, otherwise falls back to class_name/id.

decrement($attribute, $by=1)

Decrements a numerical column (numeric, integer, float). If the attribute is null, the attribute is assigned 0, and then decremented.

do_save($perform_validation=true)

Saves the record, but throws an exception on error.

id()

Always returns the record's primary key value, whatever if it's named id or not.

increment($attribute, $by=1)

Increments a numerical column (numeric, integer, float). If the attribute is null, the attribute is assigned 0, and then incremented.

new_record()

save($perform_validation=true)

Saves the record.

toggle($attribute)

Toggles a boolean from true to false (or false to true).

update_attribute($attribute, $value)

Updates a single attribute of record, without going throught the validation process.

$post->update_attribute('name', 'my first post [update]'); 

update_attributes($updates)

Updates some attributes of record.

$post = new Post(1);
$post->title    = 'my first post [update]';
$post->category = 2;
$post->update_attributes(array('title', 'category'));
$post->update_attributes('title, category');

$post->update_attributes(array(
  'title'    => 'my first post [update 2]',
  'category' => 3
)); 

Protected instance methods

after_create()

after_destroy()

after_save()

after_update()

before_create()

before_destroy()

before_save()

before_update()