Skip to content

Commit a254dbd

Browse files
authored
Add Builder On Clone callback support (#54477)
* Add onClone callbacks * Update DatabaseEloquentBuilderTest.php * Style * Update Builder.php * Style
1 parent 1eaf24b commit a254dbd

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

src/Illuminate/Database/Eloquent/Builder.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,13 @@ class Builder implements BuilderContract
157157
*/
158158
protected $afterQueryCallbacks = [];
159159

160+
/**
161+
* The callbacks that should be invoked on clone.
162+
*
163+
* @var array
164+
*/
165+
protected $onCloneCallbacks = [];
166+
160167
/**
161168
* Create a new Eloquent query builder instance.
162169
*
@@ -2170,6 +2177,19 @@ public function clone()
21702177
return clone $this;
21712178
}
21722179

2180+
/**
2181+
* Register a closure to be invoked on a clone.
2182+
*
2183+
* @param \Closure $callback
2184+
* @return $this
2185+
*/
2186+
public function onClone(Closure $callback)
2187+
{
2188+
$this->onCloneCallbacks[] = $callback;
2189+
2190+
return $this;
2191+
}
2192+
21732193
/**
21742194
* Force a clone of the underlying query builder when cloning.
21752195
*
@@ -2178,5 +2198,9 @@ public function clone()
21782198
public function __clone()
21792199
{
21802200
$this->query = clone $this->query;
2201+
2202+
foreach ($this->onCloneCallbacks as $onCloneCallback) {
2203+
$onCloneCallback($this);
2204+
}
21812205
}
21822206
}

tests/Database/DatabaseEloquentBuilderTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2485,6 +2485,32 @@ public function testClone()
24852485
$this->assertSame('select * from "users" where "email" = ?', $clone->toSql());
24862486
}
24872487

2488+
public function testCloneModelMakesAFreshCopyOfTheModel()
2489+
{
2490+
$query = new BaseBuilder(m::mock(ConnectionInterface::class), new Grammar, m::mock(Processor::class));
2491+
$builder = (new Builder($query))->setModel(new EloquentBuilderTestStub);
2492+
$builder->select('*')->from('users');
2493+
2494+
$onCloneCallbackCalledCount = 0;
2495+
2496+
$onCloneQuery = null;
2497+
2498+
$builder->onClone(function (Builder $query) use (&$onCloneCallbackCalledCount, &$onCloneQuery) {
2499+
$onCloneCallbackCalledCount++;
2500+
2501+
$onCloneQuery = $query;
2502+
});
2503+
2504+
$clone = $builder->clone()->where('email', 'foo');
2505+
2506+
$this->assertNotSame($builder, $clone);
2507+
$this->assertSame('select * from "users"', $builder->toSql());
2508+
$this->assertSame('select * from "users" where "email" = ?', $clone->toSql());
2509+
2510+
$this->assertSame(1, $onCloneCallbackCalledCount);
2511+
$this->assertSame($onCloneQuery, $clone);
2512+
}
2513+
24882514
public function testToRawSql()
24892515
{
24902516
$query = m::mock(BaseBuilder::class);

0 commit comments

Comments
 (0)