内容简介:It's only a few months beforePHP 8 will be released, and honestly there are so many good features. In this post I want to share the real-life impact that PHP 8 will have on my own code.I'm going to try not to abuseattributes, but I think configuring event
It's only a few months beforePHP 8 will be released, and honestly there are so many good features. In this post I want to share the real-life impact that PHP 8 will have on my own code.
Events subscribers with attributes
I'm going to try not to abuseattributes, but I think configuring event listeners is an example of an annotation I'll be using extensively.
You might know that I've been working on event sourced systems lately, and I can tell you: there's lots of event configuration to do. Take this simple projector, for example:
// Before
class CartsProjector implements Projector
{
use ProjectsEvents;
protected array $handlesEvents = [
CartStartedEvent::class => 'onCartStarted',
CartItemAddedEvent::class => 'onCartItemAdded',
CartItemRemovedEvent::class => 'onCartItemRemoved',
CartExpiredEvent::class => 'onCartExpired',
CartCheckedOutEvent::class => 'onCartCheckedOut',
CouponAddedToCartItemEvent::class => 'onCouponAddedToCartItem',
];
public function onCartStarted(CartStartedEvent $event): void
{ /* … */ }
public function onCartItemAdded(CartItemAddedEvent $event): void
{ /* … */ }
public function onCartItemRemoved(CartItemRemovedEvent $event): void
{ /* … */ }
public function onCartCheckedOut(CartCheckedOutEvent $event): void
{ /* … */ }
public function onCartExpired(CartExpiredEvent $event): void
{ /* … */ }
public function onCouponAddedToCartItem(CouponAddedToCartItemEvent $event): void
{ /* … */ }
}
PHP 7.4
There are two benefits attributes will give me:
- Event listener configuration and handlers are put together, I don't have to scroll to the top of the file to know whether a listener is configured correctly.
- I don't have to bother anymore writing and managing method names as strings: your IDE can't autocomplete them, there's no static analysis on typos and method renaming doesn't work.
Luckily, PHP 8 solves these problems:
class CartsProjector implements Projector
{
use ProjectsEvents;
@@SubscribesTo(CartStartedEvent::class)
public function onCartStarted(CartStartedEvent $event): void
{ /* … */ }
@@SubscribesTo(CartItemAddedEvent::class)
public function onCartItemAdded(CartItemAddedEvent $event): void
{ /* … */ }
@@SubscribesTo(CartItemRemovedEvent::class)
public function onCartItemRemoved(CartItemRemovedEvent $event): void
{ /* … */ }
@@SubscribesTo(CartCheckedOutEvent::class)
public function onCartCheckedOut(CartCheckedOutEvent $event): void
{ /* … */ }
@@SubscribesTo(CartExpiredEvent::class)
public function onCartExpired(CartExpiredEvent $event): void
{ /* … */ }
@@SubscribesTo(CouponAddedToCartItemEvent::class)
public function onCouponAddedToCartItem(CouponAddedToCartItemEvent $event): void
{ /* … */ }
}
PHP 8
Static instead of doc blocks
A smaller one, but this one will have a day-by-day impact. I often find myself still needing doc blocks because of two things: static return types en generics. The latter one can't be solved yet, but luckily the first one will in PHP 8!
When I'd write this in PHP 7.4:
/**
* @return static
*/
public static function new()
{
return new static();
}
PHP 7.4
I'll now be able to write:
public static function new(): static
{
return new static();
}
PHP 8
If you read my blog, you know I wrote quite a bit about the use of PHP's type system combined with data transfer objects . Naturally, I use lots of DTOs in my own code, so you can image how happy I am, being able to rewrite this:
class CustomerData extends DataTransferObject
{
public string $name;
public string $email;
public int $age;
public static function fromRequest(
CustomerRequest $request
): self {
return new self([
'name' => $request->get('name'),
'email' => $request->get('email'),
'age' => $request->get('age'),
]);
}
}
$data = CustomerData::fromRequest($customerRequest);
PHP 7.4
As this:
class CustomerData
{
public function __construct(
public string $name,
public string $email,
public int $age,
) {}
}
$data = new CustomerData(...$customerRequest->validated());
PHP 8
Note the use of both constructor property promotion , as well as named arguments. Yes, they can be passed using named arrays and the spread operator!
Enums and the match expression
Do you sometimes find yourself using an enum with some methods on it, that will give a different result based on the enum value?
/**
* @method static self PENDING()
* @method static self PAID()
*/
class InvoiceState extends Enum
{
private const PENDING = 'pending';
private const PAID = 'paid';
public function getColour(): string
{
return [
self::PENDING => 'orange',
self::PAID => 'green',
][$this->value] ?? 'gray';
}
}
PHP 7.4
I would argue that for complexer conditions, you're better off usingthe state pattern, yet there are cases where an enum does suffice. This weird array syntax already is a shorthand for a more verbose conditional:
/**
* @method static self PENDING()
* @method static self PAID()
*/
class InvoiceState extends Enum
{
private const PENDING = 'pending';
private const PAID = 'paid';
public function getColour(): string
{
if ($this->value === self::PENDING) {
return 'orange';
}
if ($this->value === self::PAID) {
return 'green'
}
return 'gray';
}
}
PHP 7.4 — alternative
But with PHP 8, we can use the
match
expression
instead!
/**
* @method static self PENDING()
* @method static self PAID()
*/
class InvoiceState extends Enum
{
private const PENDING = 'pending';
private const PAID = 'paid';
public function getColour(): string
{
return match ($this->value) {
self::PENDING => 'orange',
self::PAID => 'green',
default => 'gray',
};
}
PHP 8
Union types instead of doc blocks
When I mentioned the static
return type before, I forgot another use case where docblock type hints were required: union types. At least, they were required before, because PHP 8 supports them natively!
/** * @param string|int $input * * @return string */ public function sanitize($input): string;
PHP 7.4
public function sanitize(string|int $input): string;
PHP 8
Throw expressions
Before PHP 8, you couldn't use throw
in an expression, meaning you'd have to do explicit checks like so:
public function (array $input): void
{
if (! isset($input['bar'])) {
throw BarIsMissing::new();
}
$bar = $input['bar'];
// …
}
PHP 7.4
In PHP 8, throw
has become an expression, meaning you can use it like so:
public function (array $input): void
{
$bar = $input['bar'] ?? throw BarIsMissing::new();
// …
}
PHP 8
What's your favouritePHP 8 feature? Let me know via Twitter or viae-mail!
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
C语言接口与实现
David R. Hanson / 郭旭 / 人民邮电出版社 / 2011-9 / 75.00元
《C语言接口与实现:创建可重用软件的技术》概念清晰、实例详尽,是一本有关设计、实现和有效使用C语言库函数,掌握创建可重用C语言软件模块技术的参考指南。书中提供了大量实例,重在阐述如何用一种与语言无关的方法将接口设计实现独立出来,从而用一种基于接口的设计途径创建可重用的API。 《C语言接口与实现:创建可重用软件的技术》是所有C语言程序员不可多得的好书,也是所有希望掌握可重用软件模块技术的人员......一起来看看 《C语言接口与实现》 这本书的介绍吧!