I'm building a Query Builder (for practice) and for that i needed a database connection, so i created this class:
/**
* Represents a mysql server connection
*/
class MySQLServerConnection implements Connection
{
/**
* @var null|PDO
*/
private $instance = null;
/**
* @var string The host the Connection should connect to
*/
private $host;
/**
* @var string The username to login into the name
*/
private $username;
/**
* @var string The password to login into the name
*/
private $password;
/**
* @var array
*/
private $attributes = [];
/**
* @param float $host
* @param string $username
* @param string $password
* @param array $attributes
*/
public final function __construct ($host, $username, $password, $attributes = []) {
$this->host = $host;
$this->username = $username;
$this->password = $password;
$this->attributes = $attributes;
}
/**
* @throws ConnectionException
*/
public final function initialize () {
if ($this->isInitialized()) {
throw new ConnectionException("Database connection isnt open yet.");
}
$this->instance = new PDO("mysql:host=$this->host;", $this->username, $this->password);
}
/**
* @return bool
*/
public function isInitialized () {
return $this->instance !== null;
}
/**
* Closes the connection
*
* @throws ConnectionException When the connection isn't open
*/
public final function terminate () {
if (!$this->isInitialized()) {
throw new ConnectionException("Database is closed");
}
$this->instance = null;
}
/**
* @return null|PDO
*/
public function getInstance () {
return $this->instance;
}
}
This initializes a connection to a mysql server (See it as XAMPP).
To make use of a database (with its functions) in the mysql server connection, i created another class:
/**
* Represents a database (with it's functions if its correctly set up)
*/
class Database
{
/**
* The mysql server we are connected to
*
* @var MySQLServerConnection $serverConnection The mysql server connection
*/
private static $serverConnection;
/**
* The name of the database we are currently using
*
* @var string $name The database name
*/
private static $name;
/**
* Sets up a database from a initialized MySQL server connection.
*
* @see MySQLServiceConnection
*
* @param MySQLServerConnection $serverConnection
* @param string $name
*
* @return $this|DatabaseStatements
*/
public static final function setup (MySQLServerConnection $serverConnection, $name) {
/*
* Check if the database server has not been initialized yet
*/
if (!$serverConnection->isInitialized()) {
throw new LogicException("Database can't be set up, the connection to the server isn't open yet.");
}
self::$serverConnection = $serverConnection;
self::$name = $name;
if (!empty($name)) {
self::__use($name);
}
/*
* Give access to database functions
*/
return new DatabaseStatements(new self);
}
/**
* Selects the database for usage where our tables are located
*
* @param string $databaseName The database name
*/
public function __use ($databaseName) {
if (!empty($databaseName)) {
self::$serverConnection->getInstance()
->exec("USE $databaseName");
}
}
/**
* @return MySQLServerConnection
*/
public function getServerConnection () {
return self::$serverConnection;
}
/**
* Gets the name of the selected database
*
* @return string The database name
*/
public function getName () {
return self::$name;
}
}
And used it with this piece of code:
$databaseConnection = new MySQLServerConnection("127.0.0.1", "root", "");
try {
$databaseConnection->initialize();
$database = Database::setup($databaseConnection, "phpmyadmin");
} catch (ConnectionException $e) {
}
The $database
object gives now access to the DatabaseStatements
class, where all the functions are.
/**
* Class DatabaseStatements
*
* Represents all the database statements
*/
class DatabaseStatements
{
/**
* @var Database $database Which database we are executing our functions on
*/
private $database;
/**
* @param \Database $database
*/
public final function __construct (Database $database) {
$this->database = $database;
}
/**
* Selects data out of the database
*
* @param array $data The data getting selected from the database
*
* @return \SelectStatement
*/
public function select ($data) {
return new SelectStatement($data);
}
......
}
}
My idea was when you call a function in the DatabaseStatements
class, you get returned to another class (SelectStatement
in this case). So the database functions are splitted over different classes.
class SelectStatement extends Statement
{
/**
* @var array $data The data which is getting selected
*/
private $data = [];
/**
* Select's specific columns from the database
*
* @param array $data The data which is getting selected
*/
public final function __construct (array $data) {
//....
return $this;
}
/**
* @param string $location
*
* @param bool $execute
*
* @return \Statement
*/
public function from ($location, $execute = false) {
// ...
return $this;
}
}
In this class are the other functions related to the SelectStatement
(such as from()
), and the ability to build and execute the query.
When the from()
function has been called, we have access to some other database functions such as join
or when
. (These are in the Statement
class.
class Statement
{
public function join (array $tables){
}
public function when ($condition) {
}
}
Now my problem is, i cant access the $database
variable in the SelectStatement
class, and it didn't seem like a good idea to pass that in as a variable inside the SelectStatement
constructor.
Questions
How do i get access to the
$database
variable inside the classes (which represent the functions such asSelect
) on a good way. (I thought passing it in as another variable was pretty bad)Is it good to split functionality over different classes?