
Union Types have been accepted for PHP 8 - BafS
https://wiki.php.net/rfc/union_types_v2
======
yagodragon
When I started programming a few years back, I was told that PHP is legacy
tech and a terrible language I should avoid like a plague. After years of
battling with Node.js on the backend, I took a closer look at modern PHP and
the Laravel framework and I was amazed by how good the developer experience
was. The language itself feels like a lite version of Java. I believe everyone
starting on web development should know PHP. It's hugely deployed, it has a
very mature and rich ecosystem and it's a great language to build your side
project/business without spending your time on meaningless tasks. Don't be
driven by FOMO like I was, there's no such thing as a "perfect programming
language". Every language has it's quirks and that's fine. PHP might be old
and boring but it helps you get things done faster than using the new coolest
language.

~~~
idoubtit
PHP has come a long way, and nowadays it's in the same category as Python.
Worse in many ways, but better by other, like the type declarations and their
(runtime) enforcing.

Yet there are still many ugly sides to PHP, and Laravel illustrates most of
them. There is so much magic that IDE can't follow: some classes have a
`__call()` magic function that redirect methods calls to other instances. Some
functions return values of varying types, with no common interface.

I've worked with several PHP frameworks, and Laravel is by far the worst. Its
awful documentation plays a big role in this (no real reference doc, just a
tutorial ; no links to classes or function in the doc ; the API doc is a joke
; the acclaimed "laracasts" are useless for serious work). The fact that this
framework is dominant in the PHP community is worrying.

~~~
thdrdt
Laravel is popular because it allows you to setup your project very quickly.

And then the trouble starts. Remember what properties your models had? No?
Well so doesn't your IDE. There is just too much magic going on to keep things
maintainable.

If you like a framework like Laravel you should go with Symfony instead. But
don't use annotations. Keeps things separated so you and your colleagues can
find routing and database information at logical places instead of all over
the place in classes.

~~~
xellisx
Laravel, from my own experience is full of deep rooted magic, and assumptions.
Also it throws SOLID out the window.

We use Symfony at work and we turned off the annotations package, use XML
mapping for our models.

Of course, Symfony and Doctrine do have some frustation points.

~~~
thanato0s
I have the same experience. Laravel is way too magical for me.

I use Symfony for quite some time and at one point I stopped using Doctrine
data mapper. The DBAL and the query builder are enough.

~~~
xellisx
If it were up to me, it would all be SQL queries. Maybe even use the library I
rebuilt - [https://github.com/ellisgl/GeekLab-
GLPDO2](https://github.com/ellisgl/GeekLab-GLPDO2)

------
brenden2
Whether you love it or hate it, it's cool that the PHP project has come so
far. I know a lot of people still use PHP every day, so it's good to see the
language continues to improve. I imagine a significant percentage of web
services are still PHP based to this day.

~~~
bpicolo
Over 30%, thanks to Wordpress.

~~~
tambourine_man
Facebook, Wikipedia

~~~
no_wizard
I believe that Facebook is fully transitioning to hacklang

[https://hacklang.org/](https://hacklang.org/)

~~~
captn3m0
Doesn’t that count as a PHP dialect?

~~~
krapp
Depends on what you mean by "dialect." I believe complete backwards
compatibility with PHP is no longer a goal of Hack.

------
tylerjwilk00
It's nice to start out typeless during problem domain discovery and proof of
concept phase then quickly introduce types when you better understand the
problem. This change will help that phase transition with enforcement right in
the runtime as opposed to simple doc block annotations.

~~~
peterkelly
"Bad programmers worry about the code. Good programmers worry about data
structures and their relationships."

― Linus Torvalds

Discussion:
[https://news.ycombinator.com/item?id=4560334](https://news.ycombinator.com/item?id=4560334)

~~~
tylerjwilk00
Yes. We want to spend as little time as possible on code so we can quickly
find the data structure that best solves the problem we have yet to
understand.

    
    
      // I know nothing. Not sure what types would work best...
      public function method($data)
    
      // I know more
      public function method($data array)
    
      // More
      public function method($data array|false)
    
      // Even more
      public function method($data array|false) : int
    
      // Ah. Okay. I understand the problem domain and have proper data structures to solve it
      public function method($data array|false) : int|float
      
    

Notice the type system never got in our way. We organically grew into the type
system as our understanding of the data evolved.

------
ilovecaching
I wonder how stock PHP is stacking up to Hack both from the dimensions of
efficiency, safety, and productivity these days.

~~~
tylerjwilk00
The Hack HHVM JIT is typically more performant than standard PHP 7. However,
that is more of an apples to oranges comparison of JIT vs Non-JIT than Lang to
Lang comparison.

That said, PHP 7 has squeezed most of the performance from the language and
the low hanging fruit is gone.

However, PHP 8 looks to bring a standard JIT to PHP [1]. I'd guess that once
that happens Hack / HHVM may no longer have any advantage.

[1] [https://hub.packtpub.com/php-8-and-7-4-to-come-with-just-
in-...](https://hub.packtpub.com/php-8-and-7-4-to-come-with-just-in-time-jit-
to-make-most-cpu-intensive-workloads-run-significantly-faster/)

~~~
judge2020
Just to add (you didn't say otherwise), PHP on HHVM is EoL'd
[https://hhvm.com/blog/2018/09/12/end-of-php-support-
future-o...](https://hhvm.com/blog/2018/09/12/end-of-php-support-future-of-
hack.html).

~~~
tyingq
_" PHP on HHVM is EoL'd"_

True that you shouldn't expect large existing PHP projects to run. But, the
syntax is close enough that for net new projects, it's essentially PHP.

------
Supermancho
This is one bad feature among many good decisions, but bad nonetheless. The
language will have yet-another-way to do type-erasure/autoboxing that will
have to be tracked down, in the interest of removing boilerplate when multiple
types are desired to be coerced. Type safety is recognized as valuable by the
PHP core voters on one hand, and waved away by the other.

Imagine the fun!

<?php

function callit(float $numI) {

    
    
        $numB = $numI || ($numI/2);
    
        echo gettype($numB)."\n";
    
        $numF = ($numI/2);
    
        echo gettype($numF)."\n";
    
        return some($numB);
    

}

function someType(int|float $numX):int {

    
    
        echo gettype($numX)."\n";
    
        return $numX;
    

}

$ret = callit(2);

echo gettype($ret)."\n";

~~~
robotron
That's why you do this instead:

<?php declare(strict_types=1);

Your code would flag an error in the IDE and throw a TypeError exception.

------
6gvONxR4sf7o
This is cool! I wish tools like postgres had them too.

~~~
weberc2
Do any relational databases have them? I’ve never understood why not. They go
through the trouble of providing a mechanism to formally model your data
schema, but if your data involves things that can be one thing or another,
they totally punt and ask you to find a way to hack it on top via ORMs or
similar. Why not model everything in Postgres such that users can issue
requests against their actual data model and Postgres can make it fast,
instead of building a shim layer between the data model surface and Postgres
(shim layer = ORM, in case it wasn’t obvious) that can only generate queries
that are likely more difficult for Postgres to optimize for lack of missing
type information.

~~~
coldtea
> _Do any relational databases have them? I’ve never understood why not_

For one, because they need a fixed binary representation for the type, to
persist it on disk. In a programming language yoi do things in memory, so you
don't have that issue...

Still, you could have had union types, or even coerce everything as string, as
SQLite does, but it would be bad for performance as they'd need an alternate
representation.

~~~
weberc2
> For one, because they need a fixed binary representation for the type, to
> persist it on disk. In a programming language yoi do things in memory, so
> you don't have that issue...

Memory and consequently programming languages also requires a fixed binary
representation. How you represent data is orthogonal to its storage medium--
you can write application memory to disk and read it back in, no problem
(e.g., swap).

> Still, you could have had union types, or even coerce everything as string,
> as SQLite does, but it would be bad for performance as they'd need an
> alternate representation.

The problem doesn't go away by moving support out of the database and into the
application; it only makes it worse insofar as the application is limited in
its optimizations. At the end of the day, the real world has sum types,
applications use them, and they are encoded into databases--they simply aren't
encoded _well_ and the database isn't giving you any correctness guarantees as
it does for product types (i.e., structs, records, etc).

~~~
coldtea
> _Memory and consequently programming languages also requires a fixed binary
> representation_

Already covered that.

Programming languages can save their data as unions or structs, and take the
minimal hit to switch on the type.

DB's persisting data on disk can do the same but will take a much bigger hit.

> _How you represent data is orthogonal to its storage medium--you can write
> application memory to disk and read it back in, no problem (e.g., swap)._

The costs are not orthogonal to the storage medium however.

> _The problem doesn 't go away by moving support out of the database and into
> the application_

On the DBs side, it does go away. The DB only has to guarantee what it says it
supports (only store one specific type in a column). So for the DB
implementors, that's a great invariant for their implementation ease and
performance.

~~~
weberc2
> Already covered that.

Where? I didn’t see it.

> Programming languages can save their data as unions or structs, and take the
> minimal hit to switch on the type. DB's persisting data on disk can do the
> same but will take a much bigger hit.

Yeah, of course. Disk is more expensive across the board. Same applies for
storing ints, but databases don’t punt on that. And anyway, the sum types
still exist in the schema, they are just implicit, as hoc spectacles built on
the fly by the user. So you’re still dealing with performance issues, but
they’re worse.

> On the DBs side, it does go away. The DB only has to guarantee what it says
> it supports (only store one specific type in a column). So for the DB
> implementors, that's a great invariant for their implementation ease and
> performance.

This applies to every feature for every tool. You don’t have to solve the
problem if you just put it on your users.

Of course, tools have charters, and the relational axiom is that users
shouldn’t have to manage their own storage and retrieval layer, but rather
they should declare a data model and interface with it and the RDBMS would
make search and retrieval fast and correct. Sum types are necessary in data
modeling, so it fits clearly and neatly into the charter.

~~~
coldtea
> _Where? I didn’t see it._

"For one, because they need a fixed binary representation for the type, to
persist it on disk. In a programming language you do things in memory, so you
don't have that issue..."

The crucial difference I point is "persist on disk" vs "do it in memory", not
in the "binary representation". Both running programs and DBs have one, but
one absolutely needs to be persisted on disk, whereas live program memory
doesn't.

> _This applies to every feature for every tool. You don’t have to solve the
> problem if you just put it on your users._

There's also the fact that it might not be a problem just an easy cop-out from
the user.

In which case it's better to force your users into the more formal and rigid
structure, and have them rethink their model, than turn the DB into an
"anything goes anywhere" store.

~~~
weberc2
> The crucial difference I point is "persist on disk" vs "do it in memory",
> not in the "binary representation". Both running programs and DBs have one,
> but one absolutely needs to be persisted on disk, whereas live program
> memory doesn't.

Right, I agree, and my point was it doesn’t matter. Disk vs memory is a red
herring. The same principles apply to both and the fact that disk is slower
applies as much to product types as it does to sum types. In fact, sum types
are represented as product types, but the system enforces invariants about the
structure.

> There's also the fact that it might not be a problem just an easy cop-out
> from the user.

That’s a nope from me. Tools exist to solve problems. If a tool purports to
solve a problem but only does it halfway, it warrants criticism or
observation.

> In which case it's better to force your users into the more formal and rigid
> structure, and have them rethink their model, than turn the DB into an
> "anything goes anywhere" store.

RDBMSs are literally forcing their users into a _less_ formal structure. You
can’t rethink your model and make them go away (they are fundamental data
modeling primitives), you can only find ways to hack product types to
represent them, but you have to do all the work to make them fast and you
probably just have to give up on verifiable safety altogether.

And how do you get from “sum types” to “anything goes data store”? Are you
sure you understand the debate?

------
sedeki
It was long ago I worked with PHP, before PHP 5. Is typing enforced with PHP
these days? Or is it more like type hints, as in Python?

~~~
pilif
For classes it's enforced since PHP 5. For scalars you get to chose between
enforcement or type coercion for callers on a per-file basis.

However, as with other dynamically typed and interpreted languages, all of
this is happening at run-time, so one of the biggest benefits of strong typing
(type checking at compile time) doesn't apply.

~~~
weberc2
You can statically type check a dynamically typed, interpreted language.
Python via Mypy and Typescript being two examples.

~~~
j_jochem
Unfortunately, PHP doesn't ship a tool for this (and it’s hard due to the way
autoloading works). So PHP's typing is slightly less useful than e.g.
TypeScript.

~~~
normaljoe
Tooling is not the issue here, nor is autoloading.

ISO C and C++ doesn't provide tooling, nor should any language. Tooling is
better handled by third parties and implementers. Language should be focused
on application and execution of the language. Unfortunately for PHP the
language and implementation are tightly coupled as is Java and Swift.

A well constructed modern PHP project using composer has the tooling needed to
statically validate. Personally I use PHPStorm but I also use IntelliJ for
Java and Android. There are others out there as well.

Autoloading used correctly is no more than Java using a package line or
namespace.

I find no problem with TypeScript and others. I however have a 10+ million
line code base of PHP that predates TypeScript and others and needs to get a
viable transition path. This gets things closer with real type errors at
runtime. That is way better than my mainframe COBOL counterparts who have no
path forward at the level of modern code.

~~~
j_jochem
Tooling inside IDEs is somwhat useful. But being able to just run a compiler-
like CLI tool to tell you if there are type errors in your program is much
more useful still, since you can run it in pre-commit hooks and on the CI. As
far as I know, a tool which can do this _without_ requiring extensive
configuration and without throwing false positives does not exist yet for PHP.

As for the "language shouldn't provide tooling" argument: You picked C / C++
as a positive example for this. Those are standardized languages which evolve
at a glacial pace. For most of their use cases, this is a good thing. But I'd
say PHP's faster evolution over the last decade was the right thing for that
language. Other modern language projects seem to follow a strategy of a single
standard implementation with extensive tooling pretty successfully (e.g. Go,
Rust, Swift, ..).

------
baby
Now please do this for Golang :)

------
astrodev
Before the usual avalanche of posts criticising some PHP 4 features, the union
types look like a nice way to formalise something that is commonly used and
very useful.

