CodeBlanks Logo Icon CodeBlanks

Meydan okuma - Reflection uygulaması

PHP kursu · Uzman · Ders 51/54

Reflection ve özniteliklerle çalışan bir otomatik serileştirme (serializer) yazarsın.

Reflection ve özniteliklerle serileştirme

Bu derste ReflectionSerializer sınıfını yazarsın. ReflectionClass bir sınıfın yapısını okur; getProperties() özellikleri listeler. Her özelliğin getAttributes() çağrısı, o özelliğe iliştirilen öznitelikleri ReflectionAttribute dizisi olarak verir.

Öznitelikler #[Attribute] ile işaretlenmiş sınıflardır. #[Field("id")] gibi bir öznitelik, serileştirme sırasında hangi anahtarın kullanılacağını söyler. newInstance() ile öznitelik örneği üretilip değeri okunur. Böylece hangi özelliğin serileştirileceğini koddan değil, bildirimsel olarak belirlersin.

Öznitelikleri okumak

Öznitelik okumanın tipik akışı şudur: önce $prop->getAttributes(Field::class) ile belirli bir öznitelik sınıfını filtrele, ardından $attrs[0]->newInstance() ile öznitelik örneğini oluştur. Örnek üzerinde name gibi alanları okursun.

Bu desen bildirimseldir: serileştirme davranışını sınıf tanımından ayrı tutmazsın; doğrudan özelliğin üstüne yazarısın. Yeni bir alan eklediğinde tek yapman gereken #[Field("yeni")] yazmak. Serializer'ı değiştirmezsin. Bu, açık-kapalı ilkesinin tipik bir uygulamasıdır.

Uygulama ReflectionSerializer sınıfını yaz

Başlangıç kodunda ETL hattı hazır. Şimdi #[Attribute] ile işaretli Field öznitelik sınıfını tanımla: public string $name = "" yapılandırma özelliği olsun. Ardından Product sınıfını yaz: id ve name özellikleri #[Field("id")] ve #[Field("name")] ile işaretli olsun.

Son olarak ReflectionSerializer::serialize(object $obj): array yöntemini yaz. new ReflectionClass($obj) ile sınıfı oku, getProperties() ile özellikleri gez, her birinin getAttributes(Field::class) çağrısını yap; boşsa atla. newInstance() ile Field örneği üret, name boşsa özellik adını kullan, değilse name değerini. Demo Product(7, "kale") nesnesini json_encode ile yazdırsın.

Örnek çözümü göster
:serialize içinde new ReflectionClass($obj), getProperties() ile özellikleri gez, her birinin getAttributes(Field::class) çağrısıyla özniteliği al, newInstance() ile Field örneği üret, name değerini anahtar yap. Demo Product sınıfını da yaz, sonucu json_encode ile yazdır.
Örnek çözüm:
<?php
// ETL hattı + Reflection: ReflectionSerializer yaz

function readRows(array $rows): Generator {
    foreach ($rows as $row) {
        yield $row;
    }
}

function transform(iterable $rows, callable $fn): Generator {
    foreach ($rows as $row) {
        yield $fn($row);
    }
}

function pipeline(array $rows, callable $fn): Generator {
    yield from transform(readRows($rows), $fn);
}

function loadAll(iterable $rows): array {
    $out = [];
    foreach ($rows as $row) {
        $out[] = $row;
    }
    return $out;
}

#[Attribute]
class Field {
    public function __construct(public string $name = "") {}
}

class Product {
    public function __construct(
        #[Field("id")] public int $id,
        #[Field("name")] public string $name,
    ) {}
}

class ReflectionSerializer {
    public function serialize(object $obj): array {
        $rc = new ReflectionClass($obj);
        $out = [];
        foreach ($rc->getProperties() as $prop) {
            $attrs = $prop->getAttributes(Field::class);
            if (empty($attrs)) continue;
            $field = $attrs[0]->newInstance();
            $key = $field->name !== "" ? $field->name : $prop->getName();
            $out[$key] = $prop->getValue($obj);
        }
        return $out;
    }
}

// Demo:
$p = new Product(7, "kale");
$s = new ReflectionSerializer();
echo json_encode($s->serialize($p), JSON_UNESCAPED_UNICODE) . "\n";

Kendini test et

  1. Reflection kavramlarını eşleştir

    ReflectionClass
    Sınıfın yapısını okur
    getAttributes
    Öznitelik listesini verir
    newInstance
    Öznitelik örneği üretir
    getValue
    Özellik değerini döndürür
  2. ReflectionProperty::getAttributes ne döndürür?

    • Yalnızca özellik adını bir dize olarak
    • Özelliğin değerini doğrudan döndürür
    • ReflectionAttribute dizisi (boş olabilir)
    • Yeni bir ReflectionClass örneği
    Cevabı göster

    ReflectionAttribute dizisi (boş olabilir) — Doğru. getAttributes bir ReflectionAttribute dizisi döndürür; öznitelik yoksa dizi boş olur.

  3. ReflectionClass çağrısını tamamla

    $rc = ____($obj);
    Cevabı göster
    $rc = new ReflectionClass($obj);

Uzman bölümündeki tüm dersler