laravel-throw-if-throw-unless-guard-clauses-tip.png
Π¨Π°Π±Π»ΠΎΠ½ ΠΊΠΎΠ΄ΡƒLaravel

Laravel throw_if() / throw_unless(): винятки Π±Π΅Π· Π·Π°ΠΉΠ²ΠΎΠ³ΠΎ if

Π―ΠΊ Π·Π°ΠΌΡ–Π½ΠΈΡ‚ΠΈ простий if + throw Π½Π° throw_if() Π°Π±ΠΎ throw_unless(), Π²ΠΈΠ±Ρ€Π°Ρ‚ΠΈ Ρ„ΠΎΡ€ΠΌΡƒ Π±Π΅Π· ΠΏΠΎΠ΄Π²Ρ–ΠΉΠ½ΠΎΠ³ΠΎ запСрСчСння, ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΠΈ клас винятку Π· ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°ΠΌΠΈ Ρ‚Π° Π±ΡƒΠ΄ΡƒΠ²Π°Ρ‚ΠΈ Ρ‡ΠΈΡ‚Π°Π±Π΅Π»ΡŒΠ½Ρ– захисні ΠΏΠ΅Ρ€Π΅Π²Ρ–Ρ€ΠΊΠΈ.

Захисна ΠΏΠ΅Ρ€Π΅Π²Ρ–Ρ€ΠΊΠ° часто ΠΌΠ°Ρ” Π΄ΡƒΠΆΠ΅ простий зміст: якщо ΡƒΠΌΠΎΠ²Π° ΠΏΠΎΡ€ΡƒΡˆΠ΅Π½Π°, виконання Π½Π΅ ΠΏΠΎΠ²ΠΈΠ½Π½ΠΎ ΠΉΡ‚ΠΈ Π΄Π°Π»Ρ–. Π£ Π·Π²ΠΈΡ‡Π°ΠΉΠ½ΠΎΠΌΡƒ PHP Ρ†Π΅ ΠΏΡ€ΠΈΡ€ΠΎΠ΄Π½ΠΎ Π·Π°ΠΏΠΈΡΡƒΡ”Ρ‚ΡŒΡΡ Ρ‡Π΅Ρ€Π΅Π· if Ρ– throw.

Коли Ρ‚Π°ΠΊΠ° ΠΏΠ΅Ρ€Π΅Π²Ρ–Ρ€ΠΊΠ° Π·Π°ΠΉΠΌΠ°Ρ” лишС ΠΎΠ΄ΠΈΠ½ простий Π±Π»ΠΎΠΊ, Laravel дозволяє Π·Ρ€ΠΎΠ±ΠΈΡ‚ΠΈ Π½Π°ΠΌΡ–Ρ€ Ρ‰Π΅ ΠΏΠΎΠΌΡ–Ρ‚Π½Ρ–ΡˆΠΈΠΌ Ρ‡Π΅Ρ€Π΅Π· throw_if() Π°Π±ΠΎ throw_unless().

Π—Π°ΠΌΡ–ΡΡ‚ΡŒ простого if + throw

Π”ΠΎ
php
if (! $user->isActive()) {    throw new DomainException(        'User must be active.',    );}
ΠŸΡ–ΡΠ»Ρ
php
throw_unless(    $user->isActive(),    DomainException::class,    'User must be active.',);

Обидва Π²Π°Ρ€Ρ–Π°Π½Ρ‚ΠΈ Π·ΡƒΠΏΠΈΠ½ΡΡŽΡ‚ΡŒ виконання, якщо користувач Π½Π΅Π°ΠΊΡ‚ΠΈΠ²Π½ΠΈΠΉ. АлС throw_unless() Ρ‡ΠΈΡ‚Π°Ρ”Ρ‚ΡŒΡΡ як ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠ΅ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ: ΠΏΡ€ΠΎΠ΄ΠΎΠ²ΠΆΡƒΠΉ лишС Ρ‚ΠΎΠ΄Ρ–, ΠΊΠΎΠ»ΠΈ користувач Π°ΠΊΡ‚ΠΈΠ²Π½ΠΈΠΉ.

Π¦Π΅ Π½Π°ΠΉΠ±Ρ–Π»ΡŒΡˆ корисно Π½Π° ΠΏΠΎΡ‡Π°Ρ‚ΠΊΡƒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ, Π΄Π΅ ΠΊΡ–Π»ΡŒΠΊΠ° захисних ΠΏΠ΅Ρ€Π΅Π²Ρ–Ρ€ΠΎΠΊ Π²ΠΈΠ·Π½Π°Ρ‡Π°ΡŽΡ‚ΡŒ, Ρ‡ΠΈ ΠΌΠΎΠΆΠ½Π° Π²Π·Π°Π³Π°Π»Ρ– ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΡ‚ΠΈ Π΄ΠΎ основної Π»ΠΎΠ³Ρ–ΠΊΠΈ.

throw_if() Ρ– throw_unless() ΠΎΠΏΠΈΡΡƒΡŽΡ‚ΡŒ ΡƒΠΌΠΎΠ²Ρƒ Π· Ρ€Ρ–Π·Π½ΠΈΡ… Π±ΠΎΠΊΡ–Π²

PHP - Π’ΠΈΠ±ΠΈΡ€Π°ΠΉΡ‚Π΅ Ρ„ΠΎΡ€ΠΌΡƒ, яка Ρ‡ΠΈΡ‚Π°Ρ”Ρ‚ΡŒΡΡ ΠΏΡ€ΠΈΡ€ΠΎΠ΄Π½ΠΎ
throw_if(    $order->isCancelled(),    DomainException::class,    'Cancelled order cannot be processed.',); throw_unless(    $user->isActive(),    DomainException::class,    'User must be active.',);
НС Π²ΠΈΠ±ΠΈΡ€Π°ΠΉΡ‚Π΅ helper ΠΌΠ΅Ρ…Π°Π½Ρ–Ρ‡Π½ΠΎ. throw_if() Π΄ΠΎΠ±Ρ€Π΅ Ρ‡ΠΈΡ‚Π°Ρ”Ρ‚ΡŒΡΡ Π· Π½Π΅Π³Π°Ρ‚ΠΈΠ²Π½ΠΈΠΌ станом Π½Π° ΠΊΡˆΡ‚Π°Π»Ρ‚ isCancelled(), Π° throw_unless() - Π· ΠΏΠΎΠ·ΠΈΡ‚ΠΈΠ²Π½ΠΈΠΌ Ρ–Π½Π²Π°Ρ€Ρ–Π°Π½Ρ‚ΠΎΠΌ Π½Π° ΠΊΡˆΡ‚Π°Π»Ρ‚ isActive(). Π£Π½ΠΈΠΊΠ°ΠΉΡ‚Π΅ ΠΏΠΎΠ΄Π²Ρ–ΠΉΠ½ΠΈΡ… Π·Π°ΠΏΠ΅Ρ€Π΅Ρ‡Π΅Π½ΡŒ.

МоТна ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΠΈ клас винятку Ρ‚Π° Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΈ ΠΉΠΎΠ³ΠΎ конструктора

PHP - Клас винятку Π· ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°ΠΌΠΈ конструктора
final class InactiveUserException extends DomainException{    public function __construct(int $userId)    {        parent::__construct(            "User {$userId} must be active.",        );    }} throw_unless(    $user->isActive(),    InactiveUserException::class,    $user->id,);

Π”Ρ€ΡƒΠ³ΠΈΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ ΠΌΠΎΠΆΠ΅ Π±ΡƒΡ‚ΠΈ назвою класу винятку. Π―ΠΊΡ‰ΠΎ ΡƒΠΌΠΎΠ²Π° Π²ΠΈΠΌΠ°Π³Π°Ρ” ΠΊΠΈΠ½ΡƒΡ‚ΠΈ виняток, Laravel ΡΡ‚Π²ΠΎΡ€ΠΈΡ‚ΡŒ Ρ†Π΅ΠΉ клас Ρ– ΠΏΠ΅Ρ€Π΅Π΄Π°ΡΡ‚ΡŒ наступні Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΈ Π² ΠΉΠΎΠ³ΠΎ конструктор.

Π¦Π΅ Π΄ΠΎΠ±Ρ€Π΅ ΠΏΡ€Π°Ρ†ΡŽΡ” Π· ΠΏΡ€Π΅Π΄ΠΌΠ΅Ρ‚Π½ΠΈΠΌΠΈ винятками, Π΄Π΅ Π½Π°Π·Π²Π° класу ΠΏΠΎΡΡΠ½ΡŽΡ” ΠΏΡ€ΠΈΡ‡ΠΈΠ½Ρƒ Π·ΡƒΠΏΠΈΠ½ΠΊΠΈ ΠΊΡ€Π°Ρ‰Π΅ Π·Π° загальний RuntimeException.

Helper Ρ‚Π°ΠΊΠΎΠΆ ΠΏΡ€ΠΈΠΉΠΌΠ°Ρ” Π³ΠΎΡ‚ΠΎΠ²ΠΈΠΉ виняток Π°Π±ΠΎ Π·Π²ΠΈΡ‡Π°ΠΉΠ½ΠΈΠΉ тСкст

PHP - Π“ΠΎΡ‚ΠΎΠ²ΠΈΠΉ виняток Π°Π±ΠΎ RuntimeException Π· тСкстом
throw_if(    $order->isLocked(),    new LogicException('Order is locked.'),); throw_if(    $quantity < 1,    'Quantity must be greater than zero.',);

МоТна ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΠΈ Π²ΠΆΠ΅ створСний ΠΎΠ±'Ρ”ΠΊΡ‚ винятку. Π―ΠΊΡ‰ΠΎ Π΄Ρ€ΡƒΠ³ΠΈΠΌ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠΌ Ρ” Π·Π²ΠΈΡ‡Π°ΠΉΠ½ΠΈΠΉ тСкст, Laravel ΡΡ‚Π²ΠΎΡ€ΠΈΡ‚ΡŒ RuntimeException Π· Ρ†ΠΈΠΌ повідомлСнням.

Для бізнСс-ΠΏΡ€Π°Π²ΠΈΠ» ΠΎΠΊΡ€Π΅ΠΌΠΈΠΉ клас винятку часто Π΄Π°Ρ” ΠΊΡ€Π°Ρ‰ΠΈΠΉ ΠΊΠΎΠ½Ρ‚Ρ€Π°ΠΊΡ‚, Π° ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΈΠΉ тСкст Π·Ρ€ΡƒΡ‡Π½ΠΈΠΉ для Π»ΠΎΠΊΠ°Π»ΡŒΠ½ΠΈΡ… Ρ‚Π΅Ρ…Π½Ρ–Ρ‡Π½ΠΈΡ… ΠΏΠ΅Ρ€Π΅Π²Ρ–Ρ€ΠΎΠΊ.

ΠšΡ–Π»ΡŒΠΊΠ° Π½Π΅Π·Π°Π»Π΅ΠΆΠ½ΠΈΡ… ΠΏΡ€Π°Π²ΠΈΠ» Π΄ΠΎΠ±Ρ€Π΅ Ρ‡ΠΈΡ‚Π°ΡŽΡ‚ΡŒΡΡ як ΠΏΠΎΡΠ»Ρ–Π΄ΠΎΠ²Π½Ρ–ΡΡ‚ΡŒ захисних ΠΏΠ΅Ρ€Π΅Π²Ρ–Ρ€ΠΎΠΊ

PHP - ΠŸΠΎΡΠ»Ρ–Π΄ΠΎΠ²Π½Ρ– захисні ΠΏΠ΅Ρ€Π΅Π²Ρ–Ρ€ΠΊΠΈ
throw_unless(    $user->isActive(),    InactiveUserException::class,    $user->id,); throw_if(    $order->isCancelled(),    OrderCancelledException::class,    $order->id,); throw_unless(    $order->canBeProcessed(),    OrderCannotBeProcessedException::class,    $order->id,

Основна Π»ΠΎΠ³Ρ–ΠΊΠ° Π·Π°Π»ΠΈΡˆΠ°Ρ”Ρ‚ΡŒΡΡ Π²Π½ΠΈΠ·Ρƒ Π±Π΅Π· Π΄ΠΎΠ΄Π°Ρ‚ΠΊΠΎΠ²ΠΈΡ… Ρ€Ρ–Π²Π½Ρ–Π² вкладСності. КоТСн рядок ΠΏΠ΅Ρ€Π΅Π΄ нСю Π²Ρ–Π΄ΠΏΠΎΠ²Ρ–Π΄Π°Ρ” Π½Π° ΠΎΠ΄Π½Π΅ питання: яка ΡƒΠΌΠΎΠ²Π° ΠΏΠΎΠ²ΠΈΠ½Π½Π° виконуватися, Ρ‰ΠΎΠ± ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΌΡ–Π³ ΠΏΡ€ΠΎΠ΄ΠΎΠ²ΠΆΠΈΡ‚ΠΈ Ρ€ΠΎΠ±ΠΎΡ‚Ρƒ.

Π’Π°ΠΊΠΈΠΉ ΡΡ‚ΠΈΠ»ΡŒ особливо Π·Ρ€ΡƒΡ‡Π½ΠΈΠΉ, ΠΊΠΎΠ»ΠΈ ΠΏΠ΅Ρ€Π΅Π²Ρ–Ρ€ΠΊΠΈ Π½Π΅Π·Π°Π»Π΅ΠΆΠ½Ρ– ΠΎΠ΄Π½Π° Π²Ρ–Π΄ ΠΎΠ΄Π½ΠΎΡ— Ρ– ΠΊΠΎΠΆΠ½Π° ΠΌΠ°Ρ” власний виняток.

Π‘ΠΊΠ»Π°Π΄Π½Ρƒ ΡƒΠΌΠΎΠ²Ρƒ ΠΊΡ€Π°Ρ‰Π΅ спочатку Π½Π°Π·Π²Π°Ρ‚ΠΈ

Π”ΠΎ
php
throw_unless(    $user->isActive()        && ! $order->isCancelled()        && (            $order->belongsTo($user)            || $user->isAdmin()        ),    DomainException::class,    'Order cannot be processed.',);
ΠŸΡ–ΡΠ»Ρ
php
$canProcessOrder =    $user->isActive()    && ! $order->isCancelled()    && (        $order->belongsTo($user)        || $user->isAdmin()    ); throw_unless(    $canProcessOrder,    DomainException::class,    'Order cannot be processed.',);

throw_if() Ρ– throw_unless() Π½Π΅ Ρ€ΠΎΠ±Π»ΡΡ‚ΡŒ складну ΡƒΠΌΠΎΠ²Ρƒ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΡ‡Π½ΠΎ Π·Ρ€ΠΎΠ·ΡƒΠΌΡ–Π»ΠΎΡŽ. Π―ΠΊΡ‰ΠΎ Π²ΠΈΡ€Π°Π· ΡƒΠΆΠ΅ Π²Π°ΠΆΠΊΠΎ ΠΏΡ€ΠΎΡ‡ΠΈΡ‚Π°Ρ‚ΠΈ, Π΄Π°ΠΉΡ‚Π΅ ΠΉΠΎΠΌΡƒ Π½Π°Π·Π²Ρƒ Π°Π±ΠΎ Π²ΠΈΠ½Π΅ΡΡ–Ρ‚ΡŒ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ Π² ΠΎΠΊΡ€Π΅ΠΌΠΈΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄.

Π’Π°ΠΊΠΎΠΆ Ρ†Ρ– helper-Ρ„ΡƒΠ½ΠΊΡ†Ρ–Ρ— Π½Π΅ Ρ” Π·Π°ΠΌΡ–Π½ΠΎΡŽ для всіх Ρ–Π½ΡˆΠΈΡ… ΠΌΠ΅Ρ…Π°Π½Ρ–Π·ΠΌΡ–Π² Laravel. Для ΠΏΠ΅Ρ€Π΅Π²Ρ–Ρ€ΠΊΠΈ Π²Ρ…Ρ–Π΄Π½ΠΈΡ… Π΄Π°Π½ΠΈΡ… ΠΊΡ€Π°Ρ‰Π΅ використовувати validation, для ΠΏΡ€Π°Π²ΠΈΠ» доступу - policies Π°Π±ΠΎ gates, Π° для простого HTTP status response ΠΌΠΎΠΆΡƒΡ‚ΡŒ Π±ΡƒΡ‚ΠΈ Π΄ΠΎΡ€Π΅Ρ‡Π½Ρ– abort_if() Ρ‚Π° abort_unless().

Π¦Π΅ скорочСння синтаксису, Π° Π½Π΅ Π½ΠΎΠ²Π° модСль ΠΎΠ±Ρ€ΠΎΠ±ΠΊΠΈ ΠΏΠΎΠΌΠΈΠ»ΠΎΠΊ

throw_if() Ρ– throw_unless() Π½Π΅ ΡΡ‚Π²ΠΎΡ€ΡŽΡŽΡ‚ΡŒ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†Ρ–ΡŽ, Π½Π΅ Π·Π²Ρ–Ρ‚ΡƒΡŽΡ‚ΡŒ ΠΏΡ€ΠΎ виняток ΠΎΠΊΡ€Π΅ΠΌΠΈΠΌ способом Ρ– Π½Π΅ ΠΏΠ΅Ρ€Π΅Ρ‚Π²ΠΎΡ€ΡŽΡŽΡ‚ΡŒ ΠΉΠΎΠ³ΠΎ Π½Π° HTTP-Π²Ρ–Π΄ΠΏΠΎΠ²Ρ–Π΄ΡŒ самі ΠΏΠΎ собі. Π’ΠΎΠ½ΠΈ лишС ΠΏΠ΅Ρ€Π΅Π²Ρ–Ρ€ΡΡŽΡ‚ΡŒ ΡƒΠΌΠΎΠ²Ρƒ Ρ‚Π° ΠΊΠΈΠ΄Π°ΡŽΡ‚ΡŒ Π²ΠΊΠ°Π·Π°Π½ΠΈΠΉ виняток.

Коли Π·Π²ΠΈΡ‡Π°ΠΉΠ½ΠΈΠΉ if + throw ΠΊΡ€Π°Ρ‰ΠΈΠΉ

  • ΠΊΠΎΠ»ΠΈ ΠΏΠ΅Ρ€Π΅Π΄ винятком Ρ‚Ρ€Π΅Π±Π° Π²ΠΈΠΊΠΎΠ½Π°Ρ‚ΠΈ ΠΊΡ–Π»ΡŒΠΊΠ° Π΄Ρ–ΠΉ;
  • ΠΊΠΎΠ»ΠΈ ΡƒΠΌΠΎΠ²Π° ΠΌΠ°Ρ” складнС пояснСння Ρ– ΠΎΠΊΡ€Π΅ΠΌΠΈΠΉ Π±Π»ΠΎΠΊ Ρ€ΠΎΠ±ΠΈΡ‚ΡŒ ΠΊΠΎΠ΄ Π·Ρ€ΠΎΠ·ΡƒΠΌΡ–Π»Ρ–ΡˆΠΈΠΌ;
  • ΠΊΠΎΠ»ΠΈ Ρ” else Π°Π±ΠΎ ΠΊΡ–Π»ΡŒΠΊΠ° Ρ€Ρ–Π·Π½ΠΈΡ… Π³Ρ–Π»ΠΎΠΊ ΠΏΠΎΠ²Π΅Π΄Ρ–Π½ΠΊΠΈ;
  • ΠΊΠΎΠ»ΠΈ ΠΏΠ΅Ρ€Π΅Π²Ρ–Ρ€ΠΊΠ° ΠΌΡ–ΡΡ‚ΠΈΡ‚ΡŒ Π²Π°ΠΆΠ»ΠΈΠ²ΠΈΠΉ контСкст, який Π³ΡƒΠ±ΠΈΡ‚ΡŒΡΡ Π² ΠΎΠ΄Π½ΠΎΠΌΡƒ рядку;
  • ΠΊΠΎΠ»ΠΈ Π·Π²ΠΈΡ‡Π°ΠΉΠ½ΠΈΠΉ if для ΠΊΠΎΠΌΠ°Π½Π΄ΠΈ Ρ‡ΠΈΡ‚Π°Ρ”Ρ‚ΡŒΡΡ ΠΏΡ€ΠΈΡ€ΠΎΠ΄Π½Ρ–ΡˆΠ΅ Π·Π° Π½Π΅Π·Π½Π°ΠΉΠΎΠΌΡƒ helper-Ρ„ΡƒΠ½ΠΊΡ†Ρ–ΡŽ.

Π‘ΠΈΠ»Π° throw_if() Ρ– throw_unless() Π½Π΅ Π² ΠΌΡ–Π½Ρ–ΠΌΠ°Π»ΡŒΠ½Ρ–ΠΉ ΠΊΡ–Π»ΡŒΠΊΠΎΡΡ‚Ρ– рядків. Π’ΠΎΠ½ΠΈ корисні Ρ‚ΠΎΠ΄Ρ–, ΠΊΠΎΠ»ΠΈ проста захисна ΠΏΠ΅Ρ€Π΅Π²Ρ–Ρ€ΠΊΠ° ΠΏΠΎΡ‡ΠΈΠ½Π°Ρ” читатися як ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ: якщо Ρ†Π΅ΠΉ стан Π·Π°Π±ΠΎΡ€ΠΎΠ½Π΅Π½ΠΈΠΉ - Π·ΡƒΠΏΠΈΠ½ΠΈΡΡŒ; якщо Ρ†Π΅ΠΉ Ρ–Π½Π²Π°Ρ€Ρ–Π°Π½Ρ‚ Π½Π΅ Π²ΠΈΠΊΠΎΠ½ΡƒΡ”Ρ‚ΡŒΡΡ - Π·ΡƒΠΏΠΈΠ½ΠΈΡΡŒ.

#laravel-12 #laravel-13 #php-8-4 #php-8-5 #error-handling #throw-if #throw-unless #guard-clauses

Π‘Ρ…ΠΎΠΆΡ– ΠΏΠΎΡ€Π°Π΄ΠΈ

laravel-rescue-replace-try-catch-fallback-tip.pngΠŸΠΎΡ€Π°Π΄Π°
ΠŸΠ΅Ρ€Π΅Π³Π»ΡΠ½ΡƒΡ‚ΠΈ ΠΏΠΎΡ€Π°Π΄Ρƒ
#laravel-12 #laravel-13 #php-8-4 #php-8-5 #rescue #fallback #error-handling #exception-reporting
laravel-withwherehas-avoid-duplicate-conditions-tip.pngΠŸΠΎΡ€Π°Π΄Π°
ΠŸΠ΅Ρ€Π΅Π³Π»ΡΠ½ΡƒΡ‚ΠΈ ΠΏΠΎΡ€Π°Π΄Ρƒ
#eloquent #laravel-12 #laravel-13 #php-8-4 #php-8-5 #where-has #with-where-has #eager-loading #relationships
laravel-tap-side-effects-keep-original-value-tip.pngΠŸΠΎΡ€Π°Π΄Π°
ΠŸΠ΅Ρ€Π΅Π³Π»ΡΠ½ΡƒΡ‚ΠΈ ΠΏΠΎΡ€Π°Π΄Ρƒ
#eloquent #laravel-12 #laravel-13 #php-8-4 #php-8-5 #tap #helpers #tappable
laravel-firstorcreate-replace-first-create-tip.pngΠŸΠΎΡ€Π°Π΄Π°
ΠŸΠ΅Ρ€Π΅Π³Π»ΡΠ½ΡƒΡ‚ΠΈ ΠΏΠΎΡ€Π°Π΄Ρƒ
#eloquent #laravel-12 #laravel-13 #php-8-4 #php-8-5 #model-persistence #first-or-create #first-or-new