105

自動ロードと名前空間を使用しようとすると、次のエラーが発生します。

致命的なエラー:10行目の/usr/local/www/apache22/data/public/php5.3/test.phpにクラス「Class1」が見つかりません

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

これが私のコードです:

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();

?>
4

13 に答える 13

122

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

これは古い答えでありspl_autoload_register()、PHP 5.1でサポートが導入されたとは想定できなかった時代から(今では何年も前に!)状況が変わったことに注意してください。

最近では、Composerを使用している可能性があります。内部的には、これはクラスの自動読み込みを有効にするためのこのスニペットの行に沿ったものになります。

spl_autoload_register(function ($class) {
    // Adapt this depending on your directory structure
    $parts = explode('\\', $class);
    include end($parts) . '.php';
});

完全を期すために、ここに古い答えがあります:

グローバルスコープで定義されていないクラスをロードするには、オートローダーを使用する必要があります。

<?php

// Note that `__autoload()` is removed as of PHP 8 in favour of 
// `spl_autoload_register()`, see above
function __autoload($class)
{
    // Adapt this depending on your directory structure
    $parts = explode('\\', $class);
    require end($parts) . '.php';
}

use Person\Barnes\David as MyPerson;

$class = new MyPerson\Class1();

またはエイリアスなし:

use Person\Barnes\David\Class1;

$class = new Class1();
于 2009-12-09T01:35:00.977 に答える
29

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();
  • オートローダーの宣言にはphp5の推奨事項を使用しました。まだPHP4を使用している場合は、古い構文に置き換えてください。function __autoload($ class)
于 2013-05-14T01:01:43.047 に答える
19

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

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

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

于 2009-12-02T06:00:12.103 に答える
15

私はこのようなことをします:この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___
}
于 2015-05-31T18:05:04.493 に答える
4

次の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();

お役に立てれば。

于 2013-08-21T16:07:33.340 に答える
3

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);
    }
});
于 2015-02-15T20:20:26.750 に答える
3

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

spl_autoload_register(function($name){
        require_once 'lib/'.str_replace('\\','/',$name).'.php';
    });
于 2018-08-29T06:52:50.363 に答える
2

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

Classesクラスファイルを、PHPアプリケーションへのエントリポイントと同じディレクトリにあるという名前のフォルダに配置することをお勧めします。クラスが名前空間を使用する場合、名前空間はディレクトリ構造に変換されます。

他の多くの自動ローダーとは異なり、アンダースコアはディレクトリ構造に変換されません(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 Business\Deeper; classD {}
于 2017-10-26T07:33:30.023 に答える
1

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

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

    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では機能しません

于 2014-07-03T13:23:29.843 に答える
1

使用には落とし穴があります。これははるかに高速な方法ですが、すべてのファイル名が小文字である必要もあります。

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

例えば:

クラスSomeSuperClassを含むファイルにはsomesuperclass.phpという名前を付ける必要があります。これは、ファイルの名前がSomeSuperClass.phpであるが、Windowsでは問題がない場合、Linuxなどの大文字と小文字を区別するファイルシステムを使用する場合の落とし穴です。

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

では、どのようなオプションが残っているのでしょうか。

このバージョンはPHP5.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;
});
于 2015-04-08T01:28:52.057 に答える
1

最近、tanerkayの答えがとても役に立ちました!+を使用するとstrrpos()+substr()よりもわずかに高速であることを追加したかっただけです:explode()end()

spl_autoload_register( function( $class ) {
    $pos = strrpos( $class, '\\' );
    include ( $pos === false ? $class : substr( $class, $pos + 1 ) ).'.php';
});
于 2016-08-05T02:18:00.193 に答える
1

比較的初心者の場合、またはすべての理論なしで単純な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の人々は、最初にそれをテストする必要があります。

于 2016-08-22T05:45:38.893 に答える
0
<?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();
}
?>
于 2018-05-17T12:05:53.393 に答える