Skip to content

Commit 15266e8

Browse files
committed
Progress on mysqli specific querybuilder
1 parent 5c65c36 commit 15266e8

File tree

2 files changed

+150
-0
lines changed

2 files changed

+150
-0
lines changed

config/mysqli/config.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
return [
4+
'connection' => [
5+
'driver' => 'mysql',
6+
'host' => $_ENV['DB_HOST_MYSQL'] ?? $_ENV['DB_HOST'] ?? '127.0.0.1',
7+
'port' => (int) ($_ENV['DB_PORT_MYSQL'] ?? $_ENV['DB_PORT'] ?? 3306),
8+
'database' => $_ENV['DB_DATABASE_MYSQL'] ?? $_ENV['DB_DATABASE'] ?? 'test',
9+
'username' => $_ENV['DB_USERNAME_MYSQL'] ?? $_ENV['DB_USERNAME'] ?? 'root',
10+
'password' => $_ENV['DB_PASSWORD_MYSQL'] ?? $_ENV['DB_PASSWORD'] ?? '',
11+
'charset' => 'utf8mb4',
12+
'socket' => $_ENV['DB_SOCKET_MYSQL'] ?? $_ENV['DB_SOCKET'] ?? '',
13+
],
14+
15+
'pool_size' => (int) ($_ENV['DB_POOL_SIZE'] ?? 20),
16+
];

src/Config/MysqliConfigLoader.php

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<?php
2+
3+
namespace Rcalicdan\FiberAsync\Config;
4+
5+
use Dotenv\Dotenv;
6+
use Exception;
7+
8+
/**
9+
* A singleton configuration loader that automatically finds the project root.
10+
*
11+
* It searches upwards from its directory to locate the project root (identified
12+
* by a 'vendor' folder), loads the .env and config files from config/mysqli,
13+
* and then caches the results to ensure the expensive search happens only once.
14+
*/
15+
final class MysqliConfigLoader
16+
{
17+
private static ?self $instance = null;
18+
private ?string $rootPath = null;
19+
20+
/** @var array<string, mixed> */
21+
private array $config = [];
22+
23+
/**
24+
* The constructor is private to enforce the singleton pattern.
25+
* It performs the entire one-time loading process.
26+
*/
27+
private function __construct()
28+
{
29+
$this->rootPath = $this->findProjectRoot();
30+
31+
if ($this->rootPath !== null) {
32+
$this->loadDotEnv();
33+
$this->loadConfigFiles();
34+
}
35+
}
36+
37+
/**
38+
* Gets the singleton instance of the loader.
39+
*/
40+
public static function getInstance(): self
41+
{
42+
if (self::$instance === null) {
43+
self::$instance = new self;
44+
}
45+
46+
return self::$instance;
47+
}
48+
49+
/**
50+
* Resets the singleton instance, primarily for testing.
51+
*/
52+
public static function reset(): void
53+
{
54+
self::$instance = null;
55+
}
56+
57+
/**
58+
* Retrieves a configuration array by its key (the filename).
59+
* e.g., get('database') loads and returns config/mysqli/database.php
60+
*
61+
* @param mixed $default
62+
* @return mixed
63+
*/
64+
public function get(string $key, $default = null)
65+
{
66+
return $this->config[$key] ?? $default;
67+
}
68+
69+
/**
70+
* Searches upwards from the current directory to find the project root.
71+
* The root is identified by the presence of a `vendor` directory.
72+
* This operation is memoized (cached) for performance.
73+
*/
74+
private function findProjectRoot(): ?string
75+
{
76+
$dir = __DIR__;
77+
for ($i = 0; $i < 10; $i++) {
78+
if (is_dir($dir . '/vendor')) {
79+
return $dir;
80+
}
81+
82+
$parentDir = dirname($dir);
83+
if ($parentDir === $dir) {
84+
return null;
85+
}
86+
$dir = $parentDir;
87+
}
88+
89+
return null;
90+
}
91+
92+
private function loadDotEnv(): void
93+
{
94+
if ($this->rootPath === null) {
95+
throw new Exception('Root path not found, cannot load .env file');
96+
}
97+
98+
$envFile = $this->rootPath . '/.env';
99+
100+
if (file_exists($envFile)) {
101+
file_get_contents($envFile);
102+
103+
try {
104+
$dotenv = Dotenv::createImmutable($this->rootPath);
105+
$dotenv->load();
106+
} catch (\Throwable $e) {
107+
throw new Exception("Error loading .env file: {$e->getMessage()}");
108+
}
109+
} else {
110+
throw new Exception("Env file not found at: $envFile");
111+
}
112+
}
113+
114+
/**
115+
* Loads all .php files from the project root's /config/mysqli directory.
116+
*/
117+
private function loadConfigFiles(): void
118+
{
119+
if ($this->rootPath === null) {
120+
throw new Exception('Root path not found, cannot load config files');
121+
}
122+
123+
$configDir = $this->rootPath . '/config/mysqli';
124+
if (is_dir($configDir)) {
125+
$files = glob($configDir . '/*.php');
126+
if ($files !== false) {
127+
foreach ($files as $file) {
128+
$key = basename($file, '.php');
129+
$this->config[$key] = require $file;
130+
}
131+
}
132+
}
133+
}
134+
}

0 commit comments

Comments
 (0)