Кастомізація колекцій у Laravel за допомогою CollectedBy

Перекладено ШІ
Оригінал: Laravel News
Оновлено: 25 січня, 2025
У світі розробки на Laravel часто виникає потреба в налаштуванні колекцій моделей. Досліджуйте, як новий атрибут CollectedBy спростить управління колекціями, забезпечуючи при цьому більш чистий та зрозумілий код. Чи готові ви вдосконалити свої навички в Laravel? Читайте далі!

Під час роботи з колекціями Eloquent вам може знадобитися додати специфічну функціональність, що стосується певних типів моделей. Новий атрибут CollectedBy у Laravel надає декларативний спосіб налаштування колекцій без необхідності переопределяти методи моделі, що робить ваш код більш зрозумілим і легким для підтримки.

Раніше для персоналізації колекцій моделей потрібно було переоприділяти метод newCollection(), але теперній підхід на основі атрибутів пропонує більш акуратне рішення на рівні класу.

use Illuminate\Database\Eloquent\Attributes\CollectedBy;

#[CollectedBy(CustomCollection::class)]
class YourModel extends Model
{
    // Реалізація моделі
}

Розглянемо практичний приклад з каталогу продуктів електронної комерції:

// Колекція продуктів
<?php

namespace App\Collections;

use Illuminate\Database\Eloquent\Collection;

class ProductCollection extends Collection
{
    public function inStock()
    {
        return $this->filter(fn($product) => $product->stock_count > 0);
    }

    public function onSale()
    {
        return $this->filter(fn($product) => $product->discount_percentage > 0);
    }

    public function byPriceRange($min, $max)
    {
        return $this->filter(function($product) use ($min, $max) {
            $price = $product->getEffectivePrice();
            return $price >= $min && $price <= $max;
        });
    }

    public function topRated()
    {
        return $this->filter(fn($product) => $product->average_rating >= 4)
            ->sortByDesc('average_rating');
    }
}

// Модель продукту
namespace App\Models;

use App\Collections\ProductCollection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Attributes\CollectedBy;

#[CollectedBy(ProductCollection::class)]
class Product extends Model
{
    public function getEffectivePrice()
    {
        if ($this->discount_percentage > 0) {
            return $this->price * (1 - $this->discount_percentage / 100);
        }

        return $this->price;
    }
}

Атрибут CollectedBy спрощує персоналізацію колекцій, зберігаючи чистоту та читабельність коду у ваших Laravel-додатках