Skip to content

Commit 45373b5

Browse files
committed
fix: make seeder to respect database group
1 parent 4da485d commit 45373b5

File tree

8 files changed

+227
-6
lines changed

8 files changed

+227
-6
lines changed

system/Database/Seeder.php

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,27 @@
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+
$instances = Database::getConnections();
34+
unset($instances['default']);
35+
$this->setPrivateProperty(Database::class, 'instances', $instances);
36+
37+
SeederWithDBGroup::reset();
38+
SeederWithoutDBGroup::reset();
39+
}
40+
2741
public function testInstantiateNoSeedPath(): void
2842
{
2943
$this->expectException('InvalidArgumentException');
@@ -57,4 +71,61 @@ public function testCallOnEmptySeeder(): void
5771
$seeder = new Seeder(new Database());
5872
$seeder->call('');
5973
}
74+
75+
public function testSeederWithDBGroupUsesOwnConnection(): void
76+
{
77+
$config = new Database();
78+
$db = Database::connect('default');
79+
80+
$seeder = new SeederWithDBGroup($config, $db);
81+
82+
// Should use 'tests' connection (from DBGroup), not the passed 'default' connection
83+
$testsDb = Database::connect('tests');
84+
$this->assertSame($testsDb, $seeder->getDatabase());
85+
$this->assertNotSame($db, $seeder->getDatabase());
86+
}
87+
88+
public function testSeederWithoutDBGroupUsesPassedConnection(): void
89+
{
90+
$config = new Database();
91+
$db = Database::connect('tests');
92+
93+
$seeder = new SeederWithoutDBGroup($config, $db);
94+
95+
$this->assertSame($db, $seeder->getDatabase());
96+
}
97+
98+
public function testSeederWithoutDBGroupAndNoConnectionUsesDefault(): void
99+
{
100+
$config = new Database();
101+
102+
$seeder = new SeederWithoutDBGroup($config);
103+
104+
$defaultDb = Database::connect($config->defaultGroup);
105+
$this->assertSame($defaultDb, $seeder->getDatabase());
106+
}
107+
108+
public function testCallPassesConnectionToChildSeeder(): void
109+
{
110+
$config = new Database();
111+
$db = Database::connect('tests');
112+
113+
$seeder = new Seeder($config, $db);
114+
$seeder->setSilent(true)->call(SeederWithoutDBGroup::class);
115+
116+
$this->assertSame($db, SeederWithoutDBGroup::$lastConnection);
117+
}
118+
119+
public function testCallChildWithDBGroupUsesOwnConnection(): void
120+
{
121+
$config = new Database();
122+
$db = Database::connect('default');
123+
124+
$seeder = new Seeder($config, $db);
125+
$seeder->setSilent(true)->call(SeederWithDBGroup::class);
126+
127+
$testsDb = Database::connect('tests');
128+
$this->assertSame($testsDb, SeederWithDBGroup::$lastConnection);
129+
$this->assertNotSame($db, SeederWithDBGroup::$lastConnection);
130+
}
60131
}

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)