web-dev-qa-db-ja.com

autoloadでPHP名前空間を使用するにはどうすればよいですか?

Autoloadと名前空間を使用しようとすると、このエラーが発生します。

致命的なエラー:クラス 'Class1'が見つかりません/ usr/local/www/Apache22/data/public/php5.3/test.php on line 1

誰かが私が間違っていることを教えてもらえますか?

ここに私のコードがあります:

Class1.php:

<?php

namespace Person\Barnes\David
{
    class Class1
    {
        public function __construct()
        {
            echo __CLASS__;
        }
    }
}

?>

test.php:

<?php

function __autoload($class)
{
    require $class . '.php';
}

use Person\Barnes\David;

$class = new Class1();

?>
93
David Barnes

Class1はグローバルスコープ内にありません。

実際の例については、以下を参照してください。

<?php

function __autoload($class)
{
    $parts = explode('\\', $class);
    require end($parts) . '.php';
}

use Person\Barnes\David as MyPerson;

$class = new MyPerson\Class1();

編集(2009-12-14):

明確にするために、「use ... as」の私の使用法は、例を単純化することでした。

代替手段は次のとおりです。

$class = new Person\Barnes\David\Class1();

または

use Person\Barnes\David\Class1;

// ...

$class = new Class1();
112
tanerkay

Pascal MARTINで述べたように、たとえば、「\」をDIRECTORY_SEPARATORに置き換える必要があります。

$filename = BASE_PATH . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
include($filename);

また、コードを読みやすくするために、ディレクトリ構造を再編成することをお勧めします。これは代替案かもしれません:

ディレクトリ構造:

ProjectRoot
 |- lib

ファイル:/ProjectRoot/lib/Person/Barnes/David/Class1.php

<?php
namespace Person\Barnes\David
class Class1
{
    public function __construct()
    {
        echo __CLASS__;
    }
}
?>
  • 定義する各ネームスペースのサブディレクトリを作成します。

ファイル:/ProjectRoot/test.php

define('BASE_PATH', realpath(dirname(__FILE__)));
function my_autoloader($class)
{
    $filename = BASE_PATH . '/lib/' . str_replace('\\', '/', $class) . '.php';
    include($filename);
}
spl_autoload_register('my_autoloader');

use Person\Barnes\David as MyPerson;
$class = new MyPerson\Class1();
  • オートローダーの宣言には、PHP 5の推奨事項を使用しました。それでもPHP 4を使用している場合は、古い構文で置き換えてください:function __autoload($ class)
25
Kostanos

__autoload関数は、名前空間名を含む完全なクラス名を受け取ります。

これは、あなたの場合、__autoload関数が 'Person\Barnes\David\Class1'だけでなく 'Class1'を受け取ることを意味します。

そのため、この種の「より複雑な」名前に対処するには、オートロードコードを変更する必要があります。よく使用される解決策は、名前空間の「レベル」ごとに1レベルのディレクトリを使用してファイルを整理し、オートロード時に名前空間名の「\」をDIRECTORY_SEPARATORに置き換えることです。

17
Pascal MARTIN

私はこのようなことをします: このGitHubの例を参照

spl_autoload_register('AutoLoader');

function AutoLoader($className)
{
    $file = str_replace('\\',DIRECTORY_SEPARATOR,$className);

    require_once 'classes' . DIRECTORY_SEPARATOR . $file . '.php'; 
    //Make your own path, Might need to use Magics like ___DIR___
}
12
tika

次の2つの場合、オートロード機能は「完全な」クラス名のみを受け取ります(すべてのネームスペースがそれに先行します)。

[a] $a = new The\Full\Namespace\CoolClass();

[b] use The\Full\Namespace as SomeNamespace; (at the top of your source file) followed by $a = new SomeNamespace\CoolClass();

次の場合、オートロード機能が完全なクラス名を受け取らないことがわかります。

[c] use The\Full\Namespace; (at the top of your source file) followed by $a = new CoolClass();

更新:[c]は間違いであり、名前空間の動作方法とは異なります。 [c]の代わりに、次の2つのケースもうまく機能することを報告できます。

[d] use The\Full\Namespace; (at the top of your source file) followed by $a = new Namespace\CoolClass();

[e] use The\Full\Namespace\CoolClass; (at the top of your source file) followed by $a = new CoolClass();

お役に立てれば。

3
Daniel Rhodes

Flysystem からこの宝石を見つけました

spl_autoload_register(function($class) {
    $prefix = 'League\\Flysystem\\';

    if ( ! substr($class, 0, 17) === $prefix) {
        return;
    }

    $class = substr($class, strlen($prefix));
    $location = __DIR__ . 'path/to/flysystem/src/' . str_replace('\\', '/', $class) . '.php';

    if (is_file($location)) {
        require_once($location);
    }
});
3
boksiora

この単純なハックを1行で使用します。

spl_autoload_register(function($name){
        require_once 'lib/'.str_replace('\\','/',$name).'.php';
    });
1
princebillyGK

を使用するのは非常に速い方法ですが、ファイル名はすべて小文字であると想定されています。

spl_autoload_extensions(".php");
spl_autoload_register();

例えば:

SomeSuperClassクラスを含むファイルはsomesuperclass.phpという名前にする必要があります。これは、Linuxのように大文字と小文字を区別するファイルシステムを使用する場合の注意点です。

コードで__autoloadを使用しても、現在のバージョンのPHPで動作する可能性がありますが、この機能は非推奨となり、将来的には削除される予定です。

残っているオプション:

このバージョンはPHP 5.3以降で動作し、ファイル名SomeSuperClass.phpおよびsomesuperclass.phpを許可します。 5.3.2以降を使用している場合、このオートローダーはさらに高速に動作します。

<?php

if ( function_exists ( 'stream_resolve_include_path' ) == false ) {
    function stream_resolve_include_path ( $filename ) {
        $paths = explode ( PATH_SEPARATOR, get_include_path () );
        foreach ( $paths as $path ) {
            $path = realpath ( $path . PATH_SEPARATOR . $filename );
            if ( $path ) {
                return $path;
            }
        }
        return false;
    }
}

spl_autoload_register ( function ( $className, $fileExtensions = null ) {
    $className = str_replace ( '_', '/', $className );
    $className = str_replace ( '\\', '/', $className );
    $file = stream_resolve_include_path ( $className . '.php' );
    if ( $file === false ) {
        $file = stream_resolve_include_path ( strtolower ( $className . '.php' ) );
    }
    if ( $file !== false ) {
        include $file;
        return true;
    }
    return false;
});
1
Michael Bush

私は相対的な初心者や単純なspl_autoload_register()のセットアップが不要な場合に2セントを投入します:クラスごとに1つのphpファイルを作成し、そのphpファイルにクラス名と同じ名前を付け、クラスファイルを保持します問題のPHPファイルと同じディレクトリにある場合、これは動作します:

spl_autoload_register(function ($class_name) {
    require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . $class_name . '.php';
});

この関数内の部分をグーグルで調べると、どのように機能するかがわかるはずです。 PS:私はLinuxを使用していますが、これはLinuxでも動作します。 Windowsの人は最初にテストする必要があります。

1
user6659166

同じ問題があり、ちょうどこれを見つけました:

含まれているクラスの名前空間に一致するサブフォルダー構造を作成する場合、オートローダーを定義する必要さえありません。

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

それは魅力のように働いた

詳細はこちら: http://www.php.net/manual/en/function.spl-autoload-register.php#92514

編集:これはバックスラッシュのためにLinux上で問題が発生します...immeëmosolによる作業ソリューションについてはこちらをご覧ください

ネームスペース自動ロードはWindowsで動作しますが、Linuxでは動作しません

1
JohnWolf

私は最近tanerkucの回答が非常に役立つことに気付きました! strrpos() + substr()を使用すると、explode() + end()よりもわずかに高速になります。

spl_autoload_register( function( $class ) {
    $pos = strrpos( $class, '\\' );
    include ( $pos === false ? $class : substr( $class, $pos + 1 ) ).'.php';
});
1
Alan

https://thomashunter.name/blog/simple-php-namespace-friendly-autoloader-class/

PHPアプリケーションへのエントリポイントと同じディレクトリにあるClassesという名前のフォルダーにクラスファイルを配置します。クラスが名前空間を使用する場合、名前空間はディレクトリ構造に変換されます。他の多くのオートローダーとは異なり、アンダースコアはディレクトリ構造に変換されません(PHP <5.3擬似ネームスペースとPHP> = 5.3本物のネームスペースを行うのは難しいです)。

<?php
class Autoloader {
    static public function loader($className) {
        $filename = "Classes/" . str_replace("\\", '/', $className) . ".php";
        if (file_exists($filename)) {
            include($filename);
            if (class_exists($className)) {
                return TRUE;
            }
        }
        return FALSE;
    }
}
spl_autoload_register('Autoloader::loader');

次のコードをメインのPHPスクリプト(エントリポイント)に配置します。

require_once("Classes/Autoloader.php");

ディレクトリレイアウトの例を次に示します。

index.php
Classes/
  Autoloader.php
  ClassA.php - class ClassA {}
  ClassB.php - class ClassB {}
  Business/
    ClassC.php - namespace Business classC {}
    Deeper/
      ClassD.php - namespace BusinessDeeper classD {}
<?php
spl_autoload_register(function ($classname){
   // for security purpose
   //your class name should match the name of your class "file.php"
   $classname = str_replace("..", "", $classname);
   require_once __DIR__.DIRECTORY_SEPARATOR.("classes/$classname.class.php");
});
try {
  $new = new Class1();
} catch (Exception $e) {
   echo "error = ". $e->getMessage();
}
?>
0