Skip to content

Commit 04e12d1

Browse files
authored
fix: make seeder to respect database group (#9886)
1 parent 4ac1ab7 commit 04e12d1

File tree

8 files changed

+223
-7
lines changed

8 files changed

+223
-7
lines changed

system/Database/Seeder.php

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class Seeder
2727
/**
2828
* The name of the database group to use.
2929
*
30-
* @var non-empty-string
30+
* @var non-empty-string|null
3131
*/
3232
protected $DBGroup;
3333

@@ -92,10 +92,16 @@ public function __construct(Database $config, ?BaseConnection $db = null)
9292

9393
$this->config = &$config;
9494

95-
$db ??= Database::connect($this->DBGroup);
96-
97-
$this->db = $db;
98-
$this->forge = Database::forge($this->DBGroup);
95+
if (isset($this->DBGroup)) {
96+
$this->db = Database::connect($this->DBGroup);
97+
$this->forge = Database::forge($this->DBGroup);
98+
} elseif ($db instanceof BaseConnection) {
99+
$this->db = $db;
100+
$this->forge = Database::forge($db);
101+
} else {
102+
$this->db = Database::connect($config->defaultGroup);
103+
$this->forge = Database::forge($config->defaultGroup);
104+
}
99105
}
100106

101107
/**
@@ -145,7 +151,7 @@ public function call(string $class)
145151
}
146152

147153
/** @var Seeder $seeder */
148-
$seeder = new $class($this->config);
154+
$seeder = new $class($this->config, $this->db);
149155
$seeder->setSilent($this->silent)->run();
150156

151157
unset($seeder);
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of CodeIgniter 4 framework.
7+
*
8+
* (c) CodeIgniter Foundation <admin@codeigniter.com>
9+
*
10+
* For the full copyright and license information, please view
11+
* the LICENSE file that was distributed with this source code.
12+
*/
13+
14+
namespace Tests\Support\Database\Seeds;
15+
16+
use CodeIgniter\Database\BaseConnection;
17+
use CodeIgniter\Database\Seeder;
18+
19+
/**
20+
* Test seeder with explicit DBGroup set.
21+
*/
22+
class SeederWithDBGroup extends Seeder
23+
{
24+
protected $DBGroup = 'tests';
25+
26+
/**
27+
* Store the connection used during run() for testing.
28+
*/
29+
public static ?BaseConnection $lastConnection = null;
30+
31+
public function run(): void
32+
{
33+
self::$lastConnection = $this->db;
34+
}
35+
36+
/**
37+
* Expose the db connection for testing.
38+
*/
39+
public function getDatabase(): BaseConnection
40+
{
41+
return $this->db;
42+
}
43+
44+
/**
45+
* Reset static state for testing.
46+
*/
47+
public static function reset(): void
48+
{
49+
self::$lastConnection = null;
50+
}
51+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of CodeIgniter 4 framework.
7+
*
8+
* (c) CodeIgniter Foundation <admin@codeigniter.com>
9+
*
10+
* For the full copyright and license information, please view
11+
* the LICENSE file that was distributed with this source code.
12+
*/
13+
14+
namespace Tests\Support\Database\Seeds;
15+
16+
use CodeIgniter\Database\BaseConnection;
17+
use CodeIgniter\Database\Seeder;
18+
19+
/**
20+
* Test seeder without DBGroup set (should inherit connection).
21+
*/
22+
class SeederWithoutDBGroup extends Seeder
23+
{
24+
/**
25+
* Store the connection used during run() for testing.
26+
*/
27+
public static ?BaseConnection $lastConnection = null;
28+
29+
public function run(): void
30+
{
31+
self::$lastConnection = $this->db;
32+
}
33+
34+
/**
35+
* Expose the db connection for testing.
36+
*/
37+
public function getDatabase(): BaseConnection
38+
{
39+
return $this->db;
40+
}
41+
42+
/**
43+
* Reset static state for testing.
44+
*/
45+
public static function reset(): void
46+
{
47+
self::$lastConnection = null;
48+
}
49+
}

tests/system/Database/DatabaseSeederTest.php

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,23 @@
1717
use Config\Database;
1818
use Faker\Generator;
1919
use PHPUnit\Framework\Attributes\Group;
20+
use Tests\Support\Database\Seeds\SeederWithDBGroup;
21+
use Tests\Support\Database\Seeds\SeederWithoutDBGroup;
2022

2123
/**
2224
* @internal
2325
*/
24-
#[Group('Others')]
26+
#[Group('DatabaseLive')]
2527
final class DatabaseSeederTest extends CIUnitTestCase
2628
{
29+
protected function tearDown(): void
30+
{
31+
parent::tearDown();
32+
33+
SeederWithDBGroup::reset();
34+
SeederWithoutDBGroup::reset();
35+
}
36+
2737
public function testInstantiateNoSeedPath(): void
2838
{
2939
$this->expectException('InvalidArgumentException');
@@ -57,4 +67,60 @@ public function testCallOnEmptySeeder(): void
5767
$seeder = new Seeder(new Database());
5868
$seeder->call('');
5969
}
70+
71+
public function testSeederWithDBGroupUsesOwnConnection(): void
72+
{
73+
$config = new Database();
74+
$db = Database::connect('tests', false);
75+
76+
$seeder = new SeederWithDBGroup($config, $db);
77+
78+
$testsDb = Database::connect('tests');
79+
$this->assertSame($testsDb, $seeder->getDatabase());
80+
$this->assertNotSame($db, $seeder->getDatabase());
81+
}
82+
83+
public function testSeederWithoutDBGroupUsesPassedConnection(): void
84+
{
85+
$config = new Database();
86+
$db = Database::connect('tests');
87+
88+
$seeder = new SeederWithoutDBGroup($config, $db);
89+
90+
$this->assertSame($db, $seeder->getDatabase());
91+
}
92+
93+
public function testSeederWithoutDBGroupAndNoConnectionUsesDefault(): void
94+
{
95+
$config = new Database();
96+
97+
$seeder = new SeederWithoutDBGroup($config);
98+
99+
$defaultDb = Database::connect($config->defaultGroup);
100+
$this->assertSame($defaultDb, $seeder->getDatabase());
101+
}
102+
103+
public function testCallPassesConnectionToChildSeeder(): void
104+
{
105+
$config = new Database();
106+
$db = Database::connect('tests');
107+
108+
$seeder = new Seeder($config, $db);
109+
$seeder->setSilent(true)->call(SeederWithoutDBGroup::class);
110+
111+
$this->assertSame($db, SeederWithoutDBGroup::$lastConnection);
112+
}
113+
114+
public function testCallChildWithDBGroupUsesOwnConnection(): void
115+
{
116+
$config = new Database();
117+
$db = Database::connect('tests', false);
118+
119+
$seeder = new Seeder($config, $db);
120+
$seeder->setSilent(true)->call(SeederWithDBGroup::class);
121+
122+
$testsDb = Database::connect('tests');
123+
$this->assertSame($testsDb, SeederWithDBGroup::$lastConnection);
124+
$this->assertNotSame($db, SeederWithDBGroup::$lastConnection);
125+
}
60126
}

user_guide_src/source/changelogs/v4.6.5.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ Deprecations
3030
Bugs Fixed
3131
**********
3232

33+
- **Database:** Fixed a bug where ``Seeder::call()`` did not pass the database connection to child seeders, causing them to use the default connection instead of the one specified via ``Database::seeder('group')``.
34+
3335
See the repo's
3436
`CHANGELOG.md <https://github.com/codeigniter4/CodeIgniter4/blob/develop/CHANGELOG.md>`_
3537
for a complete list of bugs fixed.

user_guide_src/source/dbmgmt/seeds.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,29 @@ You can grab a copy of the main seeder through the database config class:
4444

4545
.. literalinclude:: seeds/004.php
4646

47+
Using a Different Database Group
48+
================================
49+
50+
You can specify a different database group when obtaining a seeder instance by passing the group name
51+
as the first parameter:
52+
53+
.. literalinclude:: seeds/005.php
54+
55+
When using ``call()`` to run child seeders, the database connection is automatically passed to them.
56+
This means child seeders will use the same connection as the parent seeder, unless they explicitly
57+
specify their own ``$DBGroup`` property.
58+
59+
If a seeder needs to always use a specific database group regardless of the parent seeder's connection,
60+
you can set the ``$DBGroup`` property in the seeder class:
61+
62+
.. literalinclude:: seeds/006.php
63+
64+
The connection priority is:
65+
66+
1. If ``$DBGroup`` is set in the seeder class, that connection group is always used
67+
2. Otherwise, if a connection was passed (from parent seeder via ``call()`` or from ``Database::seeder()``), it is used
68+
3. Otherwise, the default connection group is used
69+
4770
Command Line Seeding
4871
====================
4972

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?php
2+
3+
$seeder = \Config\Database::seeder('group_name');
4+
$seeder->call('TestSeeder');
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace App\Database\Seeds;
4+
5+
use CodeIgniter\Database\Seeder;
6+
7+
class UserSeeder extends Seeder
8+
{
9+
protected $DBGroup = 'group_name';
10+
11+
public function run()
12+
{
13+
// ...
14+
}
15+
}

0 commit comments

Comments
 (0)