3

I'm working on a project which is using Unit of work design pattern. It includes Storage,EntityCollection,..... Code of unit of work includes PDO Adapter code file. But the adapter is not complete for running queries. I have found the files from somewhere. I can't build queries what I want. Every time I'm writing code I faces to many problems related query. So can you please help me to make it more flexible... For example i want to run like : $db->select()->where('id>:id')->andWhere('')->orWHere()->orderBy()->groupBy()->having()->fetch()/fetchOne(); or similar to it.

<?php

namespace D\Adapter;

class PdoAdapter implements \D\DB\DatabaseInterface {

    protected $config = array();
    protected $database;
    protected $connection;
    protected $statement;
    protected $fetchMode = \PDO::FETCH_ASSOC;

    public function __construct($dsn, $username = null, $password = null, array $driverOptions = array()) {
        $this->config = compact("dsn", "username", "password", "driverOptions");
        $this->database = $driverOptions['db_name'];
    }

    public function getStatement() {
        if ($this->statement === null) {
            throw new \PDOException(
            "There is no PDOStatement object for use.");
        }
        return $this->statement;
    }

    public function connect() {
        // if there is a PDO object already, return early
        if ($this->connection) {
            return;
        }

        try {
            $this->connection = new \PDO(
                    $this->config["dsn"], $this->config["username"], $this->config["password"], $this->config["driverOptions"]);
            $this->connection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
            $this->connection->setAttribute(
                    \PDO::ATTR_EMULATE_PREPARES, false);
        } catch (\PDOException $e) {
            throw new \RunTimeException($e->getMessage());
        }
    }

    public function disconnect() {
        $this->connection = null;
    }

    public function prepare($sql, array $options = array()) {
        $this->connect();

        try {
            $this->statement = $this->connection->prepare($sql, $options);

            return $this;
        } catch (\PDOException $e) {
            throw new \RunTimeException($e->getMessage());
        }
    }

    public function execute(array $parameters = array()) {

        try {
            $this->getStatement()->execute($parameters);
            return $this;
        } catch (\PDOException $e) {
            throw new \RunTimeException($e->getMessage());
        }
    }

    public function countAffectedRows() {
        try {
            return $this->getStatement()->rowCount();
        } catch (\PDOException $e) {
            throw new \RunTimeException($e->getMessage());
        }
    }

    /**
     * countAffectedRows iin Alias
     */
    public function count() {
        try {
            return $this->getStatement()->rowCount();
        } catch (\PDOException $e) {
            throw new \RunTimeException($e->getMessage());
        }
    }

    public function getLastInsertId($name = null) {
        $this->connect();
        return $this->connection->lastInsertId($name);
    }

    public function fetch($fetchStyle = null, $cursorOrientation = null, $cursorOffset = null) {
        if ($fetchStyle === null) {
            $fetchStyle = $this->fetchMode;
        }

        try {
            return $this->getStatement()->fetch($fetchStyle, $cursorOrientation, $cursorOffset);
        } catch (\PDOException $e) {
            throw new \RunTimeException($e->getMessage());
        }
    }

    public function fetchAll($fetchStyle = null, $column = 0) {
        if ($fetchStyle === null) {
            $fetchStyle = $this->fetchMode;
        }

        try {
            return $fetchStyle === \PDO::FETCH_COLUMN ? $this->getStatement()->fetchAll($fetchStyle, $column) : $this->getStatement()->fetchAll($fetchStyle);
        } catch (\PDOException $e) {
            throw new \RunTimeException($e->getMessage());
        }
    }

    public function select($table, $bind = array(), $where = "", $options = array()) {
        if (count($bind) > 0) {
            foreach ($bind as $col => $value) {
                unset($bind[$col]);
                $bind[":" . $col] = $value;
            }
        }
        if (isset($options['fields'])) {
            $fields = $options['fields'];
        } else {
            $fields = '*';
        }
        $sql = "SELECT " . $fields . " FROM " . $table . " ";

        if (strlen($where) > 2) {
            $sql .= "WHERE " . $where;
        }

//        set_flash($sql);
        $this->prepare($sql)
                ->execute($bind);

        return $this;
    }

    public function query($sql, array $bind = array()) {
        if (is_array($bind)) {
            foreach ($bind as $col => $value) {
                unset($bind[$col]);
                $bind[":" . $col] = $value;
            }
        }

        $this->prepare($sql)
                ->execute($bind);
        return $this;
    }

    public function insert($table, array $bind) {
        $cols = implode(", ", array_keys($bind));
        $values = implode(", :", array_keys($bind));
        foreach ($bind as $col => $value) {
            unset($bind[$col]);
            $bind[":" . $col] = $value;
        }

        $sql = "INSERT INTO " . $table
                . " (" . $cols . ")  VALUES (:" . $values . ")";
        return (int) $this->prepare($sql)
                        ->execute($bind)
                        ->getLastInsertId();
    }

    public function update($table, array $bind, $where = "") {
        $set = array();
        foreach ($bind as $col => $value) {
            unset($bind[$col]);
            $bind[":" . $col] = $value;
            $set[] = $col . " = :" . $col;
        }

        $sql = "UPDATE " . $table . " SET " . implode(", ", $set)
                . (($where) ? " WHERE " . $where : " ");
        return $this->prepare($sql)
                        ->execute($bind)
                        ->countAffectedRows();
    }

    public function delete($table, $where = "") {
        $sql = "DELETE FROM " . $table . (($where) ? " WHERE " . $where : " ");
        return $this->prepare($sql)
                        ->execute()
                        ->countAffectedRows();
    }

    public function fetchAllTables() {
        $sql = "SHOW TABLES FROM " . $this->database;
        $this->prepare($sql)
                ->execute();

        return $this;
    }

    public function fetchAllFields($table) {
        $sql = "SHOW FIELDS FROM " . $table;
        $this->prepare($sql)
                ->execute();

        return $this;
    }

}

---FULL code is here--- https://github.com/batmunkhcom/mbm/tree/master/src/D

Batmunkh Moltov
  • 121
  • 2
  • 8

1 Answers1

4

First of all the concern of an UnitOfWork Pattern is to track everything you do during a business transaction that can affect the database. After transactions, it figures out everything that needs to be done to alter the database as a result of your work. Your class has other concerns.

It looks like a godclass (antipattern). It has more than one responsibility: Connection, PeparedStatement, Execution, and other helpers. Its quite difficult to scale and maintain. Try to split all responsibilities to different classes in SOLID way with corresponding design pattern.

Your idea faced in your code is already done by other frameworks. Its very hard work to implement it again. For example you can try Doctrine ORM/DBAL Framework.

Mamuz
  • 1,730
  • 12
  • 14
  • https://github.com/batmunkhcom/mbm/tree/master/src/D here is my full package list. unitof work is from somewhere in internet. I didn't want to use Doctrine or other framework. If pdo adapter is well and good integrated I can write other adapters easily. I found http://www.phpclasses.org/package/7974-PHP-Perform-SQL-database-access-operations-using-PDO.html nice pdo adapter. but it's hard to integrated to unitofwork... – Batmunkh Moltov Jan 18 '14 at 13:00
  • 1
    http://stackoverflow.com/questions/267629/whats-your-experience-with-doctrine-orm – Mamuz Jan 18 '14 at 13:05