Commit 6254f616 authored by Jens Segers's avatar Jens Segers

Adding basic relations

parent a7ece360
...@@ -3,7 +3,7 @@ Laravel Eloquent MongoDB [![Build Status](https://travis-ci.org/jenssegers/Larav ...@@ -3,7 +3,7 @@ Laravel Eloquent MongoDB [![Build Status](https://travis-ci.org/jenssegers/Larav
An Eloquent model that supports MongoDB, inspired by LMongo, but using the original Eloquent methods. An Eloquent model that supports MongoDB, inspired by LMongo, but using the original Eloquent methods.
*This model extends the original Eloquent model, so it uses exactly the same methods. Some advanced Eloquent features may not be working, but feel free to report them or issue a pull request!* *This model extends the original Eloquent model, so it uses exactly the same methods.*
For more information about Eloquent, check http://laravel.com/docs/eloquent. For more information about Eloquent, check http://laravel.com/docs/eloquent.
...@@ -189,6 +189,38 @@ You may also specify additional columns to update: ...@@ -189,6 +189,38 @@ You may also specify additional columns to update:
User::where('age', '29')->increment('age', 1, array('group' => 'thirty something')); User::where('age', '29')->increment('age', 1, array('group' => 'thirty something'));
User::where('bmi', 30)->decrement('bmi', 1, array('category' => 'overweight')); User::where('bmi', 30)->decrement('bmi', 1, array('category' => 'overweight'));
**Relations**
Support relations are:
- hasOne
- hasMany
- belongsTo
Example:
class User extends Eloquent {
public function items()
{
return $this->hasMany('Item');
}
}
And the inverse relation:
class Item extends Eloquent {
public function user()
{
return $this->belongsTo('User');
}
}
Other relations are not yet supported, but may be added in the future. Read more about these relations on http://four.laravel.com/docs/eloquent#relationships
**Raw Expressions** **Raw Expressions**
These expressions will be injected directly into the query. These expressions will be injected directly into the query.
......
<?php namespace Jenssegers\Mongodb; <?php namespace Jenssegers\Mongodb;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Jenssegers\Mongodb\DatabaseManager as Resolver; use Jenssegers\Mongodb\DatabaseManager as Resolver;
use Jenssegers\Mongodb\Builder as QueryBuilder; use Jenssegers\Mongodb\Builder as QueryBuilder;
use Jenssegers\Mongodb\Relations\BelongsTo;
use DateTime; use DateTime;
use MongoId; use MongoId;
...@@ -107,6 +111,69 @@ abstract class Model extends \Illuminate\Database\Eloquent\Model { ...@@ -107,6 +111,69 @@ abstract class Model extends \Illuminate\Database\Eloquent\Model {
return parent::getTable(); return parent::getTable();
} }
/**
* Define a one-to-one relationship.
*
* @param string $related
* @param string $foreignKey
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function hasOne($related, $foreignKey = null)
{
$foreignKey = $foreignKey ?: $this->getForeignKey();
$instance = new $related;
return new HasOne($instance->newQuery(), $this, $foreignKey);
}
/**
* Define a one-to-many relationship.
*
* @param string $related
* @param string $foreignKey
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function hasMany($related, $foreignKey = null)
{
$foreignKey = $foreignKey ?: $this->getForeignKey();
$instance = new $related;
return new HasMany($instance->newQuery(), $this, $foreignKey);
}
/**
* Define an inverse one-to-one or many relationship.
*
* @param string $related
* @param string $foreignKey
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function belongsTo($related, $foreignKey = null)
{
list(, $caller) = debug_backtrace(false);
// If no foreign key was supplied, we can use a backtrace to guess the proper
// foreign key name by using the name of the relationship function, which
// when combined with an "_id" should conventionally match the columns.
$relation = $caller['function'];
if (is_null($foreignKey))
{
$foreignKey = snake_case($relation).'_id';
}
// Once we have the foreign key names, we'll just create a new Eloquent query
// for the related models and returns the relationship instance which will
// actually be responsible for retrieving and hydrating every relations.
$instance = new $related;
$query = $instance->newQuery();
return new BelongsTo($query, $this, $foreignKey, $relation);
}
/** /**
* Get a new query builder instance for the connection. * Get a new query builder instance for the connection.
* *
......
<?php namespace Jenssegers\Mongodb\Relations;
class BelongsTo extends \Illuminate\Database\Eloquent\Relations\BelongsTo {
/**
* Set the base constraints on the relation query.
*
* @return void
*/
public function addConstraints()
{
// For belongs to relationships, which are essentially the inverse of has one
// or has many relationships, we need to actually query on the primary key
// of the related models matching on the foreign key that's on a parent.
$key = $this->related->getKeyName();
$this->query->where($key, '=', $this->parent->{$this->foreignKey});
}
/**
* Set the constraints for an eager load of the relation.
*
* @param array $models
* @return void
*/
public function addEagerConstraints(array $models)
{
// We'll grab the primary key name of the related models since it could be set to
// a non-standard name and not "id". We will then construct the constraint for
// our eagerly loading query so it returns the proper models from execution.
$key = $this->related->getKeyName();
$this->query->whereIn($key, $this->getEagerModelKeys($models));
}
}
\ No newline at end of file
<?php <?php
require_once('vendor/autoload.php');
require_once('models/User.php');
require_once('tests/app.php'); require_once('tests/app.php');
use Jenssegers\Mongodb\Facades\DB; use Jenssegers\Mongodb\Facades\DB;
......
<?php <?php
require_once('vendor/autoload.php');
require_once('tests/app.php'); require_once('tests/app.php');
use Jenssegers\Mongodb\Facades\DB; use Jenssegers\Mongodb\Facades\DB;
......
<?php <?php
require_once('vendor/autoload.php');
require_once('models/User.php');
require_once('tests/app.php'); require_once('tests/app.php');
use Jenssegers\Mongodb\Connection;
use Jenssegers\Mongodb\Model;
use Jenssegers\Mongodb\DatabaseManager;
class ModelQueryTest extends PHPUnit_Framework_TestCase { class ModelQueryTest extends PHPUnit_Framework_TestCase {
public function setUp() public function setUp()
......
<?php <?php
require_once('vendor/autoload.php');
require_once('models/User.php');
require_once('models/Soft.php');
require_once('models/Book.php');
require_once('tests/app.php'); require_once('tests/app.php');
use Jenssegers\Mongodb\Connection;
use Jenssegers\Mongodb\Model;
use Jenssegers\Mongodb\DatabaseManager;
class ModelTest extends PHPUnit_Framework_TestCase { class ModelTest extends PHPUnit_Framework_TestCase {
public function setUp() {} public function setUp() {}
......
<?php <?php
require_once('vendor/autoload.php');
require_once('tests/app.php'); require_once('tests/app.php');
use Jenssegers\Mongodb\Facades\DB; use Jenssegers\Mongodb\Facades\DB;
......
<?php
require_once('tests/app.php');
class RelationsTest extends PHPUnit_Framework_TestCase {
public function setUp() {
}
public function tearDown()
{
User::truncate();
Book::truncate();
Item::truncate();
Role::truncate();
}
public function testHasMany()
{
$author = User::create(array('name' => 'George R. R. Martin'));
Book::create(array('title' => 'A Game of Thrones', 'author_id' => $author->_id));
Book::create(array('title' => 'A Clash of Kings', 'author_id' => $author->_id));
$books = $author->books;
$this->assertEquals(2, count($books));
$user = User::create(array('name' => 'John Doe'));
Item::create(array('type' => 'knife', 'user_id' => $user->_id));
Item::create(array('type' => 'shield', 'user_id' => $user->_id));
Item::create(array('type' => 'sword', 'user_id' => $user->_id));
Item::create(array('type' => 'bag', 'user_id' => null));
$items = $user->items;
$this->assertEquals(3, count($items));
}
public function testBelongsTo()
{
$user = User::create(array('name' => 'George R. R. Martin'));
Book::create(array('title' => 'A Game of Thrones', 'author_id' => $user->_id));
$book = Book::create(array('title' => 'A Clash of Kings', 'author_id' => $user->_id));
$author = $book->author;
$this->assertEquals('George R. R. Martin', $author->name);
$user = User::create(array('name' => 'John Doe'));
$item = Item::create(array('type' => 'sword', 'user_id' => $user->_id));
$owner = $item->user;
$this->assertEquals('John Doe', $owner->name);
}
public function testHasOne()
{
$user = User::create(array('name' => 'John Doe'));
Role::create(array('type' => 'admin', 'user_id' => $user->_id));
$role = $user->role;
$this->assertEquals('admin', $role->type);
}
}
\ No newline at end of file
<?php <?php
$loader = require 'vendor/autoload.php';
$loader->add('', 'tests/models');
use Jenssegers\Mongodb\Connection; use Jenssegers\Mongodb\Connection;
use Jenssegers\Mongodb\Model; use Jenssegers\Mongodb\Model;
use Jenssegers\Mongodb\DatabaseManager; use Jenssegers\Mongodb\DatabaseManager;
......
...@@ -9,4 +9,9 @@ class Book extends Eloquent { ...@@ -9,4 +9,9 @@ class Book extends Eloquent {
protected static $unguarded = true; protected static $unguarded = true;
protected $primaryKey = 'title'; protected $primaryKey = 'title';
public function author()
{
return $this->belongsTo('User', 'author_id');
}
} }
\ No newline at end of file
<?php
use Jenssegers\Mongodb\Model as Eloquent;
class Item extends Eloquent {
protected $collection = 'roles';
protected static $unguarded = true;
public function user()
{
return $this->belongsTo('User');
}
}
\ No newline at end of file
<?php
use Jenssegers\Mongodb\Model as Eloquent;
class Role extends Eloquent {
protected $collection = 'roles';
protected static $unguarded = true;
public function user()
{
return $this->belongsTo('User');
}
}
\ No newline at end of file
...@@ -8,9 +8,19 @@ class User extends Eloquent { ...@@ -8,9 +8,19 @@ class User extends Eloquent {
protected static $unguarded = true; protected static $unguarded = true;
public function phone() public function books()
{ {
return $this->hasOne('Phone'); return $this->hasMany('Book', 'author_id');
}
public function items()
{
return $this->hasMany('Item');
}
public function role()
{
return $this->hasOne('Role');
} }
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment