Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[5.5] Model serialization on custom connection #19521

Merged
merged 3 commits into from
Jun 8, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/Illuminate/Contracts/Database/ModelIdentifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ class ModelIdentifier
*/
public $class;

/**
* The connection name of the model.
*
* @var string|null
*/
public $connection;

/**
* The unique identifier of the model.
*
Expand All @@ -24,12 +31,14 @@ class ModelIdentifier
* Create a new model identifier.
*
* @param string $class
* @param mixed $connection
* @param mixed $id
* @return void
*/
public function __construct($class, $id)
public function __construct($class, $connection, $id)
{
$this->id = $id;
$this->connection = $connection;
$this->class = $class;
}
}
7 changes: 7 additions & 0 deletions src/Illuminate/Contracts/Queue/QueueableCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ interface QueueableCollection
*/
public function getQueueableClass();

/**
* Get the connection of the entities being queued.
*
* @return string|null
*/
public function getQueueableConnection();

/**
* Get the identifiers for all of the entities.
*
Expand Down
7 changes: 7 additions & 0 deletions src/Illuminate/Contracts/Queue/QueueableEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,11 @@ interface QueueableEntity
* @return mixed
*/
public function getQueueableId();

/**
* Get the connection of the entity.
*
* @return string|null
*/
public function getQueueableConnection();
}
22 changes: 22 additions & 0 deletions src/Illuminate/Database/Eloquent/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,28 @@ public function getQueueableClass()
return $class;
}

/**
* Get the connection of the entities being queued.
*
* @return string|null
*/
public function getQueueableConnection()
{
if ($this->count() === 0) {
return;
}

$connection = $this->first()->getConnectionName();

$this->each(function ($model) use ($connection) {
if ($model->getConnectionName() !== $connection) {
throw new LogicException('Queueing collections with multiple model connections is not supported.');
}
});

return $connection;
}

/**
* Get the identifiers for all of the entities.
*
Expand Down
10 changes: 10 additions & 0 deletions src/Illuminate/Database/Eloquent/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -1199,6 +1199,16 @@ public function getQueueableId()
return $this->getKey();
}

/**
* Get the queueable identity for the entity.
*
* @return mixed
*/
public function getQueueableConnection()
{
return $this->getConnectionName();
}

/**
* Get the value of the model's route key.
*
Expand Down
10 changes: 5 additions & 5 deletions src/Illuminate/Queue/SerializesAndRestoresModelIdentifiers.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ trait SerializesAndRestoresModelIdentifiers
protected function getSerializedPropertyValue($value)
{
if ($value instanceof QueueableCollection) {
return new ModelIdentifier($value->getQueueableClass(), $value->getQueueableIds());
return new ModelIdentifier($value->getQueueableClass(), $value->getQueueableConnection(), $value->getQueueableIds());
}

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

return $value;
Expand All @@ -42,8 +42,8 @@ protected function getRestoredPropertyValue($value)

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

/**
Expand All @@ -58,7 +58,7 @@ protected function restoreCollection($value)
return new EloquentCollection;
}

$model = new $value->class;
$model = (new $value->class)->setConnection($value->connection);

return $this->getQueryForModelRestoration($model)->useWritePdo()
->whereIn($model->getQualifiedKeyName(), $value->id)->get();
Expand Down
145 changes: 145 additions & 0 deletions tests/Integration/Queue/ModelSerializationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?php

use Orchestra\Testbench\TestCase;
use Illuminate\Database\Eloquent\Model;

/**
* @group integration
*/
class ModelSerializationTest extends TestCase
{
protected function getEnvironmentSetUp($app)
{
$app['config']->set('app.debug', 'true');

$app['config']->set('database.default', 'testbench');

$app['config']->set('database.connections.testbench', [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
]);

$app['config']->set('database.connections.custom', [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
]);
}

public function setUp()
{
parent::setUp();

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

Schema::connection('custom')->create('users', function ($table) {
$table->increments('id');
$table->string('email');
});
}

/**
* @test
*/
public function it_serialize_user_on_default_connection()
{
$user = ModelSerializationTestUser::create([
'email' => '[email protected]',
]);

$user2 = ModelSerializationTestUser::create([
'email' => '[email protected]',
]);

$serialized = serialize(new ModelSerializationTestClass($user));

$unSerialized = unserialize($serialized);

$this->assertEquals('testbench', $unSerialized->user->getConnectionName());
$this->assertEquals('[email protected]', $unSerialized->user->email);

$serialized = serialize(new ModelSerializationTestClass(ModelSerializationTestUser::on('testbench')->get()));

$unSerialized = unserialize($serialized);

$this->assertEquals('testbench', $unSerialized->user[0]->getConnectionName());
$this->assertEquals('[email protected]', $unSerialized->user[0]->email);
$this->assertEquals('testbench', $unSerialized->user[1]->getConnectionName());
$this->assertEquals('[email protected]', $unSerialized->user[1]->email);
}

/**
* @test
*/
public function it_serialize_user_on_different_connection()
{
$user = ModelSerializationTestUser::on('custom')->create([
'email' => '[email protected]',
]);

$user2 = ModelSerializationTestUser::on('custom')->create([
'email' => '[email protected]',
]);

$serialized = serialize(new ModelSerializationTestClass($user));

$unSerialized = unserialize($serialized);

$this->assertEquals('custom', $unSerialized->user->getConnectionName());
$this->assertEquals('[email protected]', $unSerialized->user->email);

$serialized = serialize(new ModelSerializationTestClass(ModelSerializationTestUser::on('custom')->get()));

$unSerialized = unserialize($serialized);

$this->assertEquals('custom', $unSerialized->user[0]->getConnectionName());
$this->assertEquals('[email protected]', $unSerialized->user[0]->email);
$this->assertEquals('custom', $unSerialized->user[1]->getConnectionName());
$this->assertEquals('[email protected]', $unSerialized->user[1]->email);
}

/**
* @test
* @expectedException LogicException
* @expectedExceptionMessage Queueing collections with multiple model connections is not supported.
*/
public function it_fails_if_models_on_multi_connections()
{
$user = ModelSerializationTestUser::on('custom')->create([
'email' => '[email protected]',
]);

$user2 = ModelSerializationTestUser::create([
'email' => '[email protected]',
]);

$serialized = serialize(new ModelSerializationTestClass(
new \Illuminate\Database\Eloquent\Collection([$user, $user2])
));

unserialize($serialized);
}
}

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

class ModelSerializationTestClass
{
use \Illuminate\Queue\SerializesModels;

public $user;

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

public function getQueueableConnection()
{
return null;
}
}

class SyncQueueTestHandler
Expand Down