Skip to content

Commit

Permalink
make unserialized models reload relationships
Browse files Browse the repository at this point in the history
- add new `getQueueableRelations` method to queuable interfaces
- accept the 'relations' into the `ModelIdentifier`
- implement `getQueueableRelations` method on Eloquent Collection and Model.
- extract a method on `SerializesAndRestoresModelIdentifiers` for `restoreModel`. Load the relationships in this method.
- add test
  • Loading branch information
browner12 committed Sep 13, 2017
1 parent 2a25ee7 commit 230eeef
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 5 deletions.
11 changes: 10 additions & 1 deletion src/Illuminate/Contracts/Database/ModelIdentifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,27 @@ class ModelIdentifier
*/
public $connection;

/**
* The relationships loaded on the model.
*
* @var array
*/
public $relations;

/**
* Create a new model identifier.
*
* @param string $class
* @param mixed $id
* @param mixed $connection
* @param array $relations
* @return void
*/
public function __construct($class, $id, $connection)
public function __construct($class, $id, $connection, $relations)

This comment has been minimized.

Copy link
@otilor

otilor Nov 17, 2020

4 arguments is a lot. This might tend to expand as the codebase grows. I feel it should be refactored.

{
$this->id = $id;
$this->class = $class;
$this->connection = $connection;
$this->relations = $relations;
}
}
7 changes: 7 additions & 0 deletions src/Illuminate/Contracts/Queue/QueueableCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,11 @@ public function getQueueableIds();
* @return string|null
*/
public function getQueueableConnection();

/**
* Get the relationships of the entities being queued.
*
* @return array
*/
public function getQueueableRelations();
}
7 changes: 7 additions & 0 deletions src/Illuminate/Contracts/Queue/QueueableEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,11 @@ public function getQueueableId();
* @return string|null
*/
public function getQueueableConnection();

/**
* Get the relationships for the entity.
*
* @return array
*/
public function getQueueableRelations();
}
10 changes: 10 additions & 0 deletions src/Illuminate/Database/Eloquent/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -419,4 +419,14 @@ public function getQueueableConnection()

return $connection;
}

/**
* Get the relationships of the entities being queued.
*
* @return array
*/
public function getQueueableRelations()
{
return $this->isNotEmpty() ? $this->first()->getRelations() : [];
}
}
32 changes: 32 additions & 0 deletions src/Illuminate/Database/Eloquent/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Illuminate\Contracts\Routing\UrlRoutable;
use Illuminate\Contracts\Queue\QueueableEntity;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Contracts\Queue\QueueableCollection;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Database\ConnectionResolverInterface as Resolver;

Expand Down Expand Up @@ -1250,6 +1251,37 @@ public function getQueueableConnection()
return $this->getConnectionName();
}

/**
* Get the queueable relationships for the entity.
*
* @return array
*/
public function getQueueableRelations()
{
$relations = [];

foreach ($this->getRelations() as $key => $relation){

$relations[] = $key;

if ($relation instanceof QueueableCollection)
{
foreach($relation->getQueueableRelations() as $collectionKey => $collectionValue){
$relations[] = $key . '.' . $collectionKey;
}
}

if ($relation instanceof QueueableEntity)
{
foreach($relation->getQueueableRelations() as $entityKey => $entityValue){
$relations[] = $key . '.' . $entityValue;
}
}
}

return $relations;
}

/**
* Get the value of the model's route key.
*
Expand Down
21 changes: 17 additions & 4 deletions src/Illuminate/Queue/SerializesAndRestoresModelIdentifiers.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@ protected function getSerializedPropertyValue($value)
return new ModelIdentifier(
$value->getQueueableClass(),
$value->getQueueableIds(),
$value->getQueueableConnection()
$value->getQueueableConnection(),
$value->getQueueableRelations()
);
}

if ($value instanceof QueueableEntity) {
return new ModelIdentifier(
get_class($value),
$value->getQueueableId(),
$value->getQueueableConnection()
$value->getQueueableConnection(),
$value->getQueueableRelations()
);
}

Expand All @@ -50,8 +52,7 @@ protected function getRestoredPropertyValue($value)

return is_array($value->id)
? $this->restoreCollection($value)
: $this->getQueryForModelRestoration((new $value->class)->setConnection($value->connection))
->useWritePdo()->findOrFail($value->id);
: $this->restoreModel($value);
}

/**
Expand All @@ -72,6 +73,18 @@ protected function restoreCollection($value)
->whereIn($model->getQualifiedKeyName(), $value->id)->get();
}

/**
* @param \Illuminate\Contracts\Database\ModelIdentifier $value
* @return \Illuminate\Database\Eloquent\Model
*/
public function restoreModel($value)
{
$model = $this->getQueryForModelRestoration((new $value->class)->setConnection($value->connection))
->useWritePdo()->findOrFail($value->id);

return $model->load($value->relations);
}

/**
* Get the query for restoration.
*
Expand Down
99 changes: 99 additions & 0 deletions tests/Integration/Queue/ModelSerializationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,21 @@ public function setUp()
$table->increments('id');
$table->string('email');
});

Schema::create('orders', function ($table) {
$table->increments('id');
});

Schema::create('lines', function ($table) {
$table->increments('id');
$table->unsignedInteger('order_id');
$table->unsignedInteger('product_id');
});

Schema::create('products', function ($table) {
$table->increments('id');

});
}

/**
Expand Down Expand Up @@ -126,6 +141,50 @@ public function it_fails_if_models_on_multi_connections()

unserialize($serialized);
}

/**
* @test
*/
public function it_reloads_relationships()
{
$order = Order::create();

$product1 = Product::create();
$product2 = Product::create();

Line::create(['order_id' => $order->id, 'product_id' => $product1->id]);
Line::create(['order_id' => $order->id, 'product_id' => $product2->id]);
Line::create(['order_id' => $order->id, 'product_id' => $product1->id]);

$order->load('lines');

$serialized = serialize(new ModelRelationSerializationTestClass($order));
$unSerialized = unserialize($serialized);

$this->assertEquals($unSerialized->order->getRelations(), $order->getRelations());
}

/**
* @test
*/
public function it_reloads_nested_relationships()
{
$order = Order::create();

$product1 = Product::create();
$product2 = Product::create();

Line::create(['order_id' => $order->id, 'product_id' => $product1->id]);
Line::create(['order_id' => $order->id, 'product_id' => $product2->id]);
Line::create(['order_id' => $order->id, 'product_id' => $product1->id]);

$order->load('lines', 'lines.product');

$nestedSerialized = serialize(new ModelRelationSerializationTestClass($order));
$nestedUnSerialized = unserialize($nestedSerialized);

$this->assertEquals($nestedUnSerialized->order->getRelations(), $order->getRelations());
}
}

class ModelSerializationTestUser extends Model
Expand All @@ -135,6 +194,34 @@ class ModelSerializationTestUser extends Model
public $timestamps = false;
}

class Order extends Model
{
public $guarded = ['id'];
public $timestamps = false;

public function lines()
{
return $this->hasMany(Line::class);
}
}

class Line extends Model
{
public $guarded = ['id'];
public $timestamps = false;

public function product()
{
return $this->belongsTo(Product::class);
}
}

class Product extends Model
{
public $guarded = ['id'];
public $timestamps = false;
}

class ModelSerializationTestClass
{
use \Illuminate\Queue\SerializesModels;
Expand All @@ -146,3 +233,15 @@ public function __construct($user)
$this->user = $user;
}
}

class ModelRelationSerializationTestClass
{
use \Illuminate\Queue\SerializesModels;

public $order;

public function __construct($order)
{
$this->order = $order;
}
}
5 changes: 5 additions & 0 deletions tests/Queue/QueueSyncQueueTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ public function getQueueableConnection()
{
//
}

public function getQueueableRelations()
{
//
}
}

class SyncQueueTestHandler
Expand Down

0 comments on commit 230eeef

Please sign in to comment.