diff --git a/config/config.example.ini b/config/config.example.ini index 8b137891..3c45f302 100644 --- a/config/config.example.ini +++ b/config/config.example.ini @@ -1 +1,42 @@ +; Example configuration for Misuzu +[Database] +default = mysql_example +connections = mysql_example sqlite_example postgres_example sqlsrv_example + +[Database.mysql_example] +driver = mysql +host = localhost +port = 3306 +username = username +password = password +prefix = prefix_ +database = database +charset = utf8mb4 +collation = utf8mb4_bin + +[Database.sqlite_example] +driver = sqlite_example +database = store/database.db3 +prefix = + +[Database.postgres_example] +driver = pgsql +host = localhost +port = 5432 +username = username +password = password +prefix = prefix_ +database = database +charset = utf8 +schema = public + +[Database.sqlsrv_example] +driver = sqlsrv +host = localhost +port = 1433 +username = username +password = password +prefix = prefix_ +database = database +charset = utf8 diff --git a/misuzu.php b/misuzu.php index 3bc00b0b..adb1b838 100644 --- a/misuzu.php +++ b/misuzu.php @@ -3,6 +3,6 @@ namespace Misuzu; require_once 'vendor/autoload.php'; -$app = Application::start(); +$app = Application::start(__DIR__ . '/config/config.ini'); $app->debug(IO\Directory::exists(__DIR__ . '/vendor/phpunit/phpunit')); $app->router->add(include_once __DIR__ . '/routes.php'); diff --git a/src/Application.php b/src/Application.php index 613d3d25..c57433c1 100644 --- a/src/Application.php +++ b/src/Application.php @@ -17,13 +17,13 @@ class Application return static::$instance; } - public static function start(): Application + public static function start(...$params): Application { if (!is_null(static::$instance) || static::$instance instanceof Application) { throw new \Exception('An Application has already been set up.'); } - static::$instance = new Application; + static::$instance = new Application(...$params); return static::getInstance(); } @@ -61,10 +61,17 @@ class Application protected function __construct($configFile = null) { ExceptionHandler::register(); + $this->debug(true); + $this->addModule('config', $config = new ConfigManager($configFile)); + $this->addModule('database', new Database( + $config, + $config->get('Database', 'default', 'string', 'default') + )); $this->addModule('router', $router = new RouteCollection); $this->addModule('templating', $twig = new TemplateEngine); - $this->addModule('config', $config = new ConfigManager($configFile)); + + $this->loadConfigDatabaseConnections(); $twig->addFilter('json_decode'); $twig->addFilter('byte_symbol'); @@ -79,9 +86,35 @@ class Application public function __destruct() { + if ($this->hasConfig) { + $this->config->save(); + } + ExceptionHandler::unregister(); } + private function loadConfigDatabaseConnections(): void + { + $config = $this->config; + $database = $this->database; + + if ($config->contains('Database', 'connections')) { + $connections = explode(' ', $config->get('Database', 'connections')); + + foreach ($connections as $name) { + $section = 'Database.' . $name; + + if (!$config->contains($section)) { + continue; + } + + $database->addConnectionFromConfig($section, $name); + } + } else { + throw new \Exception('No database connections have been configured.'); + } + } + public function debug(bool $mode): void { ExceptionHandler::debug($mode); diff --git a/src/Controllers/HomeController.php b/src/Controllers/HomeController.php index 5222a5ff..c19d8843 100644 --- a/src/Controllers/HomeController.php +++ b/src/Controllers/HomeController.php @@ -2,12 +2,14 @@ namespace Misuzu\Controllers; use Misuzu\Application; +use Misuzu\Database; class HomeController extends Controller { public function index(): string { - $twig = Application::getInstance()->templating; + $app = Application::getInstance(); + $twig = $app->templating; return $twig->render('home.landing'); } diff --git a/src/Database.php b/src/Database.php new file mode 100644 index 00000000..e658e61b --- /dev/null +++ b/src/Database.php @@ -0,0 +1,129 @@ +configManager = $config; + parent::__construct(); + + $this->container['config']['database.default'] = $default; + + if ($startEloquent) { + $this->bootEloquent(); + } + + if ($setAsGlobal) { + $this->setAsGlobal(); + } + } + + public function addConnectionFromConfig(string $section, string $name = 'default'): void + { + if (!$this->configManager->contains($section, 'driver')) { + throw new \Exception('Config section not found!'); + } + + $driver = $this->configManager->get($section, 'driver'); + + if (!in_array($driver, self::SUPPORTED_DB_ALS)) { + throw new \Exception('Unsupported driver.'); + } + + $args = [ + 'driver' => $driver, + 'database' => $this->configManager->get($section, 'database', 'string', 'misuzu'), + 'prefix' => $this->configManager->get($section, 'prefix', 'string', ''), + ]; + + switch ($driver) { + case 'mysql': + $is_unix_socket = $this->configManager->contains($section, 'unix_socket'); + + $args['host'] = $is_unix_socket + ? '' + : $this->configManager->get($section, 'host', 'string', '127.0.0.1'); + + $args['port'] = $is_unix_socket + ? 3306 + : $this->configManager->get($section, 'port', 'int', 3306); + + $args['username'] = $this->configManager->get($section, 'username', 'string'); + $args['password'] = $this->configManager->get($section, 'password', 'string'); + $args['unix_socket'] = $is_unix_socket + ? $this->configManager->get($section, 'unix_socket', 'string') + : ''; + + // these should probably be locked to these types + $args['charset'] = $this->configManager->contains($section, 'charset') + ? $this->configManager->get($section, 'charset', 'string') + : 'utf8mb4'; + + $args['collation'] = $this->configManager->contains($section, 'collation') + ? $this->configManager->get($section, 'collation', 'string') + : 'utf8mb4_bin'; + + $args['strict'] = true; + $args['engine'] = null; + break; + + case 'pgsql': + $is_unix_socket = $this->configManager->contains($section, 'unix_socket'); + + $args['host'] = $is_unix_socket + ? '' + : $this->configManager->get($section, 'host', 'string', '127.0.0.1'); + + $args['port'] = $is_unix_socket + ? 5432 + : $this->configManager->get($section, 'port', 'int', 5432); + + $args['username'] = $this->configManager->get($section, 'username', 'string'); + $args['password'] = $this->configManager->get($section, 'password', 'string'); + + $args['unix_socket'] = $is_unix_socket + ? $this->configManager->get($section, 'unix_socket', 'string') + : ''; + + // these should probably be locked to these types + $args['charset'] = $this->configManager->contains($section, 'charset') + ? $this->configManager->get($section, 'charset', 'string') + : 'utf8'; + + $args['schema'] = 'public'; + $args['sslmode'] = 'prefer'; + break; + + case 'sqlsrv': + $args['host'] = $this->configManager->get($section, 'host', 'string', '127.0.0.1'); + $args['port'] = $this->configManager->get($section, 'port', 'int', 1433); + $args['username'] = $this->configManager->get($section, 'username', 'string'); + $args['password'] = $this->configManager->get($section, 'password', 'string'); + + // these should probably be locked to these types + $args['charset'] = $this->configManager->contains($section, 'charset') + ? $this->configManager->get($section, 'charset', 'string') + : 'utf8'; + break; + } + + $this->addConnection($args, $name); + } +}