Skip to content

Commit 0143e49

Browse files
authored
Merge pull request #3794 from MGatner/builder-table
Builder Tables
2 parents c623121 + bbdd9bd commit 0143e49

5 files changed

Lines changed: 97 additions & 23 deletions

File tree

system/Database/BaseBuilder.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,15 @@ class BaseBuilder
185185
*/
186186
protected $db;
187187

188+
/**
189+
* Name of the primary table for this instance.
190+
* Tracked separately because $QBFrom gets escaped
191+
* and prefixed.
192+
*
193+
* @var string
194+
*/
195+
protected $tableName;
196+
188197
/**
189198
* ORDER BY random keyword
190199
*
@@ -286,6 +295,7 @@ public function __construct($tableName, ConnectionInterface &$db, array $options
286295

287296
$this->db = $db;
288297

298+
$this->tableName = $tableName;
289299
$this->from($tableName);
290300

291301
if (! empty($options))
@@ -330,6 +340,18 @@ public function testMode(bool $mode = true)
330340

331341
//--------------------------------------------------------------------
332342

343+
/**
344+
* Gets the name of the primary table.
345+
*
346+
* @return string
347+
*/
348+
public function getTable(): string
349+
{
350+
return $this->tableName;
351+
}
352+
353+
//--------------------------------------------------------------------
354+
333355
/**
334356
* Returns an array of bind values and their
335357
* named parameters for binding in the Query object later.

system/Model.php

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,12 +1394,19 @@ public function protect(bool $protect = true)
13941394
* @param string $table
13951395
*
13961396
* @return BaseBuilder
1397-
* @throws ModelException ;
1397+
* @throws ModelException
13981398
*/
1399-
protected function builder(string $table = null)
1399+
public function builder(string $table = null)
14001400
{
1401+
// Check for an existing Builder
14011402
if ($this->builder instanceof BaseBuilder)
14021403
{
1404+
// Make sure the requested table matches the builder
1405+
if ($table && $this->builder->getTable() !== $table)
1406+
{
1407+
return $this->db->table($table);
1408+
}
1409+
14031410
return $this->builder;
14041411
}
14051412

@@ -1419,9 +1426,15 @@ protected function builder(string $table = null)
14191426
$this->db = Database::connect($this->DBGroup);
14201427
}
14211428

1422-
$this->builder = $this->db->table($table);
1429+
$builder = $this->db->table($table);
1430+
1431+
// Only consider it "shared" if the table is correct
1432+
if ($table === $this->table)
1433+
{
1434+
$this->builder = $builder;
1435+
}
14231436

1424-
return $this->builder;
1437+
return $builder;
14251438
}
14261439

14271440
/**
@@ -1973,10 +1986,7 @@ public function __call(string $name, array $params)
19731986
$result = $builder->{$name}(...$params);
19741987
}
19751988

1976-
// Don't return the builder object unless specifically requested
1977-
//, since that will interrupt the usability flow
1978-
// and break intermingling of model and builder methods.
1979-
if ($name !== 'builder' && empty($result))
1989+
if (empty($result))
19801990
{
19811991
if (! method_exists($this->builder(), $name))
19821992
{
@@ -1988,7 +1998,7 @@ public function __call(string $name, array $params)
19881998
return $result;
19891999
}
19902000

1991-
if ($name !== 'builder' && ! $result instanceof BaseBuilder)
2001+
if (! $result instanceof BaseBuilder)
19922002
{
19932003
return $result;
19942004
}

tests/system/Database/Builder/BaseTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,23 @@ public function testDbReturnsConnection()
2626

2727
$this->assertInstanceOf(MockConnection::class, $result);
2828
}
29+
30+
//--------------------------------------------------------------------
31+
32+
public function testGetTableReturnsTable()
33+
{
34+
$builder = $this->db->table('jobs');
35+
36+
$result = $builder->getTable();
37+
$this->assertEquals('jobs', $result);
38+
}
39+
40+
public function testGetTableIgnoresFrom()
41+
{
42+
$builder = $this->db->table('jobs');
43+
44+
$builder->from('foo');
45+
$result = $builder->getTable();
46+
$this->assertEquals('jobs', $result);
47+
}
2948
}

tests/system/Database/Live/ModelTest.php

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2487,19 +2487,6 @@ public function testUndefinedModelMethod()
24872487
$model->undefinedMethodCall();
24882488
}
24892489

2490-
public function testUndefinedMethodInBuilder()
2491-
{
2492-
$model = new JobModel($this->db);
2493-
2494-
$model->find(1);
2495-
2496-
$this->expectException(BadMethodCallException::class);
2497-
$this->expectExceptionMessage('Call to undefined method Tests\Support\Models\JobModel::getBindings');
2498-
2499-
$binds = $model->builder()
2500-
->getBindings();
2501-
}
2502-
25032490
/**
25042491
* @dataProvider provideAggregateAndGroupBy
25052492
*/
@@ -2643,4 +2630,37 @@ public function testSetAllowedFields()
26432630
$model->setAllowedFields($allowed2);
26442631
$this->assertSame($allowed2, $this->getPrivateProperty($model, 'allowedFields'));
26452632
}
2633+
2634+
//--------------------------------------------------------------------
2635+
2636+
public function testBuilderUsesModelTable()
2637+
{
2638+
$model = new UserModel($this->db);
2639+
$builder = $model->builder();
2640+
2641+
$this->assertEquals('user', $builder->getTable());
2642+
}
2643+
2644+
public function testBuilderRespectsTableParameter()
2645+
{
2646+
$model = new UserModel($this->db);
2647+
$builder1 = $model->builder('jobs');
2648+
$builder2 = $model->builder();
2649+
2650+
$this->assertEquals('jobs', $builder1->getTable());
2651+
$this->assertEquals('user', $builder2->getTable());
2652+
}
2653+
2654+
public function testBuilderWithParameterIgnoresShared()
2655+
{
2656+
$model = new UserModel($this->db);
2657+
2658+
$builder1 = $model->builder();
2659+
$builder2 = $model->builder('jobs');
2660+
$builder3 = $model->builder();
2661+
2662+
$this->assertEquals('user', $builder1->getTable());
2663+
$this->assertEquals('jobs', $builder2->getTable());
2664+
$this->assertEquals('user', $builder3->getTable());
2665+
}
26462666
}

user_guide_src/source/models/model.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,10 @@ need it::
670670

671671
$builder = $userModel->builder();
672672

673-
This builder is already set up with the model's $table.
673+
This builder is already set up with the model's $table. If you need access to another table
674+
you can pass it in as a parameter, but be aware that this will not return a shared instance::
675+
676+
$groupBuilder = $userModel->builder('groups');
674677

675678
You can also use Query Builder methods and the Model's CRUD methods in the same chained call, allowing for
676679
very elegant use::

0 commit comments

Comments
 (0)