Коллекции в PHP: особенности, пример на практике

Класс Collection является заменой для традиционного типа данных массива в объектно-ориентированном стиле. Он очень похож на массив, содержит переменные — свойства, хотя эти переменные, как правило, являются другими объектами, а не более простыми типами данных, такими как строки, целые числа и т.д. Затем класс предоставляет простые методы, чтобы позволить вам добавлять переменные — свойства, удалять их и извлекать, для использования в приложениях. Класс Collection имеет множество преимуществ по сравнению с использованием простого массива для хранения серии объектов, о которых мы расскажем ниже.

Цель класса Collection

Приложения часто имеют объекты, которые содержат группу других объектов. Класса Collection обеспечивает объектно-ориентированную оболочку вокруг массива, и реализует механизм, который позволяет ленивую загрузку. Ленивая загрузка откладывает создание элементов коллекции, пока они на самом деле не нужны. Это явление называется «ленивая загрузка», потому что объект самостоятельно определяет, когда ему реализовывать объекты своих компонентов, чем создавать их, когда они реализованы.

Функциональные требования класса Collection следующие:

  1. Установить обертку вокруг массива объектов.
  2. Предоставить методы для добавления, удаления и извлечения объектов-элементов предсказуемым, очевидным способом.
  3. Позволяет легко определить, сколько объектов-элементов существует в коллекции.
  4. Позволяет использовать ленивый реализацию объекта для экономии системных ресурсов.

В базовом виде класс Collection выглядит следующим образом:

class Collection {
  private $_members = array();
  public function addItem($obj, $key = null) {}
  public function removeItem($key) {}
  public function getItem($key) {}
  public function length() {}
} 

Свойство $_members предоставляет место для хранения объектов, которые являются элементами коллекции. Метод addItem() позволяет вам добавить новый объект в коллекцию, removeItem() удаляет объект, getItem() возвращает объект, а length() возвращает количество элементов в коллекции. Класс Collection не требует конструктора.

При добавлении нового объекта в коллекцию этот объект вставляется в массив $_members в место, указанное $key. Если ключ не указан, вы разрешаете PHP выбрать его. Если сделана попытка добавить объект в коллекцию, используя ключ, который уже существует, должно быть создано исключение, чтобы предотвратить непреднамеренную перезапись информации:

class Collection {
  private $_members = array();
  public function addItem($obj, $key = null) {
    if($key) {
//Throw exception if this key is already in use.
      if(isset($this->_members[$key])) {
        throw new KeyInUseException("Key \"$key\" already in use!");
      } else {
        $this->_members[$key] = $obj;
      } 
    } else {
      $this->_members[] = $obj;
    }
  }
}

Наследуемые классы Collection могут переопределять метод addItem() с помощью подсказки типа, которая гарантирует, что добавляемые элементы имеют правильный тип для желаемой коллекции. Вот пример:

class CourseCollection extends Collection {
  public function addItem(Course $obj, $key = null) {
    parent::addItem($obj, $key);
  }
} 

Используя эту технику, с помощью малого количества кода, вы можете создавать классы наследники, которые обеспечивают соблюдение типа данных для элементов коллекции.

Методы removeItem() и getItem() принимают ключ в качестве параметра, который указывает, какие элементы будут удалены или извлечены. Исключение следует выдать, если указан неверный ключ:

public function removeItem($key) {
  if(isset($this->_members[$key])) {
    unset($this->_members[$key]);
  } else {
    throw new KeyInvalidException("Invalid key \"$key\"!");
  }
}
public function getItem($key) {
  if(isset($this->_members[$key])) {
    return $this->_members[$key];
  } else {
    throw new KeyInvalidException("Invalid key \"$key\"!");
  }
}  

Поскольку параметр $key для метода addItem() является необязательным, вы не обязательно будете знать ключ, который используется для каждого элемента в коллекции. Метод под названием keys() позволяет вам предоставить список этих ключей к любому внешнему коду, который может понадобиться. Ключи будут возвращены в виде массива:

public function keys() {
  return array_keys($this->_members);
}

Возможно, вы захотите узнать, сколько предметов в коллекции. Функция sizeof возвращает количество элементов в массиве, так что вы будете использовать её для реализации вашего метода length():

public function length() { return sizeof($this->_members); }

Поскольку getItem() выдает исключение, если передан неверный ключ, вам необходимо иметь средство определение, существует ли данный ключ в коллекции. Метод exists() позволяет это проверить перед вызовом getItem():

public function exists($key) {
  return (isset($this->_members[$key]));
}

Этот подход позволяет вам использовать блок try … catch для отлова недопустимых ключей или вызвать Метод exists() перед вызовом getItem(), в зависимости от того, какой метод более удобен.

Теперь, когда мы добавили все основные методы в класс, можно рассмотреть, как класс Collection используется.

Использование класса Collection:

class Foo {
 private $_name;
 private $_number;
 public function __construct($name, $number) {
 $this->_name = $name;
 $this->_number = $number;
 }
 public function __toString() {
 return $this->_name . ' is number ' . $this->_number;
 }
}

$colFoo = new Collection();
$colFoo->addItem(new Foo("Steve", 14), "steve");
$colFoo->addItem(new Foo("Ed", 37), "ed");
$colFoo->addItem(new Foo("Bob", 49));

$objSteve = $colFoo->getItem(“steve”);

print $objSteve; //prints "Steve is number 14"
$colFoo->removeItem("steve"); //deletes the 'steve' object

try {
 $colFoo->getItem("steve"); //throws KeyInvalidException
} catch (KeyInvalidException $kie) {
 print "The collection doesn't contain anything called 'steve'";
}
 

Этот пример может быть еще не особенно полезен, но он должен дать вам некоторое представление о том, как используется класс Collection.

Добавить комментарий