3

抽象シングルトンクラスである Database.php クラスがあります。

<?php

abstract class Database
{
    protected static $_instance;
    ...

    public static function instance()
    {
        $class = get_called_class();

        if (!self::$_instance) {
            self::$_instance = new $class();
        }

        return self::$_instance;
    }
}

?>

他のデータベースはこのクラスを拡張し、抽象関数を実装しているため、使用するデータベースを変更できますが、アプリケーションがこの抽象化レイヤーの関数を使用している限り、アプリケーションが引き続き機能することを確認できます (上記の関数定義は省略しています)。コード)。

PDO.php にクラス PDO があります。データベースを拡張し、上記と同じ関数も含めますが、独自の変数instance()はありません。$_instance

class PDO extends Database
{
    //...

    public static function instance()
    {
        $class = get_called_class();

        if (!self::$_instance) {
                self::$_instance = new $class();
        }

        return self::$_instance;
    }
}

instance()もともと、この関数はデータベースから継承されているため、PDO クラスに含める必要はないと考えていました。しかし、このエラーが発生していたので、それを含めました:

Fatal error: Call to undefined method PDO::instance()

問題は、上記のコードを使用しても、まだこのエラーが発生することです。これが関連しているかどうかはわかりませんが、別の奇妙なエラーが発生していました。使用したいデータベースのタイプ (この場合は PDO) は、 からアクセスできる変数に格納されますApp::setting('DB')。私の MVC フレームワークのモデル基本クラスは、適切なデータベース クラスをロードし、$this->_db. モデルのコードは次のとおりです。

<?php

require_once 'Databases/Database.php';

class Model
{
    protected $_db;

    public function __construct()
    {
        $database = App::setting('DB'); // 'PDO' 
        require_once 'Databases/' . $database . '.php';
        $this->_db = $database::instance(); // this is what triggers the error
    }
}

?>

このコードは、PDO クラスを再宣言できないというエラーを表示していました。オンラインで検索したところ、問題は通常、include()代わりにを使用することに関連していることがわかりましたrequire_once()。私はどこでもチェックしましたが、Autoloader には何も表示されませんでしinclude()た。上記のモデルでもrequire_once()、まだエラーが発生していました (これは、PDO クラスを必要としていた唯一の場所です...)。

そのエラーを修正するために、Model コンストラクターの require を次のように置き換える応急処置を使用しています。

if (!class_exists($database)) {
    require_once 'Databases/' . $database . '.php';
}

ここで何が起こっているのか誰でも説明できますか?

4

2 に答える 2

7

クラス名PDOは PHP の標準クラスであるため、自分のPDOクラスを含めるソリューションでは、実際には自分のクラスを含めることはありません。

于 2012-07-30T06:20:18.160 に答える
0

オートローディングを使用することをお勧めします。それはあなたの人生をよりシンプルにし、それらすべての電話を取り除くことができrequireます.

PHP マニュアルに実装があり、かなり便利だと思いました。次のようになります。

function my_autoloader($class) {
    include 'classes/' . $class . '.class.php';
}

spl_autoload_register('my_autoloader');

// Or, using an anonymous function as of PHP 5.3.0
spl_autoload_register(function ($class) {
    include 'classes/' . $class . '.class.php';
});

PHP 5.3 を使用している場合は、名前空間の使用も検討してください。実際には、優れた構造とデフォルトで実装されたシンプルなオートローダーを持つ方が簡単です:

spl_autoload_extensions(".php"); // comma-separated list
spl_autoload_register();

しかし、そこでバグを覚えています。通常、次のオートローダーを含む「ブートストラップ」ファイルがあります。

spl_autoload_register(function($class) {
    if(file_exists('./lib/' . str_replace('\\', '/', $class) . '.php')) {
        require_once './lib/' . str_replace('\\', '/', $class) . '.php';
    }
});

このメカニズムを使用すると、名前空間構造を模倣したフォルダー構造が得られます。このアプローチでは、適切な構造が得られ、ライブラリや他のクラスを含めることを気にする必要はありません。

于 2012-07-30T06:48:43.057 に答える