Cutting Edge: Using PHP 8.0 in Enterprise
Tags: programming, php, codequality, codestyle
Published: 2021-02-26 10:53:45

In this article I am planning to describe perks and features of PHP 8.0, that we are already using or going to use in the one of our new microservices in existing chatbot messaging project. 

As many of PHP developers, my team can't wait to try new version of PHP as soon as possible. So, right in time when new microservice got from strategy planning stage to solution architecture choices, I already knew what it's going to be. Long story short, Symfony 5 and PHP 8.0 were the winners. Here I should mention, that we use microservices coupled with DDD business principles and Onion architecture in almost each of them. [Here](https://dev.to/soulwife/real-life-ddd-in-an-onionshell-3ohb) you can dive in. This strong decoupling made this 'on edge move' possible in such short time.

Meanwhile, what we like and use from the new features: 

#Duplicated Properties Are Dead! Long Live The Constructor

We all have so many Value Objects and Entities. And each of them looks like this:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tyn6xqth3kzqr9f2myb1.png)

PHP 8.0 and Nikita Popov gave us freedom from properties boilerplate for all simple cases, when you set your properties in constructor:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z20m05a55rajbe8v7msj.png)

Nice and easy. We use it with all our new value objects and entities, as well as other resembling classes.
Be careful: those properties are not allowed in abstract classes and interfaces as well as callable and nullable properties. Surely, you can't declare them twice: as properties and in constructor. 

#Let's make a Union with Types

It's definitely the blast! I personally voted for them, because it's such a strong adding to 'typed properties' from the one side and flexibility from the other. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l9q2uwd29unuwlgo1hh2.png)

Either you need different types of a number, string, arrays or interfaces: you can now describe all of possible types as input parameters in your methods, class variables and method return. This way you enforce types, so mistakes can be caught early, types are checked during inheritance, enforcing the Liskov Substitution Principle (L from SOLID). You can freely use Reflection, because union types are available through Reflection. The last, but not least, the syntax needs less amount of efforts, than phpdoc.

So, the question is: what types can't we have as 'union typed'. The following list would be the answer:

- The *void* type could not be part of a union, as void means that a function does not return any value.
- The nullable type notation (*?Type*) is allowed, so we can do *Type|null*, but we are not allowed to include the *?Type* notation in union types (*?Type1|Type2* is not allowed and we should use *Type1|Type2|null* instead).

As many internal functions include `false` among the return types, the `false` pseudo-type is also supported for backward compatibility.
That capability was only added to support legacy code. So, we are not planning to use it for any new code, so should not anyone.

#ValueError Exception
From now on we can catch even more bugs on early stages. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8zgox8ulse87sesaseat.png)

If `$emptyArray` will be empty, that you have ValueError Exception, that extends Exception:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5j64kllznp5gjlabvr0m.png)
 
PHP throws this exception every time you pass a value to a function, which has a valid type, but can not be used for the particular operation (for example, empty arrays, negative number in case with `json_decode`, etc.).

Sure, we will not catch this specific Error each time, but before PHP 8, all those wrong cases throws just a warning, so it was not possible to catch it with Exception, as it is now. 

#Say hello to `Throw` as an expression

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/poftrjxi1ucg5xkx9g6p.png)

Finally, we can have more readable 'possibly wrong' code with even less amount of 'exception handling' code.

For those of you, who does not need en $exception as variable in catch block, it's now possible to not define it:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ewrkfedo4n2r5xvfr6al.png)
 
# String it

PHP 8 gives us a `Stringable` interface that corresponds to an object having the __toString() magic method.

A class may implement a Stringable interface that defines a method public function __toString(): string. Useful fact: if it doesn’t, but still implements that method, the engine will add the method and return type automatically. So, we can now check type in the union type, for example, like this:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0zv3q6ktfu56lhvxdi4h.png)

# Static in return

Many of us get into the situations, when we need to call class methods in chain and get the result from the last one, for example. All those years of JS jokes saying out loud at last gives us chained methods with late static binding from now on. Self, parent and static can now be used in different usecases with chained methods.

#Do not mix with mixed

From 8.0 you can do this:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r0rd9a0hbfqa7pidsqbl.png)

Maybe, it's necessary in some rare cases, but even those cases we refactored to union types in our project. Try to avoid this 'type' as much as possible. Personally, I think it's equal to 'no type at all'. 

#Safe and sound with null

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/plud8e2jcv3erniq6gx0.png)
 
Personally, one of my favorites. No more `if` or strange looking chains with null coalescence operators.

#We have a match!

And my second favorite is `match`. It is pretty similar to well-known `switch` but with safer semantics and allowing to return values. So you don't need the variable for it anymore.
 
>Der Teufel steckt im Detail.

While `switch` compares values loosely (==) potentially leading to unexpected results, match comparison is an identity check (===). I think, it's a huge difference and we are definitely will use `match` instead of `switch`.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4b5v0ayu7shbrbvwf4la.png)

The `match` may also contain multiple comma-separated expressions, that give us opportunity to have more shortened syntax:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/69xqb1n6gsva2k7i0ux2.png)

#More functions, we need more functions

`str_contains` will definitely come in handy for almost all of us.  

Say 'no' to every PHP developer nightmare with looking for a match in string. Everytime it's `strstr` combined with `strpos` and checking to `bigger than zero`. Say 'yes' to one simple function instead of it:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ntw8ax68u9q4ixyx7wxd.png)

`str_starts_with()` and `str_ends_with()` are here for you if you need even more precise search.

#You name it

I see the main advantage of named arguments is that they allow to specify only arguments we want to change. So it's not necessary to specify default arguments if we don’t want to overwrite default values. The following example makes it clear:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i0m4pd9w9sv3j8zn7umf.png)

#Sugar, baby

`$object::class` is a new `get_class()`.

Thanks to Nikita Popov, now instead of remembering another internal function, we can just get the class for an object as simple as that `::class`.

---------------------------------

What we are definitely planning to use [attributes](https://www.php.net/manual/ru/language.attributes.overview.php). As for well-known new feature JIT, I do not see the extreme necessary or gaining some big value for our project in using it at the moment. We have `opcache` enabled, as it is by default and using Go for sockets, long time parsers, etc. But, who knows, maybe we'll try it later.

As conclusion, I should say, that PHP 8.0 got awesome changes and my team and I are so excited to try it in a real live project. We hope, that our code transforms to more clean and readable shape as well as gains performance and usability. 

Time to try it by yourself :)

---------------------------------
*Keep your code clean and clear and yourself safe and sound!*