0

I have a problem to get an object from an array-collection of objects by ID.

The following is my code:

protected $_rootLocation;

public function __construct(Location $rootLocation)
{
    $this->_rootLocation= $rootLocation;

    var_dump($this->_rootLocation);
}

public function getLocationById($id)
{
    $value = null;
    foreach($this->_rootLocationas $root)
      {
            if ($id == $root->getId())
            {
                $value = $root;
                break;
            }
       }

    return $value;
}

Then the function return "NULL" so it's dosn't work...

Edit

I do like that :

    $manager = new LocationManager($rootLocation);

    echo "<pre>";
    var_dump($manager->getLocationById('291'));
    echo "</pre>";
Nll
  • 819
  • 5
  • 19
  • 41
  • if you add this line after the foreach loop initialiser what is the result? echo $id . ' : '. $root->getId(); – Gavin Sep 29 '12 at 21:59
  • Which implies that the loop is not iterating? meaning it has nothing to loop over, of the interfaces required are not supported. Unless you have some custom buffering going on. It is hard to know more without being able to see how myClasse is formed. That leads us to the answer by @JvdBerg. Have you tried enabling error reporting: error_reporting(E_ALL); ini_set('display_errors', '1'); – Gavin Sep 29 '12 at 22:59

2 Answers2

1

Your function returns null because the object is not found!

It depends on the implementation of the myClasse object, this must implement the iterator interface and the getId() method must return a valid Id on each iteration.

JvdBerg
  • 21,777
  • 8
  • 38
  • 55
  • but I do var_dump($this->_rootObject) and it's retun me an arrayCollection of objects(type my Class)... – Nll Sep 29 '12 at 21:28
  • And the GetId() and the id's of the collection, is there a match with the requested id? – JvdBerg Sep 29 '12 at 21:33
  • yea of course but I have something very weird,when i put var_demp() inside foreach so i dont have any reaction?so it's refuse to run what inside foreach or foreach excluded? – Nll Sep 29 '12 at 21:47
  • if the foreach not loops (you get not output from var_dump) then the collection is empty! You should var_dump($rootObject) in the constructor. – JvdBerg Sep 30 '12 at 08:37
  • with var_dump in constructor it's returns me arraycollection of objects of type Myclass... – Nll Sep 30 '12 at 13:05
  • can you add the dump to your question, and method GetId() too? – JvdBerg Sep 30 '12 at 13:52
  • And does a Location object has a GetId method, and what code is in there? You should test with a value of `291`, does that give a result? – JvdBerg Sep 30 '12 at 14:56
  • I do but the result is still NULL,you can see my second edit in my first message – Nll Sep 30 '12 at 15:14
0

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:

Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836
  • I'd say your issue is more that you need to look into children as well. The type of your root element is missing in the var_dump, that would be helpful (it's at the very beginning). – hakre Sep 30 '12 at 15:18
  • i dont understand what you mean – Nll Sep 30 '12 at 15:23
  • the data-type. The var_dump output's top is cut away. – hakre Sep 30 '12 at 15:26
  • do you mean $this->_rootLocation,you want to know the return of all var_dump,in CLI i can't have all var_dump output? – Nll Sep 30 '12 at 15:33