Add database migrations, start fleshing out a specific database connection.

This commit is contained in:
Dave Smith-Hayes 2024-06-26 21:10:48 -04:00
parent 2d6dee2f0c
commit d05faaead7
8 changed files with 83 additions and 25 deletions

View File

@ -19,7 +19,7 @@ CREATE TABLE channels (
image_id INT(11) UNSIGNED NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY(`id`),
FOREIGN KEY(`owner_id`) REFERENCES users(`id`),
@ -56,6 +56,7 @@ final class CreateChannelsTable extends AbstractMigration
->addColumn('image_id', 'integer')
->addIndex([ 'name' ], [ 'unique' => true ])
->addForeignKey('owner_id', 'users')
->addForeignKey('image_id', 'images')
->create();
}
}

View File

@ -2,6 +2,8 @@
namespace Slovocast;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Slim\App;
use Slim\Factory\AppFactory;
@ -22,12 +24,14 @@ use Slovocast\Configuration\{
DatabaseConnectionSchema,
SessionSchema
};
use Twig\Error\LoaderError;
use Slovocast\Domain\Repository\{
UserRepositoryInterface,
UserRepository
};
use Slovocast\Infrastructure\{
DatabaseConnectionInterface,
PdoDatabaseConnection,
User\UserAuthorizationInterface,
User\BasicUserAuthorization
};
@ -38,7 +42,7 @@ use Monolog\Handler\StreamHandler;
use Monolog\Level;
use Odan\Session\PhpSession;
use Odan\Session\SessionInterface;
use Odan\Session\SessionManagerInterface;
use Odan\Session\SessionManagerInterface;
/**
* Defines here are used globally
@ -53,7 +57,7 @@ define('APP_TEMP_DIR', __DIR__ . '/../var/temp');
class Bootstrap
{
/**
* Pulls out all the configuration schemas and configuration values.
* Pulls out all the configuration schemas and configuration values.
*
* @return Configuration
*/
@ -77,6 +81,12 @@ class Bootstrap
],
'session' => [
'name' => 'slovocast'
],
'database' => [
'host' => '127.0.0.1',
'database' => 'slovocast',
'username' => 'slovocast',
'password' => 'Password01',
]
]);
@ -88,8 +98,9 @@ class Bootstrap
* initialization of configuration.
*
* @return Container
* @throws \Exception
*/
protected static function initContainer(): Container
protected static function initContainer(): Container
{
$containerBuilder = new ContainerBuilder();
@ -117,7 +128,7 @@ class Bootstrap
'flash' => function (ContainerInterface $container) {
return $container->get(SessionInterface::class)->getFlash();
},
/**
* Application DI
*/
@ -128,6 +139,20 @@ class Bootstrap
/**
* Database Connections
*/
DatabaseConnectionInterface::class => function(ContainerInterface $container) {
$databaseConfig = $container->get('config')->get('database');
$dsn = sprintf(
"%s:dbname=%s;host=%s",
$databaseConfig['driver'],
$databaseConfig['database'],
$databaseConfig['host']
);
$username = $databaseConfig['username'];
$password = $databaseConfig['password'];
$connection = new PdoDatabaseConnection($dsn, $username, $password);
return $connection;
},
/**
* Utility classes
@ -151,7 +176,7 @@ class Bootstrap
}
/**
* Tasking the instaniated Application, sets up all the routes for the
* Tasking the instantiated Application, sets up all the routes for the
* application.
*
* @param App $app
@ -169,6 +194,9 @@ class Bootstrap
* method.
*
* @param App $app
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws LoaderError
*/
protected static function establishMiddleware(App $app): void
{
@ -176,7 +204,7 @@ class Bootstrap
$container = $app->getContainer();
/**
* @var Configuration
* @var Configuration $config
*/
$config = $container->get('config');
@ -202,6 +230,10 @@ class Bootstrap
* Instantiates the application.
*
* @return App
* @throws ContainerExceptionInterface
* @throws LoaderError
* @throws NotFoundExceptionInterface
* @throws \Exception
*/
public static function init(): App
{

View File

@ -10,9 +10,9 @@ class DatabaseConnectionSchema
public static function getSchema(): Schema
{
return Expect::structure([
'driver' => Expect::anyOf('mysql', 'sqlite')->required(),
'driver' => Expect::anyOf('mysql', 'sqlite')->default('mysql'),
'host' => Expect::string()->default('localhost'),
'post' => Expect::int()->min(1)->max(65535),
'port' => Expect::int()->min(1)->max(65535)->default(3306),
'database' => Expect::string()->required(),
'username' => Expect::string()->required(),
'password' => Expect::string()->nullable()

View File

@ -0,0 +1,28 @@
<?php
namespace Slovocast\Controller;
use Slovocast\Controller\Controller;
use Slovocast\Infrastructure\DatabaseConnectionInterface;
use Psr\Http\Message\ResponseInterface as Response;
class HealthCheck extends Controller
{
public function __construct(
protected DatabaseConnectionInterface $connection
) { }
public function handle(): Response
{
/**
* @var PdoDatabaseConnection $this->connection
*/
$stmt = $this->connection->query("SELECT 1");
$dbResult = $stmt->fetch();
return $this->json([
'http' => true,
'database' => (bool) $dbResult[0]
]);
}
}

View File

@ -34,7 +34,7 @@ class UserRepository implements UserRepositoryInterface
/**
* @param string $query The Query for getting a User
* @param arary $params The parameters in the query
* @param array $params The parameters in the query
* @param PDO $connection The PDO connection
* @return array The column data from the Database
* @throws EntityNotFoundException The User does no exist
@ -83,8 +83,8 @@ class UserRepository implements UserRepositoryInterface
{
$query = "SELECT * FROM users WHERE email = :email LIMIT 1";
$userData = $this->queryForUser(
$query,
[ 'email' => $email ],
$query,
[ 'email' => $email ],
$this->database->getConnection()
);

View File

@ -2,14 +2,11 @@
namespace Slovocast\Infrastructure;
use PDO;
/**
* Represents an active connection to the Database through the PDO. Unlike a
* pool, these connections don't need to be returned.
*/
interface DatabaseConnectionInterface
{
public function getConnection(): PDO;
public function getName(): string;
}

View File

@ -8,20 +8,18 @@ use Slovocast\Infrastructure\DatabaseConnectionInterface;
/**
* Represents an active connection to a database
*/
class DatabaseConnection implements DatabaseConnectionInterface
class PdoDatabaseConnection extends PDO
implements DatabaseConnectionInterface
{
public function __construct(
private string $name,
private PDO $pdo
) { }
public function getConnection(): PDO
{
return $this->pdo;
}
protected string $name;
public function getName(): string
{
return $this->name;
}
public function setName(string $name): void
{
$this->name = $name;
}
}

View File

@ -4,6 +4,7 @@ namespace Slovocast;
use Slim\App;
use Slovocast\Controller\HomePage;
use Slovocast\Controller\HealthCheck;
use Slovocast\Controller\User\{
RegisterUserPage,
RegisterUserAction,
@ -20,6 +21,7 @@ class Routes
public static function init(App $app): void
{
$app->get('/', HomePage::class);
$app->get('/healthcheck', HealthCheck::class);
// User Routes
self::users($app);
}