Пых, Typhoon
namespace Photoshop;
function brighten(string $color, float $amount): string
{
// ...
}
$blue = '#4F5B93';
echo brighten($blue, 1.2);
final class Color
{
public static function fromHex(string $hex): self
{
return new self($hex);
}
var string $hex;
private function __construct(string $hex)
{
$this->hex = $hex;
}
public function brighten(float $amount): self
{
// ...
}
}
$blue = Color::fromHex('#4F5B93');
echo $blue->brighten(1.2)->hex;
/**
* @property-read string $hex
*/
final class Color
{
private string $hex;
public function __isset(string $name): bool
{
return $name === 'hex';
}
public function __get(string $name)
{
if ($name === 'hex') {
return $this->hex;
}
throw new PropertyDoesNotExist(self::class, $name);
}
// ...
}
/**
* @property-read string $hex
*/
final class Color
{
private string $hex;
public function __isset(string $name): bool {}
public function __get(string $name) {}
// ...
}
$blue = Color::fromHex('#4F5B93');
echo $blue->brighten(1.2)->hex;
final class Color
{
/**
* @psalm-readonly-allow-private-mutation
*/
public string $hex;
// ...
}
$blue = Color::fromHex('#4F5B93');
echo $blue->brighten(1.2)->hex;
final class Color
{
private string $hex;
public function getHex(): string
{
return $this->hex;
}
// ...
}
$blue = Color::fromHex('#4F5B93');
echo $blue->brighten(1.2)->getHex();
final readonly class Color
{
private function __construct(
public string $hex,
) {}
// ...
}
$blue = Color::fromHex('#4F5B93');
echo $blue->brighten(1.2)->hex;
final readonly class Color
{
private function __construct(
private int $red,
private int $green,
private int $blue,
) {}
// ...
}
$blue = Color::fromHex('#4F5B93');
echo $blue->brighten(1.2)->hex; ❌
final readonly class Color
{
public string $hex;
private function __construct(
private int $red,
private int $green,
private int $blue,
) {
$this->hex = sprintf('#%X%X%X', $red, $green, $blue);
}
// ...
}
$blue = Color::fromHex('#4F5B93');
echo $blue->brighten(1.2)->hex;
final readonly class Color
{
public string $hex;
private function __construct(
private int $red,
private int $green,
private int $blue,
) {
$this->hex = sprintf('#%X%X%X', $red, $green, $blue);
}
// ...
}
$blue = Color::fromHex('#4F5B93');
echo $blue->brighten(1.2)->hex;
final class Color
{
private function __construct(
private readonly int $red,
private readonly int $green,
private readonly int $blue,
) {}
public string $hex {
get => sprintf('#%X%X%X', $this->red, $this->green, $this->blue);
}
// ...
}
$blue = Color::fromHex('#4F5B93');
echo $blue->brighten(1.2)->hex;
final class Color
{
private function __construct(
private readonly int $red,
private readonly int $green,
private readonly int $blue,
) {}
public string $hex {
get => sprintf('#%X%X%X', $this->red, $this->green, $this->blue);
}
// ...
}
$blue = Color::fromHex('#4F5B93');
// ❌ Fatal error: Property Photoshop\Color::$hex is read-only
$blue->hex = 'сломайся';
final readonly class PageViewed {}
final class PageViewsProjection
{
/**
* @psalm-readonly-allow-private-mutation
*/
public int $views = 0;
public function onPageViewed(PageViewed $event): void
{
++$this->views;
}
}
final class PageViewsProjection
{
/**
* @psalm-readonly-allow-private-mutation
*/
public int $views = 0;
public function onPageViewed(PageViewed $event): void
{
++$this->views;
}
}
$projection = new PageViewsProjection();
$projection->onPageViewed(new PageViewed());
$projection->onPageViewed(new PageViewed());
$projection->views += 100_000;
echo $projection->views; // 100_002
final class PageViewsProjection
{
public private(set) int $views = 0;
public function on(PageViewed $event): void
{
++$this->views;
}
}
$projection = new PageViewsProjection();
// ❌ Cannot modify private(set) property from global scope
$projection->views += 100_000;
interface PageStatistics
{
public int $views { get; }
}
function controller(PageStatistics $statistics): string
{
return json_encode([
'views' => $statistics->views,
]);
}
interface PageStatistics
{
public int $views { get; }
}
final class PageViewsProjection implements PageStatistics
{
public private(set) int $views = 0;
public function on(PageViewed $event): void
{
++$this->views;
}
}
interface PageStatistics
{
public int $views { get; }
}
final readonly class PredeterminedPageStatistics implements PageStatistics
{
public function __construct(
public int $views,
) {}
}
final readonly class Report
{
public function __construct(
public array $data,
) {}
}
final class Analytics
{
public function buildReport(): Report
{
return new Report($this->loadData());
}
private function loadData(): array
{
// тяжёлые запросы
sleep(10);
return ['data'];
}
}
$report = new Analytics()->buildReport(); // ожидание 10 секунд
var_dump($report->data);
interface Report
{
public array $data { get; }
}
final class LazyReport implements Report
{
public function __construct(
private readonly Closure $loader,
) {}
public private(set) array $data {
get => $this->data ??= ($this->loader)();
set => $value;
}
}
final class LazyReport implements Report
{
public function __construct(
private readonly Closure $loader,
) {}
public private(set) array $data {
get => $this->data ??= ($this->loader)();
set => $value;
}
}
final class Analytics
{
public function buildReport(): Report
{
return new LazyReport($this->loadData(...));
}
// ...
}
$report = new Analytics()->buildReport();
var_dump($report->data); // ожидание 10 секунд
final readonly class Report
{
public function __construct(
public array $data,
) {}
}
final class Analytics
{
public function buildReport(): Report
{
return new ReflectionClass(Report::class)->newLazyGhost(
initializer: function (Report $report): void {
$report->__construct($this->loadData());
}
);
}
// ...
}
$report = new Analytics()->buildReport();
var_dump($report->data); // ожидание 10 секунд
interface Analytics
{
public function buildReport(): Report;
}
final readonly class PostgresAnalytics implements Analytics
{
public function buildReport(): Report
{
// тяжёлые запросы
sleep(10);
return new Report(['data']);
}
}
$report = new PostgresAnalytics()->buildReport(); // ожидание 10 секунд
var_dump($report->data);
final readonly class LazyAnalytics implements Analytics
{
public function __construct(
private Analytics $analytics,
) {}
public function buildReport(): Report
{
return new ReflectionClass(Report::class)->newLazyProxy(
factory: $this->analytics->buildReport(...)
);
}
}
$report = new LazyAnalytics(new PostgresAnalytics())->buildReport();
var_dump($report->data); // ожидание 10 секунд
final class Analytics
{
public function buildReport(): Report
{
return new ReflectionClass(Report::class)->newLazyGhost(
initializer: function (Report $report): void {
$report->__construct($this->loadData());
}
);
}
}
final readonly class LazyAnalytics implements Analytics
{
public function __construct(
private Analytics $analytics,
) {}
public function buildReport(): Report
{
return new ReflectionClass(Report::class)->newLazyProxy(
factory: $this->analytics->buildReport(...)
);
}
}
namespace BCMath;
final readonly class Number
{
public string $value;
public int $scale;
public function __construct(string|int $num) {}
public function add(Number|string|int $num, ?int $scale = null): self {}
public function floor(): self {}
public function round(
int $precision = 0,
RoundingMode $mode = RoundingMode::HalfAwayFromZero,
): self {}
public function __toString(): string {}
// ...
}
// value: 3.341, scale: 3
var_dump(
new Number('1.23') + new Number('2.111'),
);
// value: 3.341000, scale: 6
var_dump(
new Number('1.23')->add(new Number('2.111'), scale: 6),
);
// value: 3.3, scale: 1
var_dump(
new Number('1.23')->add(new Number('2.111'), scale: 1),
);
composer why-not php '^8.4'
composer require symfony/polyfill-php84
mb_ucfirst
, mb_lcfirst
array_find
, array_find_key
, array_any
, array_all
#[Deprecated]
CURL_HTTP_VERSION_3
, CURL_HTTP_VERSION_3ONLY