# Relationships

Kohana ORM supports four types of object relationships: `belongs_to`, `has_many`, `has_many "through"` and `has_one`. The `has_many "through"` relationship can be used to function like Active Record's `has_many_and_belongs_to` relationship type.

## belongs_to

A `belongs_to` relation should be used when you have one model that belongs to another. For example, a `Child` model belongs_to a `Parent` or a `Flag` model `belongs_to` a `Country`.

This is the base `belongs_to` relationship:

	protected $_belongs_to = array(
		'[alias name]' => array(
			'model'       => '[model name]',
			'foreign_key' => '[column]',
		),
	);

You can omit any or all of the keys/values in the array on the right, in which case defaults are used:

	protected $_belongs_to = array('[alias name]' => array());

The **alias name** is what is used to access the related model in your code. If you had a `Post` model that belonged to a `User` model and wished to use the default values of the `belongs_to` configuration then your code would look like this:

	protected $_belongs_to = array('user' => array());

To access the user model, you would use `$post->user`.  Since we're using the defaults above, the alias name will be used for the model name, and the foreign key in the posts table will be the alias name followed by `_id`, in this case it would be `user_id`. (You can change the `_id` suffix by modifying the `$foreign_key_suffix` variable in the model.)

Let's say your `Post` database table schema doesn't have a `user_id` column but instead has an `author_id` column which is a foreign key for a record in the `User` table. You could use code like this:

	protected $_belongs_to = array(
		'user' => array(
			'foreign_key' => 'author_id',
		),
	);

If you wanted access a post's author by using code like `$post->author` then you would simply need to change the alias and add the `model` index:

	protected $_belongs_to = array(
		'author' => array(
			'model'       => 'User',
		),
	);

## has_many

The standard `has_many` relationship will likely fall on the other side of a `belongs_to` relationship.  In the above examples, a post belongs to a user.  From the user's perspective, a user has many posts. A has_many relationship is defined below:

	protected $_has_many = array(
		'[alias name]' => array(
			'model'       => '[model name]',
			'foreign_key' => '[column]',
		),
	);

Again, you can omit all keys in the right array to use the defaults:

	protected $_has_many = array('[alias name]' => array());

For our user and post example, this would look like the following in the user model:

	protected $_has_many = array('posts' => array());

Using the above, the posts could be access using `$user->posts->find_all()`.  Notice the `find_all()` used in this example. With `belongs_to` and `has_one` relationship types, the model is already loaded with necessary data.  For `has_many` relationships, however, you may want to limit the number of results or add additional conditions to the SQL query; you can do so prior to the `find_all()`.

The model name used by default will be the singular name of the alias using the `inflector` class.  In this case, `posts` uses `post` as the model name.  The foreign key used by default is the owner model's name followed by `_id`.  In this case, the foreign key will be `user_id` and it must exist in the posts table as before.

Let's assume now you want to access the posts using the name `stories` instead, and are still using the `author_id` key as in the `belongs_to` example.  You would define your has_many relationship as:

	protected $_has_many = array(
		'stories' => array(
			'model'       => 'Post',
			'foreign_key' => 'author_id',
		),
	);

## has_one

A `has_one` relationship is almost identical to a `has_many` relationship.  In a `has_one` relationship, there can be 1 and only 1 relationship (rather than 1 or more in a has_many). If a user can only have one post or story, rather than many then the code would look like this:

	protected $_has_one = array(
		'story' => array(
			'model'       => 'Post',
			'foreign_key' => 'author_id',
		),
	);

## has_many "through"

A `has_many "through"` relationship is used for many-to-many relationships.  For instance, let's assume now we have an additional model, called `Category`.  Posts may belong to more than one category, and each category may have more than one post.  To link them together, an additional table is needed with columns for a `post_id` and a `category_id` (sometimes called a pivot table).  We'll name the model for this `Post_Category` and the corresponding table `categories_posts`.

To define the `has_many` "through" relationship, the same syntax for standard has_many relationships is used with the addition of a 'through' parameter.  Let's assume we're working with the Post model:

	protected $_has_many = array(
		'categories' => array(
			'model'   => 'Category',
			'through' => 'categories_posts',
			'update'  => FALSE
		),
	);

In the Category model:

	protected $_has_many = array(
		'posts' => array(
			'model'   => 'Post',
			'through' => 'categories_posts',
			'update'  => FALSE
		),
	);

To access the categories and posts, you simply use `$post->categories->find_all()` and `$category->posts->find_all()`

Methods are available to check for, add, and remove relationships for many-to-many relationships.  Let's assume you have a $post model loaded, and a $category model loaded as well.  You can check to see if the $post is related to this $category with the following call:

	$post->has('categories', $category);

The first parameter is the alias name to use (in case your post model has more than one relationship to the category model) and the second is the model to check for a relationship with.

Assuming you want to add the relationship (by creating a new record in the categories_posts table), you would simply do:

	$post->add('categories', $category);

To remove:

	$post->remove('categories', $category);

Another option is to set the `update` parameter in the relation definition to `TRUE`.

If the relation field is set all new values will be added and all removed values will be removed to the table automatically. The array should contain a list of all primary keys.

	$post->set('categories', array(1, 4, 7, 23));

