Imagine that none of all objects in the array has the ID you're looking for. Your function will just return null
. For example with an empty array.
As you can see, returning null
does not mean that the function does not work. It works perfectly and did what you specified, it is just, that no such object exists.
It's then up to you to decide what to do if this happens. As you've not told in your question, there is not much to add but to offer you some options:
You could check if the function returns null
and then take it as a "not found" case.
$result = $collection->getObjectById($id);
if (null === $result) {
# object not found
} else {
# object found
}
You can throw an Exception inside the function if the function should only be called for existing objects:
public function getObjectById($id) {
foreach ($this->_rootObject as $root) {
if ($id == $root->getId()) {
return $root;
}
}
throw new InvalidArgumentException(sprintf('Not a valid ID: %d', $id));
}
or finally:
Offer an additional function to check for an existing ID first:
private function findById($id) {
foreach ($this->_rootObject as $object) {
if ($id == $object->getId()) {
return $object;
}
}
return null;
}
public function hasObjectById($id) {
return null !== $this->findById($id);
}
public function getObjectById($id) {
if (null !== $root = $this->findById($id)) {
return $root;
}
throw new InvalidArgumentException(sprintf('Not a valid ID: %d', $id));
}
Also you might be interested to create yourself a class called that encapsulates your needs, so you do not need to implement that in your "I manage the root collection object " object which is more than indirect. This then is basically your own collection class. An example:
interface Identifiable {
public function getId();
}
/**
* Example Object Class
*/
class MyObject implements Identifiable {
private $id;
public function __construct($id) {
$this->id = (int) $id;
}
public function getId() {
return $this->id;
}
}
/**
* Example Collection
*/
class IdentifiableCollection implements Countable, IteratorAggregate
{
private $objects;
public function attach(Identifiable $object) {
$id = $object->getId();
$this->objects[$id] = $object;
}
public function count() {
return count($this->objects);
}
public function has($id) {
return isset($this->objects[$id]);
}
public function getById($id) {
if ($this->has($id)) {
return $this->objects[$id];
}
throw new InvalidArgumentException(sprintf("No object is identifiable for %d", $id));
}
public function getIterator() {
return new ArrayIterator($this->objects);
}
}
// create the collection
$collection = new IdentifiableCollection();
// fill the collection with some objects (ID 1 - 20)
foreach(range(1, 20) as $id) {
$collection->attach(new MyObject($id));
}
// test if an id exists and return object
$id = 2;
var_dump($collection->has($id), $collection->getById($id));
// iterate over the collection
foreach ($collection as $object) {
var_dump($object);
}
This collection class only offers to attach objects, not remove them but you can extend that as needed. It's also possible to extend from an existing class like ArrayObject
or SplObjectStorage
if you want to reuse existing functionality. An example is given in another answer in a somewhat related question: