3

In some of my setters, I pass an array of objects. I would like to ensure that it only contains instances from a given class. Reading the doc, here is what I do :

class Foo
{
    public function __construct()
    {

    }
}

class ErrorFoo
{
    public function __construct()
    {

    }
}

$arrayObject = Array();

array_push($arrayObject, new Foo());
array_push($arrayObject, new Foo());
array_push($arrayObject, new ErrorFoo());

$error = false;
foreach ($arrayObject as $obj)
{
    if ( $obj instanceof Foo ) 
    {
        echo "ok" . '<br>';
    }
    else 
    {
        echo "error" . '<br>';
        $error = true;  
    }
}

Do you know a simpler way than iterate through the array like this?

4
  • Not sure if always setting $error= true; helps. Commented Sep 4, 2017 at 11:05
  • oups, corrected Commented Sep 4, 2017 at 11:05
  • 4
    As part of your setter function you can validate the passed object type? Throwing exceptions if the type doesnt match what you want. Doing this will ensure the object returned in any getters are of the type expected. Commented Sep 4, 2017 at 11:06
  • @Goon3r If I pass an array as parameter, then the passed object type is Array, no ? Commented Sep 4, 2017 at 11:09

3 Answers 3

4

Create a class that extends ArrayObject, redefine its offsetSet() method and do the check in it. Use this class instead of a plain array to store the objects of type Foo.

class ArrayOfFoo extends ArrayObject
{
    public function offsetSet($index, $newval)
    {
        // Verify the input 
        if (! $newval instanceof Foo) {
            // do something
            throw new InvalidArgumentException('Invalid type');
        }

        // Let the parent class do its job
        parent::offsetSet($index, $newval);
    }
}

This code throws an exception when the object of type ErrorFoo is added to the array:

$ArrayObject = new ArrayOfFoo();

$ArrayObject[] = new Foo();
$ArrayObject[] = new Foo();
// This throws an exception
$ArrayObject[] = new ErrorFoo();

An instance of the ArrayObject class can be used in the same way an array is used (setting, unsetting and fetching values from it). Its method getArrayCopy() can be used to get an array that can be passed as argument to functions that expect arrays (explode(), f.e.)

Sign up to request clarification or add additional context in comments.

Comments

3

One alternative is using variadics to enforce types. It's an array inside the function, but not outside:

function doSomething(MyObject ...$array)
{
     // $array contains only MyObject instances in it
}

doSomething(new MyObject, new MyObject, new MyObject);

Comments

0

You could use array_map or array_walk for this:

https://php.net/manual/en/function.array-map.php

Example of array_map:

function isInstanceOfFoo($n)
{
    if(!($n instanceof Foo)) {
      throw new Exception('Error');
    }
}

$ArrayObject = Array();

array_push($ArrayObject, new Foo());
array_push($ArrayObject, new Foo());
array_push($ArrayObject, new ErrorFoo());

array_map(isInstanceOfFoo, $ArrayObject);

https://php.net/manual/en/function.array-walk.php

Example of array_walk:

function isInstanceOfFoo($n, $k)
{
    if(!($n instanceof Foo)) {
      throw new Exception('Error');
    }
}
array_walk($ArrayObject, isInstanceOfFoo);

2 Comments

the links are /de/ instead of /en/ can't edit that because It needs at least 6 characters
You could extend this to pass the class name - so becomes function isInstanceOf( $class, $n) and test becomes $n instanceOf $class. It's like using Javas generics.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.