Я создаю Query Builder (для практики), и для этого мне нужно подключение к базе данных, поэтому я создал этот класс:
/**
* 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;
}
}
Это инициализирует соединение с сервером mysql (см. Его как XAMPP).
Чтобы использовать базу данных (с ее функциями) в подключении сервера mysql, я создал другой класс:
/**
* Represents a database (with it 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;
}
}
И использовал его с этим фрагментом кода:
$databaseConnection = new MySQLServerConnection("127.0.0.1", "root", "");
try {
$databaseConnection->initialize();
$database = Database::setup($databaseConnection, "phpmyadmin");
} catch (ConnectionException $e) {
}
Объект $database
теперь дает доступ к классу DatabaseStatements
, где находятся все функции.
/**
* 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);
}
......
}
}
Моя идея заключалась в том, что когда вы вызываете функцию в классе DatabaseStatements
, вы возвращаетесь к другому классу (в этом случае SelectStatement
). Таким образом, функции базы данных разделены на разные классы.
class SelectStatement extends Statement
{
/**
* @var array $data The data which is getting selected
*/
private $data = [];
/**
* Select 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;
}
}
В этом классе находятся другие функции, связанные с SelectStatement
(например, from()
), а также возможность создания и выполнения запроса.
Когда функция from()
была вызвана, у нас есть доступ к некоторым другим функциям базы данных, таким как join
или when
. (Они находятся в классе Statement
.
class Statement
{
public function join (array $tables){
}
public function when ($condition) {
}
}
Теперь моя проблема заключается в том, что я не могу получить доступ к переменной $database
в классе SelectStatement
, и было бы неплохо передать это как переменную внутри конструктора SelectStatement
.
Вопросов
Как получить доступ к переменной $database
внутри классов (которые представляют такие функции, как Select
), на хорошем пути. (Я думал, что передать его в качестве другой переменной было довольно плохо)
Хорошо ли разделить функциональность на разные классы?
<?php
/**
* Class DatabaseStatements
*
* Represents all the database statements
*/
class DatabaseStatements
{
/**
* @var Database $database Which database we are executing our functions on
*/
private $database;
public $selectStatement;
/**
* @param \Database $database
*/
public final function __construct ($database) {
$this->database = $database;
$this->selectStatement = new SelectStatement();
}
/**
* Selects data out of the database
*
* @param array $data The data getting selected from the database
*
* @return \SelectStatement
*/
}
class SelectStatement extends Statement
{
/**
* @var array $data The data which is getting selected
*/
private $data = [];
/**
* Select specific columns from the database
*
* @param array $data The data which is getting selected
*/
public function select (array $data) {
$this->data['select'] = $data[0];
return $this;
}
/**
* @param string $location
*
* @param bool $execute
*
* @return \Statement
*/
public function from ($location, $execute = false) {
$this->data['from'] = $location;
return $this;
}
}
class Statement
{
public function join (array $tables){
}
public function when ($condition) {
}
}
$DatabaseStatements = new DatabaseStatements('database object');
$DatabaseStatements->selectStatement->select(array('test'))->from('table');
var_dump($DatabaseStatements);
Результат:
object(DatabaseStatements)[1]
private 'database' => string 'database object' (length=15)
public 'selectStatement' =>
object(SelectStatement)[2]
private 'data' =>
array (size=2)
'select' => string 'test' (length=4)
'from' => string 'table' (length=5)
return new SelectStatement($data);
а не$this->selectStatement= SelectStatement($data);
? если вы делаете это в SelectStatement, вы можете использовать $ this-> database