1

私は現在、HMVCデザインパターンを使用した学習演習として、独自のPHPフレームワークを作成しています。それはすべて機能します:)が、PHPコードで静的クラスを参照するのは悪い習慣だと何度も読んだことがあります。これは、autoload関数で行っていることとまったく同じです。

function __autoload($className) {
    $path = SERVER_ROOT . DS . 'applications' . DS . Dispatcher::getApplicationName() . DS . 'models' . DS . 'class.' . strtolower($className) . '.php';

    if (file_exists($path)) {
        require_once($path);
    } else {
        throw new Exception('Can\'t find a model at "' . $path . '".');
    }
}

ご覧のとおり、静的呼び出しを使用して現在のアプリケーションを取得しますDispatcher::getApplicationName()。これは、依存関係を導入するため、多くの人にとっては悪いことです。debug_backtrace()モデルを開始するクラスにはApplicationNameがプロパティとして含まれているため、を使用してapplicationNameを取得することもできます。それは良いですか、それとも私が考えていなかった他の選択肢がありますか?

ありがとう!

編集:上記のコードには別の問題があることを忘れてしまいました。HMVCデザインパターンを使用しているため、コントローラーのアプリケーションがディスパッチャーのアプリケーションと常に一致するとは限りません(コントローラーはコントローラー内と呼ばれます)。これは、を使用してのみ修正できますdebug_backtrace

Dispatcher::getApplicationName()編集:私が今使用する代わりにRequest::getCurrentApplicationName()。リクエストクラスがすべてのアプリケーションを保存するため、再び機能するようになりました。これは良いですか、それとももっと良い方法がありますか?

<?php

class Request {
    private static $_controllers = array();
    private static $_applicationsNames = array();

    public static function _getCurrentApplicationName() {
        return end(self::$_applicationsNames);
    }

    public static function _load($applicationName, $controllerName, $methodName) {
        // Add the application the the array (for autoloading).
        self::$_applicationsNames[] = $applicationName;

        // Check if the controller has already been instantiated.
        if (!isset(self::$_controllers[$applicationName . DS . $controllerName])) {
            require_once(APPLICATIONS_ROOT . DS . $applicationName . DS . 'controllers' . DS . 'class.' . $controllerName . '.php');
            self::$_controllers[$applicationName . DS . $controllerName] = new $controllerName($applicationName);
        }

        // Get the user arguments.
        $arguments = array_slice(func_get_args(), 3);

        // Call the method.
        $result = call_user_func_array(array(self::$_controllers[$applicationName . DS . $controllerName], $methodName), $arguments);

        // Remove the last value from the applications array.
        array_pop(self::$_applicationsNames);
    }
}
4

2 に答える 2

2

起動時に、必要なすべての情報を含むautoloadクラスの静的メンバーを設定することはできませんか?

debug_backtrace()は、信頼できる情報源にはなり得ません。誰かがあなたのライブラリオートローダーを使いたいが、開始レイヤーの1つがない場合はどうなりますか?そのようにすることは可能でしょうか?

クラス/関数で使用されるすべてのデータは、そのクラス内に配置するか、関数のパラメーターとして配置する必要があります。オートローダーは任意のコールバックになる可能性があるため、次のように実行できます。

class FrameworkAutoloader
{
    public $appName;
    public $path;

    public function setAppName($name) { $this->appName = $name; }
    public function setPath($path) { $this->path= $path; }


    function __autoload($className) {
        $path = $this->path. DS . 'applications' . DS . $this->appName . DS . 'models' . DS . 'class.' . strtolower($className) . '.php';

        if (file_exists($path)) {
             require_once($path);
        } else {
             throw new Exception('Can\'t find a model at "' . $path . '".');
        }
    }
}

$autoloader = new FrameworkAutoloader();
$autoloader->setAppName('asd'); //you can also apply those within constructor, but leave setters
$autoloader->setPath('asd');
spl_autoload_register(array($autoloader, '__autoload'));

それで全部です。セッターを使用してオブジェクトの変数を変更するだけで、パスとアプリ名を動的に設定できます。

なぜ私たちはこのようにする必要がありますか?このコードでは、「魔法」はありません。PHPDOCを使用してすべての関数にドキュメントを書くことができ、ユーザーはすべてのパラメーターがどこから来ているかを知ることができます。もう1つの利点は、このコードをどこでも使用できることです。クラスがDispatcher :: getApplicationName()を使用していることを知る必要はありません。

于 2011-08-06T23:50:58.600 に答える
0

APPLICATION_ROOTアプリケーションをブートストラップするファイルに定義を設定することを検討します。これは、だけでなく、常に利用できるようにしておくと便利です__autoload

于 2011-08-06T22:51:58.120 に答える