I have some classes in a front controller that are not namespaced and are primarily utility classes. I use them more or less for debugging in virtually every class in the app I am building. The problem is that I am switching to namespaces for all of my classes and these utility classes do not work as they did before UNLESS, it seems, I convert my utility classes (which contain static utility functions) to a namespace and then import these namespaces into every class. This is a lot of importing, (3 classes must be imported into every class by default), especially since these utility classes do not need to be imported or used in production but are my most often used classes in development.
Is there a way to have my utility classes work in a namespaced class without importing them via “use”? (And also avoiding prefacing each use with a \)
To be a bit more clear, the question is there anything I can put in a front-controller-type-script to make a class available for instantiating (or method calling) in the classes that the front controller calls. I tried doing use Debug\DebugClass in the front controller, tried importing into the global namespace (which I wasn’t sure if I was successful), and tried just requiring the class. Nothing seemed to work - I can’t call DebugClasss::method from inside a namespaced class. (I also thought about using an autoloader, but can’t seem to think of one that doesn’t rely on the previous attempts.)
You can’t even refer to built-in classes except with either a “use” or a “\”. e.g., \DateTime
Think of it like relative paths vs absolute paths. If you’re already within a namespace, then PHP looks for Some\Class relative to your current namespace. Whereas \Absolute\Path\To\Some\Class is, well, absolute.
I had to do that with PDO to get it to work; I see what you mean. Any idea what the common procedure for using debug utilities/common functions should be in a namespaced project? Am I going to have to import my utility classes for every class?
I am actually using a psr-o autoloader right now. I’ve read through the composer docs before and the psr-4 spec. Unfortunately, there are no example autoloaders there - all dead links. How do you think composer’s autoloader solves this problem? (What am I missing?) It seems like I still have to import everything with use, or get it from the global name space with a \ prefix.
Like in the op, I want to use a set of static utility functions in any file included by a front controller, without having to set each class included to specifically use the utilities class.
currently every class I make has to be:
namespace MyProject\\Folder;
use MyProject\\Debug\\DebugUtilities;
class RandomController { }
I want to get rid of the ‘use’ line and still be able to use methods like: DebugUtilities::debug();
First things first, I don’t remember much about PSR-0; I use PSR-4, so your mileage may vary…
In PSR-4, this would not work. And I believe this applies to PSR-0 as well…
In this instance, the file is already in the MyProject\Folder namespace. So when you call RandomController, it is going to search for (and not find) RandomController in the MyProject\Folder namespace.
Your only options are to retain the “use MyProject\Debug\DebugUtilities”, or to use \MyProject\Debug\DebugUtilities\RandomController() { }. That’s it; those are the choices…either prepend the backslash and call the namespace directly, or keep the use statement.
Me personally, I much prefer \MyProject\Debug\DebugUtilities\RandomController() { }
The reason for that is, when the application grows, you’ll have a bunch of “use” statements, and it can get rough keeping track of which class/function call came from which namespace. This way, there is no confusion.
However, if you retain the “use” part, you can also do this:
use MyProject\Debug\DebugUtilities\RandomController as RandomController ;
Thanks for explaining, that’s what I came up with as well. I have been using “use” and the # of imports were getting quite large for even small classes. I am still going back and forth over whether to use “use” or a \, I started using use because it let me keep a lot of code as-is without changing every object instantiation to include a namespace.
But it seemed that you originally indicated that psr-4 autoloading may let me use DebugUtilities::debug() in the RandomController class without first importing it via use (or prepending with a \). Does psr-4/composer help here or was that a mistake?
Sorry for the confusion, but no, that is not what I meant. Autoloading and namespaces go hand in hand ( they are good for any project, but the bigger the project is, the more it helps you ). If you need to use namespaces, that usually means that you are going to be importing a bunch of classes and functions, which is why I mentioned Composer – there’s nothing worse than having require_once() all over the place. Composer will take care of loading the classes for you…you just then handle the namespaces.
Also, just wanted to add another comment…
Like I said, you COULD do this:
use MyProject\Debug\DebugUtilities\RandomController as RandomController ;
but, doing that kind of defeats the whole point of namespaces. It is a PITA, but most other languages do the same thing with declaring ‘use’ statements at the top of every file as well. In PHP there is no way to “import” the namespaces from one file to another…that would be hell on earth if you were allowed to pass namespaces from one file to another. They keep it localized to the containing file for very good reason, so don’t sweat it; just get used to doing it that way.
Oh yeah this, you have to use the backslash here. Honestly I normally don’t mind backslashes, but the leading backslash is plainly ugly. I am very very annoyed by this and I absolutely hate it, which is why I always write a lot of use statements despite its inconvenience. It’s confusing and can easily lead to errors too. I don’t like how in PHP class search start at the current namespace, in any other languages the search for namespace starts at root namespace. So you have to either write a number of use statement, or get used to the ugly leading backslash. Neither way is ideal, but that’s PHP for you.
Curious - what language allows you to start at the root namespace? I read a critique of PHP’s namespaces that mentioned this once but other languages were not mentioned. (Not one of the usual bad-natured, ill-founded and outdated, anti-php rants out there - https://pornel.net/phpns a pretty good read for those interested, I agree with alot of it.)
C++, Java, C#, Python, Ruby, etc. Pretty much all other programming languages will start searching for class at root namespace rather than current namespace. For PHP, you have to use a leading backslash to bring the search space back to the root namespace, but its ugly, annoying and error-prone:
namespace A;
$pdo = new PDO($dsn, $user, $pass); \\\\Error, class A\\PDO not found!!!
$pdo = new \\PDO($dsn, $user, $pass); \\\\This will work, but leading backslash is problematic.
Or you could write use statement for every class you import, but when you use many classes in the same file/code it will be long and tedious. This is why I said there was no ideal solution to PHP’s weird namespace behavior.