Skip to content

Commit

Permalink
Merge branch 'lazy-loading' into 8.x
Browse files Browse the repository at this point in the history
  • Loading branch information
taylorotwell committed May 26, 2021
2 parents 5a92f04 + c986e12 commit 56466a9
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 1 deletion.
17 changes: 16 additions & 1 deletion src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ public function getRelationValue($key)
}

if ($this->preventsLazyLoading) {
throw new LazyLoadingViolationException($this, $key);
$this->handleLazyLoadingViolation($key);
}

// If the "attribute" exists as a method on the model, we will just assume
Expand All @@ -460,6 +460,21 @@ public function isRelation($key)
(static::$relationResolvers[get_class($this)][$key] ?? null);
}

/**
* Handle a lazy loading violation.
*
* @param string $key
* @return mixed
*/
protected function handleLazyLoadingViolation($key)
{
if (isset(static::$lazyLoadingViolationCallback)) {
return call_user_func(static::$lazyLoadingViolationCallback, $this, $key);
}

throw new LazyLoadingViolationException($this, $key);
}

/**
* Get a relationship value from a method.
*
Expand Down
18 changes: 18 additions & 0 deletions src/Illuminate/Database/Eloquent/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,13 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
*/
protected static $modelsShouldPreventLazyLoading = false;

/**
* The callback that is responsible for handling lazy loading violations.
*
* @var callable|null
*/
protected static $lazyLoadingViolationCallback;

/**
* The name of the "created at" column.
*
Expand Down Expand Up @@ -358,6 +365,17 @@ public static function preventLazyLoading($value = true)
static::$modelsShouldPreventLazyLoading = $value;
}

/**
* Register a callback that is responsible for handling lazy loading violations.
*
* @param callable $callback
* @return void
*/
public static function handleLazyLoadingViolationUsing(callable $callback)
{
static::$lazyLoadingViolationCallback = $callback;
}

/**
* Fill the model with an array of attributes.
*
Expand Down
58 changes: 58 additions & 0 deletions tests/Integration/Database/EloquentStrictLoadingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,35 @@ public function testStrictModeThrowsAnExceptionOnLazyLoadingInRelations()

$models[0]->modelTwos[0]->modelThrees;
}

public function testStrictModeWithCustomCallbackOnLazyLoading()
{
$this->expectsEvents(ViolatedLazyLoadingEvent::class);

Model::handleLazyLoadingViolationUsing(function ($model, $key) {
event(new ViolatedLazyLoadingEvent($model, $key));
});

EloquentStrictLoadingTestModel1::create();
EloquentStrictLoadingTestModel1::create();

$models = EloquentStrictLoadingTestModel1::get();

$models[0]->modelTwos;
}

public function testStrictModeWithOverriddenHandlerOnLazyLoading()
{
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Violated');

EloquentStrictLoadingTestModel1WithCustomHandler::create();
EloquentStrictLoadingTestModel1WithCustomHandler::create();

$models = EloquentStrictLoadingTestModel1WithCustomHandler::get();

$models[0]->modelTwos;
}
}

class EloquentStrictLoadingTestModel1 extends Model
Expand All @@ -114,6 +143,23 @@ public function modelTwos()
}
}

class EloquentStrictLoadingTestModel1WithCustomHandler extends Model
{
public $table = 'test_model1';
public $timestamps = false;
protected $guarded = [];

public function modelTwos()
{
return $this->hasMany(EloquentStrictLoadingTestModel2::class, 'model_1_id');
}

protected function handleLazyLoadingViolation($key)
{
throw new \RuntimeException("Violated {$key}");
}
}

class EloquentStrictLoadingTestModel2 extends Model
{
public $table = 'test_model2';
Expand All @@ -132,3 +178,15 @@ class EloquentStrictLoadingTestModel3 extends Model
public $timestamps = false;
protected $guarded = [];
}

class ViolatedLazyLoadingEvent
{
public $model;
public $key;

public function __construct($model, $key)
{
$this->model = $model;
$this->key = $key;
}
}

0 comments on commit 56466a9

Please sign in to comment.