9

最初にオートロードするこのオートローダークラスがありますが、今はオートロードも行いclassesたいと思っています。interfacesabstracts

だから私はこの答えに従って変更を加えました、

$reflection = new ReflectionClass($class_name);

# Return boolean if it is an interface.
if ($reflection->isInterface())
{
    $file_name = 'interface_'.strtolower(array_pop($file_pieces)).'.php';
}
else
{
    $file_name = 'class_'.strtolower(array_pop($file_pieces)).'.php';

}

テストしましたが、このオートローダークラスはインターフェースをまったくロードしません。私が見逃したアイデアはありますか?

たとえば、これは私のインターフェイス ファイルです。

interface_methods.php

とその内容、

interface methods 
{
    public function delete();
}

以下は、このオートローダークラス全体です。

class autoloader
{
    /**
     * Set the property.
     */
    public $directory;
    public $recursive;

    public function __construct($directory, $recursive = array('search' => 'models') ) 
    {
        # Store the data into the property.
        $this->directory = $directory;
        $this->recursive = $recursive;

        # When using spl_autoload_register() with class methods, it might seem that it can use only public methods, though it can use private/protected methods as well, if registered from inside the class:
        spl_autoload_register(array($this,'get_class'));
    }

    private function get_class($class_name)
    {
        # List all the class directories in the array.
        if ($this->recursive)
        {
            $array_directories =  self::get_recursive_directory($this->directory);
        }
        else
        {
            if (is_array($this->directory)) $array_directories =  $this->directory;
            else $array_directories =  array($this->directory);
        }

        # Determine the class is an interface.
        $reflection = new ReflectionClass($class_name);

        $file_pieces = explode('\\', $class_name);

        # Return boolean if it is an interface.
        if ($reflection->isInterface())
        {
            $file_name = 'interface_'.strtolower(array_pop($file_pieces)).'.php';
        }
        else
        {
            $file_name = 'class_'.strtolower(array_pop($file_pieces)).'.php';

        }

        # Loop the array.
        foreach($array_directories as $path_directory)
        {
            if(file_exists($path_directory.$file_name)) 
            {
                include $path_directory.$file_name;
            } 
        }

    }

    public function get_recursive_directory($directory)
    {
        $iterator = new RecursiveIteratorIterator
                    (
                        new RecursiveDirectoryIterator($directory),
                        RecursiveIteratorIterator::CHILD_FIRST
                    );

        # This will hold the result.
        $result = array();

        # Loop the directory contents.
        foreach ($iterator as $path) 
        {

            # If object is a directory and matches the search term ('models')...
            if ($path->isDir() && $path->getBasename() === $this->recursive['search']) 
            {

                # Add it to the result array.
                # Must replace the slash in the class - dunno why!
                $result[] = str_replace('\\', '/', $path).'/';
                //$result[] = (string) $path . '/';

            }

        }

        # Return the result in an array.
        return $result;
    }
}
4

1 に答える 1

11

PHP は、クラス、インターフェース、または抽象クラスに違いはありません。定義するオートローダー関数は、常にオートロードするものの名​​前を取得し、それがどれであったかについてのヒントはありません。

したがって、インターフェースに「interface_」を、クラスに「class_」を接頭辞として付けているため、命名戦略は自動ロードできません。個人的には、このような命名規則はやや面倒です。

一方、オートローダーは完全にパフォーマンスが低下しています。1 つのクラスを見つけるためだけに、ディレクトリ ツリー全体を再帰的にスキャンします。そして、次のクラスでは、以前に行ったことの恩恵を受けることなく、すべての作業をやり直さなければなりません!

どうしても自分でやりたい場合 ( composerなどを使用しない場合) は、PSR-0 オートローダーを実装し、クラスとインターフェイスの命名規則に固執してください。

そして、区別するクラス名の接頭辞または名前空間を選択してください。最初のステップとして、ロードするクラスにこの接頭辞があるかどうかをオートローダー内で確認してください。そうでない場合はすぐに戻ります。これにより、ハードドライブを回転させて、クラスのファイル名が存在するかどうかを確認する必要がなくなります。

プレフィックスが一致しない場合、ロードしたいのは「あなたの」クラスではないため、オートローダーはそれを行う方法を認識できず、試行すらすべきではありませんが、登録された別のオートローダーは認識します。

于 2013-03-27T22:47:23.193 に答える