Commit e69a0723 authored by Jens Segers's avatar Jens Segers

Merge branch 'master' into develop

parents ded65cd3 128eb7b5
...@@ -4,6 +4,7 @@ branches: ...@@ -4,6 +4,7 @@ branches:
only: only:
- master - master
- develop - develop
- 4.0
php: php:
- 5.3 - 5.3
......
...@@ -359,6 +359,49 @@ The belongsToMany relation will not use a pivot "table", but will push id's to a ...@@ -359,6 +359,49 @@ The belongsToMany relation will not use a pivot "table", but will push id's to a
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 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
### EmbedsMany Relations
If you want to embed documents, rather than referencing them, you can use the `embedsMany` relation:
use Jenssegers\Mongodb\Model as Eloquent;
class User extends Eloquent {
public function books()
{
return $this->embedsMany('Book');
}
}
Now we can access the user's books through the dynamic property:
$books = User::first()->books;
When using embedded documents, there will also be an inverse relation available:
$user = $book->user;
Inserting and updating embedded documents works just like the `belongsTo` relation:
$book = new Book(array('title' => 'A Game of Thrones'));
$user = User::first();
$book = $user->books()->save($book);
You can remove an embedded document by using the `destroy()` method:
$book = $user->books()->first();
$user->books()->destroy($book->_id);
// or
$user->books()->destroy($book);
Again, you may override the conventional local key by passing a second argument to the embedsMany method:
return $this->embedsMany('Book', 'local_key');
### MySQL Relations ### MySQL Relations
If you're using a hybrid MongoDB and SQL setup, you're in luck! The model will automatically return a MongoDB- or SQL-relation based on the type of the related model. Of course, if you want this functionality to work both ways, your SQL-models will need to extend `Jenssegers\Eloquent\Model`. Note that this functionality only works for hasOne, hasMany and belongsTo relations. If you're using a hybrid MongoDB and SQL setup, you're in luck! The model will automatically return a MongoDB- or SQL-relation based on the type of the related model. Of course, if you want this functionality to work both ways, your SQL-models will need to extend `Jenssegers\Eloquent\Model`. Note that this functionality only works for hasOne, hasMany and belongsTo relations.
......
...@@ -34,6 +34,9 @@ ...@@ -34,6 +34,9 @@
</testsuite> </testsuite>
<testsuite name="relations"> <testsuite name="relations">
<directory>tests/RelationsTest.php</directory> <directory>tests/RelationsTest.php</directory>
</testsuite>
<testsuite name="mysqlrelations">
<directory>tests/RelationsTest.php</directory>
<directory>tests/MysqlRelationsTest.php</directory> <directory>tests/MysqlRelationsTest.php</directory>
</testsuite> </testsuite>
</testsuites> </testsuites>
......
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\Relation;
use Jenssegers\Mongodb\Relations\BelongsTo; use Jenssegers\Mongodb\Relations\BelongsTo;
use Jenssegers\Mongodb\Relations\BelongsToMany; use Jenssegers\Mongodb\Relations\BelongsToMany;
use Jenssegers\Mongodb\Query\Builder as QueryBuilder; use Jenssegers\Mongodb\Query\Builder as QueryBuilder;
...@@ -33,6 +36,35 @@ abstract class Model extends \Illuminate\Database\Eloquent\Model { ...@@ -33,6 +36,35 @@ abstract class Model extends \Illuminate\Database\Eloquent\Model {
return new HasOne($instance->newQuery(), $this, $foreignKey, $localKey); return new HasOne($instance->newQuery(), $this, $foreignKey, $localKey);
} }
/**
* Define a polymorphic one-to-one relationship.
*
* @param string $related
* @param string $name
* @param string $type
* @param string $id
* @param string $localKey
* @return \Illuminate\Database\Eloquent\Relations\MorphOne
*/
public function morphOne($related, $name, $type = null, $id = null, $localKey = null)
{
// Check if it is a relation with an original model.
if (!is_subclass_of($related, 'Jenssegers\Mongodb\Model'))
{
return parent::morphOne($related, $name, $type, $id, $localKey );
}
$instance = new $related;
list($type, $id) = $this->getMorphs($name, $type, $id);
$table = $instance->getTable();
$localKey = $localKey ?: $this->getKeyName();
return new MorphOne($instance->newQuery(), $this, $type, $id, $localKey);
}
/** /**
* Define a one-to-many relationship. * Define a one-to-many relationship.
* *
...@@ -58,6 +90,38 @@ abstract class Model extends \Illuminate\Database\Eloquent\Model { ...@@ -58,6 +90,38 @@ abstract class Model extends \Illuminate\Database\Eloquent\Model {
return new HasMany($instance->newQuery(), $this, $foreignKey, $localKey); return new HasMany($instance->newQuery(), $this, $foreignKey, $localKey);
} }
/**
* Define a polymorphic one-to-many relationship.
*
* @param string $related
* @param string $name
* @param string $type
* @param string $id
* @param string $localKey
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
*/
public function morphMany($related, $name, $type = null, $id = null, $localKey = null)
{
// Check if it is a relation with an original model.
if (!is_subclass_of($related, 'Jenssegers\Mongodb\Model'))
{
return parent::morphMany($related, $name, $type, $id, $localKey);
}
$instance = new $related;
// Here we will gather up the morph type and ID for the relationship so that we
// can properly query the intermediate table of a relation. Finally, we will
// get the table and create the relationship instances for the developers.
list($type, $id) = $this->getMorphs($name, $type, $id);
$table = $instance->getTable();
$localKey = $localKey ?: $this->getKeyName();
return new MorphMany($instance->newQuery(), $this, $type, $id, $localKey);
}
/** /**
* Define an inverse one-to-one or many relationship. * Define an inverse one-to-one or many relationship.
* *
...@@ -128,9 +192,7 @@ abstract class Model extends \Illuminate\Database\Eloquent\Model { ...@@ -128,9 +192,7 @@ abstract class Model extends \Illuminate\Database\Eloquent\Model {
// title of this relation since that is a great convention to apply. // title of this relation since that is a great convention to apply.
if (is_null($relation)) if (is_null($relation))
{ {
$caller = $this->getBelongsToManyCaller(); $relation = $this->getBelongsToManyCaller();
$name = $caller['function'];
} }
// First, we'll need to determine the foreign key and "other key" for the // First, we'll need to determine the foreign key and "other key" for the
......
<?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\Eloquent\Builder; use Jenssegers\Mongodb\Eloquent\Builder;
use Jenssegers\Mongodb\Query\Builder as QueryBuilder; use Jenssegers\Mongodb\Query\Builder as QueryBuilder;
use Jenssegers\Mongodb\Relations\BelongsTo; use Jenssegers\Mongodb\Relations\EmbedsMany;
use Jenssegers\Mongodb\Relations\BelongsToMany;
use Carbon\Carbon; use Carbon\Carbon;
use DateTime; use DateTime;
...@@ -48,7 +44,44 @@ abstract class Model extends \Jenssegers\Eloquent\Model { ...@@ -48,7 +44,44 @@ abstract class Model extends \Jenssegers\Eloquent\Model {
// If there is an actual id attribute, then return that. // If there is an actual id attribute, then return that.
if ($value) return $value; if ($value) return $value;
return $this->getKey(); // Return primary key value if present
if (array_key_exists($this->getKeyName(), $this->attributes)) return $this->attributes[$this->getKeyName()];
}
/**
* Define an embedded one-to-many relationship.
*
* @param string $related
* @param string $collection
* @return \Illuminate\Database\Eloquent\Relations\EmbedsMany
*/
protected function embedsMany($related, $localKey = null, $foreignKey = null, $relation = null)
{
if (is_null($localKey))
{
$localKey = snake_case(str_plural($related)) . '_ids';
}
if (is_null($foreignKey))
{
$foreignKey = snake_case(class_basename($this));
}
// If no relation name was given, we will use this debug backtrace to extract
// the calling method's name and use that as the relationship name as most
// of the time this will be what we desire to use for the relatinoships.
if (is_null($relation))
{
list(, $caller) = debug_backtrace(false);
$relation = $caller['function'];
}
$query = $this->newQuery();
$instance = new $related;
return new EmbedsMany($query, $this, $instance, $localKey, $foreignKey, $relation);
} }
/** /**
...@@ -204,6 +237,23 @@ abstract class Model extends \Jenssegers\Eloquent\Model { ...@@ -204,6 +237,23 @@ abstract class Model extends \Jenssegers\Eloquent\Model {
return $query = $this->newQuery()->where($this->getKeyName(), $this->getKey())->unset($columns); return $query = $this->newQuery()->where($this->getKeyName(), $this->getKey())->unset($columns);
} }
/**
* Pass push to the query builder.
*
* @return mixed
*/
public function push()
{
if ($parameters = func_get_args())
{
$query = $this->newQuery();
return call_user_func_array(array($query, 'push'), $parameters);
}
return parent::push();
}
/** /**
* Create a new Eloquent query builder for the model. * Create a new Eloquent query builder for the model.
* *
......
...@@ -6,6 +6,7 @@ use MongoDate; ...@@ -6,6 +6,7 @@ use MongoDate;
use DateTime; use DateTime;
use Closure; use Closure;
use Illuminate\Database\Query\Expression;
use Jenssegers\Mongodb\Connection; use Jenssegers\Mongodb\Connection;
class Builder extends \Illuminate\Database\Query\Builder { class Builder extends \Illuminate\Database\Query\Builder {
...@@ -507,11 +508,19 @@ class Builder extends \Illuminate\Database\Query\Builder { ...@@ -507,11 +508,19 @@ class Builder extends \Illuminate\Database\Query\Builder {
*/ */
public function raw($expression = null) public function raw($expression = null)
{ {
// Execute the closure on the mongodb collection
if ($expression instanceof Closure) if ($expression instanceof Closure)
{ {
return call_user_func($expression, $this->collection); return call_user_func($expression, $this->collection);
} }
// Create an expression for the given value
else if (!is_null($expression))
{
return new Expression($expression);
}
// Quick access to the mongodb collection
return $this->collection; return $this->collection;
} }
...@@ -631,7 +640,7 @@ class Builder extends \Illuminate\Database\Query\Builder { ...@@ -631,7 +640,7 @@ class Builder extends \Illuminate\Database\Query\Builder {
* @param mixed $id * @param mixed $id
* @return mixed * @return mixed
*/ */
protected function convertKey($id) public function convertKey($id)
{ {
if (is_string($id) && strlen($id) === 24 && ctype_xdigit($id)) if (is_string($id) && strlen($id) === 24 && ctype_xdigit($id))
{ {
......
<?php namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Database\Eloquent\Collection;
use MongoId;
class EmbedsMany extends Relation {
/**
* The local key of the parent model.
*
* @var string
*/
protected $localKey;
/**
* The foreign key of the parent model.
*
* @var string
*/
protected $foreignKey;
/**
* The "name" of the relationship.
*
* @var string
*/
protected $relation;
/**
* Create a new embeds many relationship instance.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Illuminate\Database\Eloquent\Model $parent
* @param string $localKey
* @param string $relation
* @return void
*/
public function __construct(Builder $query, Model $parent, Model $related, $localKey, $foreignKey, $relation)
{
$this->query = $query;
$this->parent = $parent;
$this->related = $related;
$this->localKey = $localKey;
$this->foreignKey = $foreignKey;
$this->relation = $relation;
$this->addConstraints();
}
/**
* Set the base constraints on the relation query.
*
* @return void
*/
public function addConstraints()
{
if (static::$constraints)
{
$this->query->where($this->parent->getKeyName(), '=', $this->parent->getKey());
}
}
/**
* Set the constraints for an eager load of the relation.
*
* @param array $models
* @return void
*/
public function addEagerConstraints(array $models)
{
// There are no eager loading constraints.
}
/**
* Initialize the relation on a set of models.
*
* @param array $models
* @param string $relation
* @return void
*/
public function initRelation(array $models, $relation)
{
foreach ($models as $model)
{
$model->setRelation($relation, $this->related->newCollection());
}
return $models;
}
/**
* Match the eagerly loaded results to their parents.
*
* @param array $models
* @param \Illuminate\Database\Eloquent\Collection $results
* @param string $relation
* @return array
*/
public function match(array $models, Collection $results, $relation)
{
foreach ($models as $model)
{
$results = $this->getEmbeddedRecords($model);
$model->setRelation($relation, $this->toCollection($results));
}
return $models;
}
/**
* Get the results of the relationship.
*
* @return Illuminate\Database\Eloquent\Collection
*/
public function getResults()
{
return $this->toCollection($this->getEmbeddedRecords());
}
/**
* Shorthand to get the results of the relationship.
*
* @return Illuminate\Database\Eloquent\Collection
*/
public function get()
{
return $this->getResults();
}
/**
* Attach a model instance to the parent model.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return \Illuminate\Database\Eloquent\Model
*/
public function save(Model $model)
{
// Insert a new document.
if (!$model->exists)
{
return $this->performInsert($model);
}
// Update an existing document.
else
{
return $this->performUpdate($model);
}
}
/**
* Perform a model insert operation.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return \Illuminate\Database\Eloquent\Model
*/
protected function performInsert(Model $model)
{
// Create a new key.
if (!isset($model['_id']))
{
$model->setAttribute('_id', new MongoId);
}
// Update timestamps.
$this->updateTimestamps($model);
// Push the document to the database.
$result = $this->query->push($this->localKey, $model->getAttributes(), true);
$documents = $this->getEmbeddedRecords();
// Add the document to the parent model.
$documents[] = $model->getAttributes();
$this->setEmbeddedRecords($documents);
// Mark the model as existing.
$model->exists = true;
return $result ? $model : false;
}
/**
* Perform a model update operation.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return bool
*/
protected function performUpdate(Model $model)
{
// Update timestamps.
$this->updateTimestamps($model);
// Get the correct foreign key value.
$id = $this->getForeignKeyValue($model->getKey());
// Update document in database.
$result = $this->query->where($this->localKey . '.' . $model->getKeyName(), $id)
->update(array($this->localKey . '.$' => $model->getAttributes()));
// Get existing embedded documents.
$documents = $this->getEmbeddedRecords();
$primaryKey = $this->related->getKeyName();
$key = $model->getKey();
// Replace the document in the parent model.
foreach ($documents as $i => $document)
{
if ($document[$primaryKey] == $key)
{
$documents[$i] = $model->getAttributes();
break;
}
}
$this->setEmbeddedRecords($documents);
return $result ? $model : false;
}
/**
* Attach an array of models to the parent instance.
*
* @param array $models
* @return array
*/
public function saveMany(array $models)
{
array_walk($models, array($this, 'save'));
return $models;
}
/**
* Create a new instance of the related model.
*
* @param array $attributes
* @return \Illuminate\Database\Eloquent\Model
*/
public function create(array $attributes)
{
// Here we will set the raw attributes to avoid hitting the "fill" method so
// that we do not have to worry about a mass accessor rules blocking sets
// on the models. Otherwise, some of these attributes will not get set.
$instance = $this->related->newInstance();
$instance->setRawAttributes($attributes);
return $this->save($instance);
}
/**
* Create an array of new instances of the related model.
*
* @param array $records
* @return array
*/
public function createMany(array $records)
{
$instances = array();
foreach ($records as $record)
{
$instances[] = $this->create($record);
}
return $instances;
}
/**
* Destroy the embedded models for the given IDs.
*
* @param array|int $ids
* @return int
*/
public function destroy($ids = array())
{
// We'll initialize a count here so we will return the total number of deletes
// for the operation. The developers can then check this number as a boolean
// type value or get this total count of records deleted for logging, etc.
$count = 0;
if ($ids instanceof Model) $ids = (array) $ids->getKey();
// If associated IDs were passed to the method we will only delete those
// associations, otherwise all of the association ties will be broken.
// We'll return the numbers of affected rows when we do the deletes.
$ids = (array) $ids;
$primaryKey = $this->related->getKeyName();
// Pull the documents from the database.
foreach ($ids as $id)
{
$this->query->pull($this->localKey, array($primaryKey => $this->getForeignKeyValue($id)));
$count++;
}
// Get existing embedded documents.
$documents = $this->getEmbeddedRecords();
// Remove the document from the parent model.
foreach ($documents as $i => $document)
{
if (in_array($document[$primaryKey], $ids))
{
unset($documents[$i]);
}
}
$this->setEmbeddedRecords($documents);
return $count;
}
/**
* Delete alias.
*
* @param int|array $ids
* @return int
*/
public function detach($ids = array())
{
return $this->destroy($ids);
}
/**
* Save alias.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return \Illuminate\Database\Eloquent\Model
*/
public function attach(Model $model)
{
return $this->save($model);
}
/**
* Convert an array of embedded documents to a Collection.
*
* @param array $results
* @return Illuminate\Database\Eloquent\Collection
*/
protected function toCollection(array $results = array())
{
$models = array();
// Wrap documents in model objects.
foreach ($results as $model)
{
if ( ! $model instanceof Model)
{
$model = $this->related->newFromBuilder($model);
}
// Attatch the parent relation to the embedded model.
$model->setRelation($this->foreignKey, $this->parent);
$models[] = $model;
}
if (count($models) > 0)
{
$models = $this->eagerLoadRelations($models);
}
return $this->related->newCollection($models);
}
/**
* Get the embedded documents array.
*
* @return array
*/
protected function getEmbeddedRecords(Model $model = null)
{
if (is_null($model))
{
$model = $this->parent;
}
// Get raw attributes to skip relations and accessors.
$attributes = $model->getAttributes();
return isset($attributes[$this->localKey]) ? $attributes[$this->localKey] : array();
}
/**
* Set the embedded documents array.
*
* @param array $models
*/
protected function setEmbeddedRecords(array $models)
{
$attributes = $this->parent->getAttributes();
$attributes[$this->localKey] = array_values($models);
// Set raw attributes to skip mutators.
$this->parent->setRawAttributes($attributes);
// Set the relation on the parent.
$this->parent->setRelation($this->relation, $this->getResults());
}
/**
* Update the creation and update timestamps.
*
* @return void
*/
protected function updateTimestamps(Model $model)
{
$time = $model->freshTimestamp();
if ( ! $model->isDirty(Model::UPDATED_AT))
{
$model->setUpdatedAt($time);
}
if ( ! $model->exists && ! $model->isDirty(Model::CREATED_AT))
{
$model->setCreatedAt($time);
}
}
/**
* Get the foreign key value for the relation.
*
* @param mixed $id
* @return mixed
*/
protected function getForeignKeyValue($id)
{
// Convert the id to MongoId if necessary.
return $this->getBaseQuery()->convertKey($id);
}
}
...@@ -339,7 +339,7 @@ class ModelTest extends PHPUnit_Framework_TestCase { ...@@ -339,7 +339,7 @@ class ModelTest extends PHPUnit_Framework_TestCase {
$result = User::where('_id', $user->_id)->push('tags', 'tag1'); $result = User::where('_id', $user->_id)->push('tags', 'tag1');
$user = User::where('_id', $user->_id)->first(); $user = User::where('_id', $user->_id)->first();
#$this->assertTrue(is_int($result)); $this->assertTrue(is_int($result));
$this->assertTrue(is_array($user->tags)); $this->assertTrue(is_array($user->tags));
$this->assertEquals(1, count($user->tags)); $this->assertEquals(1, count($user->tags));
} }
......
<?php <?php
use Illuminate\Database\Eloquent\Collection;
class RelationsTest extends PHPUnit_Framework_TestCase { class RelationsTest extends PHPUnit_Framework_TestCase {
public function setUp() { public function setUp() {
...@@ -13,6 +15,7 @@ class RelationsTest extends PHPUnit_Framework_TestCase { ...@@ -13,6 +15,7 @@ class RelationsTest extends PHPUnit_Framework_TestCase {
Role::truncate(); Role::truncate();
Client::truncate(); Client::truncate();
Group::truncate(); Group::truncate();
Photo::truncate();
} }
public function testHasMany() public function testHasMany()
...@@ -67,7 +70,7 @@ class RelationsTest extends PHPUnit_Framework_TestCase { ...@@ -67,7 +70,7 @@ class RelationsTest extends PHPUnit_Framework_TestCase {
Item::create(array('type' => 'sword', 'user_id' => $user->_id)); Item::create(array('type' => 'sword', 'user_id' => $user->_id));
Item::create(array('type' => 'bag', 'user_id' => null)); Item::create(array('type' => 'bag', 'user_id' => null));
$items = Item::with('user')->get(); $items = Item::with('user')->orderBy('user_id', 'desc')->get();
$user = $items[0]->getRelation('user'); $user = $items[0]->getRelation('user');
$this->assertInstanceOf('User', $user); $this->assertInstanceOf('User', $user);
...@@ -259,4 +262,129 @@ class RelationsTest extends PHPUnit_Framework_TestCase { ...@@ -259,4 +262,129 @@ class RelationsTest extends PHPUnit_Framework_TestCase {
$this->assertEquals($group->_id, $user->groups()->first()->_id); $this->assertEquals($group->_id, $user->groups()->first()->_id);
$this->assertEquals($user->_id, $group->users()->first()->_id); $this->assertEquals($user->_id, $group->users()->first()->_id);
} }
public function testMorph()
{
$user = User::create(array('name' => 'John Doe'));
$client = Client::create(array('name' => 'Jane Doe'));
$photo = Photo::create(array('url' => 'http://graph.facebook.com/john.doe/picture'));
$photo = $user->photos()->save($photo);
$this->assertEquals(1, $user->photos->count());
$this->assertEquals($photo->id, $user->photos->first()->id);
$photo = Photo::create(array('url' => 'http://graph.facebook.com/john.doe/picture'));
$client->photos()->save($photo);
$this->assertEquals(1, $client->photos->count());
$this->assertEquals($photo->id, $client->photos->first()->id);
$photo = Photo::first();
$this->assertEquals($photo->imageable->name, $user->name);
}
public function testEmbedsManySave()
{
$user = User::create(array('name' => 'John Doe'));
$address = new Address(array('city' => 'London'));
$address = $user->addresses()->save($address);
$this->assertEquals(array('London'), $user->addresses->lists('city'));
$this->assertInstanceOf('DateTime', $address->created_at);
$this->assertInstanceOf('DateTime', $address->updated_at);
$this->assertNotNull($address->_id);
$address = $user->addresses()->save(new Address(array('city' => 'Paris')));
$user = User::find($user->_id);
$this->assertEquals(array('London', 'Paris'), $user->addresses->lists('city'));
$address->city = 'New York';
$user->addresses()->save($address);
$this->assertEquals(2, count($user->addresses));
$this->assertEquals(2, count($user->addresses()->get()));
$this->assertEquals(2, $user->addresses->count());
$this->assertEquals(array('London', 'New York'), $user->addresses->lists('city'));
$freshUser = User::find($user->_id);
$this->assertEquals(array('London', 'New York'), $freshUser->addresses->lists('city'));
$address = $user->addresses->first();
$this->assertEquals('London', $address->city);
$this->assertInstanceOf('DateTime', $address->created_at);
$this->assertInstanceOf('DateTime', $address->updated_at);
$this->assertInstanceOf('User', $address->user);
$user = User::find($user->_id);
$user->addresses()->save(new Address(array('city' => 'Bruxelles')));
$this->assertEquals(array('London', 'New York', 'Bruxelles'), $user->addresses->lists('city'));
$address = $user->addresses[1];
$address->city = "Manhattan";
$user->addresses()->save($address);
$this->assertEquals(array('London', 'Manhattan', 'Bruxelles'), $user->addresses->lists('city'));
$freshUser = User::find($user->_id);
$this->assertEquals(array('London', 'Manhattan', 'Bruxelles'), $freshUser->addresses->lists('city'));
}
public function testEmbedsManySaveMany()
{
$user = User::create(array('name' => 'John Doe'));
$user->addresses()->saveMany(array(new Address(array('city' => 'London')), new Address(array('city' => 'Bristol'))));
$this->assertEquals(array('London', 'Bristol'), $user->addresses->lists('city'));
$freshUser = User::find($user->id);
$this->assertEquals(array('London', 'Bristol'), $freshUser->addresses->lists('city'));
}
public function testEmbedsManyCreate()
{
$user = User::create(array('name' => 'John Doe'));
$user->addresses()->create(array('city' => 'Bruxelles'));
$this->assertEquals(array('Bruxelles'), $user->addresses->lists('city'));
$freshUser = User::find($user->id);
$this->assertEquals(array('Bruxelles'), $freshUser->addresses->lists('city'));
}
public function testEmbedsManyDestroy()
{
$user = User::create(array('name' => 'John Doe'));
$user->addresses()->saveMany(array(new Address(array('city' => 'London')), new Address(array('city' => 'Bristol')), new Address(array('city' => 'Bruxelles'))));
$address = $user->addresses->first();
$user->addresses()->destroy($address->_id);
$this->assertEquals(array('Bristol', 'Bruxelles'), $user->addresses->lists('city'));
$address = $user->addresses->first();
$user->addresses()->destroy($address);
$this->assertEquals(array('Bruxelles'), $user->addresses->lists('city'));
$user->addresses()->create(array('city' => 'Paris'));
$user->addresses()->create(array('city' => 'San Francisco'));
$user = User::find($user->id);
$this->assertEquals(array('Bruxelles', 'Paris', 'San Francisco'), $user->addresses->lists('city'));
$ids = $user->addresses->lists('_id');
$user->addresses()->destroy($ids);
$this->assertEquals(array(), $user->addresses->lists('city'));
$freshUser = User::find($user->id);
$this->assertEquals(array(), $freshUser->addresses->lists('city'));
}
public function testEmbedsManyAliases()
{
$user = User::create(array('name' => 'John Doe'));
$address = new Address(array('city' => 'London'));
$address = $user->addresses()->attach($address);
$this->assertEquals(array('London'), $user->addresses->lists('city'));
$user->addresses()->detach($address);
$this->assertEquals(array(), $user->addresses->lists('city'));
}
} }
<?php
use Jenssegers\Mongodb\Model as Eloquent;
class Address extends Eloquent {
protected static $unguarded = true;
}
...@@ -11,4 +11,9 @@ class Client extends Eloquent { ...@@ -11,4 +11,9 @@ class Client extends Eloquent {
{ {
return $this->belongsToMany('User'); return $this->belongsToMany('User');
} }
public function photos()
{
return $this->morphMany('Photo', 'imageable');
}
} }
<?php
use Jenssegers\Mongodb\Model as Eloquent;
class Photo extends Eloquent {
protected $collection = 'photos';
protected static $unguarded = true;
public function imageable()
{
return $this->morphTo();
}
}
...@@ -46,6 +46,16 @@ class User extends Eloquent implements UserInterface, RemindableInterface { ...@@ -46,6 +46,16 @@ class User extends Eloquent implements UserInterface, RemindableInterface {
return $this->belongsToMany('Group', null, 'users', 'groups'); return $this->belongsToMany('Group', null, 'users', 'groups');
} }
public function photos()
{
return $this->morphMany('Photo', 'imageable');
}
public function addresses()
{
return $this->embedsMany('Address');
}
/** /**
* Get the unique identifier for the user. * Get the unique identifier for the user.
* *
......
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