2014-12-24 2 views
0

Я хочу быть в состоянии сделать что-то вроде:Получить все экземпляры определенного класса в PHP

objects = getAllInstances(ClassName); 

где ИмяКласса имеет уникальное поле, так что два экземпляра не может иметь точно такое же значение, что поле.

class ClassName { 
    protected $unique_field; 

    public function __construct($value) 
    { 
     $objects = getAllInstances(self); 

     foreach($objects as $object) 
     { 
      if($object->getUniqueField() === $value) 
      { 
       return $object; 
      } 
     } 
    } 

    public function getUniqueField() 
    { 
     return $this->unique_field; 
    } 
}; 

Есть ли шаблон проектирования, встроенная функция в PHP для этой цели, или я должен использовать статический массив, который содержит все созданные экземпляры, а затем просто цикл над ним?

ответ

0

Вы можете хранить статический массив со всеми существующими экземплярами. Что-то похожее на это ...

static $instances; 

public function __construct($name) { 
    $this->unique_field = $name; 

    if (empty($instances)) { 
     self::$instances = array(); 
    } 

    foreach (self::$instances as $instance) { 
     if ($instance->getUniqueField() === $name) 
      return $instance; 
    } 

    self::$instances[] = $this; 
} 
+0

путь вы проверяете, пуст ли $ экземпляры? –

+0

Вы не можете инициализировать статическую переменную в виде массива, поэтому я начинаю ее пустым и создаю ее при необходимости – casraf

+0

Использование статического в ООП - всего лишь плохая идея. – Gnucki

1

Вы можете создать фабрику, которая хранит ссылки на все экземпляры, созданные с ней:

class ClassNameFactory 
{ 
    private $instances = []; 

    public function create($value) 
    { 
     return $this->instances[] = new ClassName($value); 
    } 

    public function getInstances() 
    { 
     return $this->instances; 
    } 
} 

$f = new ClassNameFactory(); 
$o1 = $f->create('foo'); 
$o2 = $f->create('bar'); 
print_r($f->getInstances()); 
+0

Вы можете, но это не ответственность фабрики за это. Однако это простое решение. – Gnucki

+0

@Gnucki Согласен, это баланс между SRP и прагматизмом :) –

0

Что вам нужно, это registry pattern:

class ClassNameRegistry { 
    private $instances = array(); 

    public function set($name, InterfaceName $instance) { 
     $this->instances[$name] = $instance; 
    } 

    public function get($name) { 
     if (!$this->has($name)) { 
      throw new \LogicException(sprintf(
       'No instance "%s" found for class "ClassName".', 
       $name 
      ); 
     } 

     return $this->instances[$name]; 
    } 

    public function has($name) { 
     return isset($this->instances[$name]); 
    } 

    public function getAll() { 
     return $this->instances; 
    } 
} 

Это, безусловно, лучший вариант архитектуры ООП, поскольку вы изолируете поведение в автономном классе как службу. Если у вас нет механизма внедрения зависимостей с услугами, я бы предложил вам определить класс реестра как singleton!

В моем примере я использовал InterfaceName, чтобы иметь low coupling между реестром и его обработанными экземплярами.

Смежные вопросы