PHP bir sınıfın tüm örneklerini alın

4 Cevap php

Ben belli bir sınıfın, bir nesnenin tüm örneklerini almak istiyorum.

Örneğin:

class Foo {
}

$a = new Foo();
$b = new Foo();

$instances = get_instances_of_class('Foo');

$instances şeklinde olmalıdır array($a, $b) veya array($b, $a) (sırası önemli değildir).

Bu gerekli değildir ama işlevi, istenen sınıfın bir üst sınıfı var örneklerini dönecekti eğer bir artı.

Aklıma bir yöntem örneklerini dizisi tutan bir statik sınıf üye değişkeni kullanıyor. Sınıfının yapıcı ve yıkıcı, ben eklersiniz veya diziden $this çıkarın. Ben birçok sınıflar bunu yapmak varsa bu oldukça zahmetli ve hata eğilimli.

4 Cevap

Bir TrackableObject sınıftan tüm objeleri elde ederse, bu sınıf böyle şeyler (sadece alt sınıflarından bu aşırı yükleme yaparken parent::__construct() ve parent::__destruct() çağrı emin olun işlemek için ayarlanmış olabilir.

class TrackableObject
{
    protected static $_instances = array();

    public function __construct()
    {
        self::$_instances[] = $this;
    }

    public function __destruct()
    {
        unset(self::$_instances[array_search($this, self::$_instances, true)]);
    }

    /**
     * @param $includeSubclasses Optionally include subclasses in returned set
     * @returns array array of objects
     */
    public static function getInstances($includeSubclasses = false)
    {
        $return = array();
        foreach(self::$_instances as $instance) {
            if ($instance instanceof get_class($this)) {
                if ($includeSubclasses || (get_class($instance) === get_class($this)) {
                    $return[] = $instance;
                }
            }
        }
        return $return;
    }
}

Bu birlikte büyük sorun hiçbir nesne otomatik olarak, yani __destruct() manuel denilen olması gerekir (buna bir referans hala TrackableObject::$_instances içinde var olduğu gibi) tarafından çöp toplama alınmayı olduğunu yok nesne dedi. (Dairesel Referans Çöp Toplama PHP 5.3 eklendi ve ek çöp toplama olanakları sunabilir)

Ben bir olay sistemi yapıyorum çünkü bu ihtiyaç ve (dinamik bağlı, eğer sen global bir bildirim) belli bir sınıfın tüm nesneleri olayları gönderilen gerekiyor.

Ben (An observer pattern) ile nesneleri kaydetmek ayrı bir nesne sahip öneririm. PHP yerleşik olan bu destek, SPL aracılığıyla; Bakınız: SplObserver ve SplSubject.

Burada olası bir çözüm:

function get_instances_of_class($class) {
    $instances = array();

    foreach ($GLOBALS as $value) {
    	if (is_a($value, $class) || is_subclass_of($value, $class)) {
    		array_push($instances, $value);
    	}
    }

    return $instances;
}

Edit: $class bir üst sınıf olup olmadığını kontrol etmek için kod güncellendi.

Edit 2: biraz yerine sadece üst düzey nesneleri her nesnenin değişkenlerini kontrol özyinelemeli işlevi Messier Halısı:

function get_instances_of_class($class, $vars=null) {
    if ($vars == null) {
    	$vars = $GLOBALS;
    }

    $instances = array();

    foreach ($vars as $value) {
    	if (is_a($value, $class)) {
    		array_push($instances, $value);
    	}

    	$object_vars = get_object_vars($value);
    	if ($object_vars) {
    		$instances = array_merge($instances, get_instances_of_class($class, $object_vars));
    	}
    }

    return $instances;
}

Ben belirli nesnelerle sonsuz özyinelemeye geçebiliriz eğer emin değilim, bu yüzden dikkatli olun ...

AFAIK, PHP zamanı yatan nesne yer göstermiyor, bu yüzden bir nesne örnekleri için bunu sorgulamak mümkün olmazdı.