Laravel - 在具有另一个类的文件中贴花的枚举在调用“主”类之前不会加载

问题描述 投票:0回答:2

我有一个文件。我们称之为

Foo.php
。看起来像这样:

namespace App\Helpers;

enum FooTypes: string {
    case A = "A";
    case B = "B";
}

class Foo {

   const BAR = "Bar";
   // ...
}

这会起作用:

use App\Helpers\{ Foo, FooTypes };

echo Foo::BAR;
echo FooTypes::A->value;

这将失败并出现

"class FooTypes not found"
错误:

use App\Helpers\{ Foo, FooTypes };

// echo Foo::BAR;
echo FooTypes::A->value;

看起来我必须使用“主”类

Foo
才能使用同一文件中的任何枚举。但这似乎有点荒谬。怎么了?我该如何解决这个问题?我也许可以将枚举分成一个单独的文件,但在我的用例中它对我来说确实没有意义。

php enums
2个回答
2
投票

因为

use
语句在您调用文件中的内容之前不会真正“加载”文件,

当您调用

Foo::BAR
时,它会加载文件
App\Helpers\Foo.php
,因此您可以使用也来自该文件的
FooTypes

这里是另一个例子,它可以正常工作,但是如果你注释第一个 return 语句,它会抛出错误

// assume file is in app\Helpers\Foo.php
use \App\Helpers;

// this nonsense doesn't exist, but as long as its not called, theres no problem;
use \Something\That\Dont\Exist;

Route::get('/something', function() {    
    
    //Works Fine as it loads app\Helpers\Foo.php first and able to find FooTypes inside that file
    return [Helpers\Foo::BAR, Helpers\FooTypes::A];

     //trows an error because it tries to load app\Helpers\FooTypes.php first
    return [Helpers\FooTypes::A, Helpers\Foo::BAR];

});

0
投票

use
语句纯粹是一种在特定文件中为不同命名空间中的符号(类、函数、枚举等)提供简写的方法。请参阅 PHP 手册中的使用名称空间:别名/导入。它可以让您输入
echo FooTypes::A->value;
而不是
echo \App\Helpers\FooTypes::A->value;
,但这就是它的 全部

这与特定符号的定义如何加载完全无关。为此,您可能依赖于autoloading,它会在首次使用特定类/枚举/等时运行回调函数。回调函数通常包含一个定义该符号的文件。

要完全清楚的是,使用

use

 语句定义符号的别名,
不会 触发自动加载器运行。只有实际执行需要该定义的代码才会触发自动加载器。

最常见的约定是将每个定义放入一个单独的文件中,然后配置自动加载器以根据该名称加载文件;但是

这只是一个约定。如果您想有不同的约定,例如任何以“Types”结尾的名称都与没有该结尾的类位于同一文件中,您可以编写一个自动加载函数来实现它。例如:

function my_autoload_callback(string $nameToLoad): void { $filePath = PROJECT_ROOT . '/' . str_replace('\\', '/', $nameToLoad) . '.php'; if ( file_exists($filePath) ) { require_once $filePath; } else { // try without "Types" on the end // should probably have another file_exists check here require_once str_replace('Types.php', '.php', $filePath); // we could check if this has found the right class } // if the function reaches here without loading the required class, // you will get a "class not found" error from PHP }
请注意,自动加载器不知道它是否正在寻找类、接口、特征或枚举;您将获得的唯一输入是完全限定名称,例如 

"App\Helpers\FooTypes"

© www.soinside.com 2019 - 2024. All rights reserved.