Everything you need (and don't need) to know about PHP's type system
thephp.website
thephp.website
I'm often amused by developers that revile PHP, while going on to use another language, which suffers from a similar set of problems to PHP, oftentimes with poorer performance and more complex toolchains.
PHP deserves a little more love, imo.
But truth be told, the hate is deserved. It never was a particularly efficient language, which might not matter that much, but it was riddled with gotchas, warts and horrible solutions to many technical and social problems.
Today PHP is faster than many alternatives, many of its warts got fixed, but I cannot brush off the fact that it's still based on a poorly-designed base and runtime library.
I'm still using PHP when it makes sense, in the same way I'm still using perl where it makes sense.
I'm happy that the language is evolving and there is a strong ecosystem with quality libraries and developers unlike what it used to be 5 years ago.
I've been doing several languages (Scala, and Typescript. also Go recently) in last few years. But, I still follow PHP ecosystem closely and I'd definitely choose it for my next web startup. It's just 10x faster and ultimately cheaper to build web with PHP. That's why there are so many big success stories that started with PHP even in areas that you wouldn't believe. Surprisingly enough, not only web! One of Cloudflare's founders said on an interview that their back-end was written in PHP and it was used for a long time. That's one of the things that you think no one would do.
JS ecosystem still lacks good reliable vendors and that holds some companies away from it. Surprisingly it's holding up really well even though must of the packages are maintained by individual contributors.
Not true, actually. The (admittedly obscure) syntax to access a property beginning with a numeral is `$obj->{0}`. Usually when this happens it's because someone was trying to be clever with JSON.
* A "list" type representing a non-associative array
* Types representing specific kinds of values, like numeric-string or non-empty-array, as well as exact values as types (like true and false, or string constants).
* Typing on keys and values in arrays, e.g. array<class-string,int> for an array with class names as keys and integers as values
* Complex typing on the contents of associative arrays, e.g. array{foo:int, bar:string}
* Templated types on functions, like a function which returns an instance of a class whose name is passed in as a string:
/**
* @template T
* @param T::class $class_name
* @return T
*/
[1]: https://psalm.dev/For example, in a project using doctrine I have to add a bunch of is null/@psal-mutation-free annotations. As all the methods can return null.
However, if Psalm had support for something like phantom types, maybe I could tag entities returned from the database for whom certain fields are guaranteed to have values.
https://plugins.jetbrains.com/plugin/10215-php-inspections-e... is amazing and well worth the price.
It has a free variant which is still amazing but lacks all the inspections of the paid variant.
https://plugins.jetbrains.com/plugin/7622-php-inspections-ea...
Maybe the `@psalm-ignore-nullable-return` annotation is more appropriate for those methods?
Do you use the Doctrine plugin?
I was not aware of the any psalm doctrine plugin and will definitely have a look at it. Thanks for the suggestion.
In terms of @psalm-ignore-nullable-return annotation. That definitely sounds like a practical workaround, at the moment.
1. "they all inherit from stdClass" -- this is simply not true
2. callables should've mentioned anonymous functions
3. a special typed value can't be casted to anything. -- this is not true, NULLs can be casted to anything (it becomes 0, "", array() ) and even resources can be casted to anything with dubious utility value.
4. casting should mention the intval() , strval() , doubleval() functions
5. php does not support explicit type definition in variable declaration -- PHP 7.4 however supports typed properties. https://wiki.php.net/rfc/typed_properties_v2
Two special notes:
About 1. stdClass, you're right and I don't know why I just took it for granted without even testing. My Bad.
About 3. casting special types, you're right again. I didn't phrase it properly. Casting null to other types won't yield errors and casting resources too. Their values are normally nothing we should rely on, but doesn't mean one "can't" perform such casts.
Thanks a lot for your comments, they are incredibly helpful! Cheers!
I've been knee deep in PHP for the last 6 months after keeping it at arm's length for probably 10 years. It's really quite incredible how much it's improved and I think the type system is the major factor for me. It's not perfect but damn - I can get some stuff done really quick now.
I'm more of a Symfony than Laravel guy but I've done both enough to know that application architecture and environment configuration has more of an impact than either framework's "performance" does.
Silly things are slow in most web frameworks.
Any framework bears overhead, they all optimize programmer's time invested into solving the problem. It's cheaper to buy hardware and scale horizontally rather than swap languages and frameworks hunting for performance.
PHP being synchronous by nature is what limits its performance, but we have Swoole that fixes it and makes it faster.
For the ones who will google what Swoole is, some benchmarks I've done on my laptop show 5x (yes, 5 times, 500%) increase in performance when Laravel is ran via Swoole.
No, that's outright wrong. Please see the well respected techempower web benchmark: https://www.techempower.com/benchmarks/
> For the ones who will google what Swoole is, some benchmarks I've done on my laptop show 5x (yes, 5 times, 500%) increase in performance when Laravel is ran via Swoole.
Yup, that seems to be correct. What are the drawbacks of Swoole?
I just notified the servers I've to manage (and my coworkers) that we're outright wrong and the load we're seeing is phantasm and that guy from internet told us so since he linked the well respected techempower benchmarks, which apparently reflect real world situation :)
7.4 added typed properties. 8 is adding better caching, a jit and my favourite feature
match()
https://php.watch/versions/8.0#match-expressionfor all the enterprise heavy stuff I write a nicer cleaner and safer (by default) alternative to switch is going to make some code much cleaner to write and read and really that is what I care about more than almost anything else.
That it also returns a value is just the cherry on top. I am so tired of reading bad code with poor intent that has no comments and no documentation that's written in the most counter intuitive way.
This is one of my most common sources of bugs, and it is frustrating not having this be available, when it makes my life so much easier in Perl.
Lately I've been thinking about doing something crazy like implementing my own variable system...
I can't quite think of the type of validation you'd be able to avoid with the sort of "inverted" strictness you're describing.
Certainly I can think of issues people could have if not using strict types (basically, unexpected casts), but not things that you could actually validate from within the function.
Use a configure file that sets env variables for your project files. Put call in that file.
For example, you can set strict typing on a per-file basis.
`declare(strict_types=1);`
I believe that the performance difference between the two is negligible now too. So it really just comes down to personal preference/platform legacy.
But Hack is on a different path which is potentially going to make it harder to share code between PHP and Hack.
PHP still has by far the larger community.
Given the choice today, I’d run with PHP.
I believe this extra step is incredibly important, given most of your dependencies you won't control and forcing strict types to them is not very clever IMO.
Type system doesn't guarantee that the programmer will utilize it properly, produce optimal code or even figure out the problem that is being solved by writing an algorithm.
You also need to pay attention to the ecosystem, problems that come with HHVM, the fact you're undoubtedly tying yourself with Facebook and what you're gaining / losing with the decision to go with a fork of PHP.
(Sad because I use Hack in my day job and PHP for my open source projects, and find Hack way more pleasant and productive)
That said: the website is open source, feel free to submit a PR if you find time before I do :D
It may make it slightly slower
So better typing can definitely help to catch those before pushing and running your code.
The answers below show a good solution for this issue: use static analysis tools in build time and potentially even as a pre-commit hook.