Commit 745be082 authored by Ditty's avatar Ditty

Removed embedded relations

Removed embedded relations
Updated documenation
Added changelog
parent a8041180
......@@ -2,3 +2,5 @@
All notable changes to this project will be documented in this file.
## [Unreleased]
### Removed
- EmbedsOne and EmbedsMany relations by [@divine](https://github.com/divine).
......@@ -30,8 +30,6 @@ This package adds functionalities to the Eloquent model and Query builder for Mo
- [Relationships](#relationships)
- [Basic Usage](#basic-usage-1)
- [belongsToMany and pivots](#belongstomany-and-pivots)
- [EmbedsMany Relationship](#embedsmany-relationship)
- [EmbedsOne Relationship](#embedsone-relationship)
- [Query Builder](#query-builder)
- [Basic Usage](#basic-usage-2)
- [Available operations](#available-operations)
......@@ -419,7 +417,7 @@ Aggregations can be also used on sub-documents:
$total = Order::max('suborder.price');
```
**NOTE**: This aggregation only works with single sub-documents (like `EmbedsOne`) not subdocument arrays (like `EmbedsMany`).
**NOTE**: This aggregation only works with single sub-documents not arrays.
**Incrementing/Decrementing the value of a column**
......@@ -712,10 +710,6 @@ The only available relationships are:
- belongsTo
- belongsToMany
The MongoDB-specific relationships are:
- embedsOne
- embedsMany
Here is a small example:
```php
......@@ -764,152 +758,6 @@ class User extends Model
}
```
### EmbedsMany Relationship
If you want to embed models, rather than referencing them, you can use the `embedsMany` relation. This relation is similar to the `hasMany` relation but embeds the models inside the parent object.
**REMEMBER**: These relations return Eloquent collections, they don't return query builder objects!
```php
use Jenssegers\Mongodb\Eloquent\Model;
class User extends Model
{
public function books()
{
return $this->embedsMany(Book::class);
}
}
```
You can access the embedded models through the dynamic property:
```php
$user = User::first();
foreach ($user->books as $book) {
//
}
```
The inverse relation is auto*magically* available. You don't need to define this reverse relation.
```php
$book = Book::first();
$user = $book->user;
```
Inserting and updating embedded models works similar to the `hasMany` relation:
```php
$book = $user->books()->save(
new Book(['title' => 'A Game of Thrones'])
);
// or
$book =
$user->books()
->create(['title' => 'A Game of Thrones']);
```
You can update embedded models using their `save` method (available since release 2.0.0):
```php
$book = $user->books()->first();
$book->title = 'A Game of Thrones';
$book->save();
```
You can remove an embedded model by using the `destroy` method on the relation, or the `delete` method on the model (available since release 2.0.0):
```php
$book->delete();
// Similar operation
$user->books()->destroy($book);
```
If you want to add or remove an embedded model, without touching the database, you can use the `associate` and `dissociate` methods.
To eventually write the changes to the database, save the parent object:
```php
$user->books()->associate($book);
$user->save();
```
Like other relations, embedsMany assumes the local key of the relationship based on the model name. You can override the default local key by passing a second argument to the embedsMany method:
```php
use Jenssegers\Mongodb\Eloquent\Model;
class User extends Model
{
public function books()
{
return $this->embedsMany(Book::class, 'local_key');
}
}
```
Embedded relations will return a Collection of embedded items instead of a query builder. Check out the available operations here: https://laravel.com/docs/master/collections
### EmbedsOne Relationship
The embedsOne relation is similar to the embedsMany relation, but only embeds a single model.
```php
use Jenssegers\Mongodb\Eloquent\Model;
class Book extends Model
{
public function author()
{
return $this->embedsOne(Author::class);
}
}
```
You can access the embedded models through the dynamic property:
```php
$book = Book::first();
$author = $book->author;
```
Inserting and updating embedded models works similar to the `hasOne` relation:
```php
$author = $book->author()->save(
new Author(['name' => 'John Doe'])
);
// Similar
$author =
$book->author()
->create(['name' => 'John Doe']);
```
You can update the embedded model using the `save` method (available since release 2.0.0):
```php
$author = $book->author;
$author->name = 'Jane Doe';
$author->save();
```
You can replace the embedded model with a new model like this:
```php
$newAuthor = new Author(['name' => 'Jane Doe']);
$book->author()->save($newAuthor);
```
Query Builder
-------------
......@@ -1098,39 +946,10 @@ Jenssegers\Mongodb\MongodbQueueServiceProvider::class,
Upgrading
---------
#### Upgrading from version 2 to 3
In this new major release which supports the new MongoDB PHP extension, we also moved the location of the Model class and replaced the MySQL model class with a trait.
#### Upgrading from version 3 to 4
Please change all `Jenssegers\Mongodb\Model` references to `Jenssegers\Mongodb\Eloquent\Model` either at the top of your model files or your registered alias.
This new major release contains breaking changes which is listed below:
```php
use Jenssegers\Mongodb\Eloquent\Model;
- EmbedsOne and EmbedsMany relations has been removed completely. See explanation [here](https://github.com/jenssegers/laravel-mongodb/issues/1974#issuecomment-592859508)
class User extends Model
{
//
}
```
If you are using hybrid relations, your MySQL classes should now extend the original Eloquent model class `Illuminate\Database\Eloquent\Model` instead of the removed `Jenssegers\Eloquent\Model`.
Instead use the new `Jenssegers\Mongodb\Eloquent\HybridRelations` trait. This should make things more clear as there is only one single model class in this package.
```php
use Jenssegers\Mongodb\Eloquent\HybridRelations;
class User extends Model
{
use HybridRelations;
protected $connection = 'mysql';
}
```
Embedded relations now return an `Illuminate\Database\Eloquent\Collection` rather than a custom Collection class. If you were using one of the special methods that were available, convert them to Collection operations.
```php
$books = $user->books()->sortBy('title')->get();
```
For any other minor changes, please take a look at our [changelog](CHANGELOG.md)
......@@ -31,7 +31,6 @@
</testsuite>
<testsuite name="relations">
<file>tests/RelationsTest.php</file>
<file>tests/EmbeddedRelationsTest.php</file>
</testsuite>
<testsuite name="mysqlrelations">
<file>tests/RelationsTest.php</file>
......
......@@ -35,14 +35,6 @@ class Builder extends EloquentBuilder
*/
public function update(array $values, array $options = [])
{
// Intercept operations on embedded models and delegate logic
// to the parent relation instance.
if ($relation = $this->model->getParentRelation()) {
$relation->performUpdate($this->model, $values);
return 1;
}
return $this->toBase()->update($this->addUpdatedAtColumn($values), $options);
}
......@@ -51,14 +43,6 @@ class Builder extends EloquentBuilder
*/
public function insert(array $values)
{
// Intercept operations on embedded models and delegate logic
// to the parent relation instance.
if ($relation = $this->model->getParentRelation()) {
$relation->performInsert($this->model, $values);
return true;
}
return parent::insert($values);
}
......@@ -67,14 +51,6 @@ class Builder extends EloquentBuilder
*/
public function insertGetId(array $values, $sequence = null)
{
// Intercept operations on embedded models and delegate logic
// to the parent relation instance.
if ($relation = $this->model->getParentRelation()) {
$relation->performInsert($this->model, $values);
return $this->model->getKey();
}
return parent::insertGetId($values, $sequence);
}
......@@ -83,14 +59,6 @@ class Builder extends EloquentBuilder
*/
public function delete()
{
// Intercept operations on embedded models and delegate logic
// to the parent relation instance.
if ($relation = $this->model->getParentRelation()) {
$relation->performDelete($this->model);
return $this->model->getKey();
}
return parent::delete();
}
......@@ -99,23 +67,6 @@ class Builder extends EloquentBuilder
*/
public function increment($column, $amount = 1, array $extra = [])
{
// Intercept operations on embedded models and delegate logic
// to the parent relation instance.
if ($relation = $this->model->getParentRelation()) {
$value = $this->model->{$column};
// When doing increment and decrements, Eloquent will automatically
// sync the original attributes. We need to change the attribute
// temporary in order to trigger an update query.
$this->model->{$column} = null;
$this->model->syncOriginalAttribute($column);
$result = $this->model->update([$column => $value]);
return $result;
}
return parent::increment($column, $amount, $extra);
}
......@@ -124,21 +75,6 @@ class Builder extends EloquentBuilder
*/
public function decrement($column, $amount = 1, array $extra = [])
{
// Intercept operations on embedded models and delegate logic
// to the parent relation instance.
if ($relation = $this->model->getParentRelation()) {
$value = $this->model->{$column};
// When doing increment and decrements, Eloquent will automatically
// sync the original attributes. We need to change the attribute
// temporary in order to trigger an update query.
$this->model->{$column} = null;
$this->model->syncOriginalAttribute($column);
return $this->model->update([$column => $value]);
}
return parent::decrement($column, $amount, $extra);
}
......
<?php
namespace Jenssegers\Mongodb\Eloquent;
use Illuminate\Support\Str;
use Jenssegers\Mongodb\Relations\EmbedsMany;
use Jenssegers\Mongodb\Relations\EmbedsOne;
trait EmbedsRelations
{
/**
* Define an embedded one-to-many relationship.
* @param string $related
* @param string $localKey
* @param string $foreignKey
* @param string $relation
* @return \Jenssegers\Mongodb\Relations\EmbedsMany
*/
protected function embedsMany($related, $localKey = null, $foreignKey = null, $relation = null)
{
// 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 relationships.
if ($relation === null) {
list(, $caller) = debug_backtrace(false);
$relation = $caller['function'];
}
if ($localKey === null) {
$localKey = $relation;
}
if ($foreignKey === null) {
$foreignKey = Str::snake(class_basename($this));
}
$query = $this->newQuery();
$instance = new $related;
return new EmbedsMany($query, $this, $instance, $localKey, $foreignKey, $relation);
}
/**
* Define an embedded one-to-many relationship.
* @param string $related
* @param string $localKey
* @param string $foreignKey
* @param string $relation
* @return \Jenssegers\Mongodb\Relations\EmbedsOne
*/
protected function embedsOne($related, $localKey = null, $foreignKey = null, $relation = null)
{
// 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 relationships.
if ($relation === null) {
list(, $caller) = debug_backtrace(false);
$relation = $caller['function'];
}
if ($localKey === null) {
$localKey = $relation;
}
if ($foreignKey === null) {
$foreignKey = Str::snake(class_basename($this));
}
$query = $this->newQuery();
$instance = new $related;
return new EmbedsOne($query, $this, $instance, $localKey, $foreignKey, $relation);
}
}
......@@ -17,7 +17,7 @@ use MongoDB\BSON\UTCDateTime;
abstract class Model extends BaseModel
{
use HybridRelations, EmbedsRelations;
use HybridRelations;
/**
* The collection associated with the model.
......@@ -143,11 +143,6 @@ abstract class Model extends BaseModel
return $this->getAttributeValue($key);
}
// This checks for embedded relation support.
if (method_exists($this, $key) && !method_exists(self::class, $key)) {
return $this->getRelationValue($key);
}
return parent::getAttribute($key);
}
......
<?php
namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Model as EloquentModel;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;
use MongoDB\BSON\ObjectID;
class EmbedsMany extends EmbedsOneOrMany
{
/**
* @inheritdoc
*/
public function initRelation(array $models, $relation)
{
foreach ($models as $model) {
$model->setRelation($relation, $this->related->newCollection());
}
return $models;
}
/**
* @inheritdoc
*/
public function getResults()
{
return $this->toCollection($this->getEmbedded());
}
/**
* Save a new model and attach it to the parent model.
* @param Model $model
* @return Model|bool
*/
public function performInsert(Model $model)
{
// Generate a new key if needed.
if ($model->getKeyName() == '_id' && !$model->getKey()) {
$model->setAttribute('_id', new ObjectID);
}
// For deeply nested documents, let the parent handle the changes.
if ($this->isNested()) {
$this->associate($model);
return $this->parent->save() ? $model : false;
}
// Push the new model to the database.
$result = $this->getBaseQuery()->push($this->localKey, $model->getAttributes(), true);
// Attach the model to its parent.
if ($result) {
$this->associate($model);
}
return $result ? $model : false;
}
/**
* Save an existing model and attach it to the parent model.
* @param Model $model
* @return Model|bool
*/
public function performUpdate(Model $model)
{
// For deeply nested documents, let the parent handle the changes.
if ($this->isNested()) {
$this->associate($model);
return $this->parent->save();
}
// Get the correct foreign key value.
$foreignKey = $this->getForeignKeyValue($model);
$values = $this->getUpdateValues($model->getDirty(), $this->localKey . '.$.');
// Update document in database.
$result = $this->getBaseQuery()->where($this->localKey . '.' . $model->getKeyName(), $foreignKey)
->update($values);
// Attach the model to its parent.
if ($result) {
$this->associate($model);
}
return $result ? $model : false;
}
/**
* Delete an existing model and detach it from the parent model.
* @param Model $model
* @return int
*/
public function performDelete(Model $model)
{
// For deeply nested documents, let the parent handle the changes.
if ($this->isNested()) {
$this->dissociate($model);
return $this->parent->save();
}
// Get the correct foreign key value.
$foreignKey = $this->getForeignKeyValue($model);
$result = $this->getBaseQuery()->pull($this->localKey, [$model->getKeyName() => $foreignKey]);
if ($result) {
$this->dissociate($model);
}
return $result;
}
/**
* Associate the model instance to the given parent, without saving it to the database.
* @param Model $model
* @return Model
*/
public function associate(Model $model)
{
if (!$this->contains($model)) {
return $this->associateNew($model);
}
return $this->associateExisting($model);
}
/**
* Dissociate the model instance from the given parent, without saving it to the database.
* @param mixed $ids
* @return int
*/
public function dissociate($ids = [])
{
$ids = $this->getIdsArrayFrom($ids);
$records = $this->getEmbedded();
$primaryKey = $this->related->getKeyName();
// Remove the document from the parent model.
foreach ($records as $i => $record) {
if (in_array($record[$primaryKey], $ids)) {
unset($records[$i]);
}
}
$this->setEmbedded($records);
// We 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.
return count($ids);
}
/**
* Destroy the embedded models for the given IDs.
* @param mixed $ids
* @return int
*/
public function destroy($ids = [])
{
$count = 0;
$ids = $this->getIdsArrayFrom($ids);
// Get all models matching the given ids.
$models = $this->getResults()->only($ids);
// Pull the documents from the database.
foreach ($models as $model) {
if ($model->delete()) {
$count++;
}
}
return $count;
}
/**
* Delete all embedded models.
* @return int
*/
public function delete()
{
// Overwrite the local key with an empty array.
$result = $this->query->update([$this->localKey => []]);
if ($result) {
$this->setEmbedded([]);
}
return $result;
}
/**
* Destroy alias.
* @param mixed $ids
* @return int
*/
public function detach($ids = [])
{
return $this->destroy($ids);
}
/**
* Save alias.
* @param Model $model
* @return Model
*/
public function attach(Model $model)
{
return $this->save($model);
}
/**
* Associate a new model instance to the given parent, without saving it to the database.
* @param Model $model
* @return Model
*/
protected function associateNew($model)
{
// Create a new key if needed.
if ($model->getKeyName() === '_id' && !$model->getAttribute('_id')) {
$model->setAttribute('_id', new ObjectID);
}
$records = $this->getEmbedded();
// Add the new model to the embedded documents.
$records[] = $model->getAttributes();
return $this->setEmbedded($records);
}
/**
* Associate an existing model instance to the given parent, without saving it to the database.
* @param Model $model
* @return Model
*/
protected function associateExisting($model)
{
// Get existing embedded documents.
$records = $this->getEmbedded();
$primaryKey = $this->related->getKeyName();
$key = $model->getKey();
// Replace the document in the parent model.
foreach ($records as &$record) {
if ($record[$primaryKey] == $key) {
$record = $model->getAttributes();
break;
}
}
return $this->setEmbedded($records);
}
/**
* @param null $perPage
* @param array $columns
* @param string $pageName
* @param null $page
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
*/
public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
{
$page = $page ?: Paginator::resolveCurrentPage($pageName);
$perPage = $perPage ?: $this->related->getPerPage();
$results = $this->getEmbedded();
$results = $this->toCollection($results);
$total = $results->count();
$start = ($page - 1) * $perPage;
$sliced = $results->slice(
$start,
$perPage
);
return new LengthAwarePaginator(
$sliced,
$total,
$perPage,
$page,
[
'path' => Paginator::resolveCurrentPath()
]
);
}
/**
* @inheritdoc
*/
protected function getEmbedded()
{
return parent::getEmbedded() ?: [];
}
/**
* @inheritdoc
*/
protected function setEmbedded($models)
{
if (!is_array($models)) {
$models = [$models];
}
return parent::setEmbedded(array_values($models));
}
/**
* @inheritdoc
*/
public function __call($method, $parameters)
{
if (method_exists(Collection::class, $method)) {
return call_user_func_array([$this->getResults(), $method], $parameters);
}
return parent::__call($method, $parameters);
}
/**
* Get the name of the "where in" method for eager loading.
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @return string
*/
protected function whereInMethod(EloquentModel $model, $key)
{
return 'whereIn';
}
}
<?php
namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Model as EloquentModel;
use MongoDB\BSON\ObjectID;
class EmbedsOne extends EmbedsOneOrMany
{
/**
* @inheritdoc
*/
public function initRelation(array $models, $relation)
{
foreach ($models as $model) {
$model->setRelation($relation, null);
}
return $models;
}
/**
* @inheritdoc
*/
public function getResults()
{
return $this->toModel($this->getEmbedded());
}
/**
* Save a new model and attach it to the parent model.
* @param Model $model
* @return Model|bool
*/
public function performInsert(Model $model)
{
// Generate a new key if needed.
if ($model->getKeyName() == '_id' && !$model->getKey()) {
$model->setAttribute('_id', new ObjectID);
}
// For deeply nested documents, let the parent handle the changes.
if ($this->isNested()) {
$this->associate($model);
return $this->parent->save() ? $model : false;
}
$result = $this->getBaseQuery()->update([$this->localKey => $model->getAttributes()]);
// Attach the model to its parent.
if ($result) {
$this->associate($model);
}
return $result ? $model : false;
}
/**
* Save an existing model and attach it to the parent model.
* @param Model $model
* @return Model|bool
*/
public function performUpdate(Model $model)
{
if ($this->isNested()) {
$this->associate($model);
return $this->parent->save();
}
$values = $this->getUpdateValues($model->getDirty(), $this->localKey . '.');
$result = $this->getBaseQuery()->update($values);
// Attach the model to its parent.
if ($result) {
$this->associate($model);
}
return $result ? $model : false;
}
/**
* Delete an existing model and detach it from the parent model.
* @return int
*/
public function performDelete()
{
// For deeply nested documents, let the parent handle the changes.
if ($this->isNested()) {
$this->dissociate();
return $this->parent->save();
}
// Overwrite the local key with an empty array.
$result = $this->getBaseQuery()->update([$this->localKey => null]);
// Detach the model from its parent.
if ($result) {
$this->dissociate();
}
return $result;
}
/**
* Attach the model to its parent.
* @param Model $model
* @return Model
*/
public function associate(Model $model)
{
return $this->setEmbedded($model->getAttributes());
}
/**
* Detach the model from its parent.
* @return Model
*/
public function dissociate()
{
return $this->setEmbedded(null);
}
/**
* Delete all embedded models.
* @return int
*/
public function delete()
{
return $this->performDelete();
}
/**
* Get the name of the "where in" method for eager loading.
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @return string
*/
protected function whereInMethod(EloquentModel $model, $key)
{
return 'whereIn';
}
}
<?php
namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model as EloquentModel;
use Illuminate\Database\Eloquent\Relations\Relation;
use Jenssegers\Mongodb\Eloquent\Model;
abstract class EmbedsOneOrMany 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 Builder $query
* @param Model $parent
* @param Model $related
* @param string $localKey
* @param string $foreignKey
* @param string $relation
*/
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;
// If this is a nested relation, we need to get the parent query instead.
if ($parentRelation = $this->getParentRelation()) {
$this->query = $parentRelation->getQuery();
}
$this->addConstraints();
}
/**
* @inheritdoc
*/
public function addConstraints()
{
if (static::$constraints) {
$this->query->where($this->getQualifiedParentKeyName(), '=', $this->getParentKey());
}
}
/**
* @inheritdoc
*/
public function addEagerConstraints(array $models)
{
// There are no eager loading constraints.
}
/**
* @inheritdoc
*/
public function match(array $models, Collection $results, $relation)
{
foreach ($models as $model) {
$results = $model->$relation()->getResults();
$model->setParentRelation($this);
$model->setRelation($relation, $results);
}
return $models;
}
/**
* Shorthand to get the results of the relationship.
* @param array $columns
* @return Collection
*/
public function get($columns = ['*'])
{
return $this->getResults();
}
/**
* Get the number of embedded models.
* @return int
*/
public function count()
{
return count($this->getEmbedded());
}
/**
* Attach a model instance to the parent model.
* @param Model $model
* @return Model|bool
*/
public function save(Model $model)
{
$model->setParentRelation($this);
return $model->save() ? $model : false;
}
/**
* Attach a collection of models to the parent instance.
* @param Collection|array $models
* @return Collection|array
*/
public function saveMany($models)
{
foreach ($models as $model) {
$this->save($model);
}
return $models;
}
/**
* Create a new instance of the related model.
* @param array $attributes
* @return 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($attributes);
$instance->setParentRelation($this);
$instance->save();
return $instance;
}
/**
* Create an array of new instances of the related model.
* @param array $records
* @return array
*/
public function createMany(array $records)
{
$instances = [];
foreach ($records as $record) {
$instances[] = $this->create($record);
}
return $instances;
}
/**
* Transform single ID, single Model or array of Models into an array of IDs.
* @param mixed $ids
* @return array
*/
protected function getIdsArrayFrom($ids)
{
if ($ids instanceof \Illuminate\Support\Collection) {
$ids = $ids->all();
}
if (!is_array($ids)) {
$ids = [$ids];
}
foreach ($ids as &$id) {
if ($id instanceof Model) {
$id = $id->getKey();
}
}
return $ids;
}
/**
* @inheritdoc
*/
protected function getEmbedded()
{
// Get raw attributes to skip relations and accessors.
$attributes = $this->parent->getAttributes();
// Get embedded models form parent attributes.
$embedded = isset($attributes[$this->localKey]) ? (array) $attributes[$this->localKey] : null;
return $embedded;
}
/**
* @inheritdoc
*/
protected function setEmbedded($records)
{
// Assign models to parent attributes array.
$attributes = $this->parent->getAttributes();
$attributes[$this->localKey] = $records;
// Set raw attributes to skip mutators.
$this->parent->setRawAttributes($attributes);
// Set the relation on the parent.
return $this->parent->setRelation($this->relation, $records === null ? null : $this->getResults());
}
/**
* Get the foreign key value for the relation.
* @param mixed $id
* @return mixed
*/
protected function getForeignKeyValue($id)
{
if ($id instanceof Model) {
$id = $id->getKey();
}
// Convert the id to MongoId if necessary.
return $this->getBaseQuery()->convertKey($id);
}
/**
* Convert an array of records to a Collection.
* @param array $records
* @return Collection
*/
protected function toCollection(array $records = [])
{
$models = [];
foreach ($records as $attributes) {
$models[] = $this->toModel($attributes);
}
if (count($models) > 0) {
$models = $this->eagerLoadRelations($models);
}
return $this->related->newCollection($models);
}
/**
* Create a related model instanced.
* @param array $attributes
* @return Model
*/
protected function toModel($attributes = [])
{
if ($attributes === null) {
return;
}
$connection = $this->related->getConnection();
$model = $this->related->newFromBuilder(
(array) $attributes,
$connection ? $connection->getName() : null
);
$model->setParentRelation($this);
$model->setRelation($this->foreignKey, $this->parent);
// If you remove this, you will get segmentation faults!
$model->setHidden(array_merge($model->getHidden(), [$this->foreignKey]));
return $model;
}
/**
* Get the relation instance of the parent.
* @return Relation
*/
protected function getParentRelation()
{
return $this->parent->getParentRelation();
}
/**
* @inheritdoc
*/
public function getQuery()
{
// Because we are sharing this relation instance to models, we need
// to make sure we use separate query instances.
return clone $this->query;
}
/**
* @inheritdoc
*/
public function getBaseQuery()
{
// Because we are sharing this relation instance to models, we need
// to make sure we use separate query instances.
return clone $this->query->getQuery();
}
/**
* Check if this relation is nested in another relation.
* @return bool
*/
protected function isNested()
{
return $this->getParentRelation() != null;
}
/**
* Get the fully qualified local key name.
* @param string $glue
* @return string
*/
protected function getPathHierarchy($glue = '.')
{
if ($parentRelation = $this->getParentRelation()) {
return $parentRelation->getPathHierarchy($glue) . $glue . $this->localKey;
}
return $this->localKey;
}
/**
* @inheritdoc
*/
public function getQualifiedParentKeyName()
{
if ($parentRelation = $this->getParentRelation()) {
return $parentRelation->getPathHierarchy() . '.' . $this->parent->getKeyName();
}
return $this->parent->getKeyName();
}
/**
* Get the primary key value of the parent.
* @return string
*/
protected function getParentKey()
{
return $this->parent->getKey();
}
/**
* Return update values
* @param $array
* @param string $prepend
* @return array
*/
public static function getUpdateValues($array, $prepend = '')
{
$results = [];
foreach ($array as $key => $value) {
$results[$prepend . $key] = $value;
}
return $results;
}
/**
* Get the foreign key for the relationship.
* @return string
*/
public function getQualifiedForeignKeyName()
{
return $this->foreignKey;
}
/**
* Get the name of the "where in" method for eager loading.
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @return string
*/
protected function whereInMethod(EloquentModel $model, $key)
{
return 'whereIn';
}
}
This diff is collapsed.
......@@ -640,26 +640,6 @@ class QueryBuilderTest extends TestCase
$results = DB::collection('users')->where('name', 'not regexp', '/.*doe/i')->get();
$this->assertCount(1, $results);
DB::collection('users')->insert([
[
'name' => 'John Doe',
'addresses' => [
['city' => 'Ghent'],
['city' => 'Paris'],
],
],
[
'name' => 'Jane Doe',
'addresses' => [
['city' => 'Brussels'],
['city' => 'Paris'],
],
],
]);
$users = DB::collection('users')->where('addresses', 'elemMatch', ['city' => 'Brussels'])->get();
$this->assertCount(1, $users);
$this->assertEquals('Jane Doe', $users[0]['name']);
}
public function testIncrement()
......
......@@ -2,15 +2,10 @@
declare(strict_types=1);
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
use Jenssegers\Mongodb\Relations\EmbedsMany;
class Address extends Eloquent
{
protected $connection = 'mongodb';
protected static $unguarded = true;
public function addresses(): EmbedsMany
{
return $this->embedsMany('Address');
}
}
......@@ -67,16 +67,6 @@ class User extends Eloquent implements AuthenticatableContract, CanResetPassword
return $this->morphMany('Photo', 'imageable');
}
public function addresses()
{
return $this->embedsMany('Address');
}
public function father()
{
return $this->embedsOne('User');
}
public function getDateFormat()
{
return 'l jS \of F Y h:i:s A';
......
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