Модель PDO Singleton - Иерархия - PullRequest
3 голосов
/ 18 февраля 2012

Извините за плохой английский, я бразилец, и еще хуже говорю о программировании.Поехали.У меня есть это:

class DataBase extends PDO
{

/**
 * @var object PDO
 */
private static $instance;


/**
 * Cria uma instância do PDO representando a conexão ao banco de dados e torna a instância disponível como "singleton"
 *
 * @param string $dsn            O DSN completo, ex.: mysql:host=localhost;dbname=testdb
 * @param string $username       O nome de usuário para a string DSN. Esse parâmetro é opcional para alguns drivers do PDO.
 * @param string $password       A senha para a string DSN. Esse parâmetro é opcional para alguns drivers do PDO.
 * @param array  $driver_options Um array key => value de opções de conexão específicas do driver
 *
 * @return PDO
 */
public
function __construct()
{

    global $config;

    $dsn      = "mysql:dbname={$config['database'][AMBIENTE]['banco']};host={$config['database'][AMBIENTE]['url']}";
    $username = $config['database'][AMBIENTE]['usuario'];
    $password = $config['database'][AMBIENTE]['senha'];

    if ( !isset ( self::$instance ) )
    {
        try
        {
            self::$instance = parent::__construct( $dsn , $username , $password );
        }
        catch ( PDOException $e )
        {
            Functions::Log( 'Erro de conexão de banco de dados: ' . $e->getMessage() );
            header( 'HTTP/1.1 500 Internal Server Error' );
        }
    }

    $this->storage = new ArrayObject();

}

public static
function getInstance()
{
    if ( !self::$instance )
    {
        self::$instance = new DataBase;
    }

    return self::$instance;
}

 }

и модель, которая расширяет класс DataBase:

class Model extends DataBase
{
protected $TABLE_NAME;
protected $TABLE_PREFIX;
/* all logic here, like getters, setters and methods like update, delete and insert... */
}

Но я не могу использовать переменную $ this для доступа к методам PDO, таким как запрос ИЛИ подготовить,В нем говорится, что меня не называют конструктором PDO, даже если мой конструктор класса Model вызывает getInstance.

Возможно?

Ответы [ 2 ]

2 голосов
/ 18 февраля 2012

Чтобы ваш пример работал, вы можете попробовать это.

define('DB_CONN','mysql:dbname=;host=');
define('DB_USER', '');
define('DB_PASS', '');

interface iMySQL
{

    public
    function query( $string );

    public
    function select();

    public
    function selectAll();

    public
    function insert();

    public
    function update();

    public
    function delete();

    public
    function load();

}



class DataBase
{

    /**
     * @var object PDO
     */
    private static $instance = null;


    /**
     * Cria uma instância do PDO representando a conexão ao banco de dados e torna a instância disponível como "singleton"
     *
     * @param string $dsn            O DSN completo, ex.: mysql:host=localhost;dbname=testdb
     * @param string $username       O nome de usuário para a string DSN. Esse parâmetro é opcional para alguns drivers do PDO.
     * @param string $password       A senha para a string DSN. Esse parâmetro é opcional para alguns drivers do PDO.
     * @param array  $driver_options Um array key => value de opções de conexão específicas do driver
     *
     */
    private function __construct() {

    }

    public static function getInstance()
    {
        if ( self::$instance === null )
        {
            self::$instance = new PDO(DB_CONN, DB_USER, DB_PASS);
        }
        return self::$instance;
    }

}

class Model
{
    protected $TABLE_NAME;
    protected $TABLE_PREFIX;
    protected $clausula;

    private $storage;

    /**
     * Recupera um registro utilizando sua chave
     *
     * @param string $key
     *
     * @return mixed O valor armazenado
     * @throws RuntimeException Se não houver um registro para a chave especificada
     */
    public
    function __get( $key )
    {

    }

    /**
     * Registra um valor à uma chave
     *
     * @param string $key   A chave que será utilizada no registro
     * @param mixed  $value O valor que será registrado
     *
     * @throws LogicException Se a chave já estiver registrada
     */
    public
    function __set( $key , $value )
    {
        //echo $key;
    }


    public static
    function __callStatic( $method , $args )
    {

        $database = DataBase::getInstance();
        $callback = array( $database , $method );
        return call_user_func_array( $callback , $args );

    }

    public
    function __call( $method , $args )
    {

        $database = DataBase::getInstance();
        $callback = array( $database , $method );
        return call_user_func_array( $callback , $args );

    }

    public function __construct( $table_name = null , $id = null )
    {

        $this->TABLE_PREFIX = $this->config['database']['table_prefix'];
        $this->TABLE_NAME   = $this->TABLE_PREFIX . $table_name;

        $this->storage = new ArrayObject();

        if ( !is_null( $table_name ) )
        {
            $array = $this->query( "SHOW COLUMNS FROM `$this->TABLE_NAME`" )->fetchAll();

            $colunas      = array();
            $obrigatorias = array();

            foreach ( $array as $value )
            {
                $colunas[] = $value[0];
                if ( $value['Null'] === 'NO' )
                {
                    $obrigatorias[] = $value['Field'];
                }
            }

            $this->colunas       = $colunas;
            $this->obrigatorias  = $obrigatorias;
            $this->total_colunas = count( $this->colunas );

            // Se passou um id por parâmetro, salva nas propriedades do objeto
            if ( !is_null( $id ) AND is_numeric( $id ) )
            {
                $this->id = $id;

                // E já carrega o objeto
                $select = $this->query( 'SELECT * FROM {tabela_nome} WHERE `id` = ' . $id )->fetchObject();
                $this->load( $select );
            }
        }

    }

    public
    function insert()
    {
    }

    public
    function update()
    {
    }

    public
    function delete()
    {
    }

    public
    function select( $clausula = NULL , $is_array = FALSE )
    {
        // Caso seja passado uma cláusula diretamente para a função, executa ela
        if ( !is_null( $clausula ) )
        {
            $this->clausula = $clausula;
        }

        // Troca uma possível variável pelo nome da tabela do Model
        $this->clausula = ( str_replace( '{TABLE_NAME}' , $this->TABLE_NAME , $this->clausula ) );
        $this->clausula = ( str_replace( '{TABLE_PREFIX}' , $this->TABLE_PREFIX , $this->clausula ) );

        // Executa o SELECT no banco de dados
        $query = $this->query( $this->clausula );

        if ( $query AND $query->rowCount() > 0 )
        {

            if ( $query->rowCount() == 1 AND !$is_array )
            {
                return $query->fetchObject( get_class( $this ) );
            }
            else
            {
                $objetos = array();
                while ( $linha = $query->fetchObject( get_class( $this ) ) )
                {
                    $objetos[] = $linha;
                }
                return ( count( $objetos ) > 0 ) ? $objetos : FALSE;
            }
        }
        else
        {
            return FALSE;
        }
    }

    public
    function selectAll()
    {
    }

    public
    function load()
    {
    }
}



$model = new Model();
$stmt = $model->query();
$fetch = $stmt->fetchAll();
var_dump($fetch);

Это не проверено.Но это должно дать вам представление о том, как решить проблему.Попробуйте этот подход.

define('DB_TYPE', 'DB_Class_One');


class DB_Class_One extends PDO {
    public function getData() {
        print 'Class One';
    }
}

class DB_Class_Two extends PDO {
   public function getData() {
        print 'Class Two';
    }
}

class DB_Class_Three extends PDO {
   public function getData() {
        print 'Class Three';
    }
}

class DataBase {

    private static $instance = null;

    private function __construct() {

    }

    private function __clone() {

    }

    public static function getInstance() {
        $class = DB_TYPE;

        if (self::$instance === null) {
            self::$instance = new $class("mysql:host=;dbname=", '', '');
        }
        return self::$instance;
    }


}




$db = DataBase::getInstance();

$stmt = $db->query();

$result = $stmt->fetch();

$db->getData();
0 голосов
/ 18 февраля 2012

Что-то смешное в вашем getInstance() методе и , который ваш конструктор присваивает self::$instance:

function getInstance()
{
    if ( !self::$instance )
    {
        self::$instance = new DataBase;
    }

/* .... */

function __construct()
{

/* .... */

    if ( !isset ( self::$instance ) )
    {
        try
        {
            self::$instance = parent::__construct( $dsn , $username , $password );
        }

Удалите назначение из getInstance() и посмотрите, работает ли оно.

...