پرش به مطلب اصلی

Collection های سفارشی در PHP

نکته

چرا از آرایه‌های ساده اجتناب کنیم؟

آرایه‌ها در PHP انعطاف‌پذیر هستند اما فاقد Type Safety هستند، که می‌تواند منجر به باگ‌های پنهان و رفتار غیرقابل پیش‌بینی شود، به خصوص در کدبیس‌های بزرگ یا فریمورک‌هایی مانند Laravel.

چرا از Collection های سفارشی استفاده کنیم؟

  • Type Safety: Collection های سفارشی تضمین می‌کنند که فقط انواع مشخصی از اشیاء ذخیره شوند و خطاها را زودتر شناسایی می‌کنند ("fail fast").
  • خوانایی: برگرداندن FacultyCollection به جای یک آرایه عمومی، هدف را واضح می‌کند—هر کسی که کد را می‌خواند دقیقاً می‌داند که داخل آن چیست.
  • متدهای داخلی: Collection ها می‌توانند متدهایی مانند groupBy، first، last، map، filter و غیره را به صورت پیش‌فرض ارائه دهند.
  • سازگاری: استفاده از Collection ها سبک کدنویسی یکپارچه و رفتار قابل پیش‌بینی در پروژه شما ایجاد می‌کند.
اخطار

از استفاده آرایه‌ها به عنوان ورودی/خروجی توابع اجتناب کنید، مگر اینکه فریمورک یا قرارداد خارجی آن را الزامی کند.

مثال: پیاده‌سازی Typed Collection

src/Shared/Domain/Read/TypedCollection.php
<?php
declare(strict_types=1);
namespace App\Shared\Domain\Read;
use Webmozart\Assert\Assert;
abstract class TypedCollection extends Collection {
public function __construct(array $elements = []) {
Assert::allIsInstanceOf($elements, $this->type());
parent::__construct($elements);
}
abstract protected function type(): string;
public function add(mixed $element): void {
Assert::isInstanceOf($element, $this->type());
parent::add($element);
}
}
src/Context/Foo/Domain/Read/View/FooCollection.php
<?php
declare(strict_types=1);
namespace App\Context\Foo\Domain\Read\View;
use App\Shared\Domain\Read\TypedCollection;
final class FooCollection extends TypedCollection {
protected function type(): string {
return Foo::class;
}
}

چه زمانی باید از Collection سفارشی استفاده کنید؟

  • زمانی که منطق مربوط به یک آرایه در چندین مکان تکرار می‌شود (مثل filtering، mapping، counting).
  • زمانی که می‌خواهید کلاینت‌ها را از ساختار داخلی داده‌هایتان جدا کنید.
  • زمانی که می‌خواهید تبدیل‌های معنادار و نام‌گذاری شده ارائه دهید (مثل $faculties->activeOnly() به جای array_filter(...)).

بهترین شیوه‌ها

  • Immutability: ترجیح دهید که برای تبدیل‌ها، نمونه‌های جدید Collection برگردانید، به جای تغییر نمونه اصلی.
  • Interface حداقلی: فقط متدهایی را پیاده‌سازی کنید که کلاینت‌هایتان واقعاً استفاده می‌کنند.
  • پشتیبانی Iterator: IteratorAggregate را پیاده‌سازی کنید و ArrayIterator برگردانید تا foreach به راحتی کار کند.
final class Names implements IteratorAggregate {
private array $names;
public function __construct(array $names) {
Assert::that()->allIsString($names);
$this->names = $names;
}
public function getIterator(): Iterator {
return new ArrayIterator($this->names);
}
}

خلاصه

Collection های سفارشی ابزاری ساده اما قدرتمند برای بهبود کیفیت کد، سرعت توسعه و کاهش باگ‌ها در پروژه‌های PHP هستند. آن‌ها ساختار، Type Safety و وضوح فراهم می‌کنند—کدبیس شما را قابل نگهداری‌تر و مقاوم‌تر می‌سازند.

اطلاع

راهنمایی CTO تیم: از Collection های عمومی اجتناب کنید

"Collection های عمومی فقط حدود 30% بهتر از آرایه‌ها هستند. اما برای دستیابی به 70% باقی‌مانده مزایا، باید تا حد امکان از Collection های عمومی اجتناب کنیم و به جای آن Collection های بسیار مشخص ایجاد کنیم. هر Collection باید نوع کلاس دقیق و مورد انتظاری داشته باشد. همیشه از خود بپرسید: آیا این Collection تا حد امکان مشخص است؟"

قانون عملی:

  • Collection های بسیار مشخص با انواع مورد انتظار سخت‌گیرانه را بر Collection های عمومی ترجیح دهید.
  • فقط زمانی از Collection های عمومی استفاده کنید که کاملاً ضروری باشد.