How to check if array is a collection of specific object?

Viewed 7673

In my class I have a method which expects as array, and this array should be used differently depending on the collection type. The array items should be objects, and I need to know which class instance these objects are.

For example: in the array($obj1, $obj2), I need to check the instance of these objects, which class they were created from.

Here some code:

public function convertDataToInsert($data)
{
    if (is_array($data)) {
        foreach ($data as $obj) {
            if ($obj instanceof CriterioDigital) {
                //Ok, an array of CriterioDigital
            } elseif ($obj instanceof ArquivoDigital) {
                //Ok, an array of ArquivoDigital
            } else {
                throw new \Exception('Invalid parameter');
            }
            break;
        }
    }

Or maybe:

public function convertDataToInsert($data)
{
    if (is_array($data)) {
        $obj = $data[0];
        if ($obj instanceof CriterioDigital) {
            //Ok, an array of CriterioDigital
        } elseif ($obj instanceof ArquivoDigital) {
            //Ok, an array of ArquivoDigital
        } else {
            throw new \Exception('Invalid parameter');
        }
    }
}

I only need to check the collection type of this array. I know I can iterate it, but is there any better way in php to do so?

5 Answers

Use an array filter :

if (count(array_filter($data, function ($entry) {
        return !($entry instanceof CriterioDigital);
})) > 0) {
    throw new \DomainException('an array of CriterioDigital must be provided');
}

There's another way to achieve this:

<?php // ConvertibleDataCollection.php

abstract class ConvertibleDataCollection
{
    protected $data = [];

    public function setData($data)
    {
        $this->data = $data;
    }

    public function getData()
    {
        return $this->data;
    }

    abstract public function convert();
}
<?php // CriterioDigitalCollection.php

class CriterioDigitalCollection extends ConvertibleDataCollection
{
    public function convert()
    {
    }
}
<?php // ArquivoDigitalCollection.php

class ArquivoDigitalCollection extends ConvertibleDataCollection
{
    public function convert()
    {
    }
}

And then in your class:


    public function convertDataToInsert(ConvertibleDataCollection $dataCollection)
    {
        return $dataCollection->convert();
    }

A colleague showed me an easy way to check, if an array contains instances of one class only:

class A {}
class B {}
class C extends A {}

$tests = [
    1 => [new A(), new A()], // succeeds
    2 => [new A(), new B()], // fails
    3 => [new C(), new C()], // succeeds, because C extends A
];

foreach ($tests as $index => $collection) {
    try {
        \array_map(static function (A $object): void {}, $collection);
    } catch (\TypeError $e) {
        // Implement your error handling here.
    }
}

Here's an example with output: https://3v4l.org/1IVg9

Related