Collection های سفارشی در PHP
چرا از آرایههای ساده اجتناب کنیم؟
آرایهها در PHP انعطافپذیر هستند اما فاقد Type Safety هستند، که میتواند منجر به باگهای پنهان و رفتار غیرقابل پیشبینی شود، به خصوص در کدبیسهای بزرگ یا فریمورکهایی مانند Laravel.
چرا از Collection های سفارشی استفاده کنیم؟
- Type Safety: Collection های سفارشی تضمین میکنند که فقط انواع مشخصی از اشیاء ذخیره شوند و خطاها را زودتر شناسایی میکنند ("fail fast").
- خوانایی: برگرداندن
FacultyCollectionبه جای یک آرایه عمومی، هدف را واضح میکند—هر کسی که کد را میخواند دقیقاً میداند که داخل آن چیست. - متدهای داخلی: Collection ها میتوانند متدهایی مانند
groupBy،first،last،map،filterو غیره را به صورت پیشفرض ارائه دهند. - سازگاری: استفاده از Collection ها سبک کدنویسی یکپارچه و رفتار قابل پیشبینی در پروژه شما ایجاد میکند.
از استفاده آرایهها به عنوان ورودی/خروجی توابع اجتناب کنید، مگر اینکه فریمورک یا قرارداد خارجی آن را الزامی کند.
مثال: پیادهسازی Typed Collection
<?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);
}
}
<?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 به راحتی کار کند.
- PHP
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 های عمومی استفاده کنید که کاملاً ضروری باشد.