方法链接覆盖变量

时间:2017-07-05 23:18:36

标签: php method-chaining

我已经实现了数据库的方法链接。我的问题是,当我调用Database类时,它会用新的变量覆盖变量。我怎样才能保留我的变量。这是我的代码。

当我使用此代码时:

Database::('table')
           ->set(['name', 'test'])
           ->select([
             Database::('table2')
                ->set(['name', 'test2')])
           ]);

它会覆盖$set上使用的Database::('table')->set变量,并覆盖新的Database::('table2')->set变量。

数据库类:

namespace VendorName;

class Database
{
    private static $reserved_words = [
        'NOW()', 'IS NOT NULL', 'IS NULL',
    ];

    private static $connection = null;
    private static $table = '';
    private static $join = '';
    private static $values = '';
    private static $set = '';
    private static $where = '';
    private static $show = null;
    private static $select = null;
    private static $order_by = '';
    private static $params = [];

    /**
     * Call the database table to be used.
     *
     * @param string $table
     */
    public static function table($table)
    {
        self::$table .= $table;

        return new static;
    }

    public static function set($set)
    {
        self::$set .= ' SET';

        $index = 0;

        foreach ($set as $value) {
            if ($index++ > 0) {
                self::$set .= ', ';
            }

            if (in_array($value[1], self::$reserved_words)) {
                self::$set .= " {$value[0]} = {$value[1]}";
            } else {
                self::$set .= " {$value[0]} = ?";
            }
        }

        if (self::checkColumn('updated_at') && self::checkColumn('updated_by')) {
            self::$set .= ', updated_at = NOW(), updated_by = ' . Authentication::getAuthenticatedUser();
        }

        self::$params = array_merge(self::$params, $set);

        return new static;
    }

    /**
     * Create a WHERE query based on given parameters.
     *
     * @param array $where
     */
    public static function where($where)
    {
        self::$where .= ' WHERE';

        $index = 0;

        foreach ($where as $value) {
            if ($index++ > 0) {
                self::$where .= ' AND';
            }

            if (in_array($value[1], self::$reserved_words)) {
                self::$where .= " {$value[0]} {$value[1]}";
            } else {
                self::$where .= " {$value[0]} {$value[1]} ?";
            }
        }

        self::$params = array_merge(self::$params, $where);

        return new static;
    }

    /**
     * select data from the database.
     *
     * @param array $columns
     */
    public static function select($columns = ['*'])
    {
        self::$select = self::$connection->prepare('SELECT ' . implode(',', $columns) . ' FROM ' . self::$table . self::$join . self::$where . self::$order_by . self::$show);

        $index = 1;

        foreach (self::$params as $key => $value) {
            if (!in_array($value[count($value) - 1], self::$reserved_words)) {
                self::$select->bindValue($index++, $value[count($value) - 1]);
            }
        }

        //echo 'SELECT ' . implode(',', $columns) . ' FROM ' . self::$table . self::$join . self::$where . self::$show;

        self::$select->execute();

        return new static;
    }

    /**
     * fetch data from the database.
     *
     * @return array
     */
    public static function fetch()
    {
        $result = self::$select->fetch();

        self::clean();

        return $result;
    }

    /**
     * fetch data as associative array from the database.
     *
     * @return array
     */
    public static function fetchAll()
    {
        $result = self::$select->fetchAll(\PDO::FETCH_ASSOC);

        self::clean();

        return $result;
    }
}

1 个答案:

答案 0 :(得分:0)

您似乎正在尝试实施Singleton pattern设计。在此设计中,类仅限于只有一个实例,由实例控制:

<?php

class Database {
    static private $singleton;
    private $data; // Some other data members...

    static public function getInstance() {
        if (!isset(self::$singleton)) {
            self::$singleton = new self; // works for derived classes also
        }

        return self::$singleton;
    }

    private function __construct() {
        // Do some useful initialization...
    }

    public function chainedOperation($param) {
        // Do some useful database operation...
        echo "I did something useful with '$param'." . PHP_EOL;

        return $this;
    }
}

Database::getInstance()->chainedOperation('apple')
                       ->chainedOperation('pear')
                       ->chainedOperation('php');

// I cannot create a Database instance conventionally.
// error: Call to private Database::__construct() from invalid context
// $db = new Database;