I have a file. Let’s call it Foo.php
. It looks like this:
namespace AppHelpers;
enum FooTypes: string {
case A = "A";
case B = "B";
}
class Foo {
const BAR = "Bar";
// ...
}
This will work:
use AppHelpers{ Foo, FooTypes };
echo Foo::BAR;
echo FooTypes::A->value;
This will fail with a "class FooTypes not found"
error:
use AppHelpers{ Foo, FooTypes };
// echo Foo::BAR;
echo FooTypes::A->value;
It looks like I have to use the "main" class Foo
before I can use any of the enums decalred in the same file. But that seems kind of absurd. What is happening? How do I resolve this? I could maybe seperate the enum into a seperate file but it really doesn’t make sense to me in my use case.
2
Answers
because
use
statement does not really "load" the file until you call what’s in it,when you call
Foo::BAR
it loads the fileAppHelpersFoo.php
thus you able to useFooTypes
which also from that file.Here another example, it will work fine, but if you comment the 1st return statement, it will throw an error
The
use
statement is purely a way to provide a short-hand within a particular file for a symbol (class, function, enum, etc) which is in a different namespace. See Using namespaces: aliasing/importing in the PHP manual. It lets you typeecho FooTypes::A->value;
instead ofecho AppHelpersFooTypes::A->value;
but that is all it does.This is completely unrelated to how the definition of a particular symbol is loaded. For that, you are probably relying on autoloading, which runs a callback function when a particular class / enum / etc is first used. The callback function then generally includes a file defining that symbol.
To be completely clear, defining an alias for a symbol with a
use
statement, does not trigger the autoloader to be run. Only actually executing code that needs that definition will trigger the autoloader.The most common convention is to put each definition into a separate file, and then configure the autoloader to load the file based on that name; but that is just a convention. If you want to have a different convention, e.g. that any name ending with "Types" is in the same file as the class without that ending, you can write an autoload function which implements that. For instance:
Note that the autoloader does not know whether it is looking for a class, an interface, a trait, or an enum; the only input you will get is the fully-qualified name, such as
"AppHelpersFooTypes"
.