单例 PDO 模型 - 层次结构

发布于 2025-01-06 09:17:23 字数 1919 浏览 2 评论 0原文

抱歉英语不好,我是巴西人,更糟糕的是谈论编程。 我们走吧。我有这个:

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 方法,例如查询或准备。据说即使我的 Model 类构造函数调用 getInstance,我也不会被称为 PDO 构造函数。

有可能吗?

Sorry for poor english, I'm Brazilian, and even worse talking about programming.
Let's go. I have this:

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

 }

and the model that extends the class DataBase:

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

But I can't use the $this variable to access the PDO methods like query OR prepare. It's says that I'm not called the PDO constructor, even if my Model class constructor call getInstance.

It's possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

把昨日还给我 2025-01-13 09:17:23

为了让你的例子工作,你可以尝试这个。

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();

To make your example work, you might try this.

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);

This is not tested. But it should give you an idea how to solve the problem.
Try this approach.

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();
万劫不复 2025-01-13 09:17:23

您的 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 中删除分配() 看看是否有效。

Something seems funny about your getInstance() method and your constructor both assigning to 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 );
        }

Remove the assignment from getInstance() and see if that works.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文