I'm just a PHP programmer for work, but I worry about the orientation PHP has chosen. As French people say: better is the enemy of good (Le mieux est l'ennemi du bien). The two new language features bring a higher language complexity for dubious gains. I hope I won't have to work with these.
Property hooks mean that some language magic will turn a property access into a call to methods. It implies that `$this->x` has a different meaning if it's inside a hook or outside hooks. I've used this kind of feature (getters/setters) with JS code (and with Moose/Perl decades ago), and I wasn't convinced. Plain methods are more explicit, have less cognitive charge, and are easier to extend.
On the bright side, I'm glad that the language is still thriving. In 2021, I was worried when the foundation was created, especially as I read that Nikita Popov had left. He was the creator of PHP's JIT code, and at the time the only developer who could fully understand it. But it seems there was no need to worry. PHP is now longer "the elephant in the room" of web programming, but it's still a good language, with many active developers at its core.
Just to set the record straight, Nikita is not the creator of the PHP JIT code, that is Dmitry and he is employed by Zend owned by Perforce working mostly on this.
Of course it's not required but when you start pushing the boundaries of a language with the goal of achieving a clean interface, obscure features you wouldn't normally resort to become appealing. I dislike all of the magic around Laravel's Eloquent ORM - model relationships, query builder, abuse of ForwardsCalls trait, etc, but at the same time I can appreciate how "clean" it all looks once it's put together.
> Property hooks mean that some language magic will turn a property access into a call to methods.
__get / __set was doing that already and some frameworks very heavily rely on those.
> It implies that `$this->x` has a different meaning if it's inside a hook or outside hooks.
this is a valid critique but hopefully hooks will be super short and this won't be a major issue. Indeed, if your get is not an arrow function -- which only allows one statement -- then it needs a good thinking over whether this is indeed the best solution. Ie if your get is so complicated then perhaps a helper method is best and then you have get => $this->foo($this->thing) and that's the only place where $this->thing is special.
> hopefully hooks will be super short and this won't be a major issue.
Even if a PHP project has a policy of short hooks, I think hooks impede clarity.
public string $countryCode
{
set (string $countryCode) {
$this->countryCode = strtoupper($countryCode);
$this->country = nameCountry($this->countryCode);
}
get => ...
In this short hook, the first line of the setter obviously uses the underlying property. But the second line of the setter...
Does `$this->country =` use the setter even if it's in a hook (but not a `country` hook)?
Does reading `$this->countryCode` use the getter hook, even it's from a `countryCode` hook?
If not, is there a way to call the `countryCode` getter from this setter?
If quickly parsed the doc and the RFC, so I don't have answers (I suppose it's yes, no, no). But even if I knew how this code behaved, I would still think it's much more complex than plain methods.
> Does `$this->country =` use the setter even if it's in a hook (but not a `country` hook)?
To me it is obvious hooks won't use other hooks because that could lead to an infinite loop in a hurry
> Does reading `$this->countryCode` use the getter hook, even it's from a `countryCode` hook?
same
> If not, is there a way to call the `countryCode` getter from this setter?
There is although it's a bit tricky and not intuitive but I feel this falls under the "it is enough this is possible, there's no need for it to be easy": "Be aware, the detection logic works on $this->[propertyName] directly at compile time, not on dynamic forms of it like $prop = 'beep'; $this->$prop. That will not trigger a backing value." Using dynamic properties in what should be simple code should be rare enough this is not a problem. It's like a bridge convention, the benefits vastly outweigh the drawbacks.
> Does `$this->country =` use the setter even if it's in a hook (but not a `country` hook)?
To me it is obvious hooks won't use other hooks because that could lead to an infinite loop in a hurry
I would expect hooks for properties other than `$this->contryCode` to be called inside of a `$this->contryCode` hook.
Btw the docs that are linked in the post[0] seem to be clearer than the example in the announcement. Reads less ambiguously to me.
This should work in Python, too. With Django, I think you need to use https://pypi.org/project/django-browser-reload/, and rith most other frameworks / WSGI servers just try adding --reload flag.
Edit: Django should wor out of rhe box actually – that package is for refreshing the page in browser.
> Easy to deploy. Upload files, done.
I can see the appeal, but generally you’d want to avoid that (for anything other than quick prototypes, maybe). Set up a CI, push to deploy. This goes for modern PHP as well.
If you want something simple to deploy webapps and know a little Docker, I’ve built a deployment tool you can run on your own VPS: https://lunni.dev/. (Feel free to reach out if you need any help!)
There are of course ways to get "reload page, see results" to work even with Python. After all, computers are touring complete.
But in PHP you have it out of the box. Faster, with less complexity and less resource consumption. And you can use the same setup in development as you can use in production.
Maybe I'm missing something, but PHP is not more efficient in that regard.
When you load a Python page, it is served by an in-memory process. If code is updated, the process is restarted, parsing the code and initialising the application, but it is done only once.
When you load a PHP page, it parses the code and initializes the app for each request. It then tears everything down after the request. There are less wasteful ways (most recent are app servers, just like in Python or other langs), but I'm not sure if those are widely used in local development. Even then, it’s same as Python, Node or pretty much anything else.
And of course, I’m not trying to diss on PHP here – it’s gotten pretty good recently. But reload on change is built in pretty much every app framework nowadays. It works out of the box and is negligibly fast. It’s not a good point to compare.
> When you load a PHP page, it parses the code and initializes the app for each request. It then tears everything down after the request. There are less wasteful ways (most recent are app servers, just like in Python or other langs), but I'm not sure if those are widely used in local development.
There are things like opcode caches that make PHP more efficient transparently, while still feeling to the developer like a reload each time.
There are reliability and development advantages to starting each request from scratch. NO leaks, no state you need worry about.
PHP is always blazing fast, with no additional setup to make "Reload page, see results" work.
Python needs additional setup. Either by monitoring the filesystem and pessimistically recompiling the application every time a file changes. Causing resource consumption every time you hit save in your editor. Or by having the web workers that serve the requests die after 1s of inactivity or so. Which makes the next pageview slow again, even if no code changed.
I think PHP's advantage is because of 3 things:
1: Recompiling changed files is built in.
2: With PHP you can set your project up in a way that only the code necessary to answer a single request is updated. With Python and Django, all the code for all requests is updated and even code paths that are actually never used.
3: PHP keeps each file compiled to bytecode in memory and only recompiles files that have been changed. Although you might accomplish something similar in Python if you let it pollute your filesystem with cached bytecode files.
To get to know Laravel, I forced myself to build a project with it for a few weeks and I did not like it.
I found myself getting sucked in into a complex project structure and dealing with all kinds of strangeness like "artisan commands", "the autoload cache" etc.
With Django, I can build a web application in a single file that has "import django" on top and take it from there:
Most PHP apps use a deployment method where a symlink gets set to a directory with a new version of the code. Because of how opcache works this has no impact on running requests, while new requests get handled with the new code.
You can use the same strategy with PHP. Preload all your scripts in opcache. Once you're done making changes, reset your opcache.
In practice, any serious project is likely to be version-controlled. Git pull is generally fast enough that it behaves like an atomic change. (By default, opcache will not reload a file that's less than 2 seconds old.)
I'm pretty sure many PHP dev don't know about OPCache. Many of my colleagues don't know for sure. My point is "be aware of the state of your app code and what you execute", and so be aware of the shortcomings of this deployment "strategy". It's sure perfectly fine and easy for small apps / low traffic / not critical apps. I just want to point that it's not inherently good enough and definitely not the universal way to deploy a PHP app.
Python’s packaging and dependencies system is lacking, but trying to get better. But too many choices not always compatible nor working perfectly right (should you use pip, poetry or pipenv? Well, you see…)
I know people love to say this, but does anyone realistically make websites or web apps that way? No, not really. Even with PHP there are frameworks, there is a package manager, there is version control, and there are deployment systems.
Pretending that PHP developers are uploading a .php file to a shared hosting server (like in 2002) to suit the narrative feels disingenuous to me as it doesn’t align with what I see PHP developers doing at all.
Not sure where you got that from. It’s equally if not faster then python, faster then Java, slower then compiled language, faster then ruby. Loses to NodeJS most of the time.
But who cares, we are literally talking millisecond differences between them all. Throw a reverse proxy, DB into the mix and a few packages and they are all slow.
Great PHP release. Better stack traces for closures, performance improvements (always nice), HTML5 support, lazy objects and much more. Great work and a big thanks to everyone involved!
Property hooks are the headline feature, but they seem like something I'd rarely use in practice. It is nice to have the option available though, in case I need to add extra logic to a property without breaking everywhere that it's accessed.
If you want any evidence that terrible language design is alive and well in PHP, look no further than the new array_find function.
Not only is it yet another global function in a namespace already chock full of random array helpers, it is extremely similar in both name and usage to array_search - a global function since PHP 4. Except, of course, that in typical PHP fashion, array_find’s argument order is ($array, $filter_callback) while the older array_search is ($search_value, $array).
There are literally hundreds of hits for existing, global, functions named array_find. If these are loaded from a library, they will break uses of the new built-in function in exciting ways. Yet, even with this mentioned in the RFC (https://wiki.php.net/rfc/array_find) it seems to have been no obstacle whatsoever to its inclusion - despite the fact that the implementation is literally three lines of code.
I have to question if the benefits of this global function really outweigh the benefits. PHP devs claim that other languages have these functions so PHP should too - but neglect to note that most languages don’t make them global functions (rather, they’re usually array methods or in some utility module).
I have a question to the PHP-in-production crowd: how long do you wait before migrating to higher version of PHP? Is the first release usually already fine, or is it better to wait for a few months and let someone else catch the early errors?
I wait 1-3 months, but then update. It used to take way longer, because Amazon's Elastic Beanstalk platform would take longer to update, but I've now changed to Platform.sh and the transition should be easier.
It has been very backward-compatible (i.e. stuff that works in 8.n also works in 8.n+1; and unless you use exotic functions or are relying on special functionality, it should work for you, too).
Once I'm at 8.4, I would slowly update the code / syntax with rector and the assistance of phpstan.
For framework updates I wait 1-2 patch versions before updating, because of composer dependency problems and sometimes bugs do still find themselves into new releases (e.g. I would wait at least until Symfony 7.2.1 before upgrading from Symfony 7.1.x).
We start making sure our application runs on the next version around the time Beta 1 comes out.
We upgrade the development environment around the time when our tooling (phpstan, cs-fixer) runs on the next version, but doesn't necessarily support new language features.
We upgrade the production environment when our tooling supports most of the new language features and at least all of the ones we want to make use of.
This usually happens within 3-6 months of the release. By that time the version has stabilized enough to be safe for production use.
I usually wait 6mo to a year in order for composer dependencies I use to get updated. Then its usually a trivial upgrade. I've upgraded sooner before for simpler projects though and things are usually pretty stable upon release.
The last few point releases have been very stable, so normally within a week or so. Obviously this relies on having a pretty good test suite (we run ~8,000 tests in ~60 seconds so not too bad for us).
For PHP 8.3, we upgraded production during the RC phase, but were prepared to revert back to an older one by not relying on the new functionality. Docker makes this easy.
As long as you do not use the new functionality, I'd claim that a new PHP version is no less stable than an older one. And on a contrary you would be missing out on some bugfixes that were deemed too risky to apply to an existing version.
Disclosure: I've got a commit-bit for PHP, so we had in-house expertise to diagnose issues ourselves.
For a project like Wikipedia, stability and continuity are far more important than latest and greatest feature support; in fact, there's an argument to be made to avoid newer language features to ensure consistency, that is, if new features are used, they should be used everywhere at once. Else you end up with frankenstein code where every file could use a different style.
Oftentimes many of the significant new PHP features are to fix the shortsighted implementation in the previous ones - for example this method chaining with `new` - there was precedent already,
C++ got it right well before PHP even existed and with the very same arrow operator that PHP borrowed (and so did Java and JavaScript with .), so the question is why did PHP have to get it wrong at first and for so long.
Another pet peeve of me is that the global namespace is littered with these utility functions that should be easily composable or maybe be methods on the objects themselves - and looks like PHP 8.4 adds four more `array_*` functions.
For comparison, Python's builtin namespace has a total of 71 functions and a couple of exception classes. PHP's builtin namespace has more functions for dealing with arrays and now 58 of those are prefixed with `array_`.
The global namespace change would break everything. It’s unlikely they would ever do something like that.
It’s hard to build on a language used by so many, when you can’t modify the base. Python decided to do 2.7 vs 3 and fragmented the eco system terribly.
They could help by not adding any more cruft to the global namespace.
Adding any globals should be a carefully-considered change. User-defined functions are global by default, and although there are (now) much better ways to write PHP libraries, I can absolutely see some old library defining array_find (one of the new global functions in 8.4) in an incompatible way and breaking new code that attempts to use the built-in function.
Sure, you can’t touch the existing pile of globals, but at least stop pouring fuel on that particular fire…
That would be some really old library. Already in 2012 when Composer was released there was PSR-0 and today almost all libraries are Composer managed and using a namespace following PSR-4 which itself is ten years old. A library that old would almost surely not run on PHP 8 unchanged anyways.
Surrendering the global namespace to the language is not so bad an idea.
Suppose I want to add some new code to an old website? Or I want to gradually upgrade an ancient code base - twelve years is not so old for PHP, when ancient frameworks like Wordpress are still alive and kicking.
If we hitched language development on Wordpress we would still be on PHP4 as they refused to join gophp5 some seventeen years ago.
Again, an ancient enough codebase which contains a library using array_find will need enough upgrades to run on PHP8 much less PHP8.4 the change from array_find to something else is the least of your worries.
Seriously? 2k results for array_find in PHP on GitHub: https://github.com/search?q=array_find++language%3APHP&type=.... RFC authors (https://wiki.php.net/rfc/array_find) explicitly noted over 600 hits for definitions of array_find, around 30% of which are not false positives - that is, there's a good possibility that there are 200+ implementations of global array_find in just open-source projects.
There are so many more examples. Lots of the hits are from codebases that have seen updates in the last few years. Many more are plugins or other addons for PHP frameworks or apps which are still widely used (WordPress, phpBB, etc.).
I think the bigger issue is that these lessons have already been learned. However, PHP (Personal Home Page) was not created carefully by someone to become a fully fledged language. It grew into that role organically which is why it has so many warts in hindsight.
The design philosophy of PHP is to include whatever common methods would otherwise be in a popular library. (PHP actually began more as a library than as a language.) This differs from, eg, Python, but doesn't hurt.
The decision not not to make methods on the objects, but to include everything in the main namespace (so array_walk instead of Array.walk or Array()->walk etc) is another function of the same philosophy. It may not fit your idea of cosmetics, but there is nothing wrong with it.
On the other hand, I would love if PhP gained chainability ([].array_map.array_find()) and then the names would be a pain. If that ever happens there are solutions.
Whats the problem with global namespace littered with utility functions. Do they get in the way? They hurt you? They whisper in your ear? Or with the badly named functions? Or the type juggling? Do they eat your soul?
It could be much easier for user defined functions to collide with standard functions, especially when it happens unintentionally.
Someone else creates a function named array_something in the namespace. Maybe it already exists in earlier versions, maybe it happens to collide with one of the four introduced in 8.4. This function is accessible to you in the current scope. Now, you try to call the function like the way it is defined in the standard library. You get a very confusing error and spend 10 minutes trying to figure if it is you or PHP that is hallucinating. Turns out you have been inadvertently calling that other user defined function. The other user may be completely unaware of the fact that they created a function with naming collision.
To combat this, you need strong IDE help including static type checking, which is not always there for everybody. And it still doesn't help with cases where the user defined function collides with a new standard function.
Most "modern" languages have very few built-in functions in the global namespace. Another example is Go. Correct me if I am wrong, but I believe there is 0 function in global namespace in Rust. println! exists but that's a macro. In other words, the example I mentioned just never happens with these languages.
Not to mention the long list of junk you see in IDE when you type "array_".
Rust namespaces everything in the standard library to std:: or core::, and has a clear distinction between them.
However, it does implicitly include the entirety of the std::prelude namespace (https://doc.rust-lang.org/std/prelude/index.html) into every source file, as well as including every macro directly exported under std:: (including println!). This enables the unprefixed use of things like Result, Option, Some, Send, etc.
The prelude and std:: macros are the closest thing that Rust has to a global namespace, and even they can be disabled in crates that specifically request it.
I'm just a PHP programmer for work, but I worry about the orientation PHP has chosen. As French people say: better is the enemy of good (Le mieux est l'ennemi du bien). The two new language features bring a higher language complexity for dubious gains. I hope I won't have to work with these.
Property hooks mean that some language magic will turn a property access into a call to methods. It implies that `$this->x` has a different meaning if it's inside a hook or outside hooks. I've used this kind of feature (getters/setters) with JS code (and with Moose/Perl decades ago), and I wasn't convinced. Plain methods are more explicit, have less cognitive charge, and are easier to extend.
On the bright side, I'm glad that the language is still thriving. In 2021, I was worried when the foundation was created, especially as I read that Nikita Popov had left. He was the creator of PHP's JIT code, and at the time the only developer who could fully understand it. But it seems there was no need to worry. PHP is now longer "the elephant in the room" of web programming, but it's still a good language, with many active developers at its core.
Just to set the record straight, Nikita is not the creator of the PHP JIT code, that is Dmitry and he is employed by Zend owned by Perforce working mostly on this.
Thanks for correcting me, and sorry for the error. I should have checked before writing.
Don't you get tired of managing getters/setters in your entities?
None of this is required. You can still write spaghetti code perfectly fine.
Of course it's not required but when you start pushing the boundaries of a language with the goal of achieving a clean interface, obscure features you wouldn't normally resort to become appealing. I dislike all of the magic around Laravel's Eloquent ORM - model relationships, query builder, abuse of ForwardsCalls trait, etc, but at the same time I can appreciate how "clean" it all looks once it's put together.
> Property hooks mean that some language magic will turn a property access into a call to methods.
__get / __set was doing that already and some frameworks very heavily rely on those.
> It implies that `$this->x` has a different meaning if it's inside a hook or outside hooks.
this is a valid critique but hopefully hooks will be super short and this won't be a major issue. Indeed, if your get is not an arrow function -- which only allows one statement -- then it needs a good thinking over whether this is indeed the best solution. Ie if your get is so complicated then perhaps a helper method is best and then you have get => $this->foo($this->thing) and that's the only place where $this->thing is special.
> hopefully hooks will be super short and this won't be a major issue.
Even if a PHP project has a policy of short hooks, I think hooks impede clarity.
In this short hook, the first line of the setter obviously uses the underlying property. But the second line of the setter...Does `$this->country =` use the setter even if it's in a hook (but not a `country` hook)?
Does reading `$this->countryCode` use the getter hook, even it's from a `countryCode` hook?
If not, is there a way to call the `countryCode` getter from this setter?
If quickly parsed the doc and the RFC, so I don't have answers (I suppose it's yes, no, no). But even if I knew how this code behaved, I would still think it's much more complex than plain methods.
> Does `$this->country =` use the setter even if it's in a hook (but not a `country` hook)?
To me it is obvious hooks won't use other hooks because that could lead to an infinite loop in a hurry
> Does reading `$this->countryCode` use the getter hook, even it's from a `countryCode` hook?
same
> If not, is there a way to call the `countryCode` getter from this setter?
There is although it's a bit tricky and not intuitive but I feel this falls under the "it is enough this is possible, there's no need for it to be easy": "Be aware, the detection logic works on $this->[propertyName] directly at compile time, not on dynamic forms of it like $prop = 'beep'; $this->$prop. That will not trigger a backing value." Using dynamic properties in what should be simple code should be rare enough this is not a problem. It's like a bridge convention, the benefits vastly outweigh the drawbacks.
> Does `$this->country =` use the setter even if it's in a hook (but not a `country` hook)? To me it is obvious hooks won't use other hooks because that could lead to an infinite loop in a hurry
I would expect hooks for properties other than `$this->contryCode` to be called inside of a `$this->contryCode` hook.
Btw the docs that are linked in the post[0] seem to be clearer than the example in the announcement. Reads less ambiguously to me.
[0]: https://www.php.net/manual/en/migration84.new-features.php#m...
These days, I am super torn about what language to use for new web projects.
PHP:
Python:> Reload page, see changes.
This should work in Python, too. With Django, I think you need to use https://pypi.org/project/django-browser-reload/, and rith most other frameworks / WSGI servers just try adding --reload flag.
Edit: Django should wor out of rhe box actually – that package is for refreshing the page in browser.
> Easy to deploy. Upload files, done.
I can see the appeal, but generally you’d want to avoid that (for anything other than quick prototypes, maybe). Set up a CI, push to deploy. This goes for modern PHP as well.
If you want something simple to deploy webapps and know a little Docker, I’ve built a deployment tool you can run on your own VPS: https://lunni.dev/. (Feel free to reach out if you need any help!)
There are of course ways to get "reload page, see results" to work even with Python. After all, computers are touring complete.
But in PHP you have it out of the box. Faster, with less complexity and less resource consumption. And you can use the same setup in development as you can use in production.
Maybe I'm missing something, but PHP is not more efficient in that regard.
When you load a Python page, it is served by an in-memory process. If code is updated, the process is restarted, parsing the code and initialising the application, but it is done only once.
When you load a PHP page, it parses the code and initializes the app for each request. It then tears everything down after the request. There are less wasteful ways (most recent are app servers, just like in Python or other langs), but I'm not sure if those are widely used in local development. Even then, it’s same as Python, Node or pretty much anything else.
And of course, I’m not trying to diss on PHP here – it’s gotten pretty good recently. But reload on change is built in pretty much every app framework nowadays. It works out of the box and is negligibly fast. It’s not a good point to compare.
> When you load a PHP page, it parses the code and initializes the app for each request. It then tears everything down after the request. There are less wasteful ways (most recent are app servers, just like in Python or other langs), but I'm not sure if those are widely used in local development.
There are things like opcode caches that make PHP more efficient transparently, while still feeling to the developer like a reload each time.
There are reliability and development advantages to starting each request from scratch. NO leaks, no state you need worry about.
PHP is very much like serverless.
This is true when you call PHP using CGI or CLI. Then opcode is build, running and thrown away.
But when u are using FCGI or PHP-FPM then you have running process where opcode is cached except on first request where opcode cache is build.
In my experience:
PHP is always blazing fast, with no additional setup to make "Reload page, see results" work.
Python needs additional setup. Either by monitoring the filesystem and pessimistically recompiling the application every time a file changes. Causing resource consumption every time you hit save in your editor. Or by having the web workers that serve the requests die after 1s of inactivity or so. Which makes the next pageview slow again, even if no code changed.
I think PHP's advantage is because of 3 things:
1: Recompiling changed files is built in.
2: With PHP you can set your project up in a way that only the code necessary to answer a single request is updated. With Python and Django, all the code for all requests is updated and even code paths that are actually never used.
3: PHP keeps each file compiled to bytecode in memory and only recompiles files that have been changed. Although you might accomplish something similar in Python if you let it pollute your filesystem with cached bytecode files.
Don't forget Laravel for PHP.
To get to know Laravel, I forced myself to build a project with it for a few weeks and I did not like it.
I found myself getting sucked in into a complex project structure and dealing with all kinds of strangeness like "artisan commands", "the autoload cache" etc.
With Django, I can build a web application in a single file that has "import django" on top and take it from there:
https://news.ycombinator.com/item?id=40788329
You can do that with Symfony.
https://symfony.com/doc/current/configuration/micro_kernel_t...
https://symfony.com/blog/new-in-symfony-7-2-simpler-single-f...
I had hoped to forget
I much prefer Symfony, but that's mainly because it's the framework I started with.
> - Easy to deploy: Upload files, done.
Sure, it works for simple/less important cases. But it also means that your application code is inconsistent while the files are uploading.
Stop your service, upload the files, start the service: safer.
For a Django app you would upload files and ask Gunicorn to graceful reload... similar, just cleaner.
Most PHP apps use a deployment method where a symlink gets set to a directory with a new version of the code. Because of how opcache works this has no impact on running requests, while new requests get handled with the new code.
You can use the same strategy with PHP. Preload all your scripts in opcache. Once you're done making changes, reset your opcache.
In practice, any serious project is likely to be version-controlled. Git pull is generally fast enough that it behaves like an atomic change. (By default, opcache will not reload a file that's less than 2 seconds old.)
I'm pretty sure many PHP dev don't know about OPCache. Many of my colleagues don't know for sure. My point is "be aware of the state of your app code and what you execute", and so be aware of the shortcomings of this deployment "strategy". It's sure perfectly fine and easy for small apps / low traffic / not critical apps. I just want to point that it's not inherently good enough and definitely not the universal way to deploy a PHP app.
Git pull to deploy is something I avoid.
Python’s packaging and dependencies system is lacking, but trying to get better. But too many choices not always compatible nor working perfectly right (should you use pip, poetry or pipenv? Well, you see…)
How’s php’s?
> Python’s packaging and dependencies system is lacking
It is? I never had problems with poetry. Though I agree that there are mroe options than necessary.
> Easy to deploy: Upload files, done
I know people love to say this, but does anyone realistically make websites or web apps that way? No, not really. Even with PHP there are frameworks, there is a package manager, there is version control, and there are deployment systems.
Pretending that PHP developers are uploading a .php file to a shared hosting server (like in 2002) to suit the narrative feels disingenuous to me as it doesn’t align with what I see PHP developers doing at all.
PHP has a rather nice type system. It also doesn't use whitespace as syntax, which makes it much easier to generate ad hoc.
Slim is a pretty nice framework: https://www.slimframework.com/
PHP fast? Compared to all popular web frameworks it's quite low in the pecking order when it comes to performance.
Not sure where you got that from. It’s equally if not faster then python, faster then Java, slower then compiled language, faster then ruby. Loses to NodeJS most of the time.
But who cares, we are literally talking millisecond differences between them all. Throw a reverse proxy, DB into the mix and a few packages and they are all slow.
And if we actually want to talk speed, PHP with something like Swoole or ReactPHP is many times even faster[0] than the already fast regular PHP.
[0]: https://medium.com/@dimdev/9-php-runtimes-performance-benchm...
> faster then Java
You sure about that? Not what I would have expected. Source?
Great PHP release. Better stack traces for closures, performance improvements (always nice), HTML5 support, lazy objects and much more. Great work and a big thanks to everyone involved!
Property hooks are the headline feature, but they seem like something I'd rarely use in practice. It is nice to have the option available though, in case I need to add extra logic to a property without breaking everywhere that it's accessed.
If you want any evidence that terrible language design is alive and well in PHP, look no further than the new array_find function.
Not only is it yet another global function in a namespace already chock full of random array helpers, it is extremely similar in both name and usage to array_search - a global function since PHP 4. Except, of course, that in typical PHP fashion, array_find’s argument order is ($array, $filter_callback) while the older array_search is ($search_value, $array).
There are literally hundreds of hits for existing, global, functions named array_find. If these are loaded from a library, they will break uses of the new built-in function in exciting ways. Yet, even with this mentioned in the RFC (https://wiki.php.net/rfc/array_find) it seems to have been no obstacle whatsoever to its inclusion - despite the fact that the implementation is literally three lines of code.
I have to question if the benefits of this global function really outweigh the benefits. PHP devs claim that other languages have these functions so PHP should too - but neglect to note that most languages don’t make them global functions (rather, they’re usually array methods or in some utility module).
I have a question to the PHP-in-production crowd: how long do you wait before migrating to higher version of PHP? Is the first release usually already fine, or is it better to wait for a few months and let someone else catch the early errors?
Solo Dev on my own PHP project since 14 years.
I wait 1-3 months, but then update. It used to take way longer, because Amazon's Elastic Beanstalk platform would take longer to update, but I've now changed to Platform.sh and the transition should be easier.
It has been very backward-compatible (i.e. stuff that works in 8.n also works in 8.n+1; and unless you use exotic functions or are relying on special functionality, it should work for you, too).
Once I'm at 8.4, I would slowly update the code / syntax with rector and the assistance of phpstan.
For framework updates I wait 1-2 patch versions before updating, because of composer dependency problems and sometimes bugs do still find themselves into new releases (e.g. I would wait at least until Symfony 7.2.1 before upgrading from Symfony 7.1.x).
We start making sure our application runs on the next version around the time Beta 1 comes out.
We upgrade the development environment around the time when our tooling (phpstan, cs-fixer) runs on the next version, but doesn't necessarily support new language features.
We upgrade the production environment when our tooling supports most of the new language features and at least all of the ones we want to make use of.
This usually happens within 3-6 months of the release. By that time the version has stabilized enough to be safe for production use.
Basically I follow Debian Stable releases and migrate all my code to it when a new version is pushed. So so far I'm on 8.2.
It also often fit with the current Laravel version (11).
I usually wait 6mo to a year in order for composer dependencies I use to get updated. Then its usually a trivial upgrade. I've upgraded sooner before for simpler projects though and things are usually pretty stable upon release.
The last few point releases have been very stable, so normally within a week or so. Obviously this relies on having a pretty good test suite (we run ~8,000 tests in ~60 seconds so not too bad for us).
For PHP 8.3, we upgraded production during the RC phase, but were prepared to revert back to an older one by not relying on the new functionality. Docker makes this easy.
As long as you do not use the new functionality, I'd claim that a new PHP version is no less stable than an older one. And on a contrary you would be missing out on some bugfixes that were deemed too risky to apply to an existing version.
Disclosure: I've got a commit-bit for PHP, so we had in-house expertise to diagnose issues ourselves.
> how long do you wait before migrating to higher version of PHP?
I still have a PHP5 project that somehow still runs.
Wikipedia is still on php 7.4.33 so don't feel too bad if you are behind.
For a project like Wikipedia, stability and continuity are far more important than latest and greatest feature support; in fact, there's an argument to be made to avoid newer language features to ensure consistency, that is, if new features are used, they should be used everywhere at once. Else you end up with frankenstein code where every file could use a different style.
"Else you end up with frankenstein code where every file could use a different style."
Yeah, this is a huge problem, but also, in the long run, inevitable.
Plenty of Kernighan & Ritchie C code still out there...
8.2 and 8.3, respectively.
I enjoy the PHP 8 new features such as named arguments, constructor arguments promotion and nullsafe operators. Made my new code a lot more readable.
I am not that sure about 8.4 yet, though the new array_ functions and new DOM look interesting.
I wait one version, I’ll upgrade to 8.3 now and 8.4 when 8.5 is out.
new MyClass()->method() without parentheses
ewwww
For urban design I can recommend the following YouTube channel: https://m.youtube.com/@NotJustBikes
Wrong thread?
Oftentimes many of the significant new PHP features are to fix the shortsighted implementation in the previous ones - for example this method chaining with `new` - there was precedent already, C++ got it right well before PHP even existed and with the very same arrow operator that PHP borrowed (and so did Java and JavaScript with .), so the question is why did PHP have to get it wrong at first and for so long.
Another pet peeve of me is that the global namespace is littered with these utility functions that should be easily composable or maybe be methods on the objects themselves - and looks like PHP 8.4 adds four more `array_*` functions. For comparison, Python's builtin namespace has a total of 71 functions and a couple of exception classes. PHP's builtin namespace has more functions for dealing with arrays and now 58 of those are prefixed with `array_`.
The global namespace change would break everything. It’s unlikely they would ever do something like that.
It’s hard to build on a language used by so many, when you can’t modify the base. Python decided to do 2.7 vs 3 and fragmented the eco system terribly.
They could help by not adding any more cruft to the global namespace.
Adding any globals should be a carefully-considered change. User-defined functions are global by default, and although there are (now) much better ways to write PHP libraries, I can absolutely see some old library defining array_find (one of the new global functions in 8.4) in an incompatible way and breaking new code that attempts to use the built-in function.
Sure, you can’t touch the existing pile of globals, but at least stop pouring fuel on that particular fire…
That would be some really old library. Already in 2012 when Composer was released there was PSR-0 and today almost all libraries are Composer managed and using a namespace following PSR-4 which itself is ten years old. A library that old would almost surely not run on PHP 8 unchanged anyways.
Surrendering the global namespace to the language is not so bad an idea.
Suppose I want to add some new code to an old website? Or I want to gradually upgrade an ancient code base - twelve years is not so old for PHP, when ancient frameworks like Wordpress are still alive and kicking.
If we hitched language development on Wordpress we would still be on PHP4 as they refused to join gophp5 some seventeen years ago.
Again, an ancient enough codebase which contains a library using array_find will need enough upgrades to run on PHP8 much less PHP8.4 the change from array_find to something else is the least of your worries.
Seriously? 2k results for array_find in PHP on GitHub: https://github.com/search?q=array_find++language%3APHP&type=.... RFC authors (https://wiki.php.net/rfc/array_find) explicitly noted over 600 hits for definitions of array_find, around 30% of which are not false positives - that is, there's a good possibility that there are 200+ implementations of global array_find in just open-source projects.
First page hits https://github.com/hawind/gdoo/blob/master/app/Support/helpe..., a PHP app last updated just two years ago (140 stars, 63 forks) which only supports PHP 8.x. Implementation is thoroughly incompatible with 8.4's array_find.
There are so many more examples. Lots of the hits are from codebases that have seen updates in the last few years. Many more are plugins or other addons for PHP frameworks or apps which are still widely used (WordPress, phpBB, etc.).
I think the bigger issue is that these lessons have already been learned. However, PHP (Personal Home Page) was not created carefully by someone to become a fully fledged language. It grew into that role organically which is why it has so many warts in hindsight.
I don't get your issue with builtin utilities.
The design philosophy of PHP is to include whatever common methods would otherwise be in a popular library. (PHP actually began more as a library than as a language.) This differs from, eg, Python, but doesn't hurt.
The decision not not to make methods on the objects, but to include everything in the main namespace (so array_walk instead of Array.walk or Array()->walk etc) is another function of the same philosophy. It may not fit your idea of cosmetics, but there is nothing wrong with it.
On the other hand, I would love if PhP gained chainability ([].array_map.array_find()) and then the names would be a pain. If that ever happens there are solutions.
There is a RFC on it (https://wiki.php.net/rfc/function-composition) which I'd love if it made it through. Until then Crell's FP library is a good option (https://github.com/Crell/fp).
Whats the problem with global namespace littered with utility functions. Do they get in the way? They hurt you? They whisper in your ear? Or with the badly named functions? Or the type juggling? Do they eat your soul?
It could be much easier for user defined functions to collide with standard functions, especially when it happens unintentionally.
Someone else creates a function named array_something in the namespace. Maybe it already exists in earlier versions, maybe it happens to collide with one of the four introduced in 8.4. This function is accessible to you in the current scope. Now, you try to call the function like the way it is defined in the standard library. You get a very confusing error and spend 10 minutes trying to figure if it is you or PHP that is hallucinating. Turns out you have been inadvertently calling that other user defined function. The other user may be completely unaware of the fact that they created a function with naming collision.
To combat this, you need strong IDE help including static type checking, which is not always there for everybody. And it still doesn't help with cases where the user defined function collides with a new standard function.
Most "modern" languages have very few built-in functions in the global namespace. Another example is Go. Correct me if I am wrong, but I believe there is 0 function in global namespace in Rust. println! exists but that's a macro. In other words, the example I mentioned just never happens with these languages.
Not to mention the long list of junk you see in IDE when you type "array_".
I guess you haven't written much MATLAB.
Rust namespaces everything in the standard library to std:: or core::, and has a clear distinction between them.
However, it does implicitly include the entirety of the std::prelude namespace (https://doc.rust-lang.org/std/prelude/index.html) into every source file, as well as including every macro directly exported under std:: (including println!). This enables the unprefixed use of things like Result, Option, Some, Send, etc.
The prelude and std:: macros are the closest thing that Rust has to a global namespace, and even they can be disabled in crates that specifically request it.
> PHP 8.4 is a major update of the PHP language.
No it’s not: it’s a MINOR update.
It can be a major update even though it's a minor version bump.
It could have been, but isn’t. Most of those are rather small, incremental quality-of-life improvements. Nothing revolutionary.
I wouldn't consider all the new features small, but even many small improvements can result in a major improvement.