6 ms·
I am surprised there is no discussion in the PHP community to introduce a module system. The current solution for code reuse (use longer class names to avoid c
by TekMol 4y ago
I am surprised there is no discussion in the PHP community to introduce a module system.
The current solution for code reuse (use longer class names to avoid clashes, we help you with syntactic sugar called "namespaces") is the wrong approach imo.
- supriyo-biswas 4y agoComposer autoloading and the PSR-4 naming convention works just fine, since you have to separate the class names with some kind of information about the developer, followed by the name of the class. Java uses a similar naming scheme too ("org.apache.commons.SomeClass" etc.) though autoloading is specific to PHP. I'm curious as to why you consider autoloading over PSR-4 namespaces as insufficient.
- morelisp 4y agoTo begin with, the fact the "module" system is tied to classes is a horrible design flaw. (Also in Java, but Java leans into it - PHP still has functions and lots of stuff is clearer as functions.)
- 9dev 4y ago…and you can have namespaces for functions and import namespaced functions just fine.
- morelisp 4y agoYou can namespace them, but you can't `use` them or otherwise autoload them.
- yurishimo 4y agoAre you sure? I've definitely written a `use` statement to import a function. https://www.php.net/manual/en/language.namespaces.importing.php https://www.php.net/manual/en/language.namespaces.importing....
- morelisp 4y agoAFAIK this only works if the function has already been loaded for some other reason (i.e. in the same file as a class or an explicit require). I do cop to not having used PHP recently, so maybe 8 fixed it? At least in the PHP I'm familiar with, nothing "happens" at `use` time; the first time you call a method on a class it autoloads. The autoloader is then what does the work of finding and requiring the file. No class, no autoloader.
- porker 4y agoPHP 8 hasn't fixed function autoloading, and Composer still has hacks like you can specify function containing files it will always load.
- TekMol 4y agoWorking around underlying problems with tools and conventions is something that is fine when you get paid for your time. As a maker, I prefer a clean stack. So that its complexity does not slow me down. Workarounds make development slower and slower, the more it becomes a giant hairball of workarounds and workarounds around workarounds. In Python and JavaScript, I don't need those workarounds. Would be awesome if PHP catches up.
- deleted 4y ago[deleted]
- Cyykratahk 4y agoVersion conflicts on shared transitive dependencies is a real problem, to the point that there are tools available to library authors that allow them to rename their dependencies to be under their own namespace to avoid collisions. If two packages I require depend on incompatible versions of some third package, there aren't any easy ways for me to resolve it. This problem exists because of the global nature of PHP namespaces.
- DJBunnies 4y agoI have encountered this once in my career, it’s pretty rare.
- supriyo-biswas 4y agoPeople complain about the size of node_modules. I think Composer's approach to find a common set of dependencies that satisfy all version constraints keeps things lean.
- onlypositive 4y ago"works just fine" - obviously never watched xdebug shart the bed while composer tries to version match phpunit. A module system and less reliance on PSR the better. Why exactly does PSR still exist?
- 9dev 4y agoPSR is intended for framework authors, and I strongly think it was one of the best things that happened to the php ecosystem. The PSR-7 http messages alone have made SO MANY things compatible at once, it’s incredible. And it works so well that most php developers aren’t ever aware that PSR underpinnings power most dependencies they use!
- onlypositive 4y ago> PSR is intended for framework authors That's my problem with it. It should be focused on what's good for developers. Not what makes it easier to overengineer the next flavour of the month.
- yurishimo 4y agoGenuine question, why are you version matching PHPUnit? It's arguably one of the most backwards compatible software packages still being actively developed. I have multiple projects using phpunit version (*) with no issues. I will readily admit that 99% of my assertions are some variation of `$this->assertEquals()`
- throw_m239339 4y ago> The current solution for code reuse (use longer class names to avoid clashes, we help you with syntactic sugar called "namespaces") is the wrong approach imo. You can in theory create modules with require. module.php <?php return (function(){ $foo = function(){echo "hello from PHP";}; return [ "greet"=>$foo ]; })(); script.php <?php $module = require('./module.php'); $module["greet"](); But PHP namespaces and autoloading via composer ARE the community accepted way to handle namespacing. The ecosystem is so large developers aren't going to move to a different module system at that point. Especially when composer is the defacto package manager for PHP.
- tored 4y agoNamespaces and modules are orthogonal, you can support both like Typescript. Your solution works, but unfortunately not something that has any community support. I proposed something similar a year ago but use classes instead because classes seems to be the internal building block in PHP. For both our solutions is would relatively easy to add a shim to older PHP versions. module.php <?php return new class { public const MY_CONST = 47; private const MY_PRIVATE_CONST = 127; // with PHP 8.1 you also have readonly properties public string $myPublic = 'foo'; private int $myPrivate = 17; public function helloWorld(string $name): void { echo "Hello, World {$name}!"; } }; main.php <?php final class ModuleException extends Exception { } function module(string $name): object { static $modules = []; if (isset($modules[$name])) { return $modules[$name]; } try { $module = @require $name; } catch (Error $error) { throw new ModuleException("No such module {$name}", 0, $error); } if (!is_object($module)) { throw new ModuleException("Module {$name} is not an object"); } $modules[$name] = $module; return $module; } $my = module('module.php'); $my->helloWorld('Module system'); $other = module('module.php'); assert($my === $other); https://news.ycombinator.com/item?id=30242974 https://news.ycombinator.com/item?id=30242974
- deleted 4y ago[deleted]
- n0n0n4t0r 4y agoHonestly, as a PHP développer, the node's module system impress me A LOT. I went on several projects that had not kept their dependencies on the "edge version". For some, it was more than a year of work just to be able to move from php7 to php8. PHP dependencies are so intertwined that for projects that abuse and use more than a reasonable amount (aka their ability to invest time keeping them and the code using it up to date) the update process can become a nightmare of complexity. Node's module system let you move each dependency at it's own pace. This is such a breath! The problem is that when you only know of the solution of your ecosystem, it's hard to see the added value you miss out.
- tored 4y agoMy recommendation for every PHP projects that uses external libraries is to use your own wrapper function/class to minimize contamination of the project. If you use a framework then try to write all your own code outside of the framework and pass in all needed framework data as arguments to your own classes/functions.
- n0n0n4t0r 4y agoI agree with you: this is a good practice. However, what I was speaking about is the version handling of (sometimes direct but mostly) indirect dependencies. The domain of `composer why` and `composer why-not`. One if the most speaking example I can think of is: if two libs depends on guzzle 5, then you can't update only one on a version that depends on guzzle 6: you must upgrade both at the same time. Each to an intercompatible lock on guzzle version.