3

PHP __autoload 関数をできるだけ防弾で柔軟に定義しようとしています。

私のアプリケーションの構造の内訳は次のとおりです。

/dev (root)
    /my_app
        /php
            /classes
                - Class1.php
                - Class2.php
                - Class3.php
        /scripts
            myscript.php (the file I have to include the classes in)

それはかなり簡単です。私の問題は次のとおりです。呼び出し元のファイルがディレクトリ構造内でどれほど深くネストされているかに関係なく、必要なクラスを含めることができるように、__autoload 関数をどのように記述すればよいでしょうか。__FILE__realpathおよび関数と関係があることは知っていますがdirname、それらを組み合わせて私が求めている柔軟性を実現する適切な方法については確信が持てません。

これが私が行った簡単なテストです:

<?php
echo realpath(dirname(__FILE__)) . "/php/classes/Class1.php";
?>

結果:

/home/mydirectory/dev.mysite.com/my_app/php/scripts/php/classes/Class1.php

ご覧のとおり、結果はクラスが配置されている場所と一致しません。ただし、myscript.php ファイルを /my_app フォルダーに移動すると、正しく印刷されます。

これをより柔軟にするための提案はありますか?

4

4 に答える 4

3

を調べることをお勧めしspl_autoloadます。適切なディレクトリをあなたに追加するだけですinclude_path

このようなものは、おそらくあなたが始めるのに役立ちます:

ini_set($your_class_dir_here .PATH_SEPERATOR. ini_get('include_path'));

独自のオートローダーを使用するspl_autoload_registerか、すべてのファイル名を小文字にする必要があります。

これは、いくつかのディレクトリの問題を解決するために php 名​​前空間を使用する、私自身のオートローダーの 1 つです。

<?php

namespace Red
{
    // since we don't have the Object yet as we load this file, this is the only place where this needs to be done.
    require_once 'Object.php';

    /**
     * Loader implements a rudimentary autoloader stack.
     */
    class Loader extends Object
    {
        /**
         * @var Loader 
         */
        static protected $instance = null;

        /**
         * @var string 
         */
        protected $basePath;

        /**
         * @return Loader
         */
        static public function instance()
        {
            if (self::$instance == null)
            {
                self::$instance = new self();
            }
            return self::$instance;
        }

        /**
         * Initialize the autoloader. Future expansions to the 
         * autoloader stack should be registered in here.
         */
        static public function Init()
        {
            spl_autoload_register(array(self::instance(), 'autoLoadInNamespace'));
        }

        /**
         * PHP calls this method when a class is used that has not been
         * defined yet. 
         * 
         * I'm returning a boolean for success which isn't required (php ignores it)
         * but makes life easier when the stack grows.
         * 
         * @param string $fullyQualifiedClassName
         * @return boolean 
         */
        public function autoLoadInNamespace($fullyQualifiedClassName)
        {
            $pathParts = preg_split('/\\\\/', $fullyQualifiedClassName, -1, PREG_SPLIT_NO_EMPTY);
            array_unshift($pathParts, $this->basePath);
            $pathToFile = implode(DIRECTORY_SEPARATOR, $pathParts) . '.php';

            if (file_exists($pathToFile))
            {
                require_once $pathToFile;
                return true;
            }
            return false;
        }

        /**
         * Constructor is protected because we don't want multiple instances
         * But we do want an instance to talk to later on.
         */
        protected function __construct()
        {
            $this->basePath = realpath(dirname(__FILE__) . DIRECTORY_SEPARATOR . '..');
        }
    }
}

#EOF;

名前空間で名前が付けられたクラスの一部であり、単純なブートストラップ ファイルから初期化されLoaderます。\Red

<?php
// This is where the magic is prepared. 
require_once implode(DIRECTORY_SEPARATOR, array(dirname(__FILE__), 'Red', 'Loader.php'));
// Initialize the autoloader, no more require_once for every class
// and everything is OOP from here on in.
Red\Loader::Init();

#EOF
于 2010-07-17T21:15:03.530 に答える
1

ファイルの場所の自動検出は選択しません。それがセキュリティの脆弱性になる可能性があることをよく考えない限り、サブディレクトリをサポートする命名スキームを設計する必要があり、クラスごとに 1 つのファイルを使用する必要があります (これは良いことも悪いこともありますが、柔軟性がないと思います)。className => pathToClass のマッピングを保持するグローバル配列または静的配列を使用します。

于 2010-07-17T21:15:11.143 に答える
1

$_SERVER['DOCUMENT_ROOT']Web サーバーのルート ディレクトリへのフル パスが含まれている必要があります。そこから、フォルダー構造を介してクラス ディレクトリへのパスを継続できるはずです。アプリ名をセッションに保存した場合、同じコードをほぼどこでも使用できます。

//set in config file
if(!isset($_SESSION['APP_DIR'])) $_SESSION['APP_DIR'] = "my_app";

//autoload
//builds a string with document root/app_name/classes
//takes the app name and replaces anything not alphanumeric or _ with an _ and
//makes it lowercase in case of case sensitive. as long as you follow this naming
//scheme for app directories it should be fine for multiple apps.
$classPath = $_SERVER['DOCUMENT_ROOT'] . '/' .
           strtolower(preg_replace('/\W+/', '_', $_SESSION['APP_DIR'])) .
           '/classes/';
于 2010-07-17T21:30:10.410 に答える
0

基本的に2つの方法があります。クラス ディレクトリ ( ) への完全な絶対パスを指定するか、/home/mydirectory/dev.mysite.com/my_app/php/classes/ホストを変更する場合に絶対パスを変更する必要があるため、お勧めしません。または、相対パスを使用することもできます。これは、より簡単で移植性があります。

require_once '../classes/'.$classname;

ここを取得する必要はありませんrealpath。PHP は相対パスで問題ありません。;)

PS:realpath(dirname(__FILE__))重複していると思います。__FILE__はすでに「実際のパス」であるため、呼び出す必要はありませんrealpath

于 2010-07-17T21:03:48.540 に答える