Java solved this by using domain names as unique identifiers. I can use com.banffy and be sure only a complete a*hole would make a package in this space.
This is similar to NPM’s organisation prefix (@foo/bar).
But yeah, I’m not defending the hacky way namespaces are resolved through autoloading. I do prefer actual language support for a module system (but Ruby suffers from this problem too).
With Rails 7 and Zeitwerk, the Ruby community has landed on a very similar auto-loading system as PHP now[2] with constants translating to paths by convention.
[0]: https://github.com/php-fig/fig-standards/blob/master/accepte...
[1]: https://www.php-fig.org/psr/psr-4/
[2]: https://github.com/fxn/zeitwerk#the-idea-file-paths-match-co...
I do wish they would extend auto loading for standalone functions and constants though.