Modern PHP is great. Many powerful language features, excellent performance, great community and package ecosystem, and decent enough safety with modern static analysis tools.
I'm not too sure I agree with the author's complaints here. When using something like array_filter, you're typically mapping from collection to collection (i.e. you don't care about the first element--you care about the whole thing) and so this problem is really a non-issue. The next follow up step would usually be foreach, or another operation like array_map, in which case it's a non-issue.
If you really do need the first element, you can use array_first. And if you really do need a fixed-sized collection, you can use SplFixedArray.
The point on properties is valid to an extent, but IMO not really an issue you commonly run into in the real world (regardless of language, your constructors should generally return an object in a usable state).
I heard this a long time ago about perl. CPAN is great.
Well ... perl entered the fossilized era. I think people do not really observe things correctly. I am noticing the same with ruby right now - everyone sees that ruby is in decline, very strongly so, in the last 3 years. Yet you have blog posts such as "ruby is not dying - it is aging like fine wine". And these are all NOT BASED ON FACTUAL ANALYSIS. I still think ruby is a great language, but if people are not realistic in their assessment of a situation, what does this tell us about people's evaluation in general? People seem to shy away from criticism. You can see this on reddit too, where moderators ban and censor willy-nilly, or even on github, where you can also quickly get eliminated for not conforming to xyz. It's as if some people are very afraid of strong opinions. I don't understand why - an opinion that is objectively false, can be shown to be false.
> Ruby is dying
How exactly do you define these “objective” criteria for such sensationalism?
What actual criticism of PHP is anyone shying away from?
PHP got bashed for such a long time, while simply nothing steps up to do what it does better. Something that, for example, is available on every webhost you can just throw files at, where all (meaningful) config and state can be in those files.
Why do I bring up containers? Because part of why PHP was so dope in this way was the way you can just define 1 file per endpoint and drop it in public_html, and have no server setup to do. Running say, Rails or ASP.NET or a Java site back then meant doing… a lot more, to your server.
But with Docker, you can just steal a good Dockerfile template from someone else, and it’s just like 3-4 simple files for you to manage for a simple Sinatra (Ruby) or node.js version of the “one-off PHP file” things.
edit: Granted, I agree that if you want to do all sorts of things on the internet, maybe PHP is not the right choice. But for simple, dynamic web things that I want to just make and then run like this forever, that I can work on but don't have to? PHP and vanilla HTML and Javascript are where it's at for me, hands down. Everything else I know is either too new or seems to have constant churn or issues. That you hear nothing about PHP other than complaining it's "outdated" or whatever from the outside -- always "why are you using this?" never "why oh why am I using this?" -- is because it just hums along, IMO. I like it better than Python, and I kinda view it as in that class.
Unfortunately newer versions of PHP killed it and it's dead now, and even more unfortunately while PHP absorbed a lot of features from Hack, native XML was not one of them. There was even going to be a Hack version of the Composer package manager but that never got finished AFAIK. Distros stopped supporting it. I think I still have my half-finished attempt at a Hacker News fork in Hack sitting around on a hard drive somewhere. I can't even find an environment to run it in anymore.
Doing so now raises a deprecation warning, unless you add #[AllowDynamicProperties], and PHP 9 will convert it to an error. I'm told this will simplify internals and unlock optimizations.
Arrays are still fairly awful, but generics may become a reality sooner rather than later, and on that could be built Vec and Dict types, à la Hack. PHP is going to be stuck with arrays as they are now for forever, but they'll at least become optional for new code.
> Not a warning—a FATAL error occurs if you try to access an uninitialized property. This comes up a lot in cases where you try to deserialize data into a PHP object. If a field's data isn't present you might not initialize the property at all.
I don't think that is an issue, except in interpretet type-unsafe languages it is harder to anticipate when writing code whether that value is NULL or undefined/uninitialized. E.g. it is basically the same in C#, but here the compiler warns you that the value is not initialized and forbids some actions (like reading the value of it).
The one thing I really wish PHP would add is structurally typed objects. I really miss it when moving back and forth between PHP and TypeScript.
They could call them anonymous objects if they want to (that would be a more culturally correct analogue to anonymous classes).
Like, I wish it was possible to do
{
string $mystring = $myvar,
}
and have it be equivalent to new class($myvar) {
public function __construct(
readonly public string $mystring,
) {}
}
and then be able to typehint it like function ({ string $mystring } $myobj) {
echo $myobj->mystring;
}
and honestly, why not go all the way and allow type definitions/aliases, something like type myobj_type = { string $mystring };
That'd be great. /** @psalm-type MyobjType = object{mystring: string} */
/**
* @param MyobjType $myobj
*/
function (object $myobj): void
Here are some documentation and examples:- For Psalm, see https://psalm.dev/docs/annotating_code/type_syntax/utility_t...
- For PHPstan, see https://phpstan.org/writing-php-code/phpdoc-types
It may work in your IDE (autocompletion, etc.) but there is no standard on this side. Some IDE have their own parsers, others use one of the LSPs for PHP.
- PHP has `SplFixedArray`[^1] that work similar to the standard arrays you expect from other languages. SPL extension is always available in PHP 5.3+, it is not even possible to compile PHP without it anymore. There is no specific type for list-arrays and associative arrays, but there is an `array_is_list` function to quickly check it.
- For typed properties, if a property is not typed, it is effectively considered `mixed $var = null`. If the property is typed, and has no default value, then it is considered uninitialized, and not allowed to access.
Having them as key-value means, that you can easily just remove some items in the middle, during iteration etc. No automatic shifting happening.
The thing which bites me is when some internal functions actually reindex the array. array_filter does not, but for example array_reverse, array_slice etc. do (preserve_keys always defaults to false). And for array_merge too, but there it's no array_merge(preserve_keys: false), but instead the + operator. (Why is this operator overloaded?!)
On the topic of the uninitialized state, as co-author of that RFC:
I agree with the author that nullable properties should have been auto-initialized to NULL. I haven't ever seen any benefit of an uninitialized state for these. Some co-authors of that RFC disagreed and wished for consistency with the other typed properties. The good thing probably is, that we still could opt to change this with a relatively minor BC break.
For non-nullable properties, I do think there is value. Not every value is actually available/ready in a constructor. Sure you can assign dummy values to properties. But it's requiring you to then manually guard/assert that the property is actually initialized. If you happen to access a non-nullable typed property without isset(), then your code is likely broken anyway and I'm grateful for the Error exception thrown.
Also, PHP has this peculiar feature of ReflectionClass::newInstanceWithoutConstructor(). This is forcibly having an object in an uninitialized state. Whether that feature should exist or not is a good question, but in practice it's helpful for object hydration for example. This was one further motivation to introduce the uninitialized state.
The author of the post suggests checking at the constructor boundary. But this doesn't inhibit objects leaking / not finishing the initialization properly. (class Foo { public stdClass $object; function __construct() { global $foo; $foo = $this; } } new Foo; $foo->object ... is now still existing? PHP doesn't have mechanisms to invalidate objects at a distance. That would be the alternative, but also spooky.) Some choices need to be made, and all choices will have some rough edges.
Side note: I personally never use is_null(), but nearly always isset(). This nicely checks for the uninitialized state too. Static analysis tells me anyway, when I access a variable or property name which can never exist.
This can lead to some unexpected behaviors. For example, I've already been bitten by `array_merge()` whose result is different if its parameters are arrays with numeric indexes.
array_merge(["4 " => "four"], ["5 " => "five"])
// ["4 " => "four", "5 " => "five"]
array_merge(["4" => "four"], ["5" => "five"])
// [0 => "four", 1 => "five"]