将对象从类传递给类

时间:2014-12-12 15:49:09

标签: php oop dependency-injection

我正在构建一个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'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;
    }
}

并将其与这段代码一起使用:

$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'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;
    }
}

在这个类中是与SelectStatement相关的其他函数(例如from()),以及构建和执行查询的能力。

调用from()函数后,我们可以访问其他一些数据库函数,例如joinwhen。 (这些都在Statement班。

class Statement
{

    public function join (array $tables){

    }

    public function when ($condition) {

    }
}

现在我的问题是,我无法访问$database类中的SelectStatement变量,并且将其作为变量传递到{{1}内部似乎不是一个好主意构造函数。

问题

  • 如何以良好的方式访问类中的SelectStatement变量(代表$database等函数)。 (我认为传递它作为另一个变量非常糟糕)

  • 将功能划分到不同的类别是否合适?

1 个答案:

答案 0 :(得分:0)

<?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's 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)