The short answer is no.

My understanding is that enforcing such a thing has terrible performance problems. Some people want to go all the way and have full blown generics, others just want type-safe collections. Some people worry that implementing the latter first might hinder the development of the former in the future. So we’re at a standstill.

There’s the occasional discussion in the community such as this: https://externals.io/message/108175

Edit Depending on how you interpret the question, @Pierre's answer could be considered more correct, since the OP said "type hint", although they showed a "type declaration".

There's a good thread from a while back arguing about the implications of what to call it, and that PHP's implementation is not a hint but a declaration. Some people argued that although calling it a "hint" is a misnomer, that shipped sailed and no matter what core changes, the community would still call it a hint. They did eventually update the documentation, however, to use "type declaration".

Personally, I find myself still saying "type hint" for the explicit type declaration, but I try to catch and correct myself. I do this because I'm trying to change my mindset so that if I talk to a non-PHP person (usually a JavaScript person), they know that I'm not talking about IDE hints but true language features.

Edit There’s a great post on the PHP Foundation's blog that shows the state of things as of August of 2024: State of Generics and Collections

Answer from Chris Haas on Stack Overflow
🌐
SitePoint
sitepoint.com › blog › design patterns › creating strictly typed arrays and collections in php
Creating Strictly Typed Arrays and Collections in PHP — SitePoint
November 13, 2024 - You can enforce type checking in ... in the file. Yes, you can create a strictly typed array of objects in PHP by creating a class that enforces type checking on the objects added to the array....
🌐
PHP
php.net › manual › en › language.types.object.php
PHP: Objects - Manual
As of PHP 5.4, we can create stdClass objects with some properties and values using the more beautiful form: <?php $object = (object) [ 'propertyOne' => 'foo', 'propertyTwo' => 42, ]; ?> ... <!--Example shows how to convert array to stdClass ...
Discussions

Typed array of objects?
There was quite a lot of noise for this historically. Have a look through the old php proposals. There are also lots of github projects trying to facilitate it, so there is at least some demand. I'd also love to see it as a proper part of the language but the last time I looked I to it, the idea seemed to have been pretty comprehensively debated and dismissed Edit: Managed to dig up a decent summary: https://stackoverflow.com/a/20763981 More on reddit.com
🌐 r/PHP
31
3
July 8, 2021
Is there a type hint for an array of objects of a specific class in PHP 8.3? - Stack Overflow
Is there a type hint in PHP 8.3 which allows using ExampleClass[] for declaring it is an array of objects of the class ExampleClass? In my specific case, ExampleClass is called Task What I want bu... More on stackoverflow.com
🌐 stackoverflow.com
Type hinting in PHP 7 - array of objects - Stack Overflow
Maybe I missed something but is there any option to define that function should have argument or return for example array of User objects? Consider the following code: More on stackoverflow.com
🌐 stackoverflow.com
php - Is it possible to declare an array of objects? - Stack Overflow
' ' . $car->type . "\n"; } ... I've tried the php site and haven't been able to find anything. I am also sitting with the book "PHP Objects, Patters, and Practice" by Matt Zandstra. and haven't been able to find any information. 2011-12-23T04:38:44.137Z+00:00 ... Question: Suppose that you wanted to just print the color of just one Car in that array... More on stackoverflow.com
🌐 stackoverflow.com
🌐
Reddit
reddit.com › r/php › typed array of objects?
r/PHP on Reddit: Typed array of objects?
July 8, 2021 -

I heavily use and appreciate the strictly typed mode.

I see a lot of additions throughout the versions of php, however there is a heavy one that does not seem to be requested: typed arrays.

/**
 * @return User[]
 */
public function search(int $status): array
{
    [...]
    return $this->fetchEntities($sql);
}

public function search(int $status): User[]
{
    [...]
    return $this->fetchEntities($sql);
}

I know the workarounds, but an official implementation would simplify our projects, improve the quality of the code while standardizing its use in the php community.

Do you know why there is no demand for it?

Top answer
1 of 4
27

The short answer is no.

My understanding is that enforcing such a thing has terrible performance problems. Some people want to go all the way and have full blown generics, others just want type-safe collections. Some people worry that implementing the latter first might hinder the development of the former in the future. So we’re at a standstill.

There’s the occasional discussion in the community such as this: https://externals.io/message/108175

Edit Depending on how you interpret the question, @Pierre's answer could be considered more correct, since the OP said "type hint", although they showed a "type declaration".

There's a good thread from a while back arguing about the implications of what to call it, and that PHP's implementation is not a hint but a declaration. Some people argued that although calling it a "hint" is a misnomer, that shipped sailed and no matter what core changes, the community would still call it a hint. They did eventually update the documentation, however, to use "type declaration".

Personally, I find myself still saying "type hint" for the explicit type declaration, but I try to catch and correct myself. I do this because I'm trying to change my mindset so that if I talk to a non-PHP person (usually a JavaScript person), they know that I'm not talking about IDE hints but true language features.

Edit There’s a great post on the PHP Foundation's blog that shows the state of things as of August of 2024: State of Generics and Collections

2 of 4
19

If you're using PhpStorm, PHPStan or Psalm, types can be defined in PHPDocs and these tools will do the type checking, among many other things.

/** @var Task[] $tasks */
private array $tasks;
Top answer
1 of 8
147

It's not included.

If it's not included, do you have Any clue why it was not included when type hinting was added?

With the current array implementation, it would require checking all array elements at runtime, because the array itself contains no type information.

It has actually already been proposed for PHP 5.6 but rejected: RFC "arrayof" - interestingly not because of performance issues which turned out to be neglible, but because there was no agreement in how exactly it should be implemented. There was also the objection that it is incomplete without scalar type hints. If you are interested in the whole discussion, read it in the mailing list archive.

IMHO array type hints would provide most benefit together with typed arrays, and I'd love to see them implemented.

So maybe it's about time for a new RFC and to reopen this discussion.


Partial Workaround:

you can type hint variadic arguments and thus write the signature as

function findUserByAge(int $age, User ...$users) : array

Usage:

findUserByAge(15, ...$userInput);

In this call, the argument $userInput will be "unpacked" into single variables, and in the method itself "packed" back into an array $users. Each item is validated to be of type User. $userInput can also be an iterator, it will be converted to an array.

Unfortunately there is no similar workaround for return types, and you can only use it for the last argument.

2 of 8
12

In our codebase, we have the concept of collections. These are based upon a class called TypedArray which is based upon ArrayObject.

class ArrayObject extends \ArrayObject
{
    /**
     * Clone a collection by cloning all items.
     */
    public function __clone()
    {
        foreach ($this as $key => $value) {
            $this[$key] = is_object($value) ? clone $value : $value;
        }
    }

    /**
     * Inserting the provided element at the index. If index is negative, it will be calculated from the end of the Array Object
     *
     * @param int $index
     * @param mixed $element
     */
    public function insert(int $index, $element)
    {
        $data = $this->getArrayCopy();
        if ($index < 0) {
            $index = $this->count() + $index;
        }

        $data = array_merge(array_slice($data, 0, $index, true), [$element], array_slice($data, $index, null, true));
        $this->exchangeArray($data);
    }

    /**
     * Remove a portion of the array and optionally replace it with something else.
     *
     * @see array_splice()
     *
     * @param int $offset
     * @param int|null $length
     * @param null $replacement
     *
     * @return static
     */
    public function splice(int $offset, int $length = null, $replacement = null)
    {
        $data = $this->getArrayCopy();

        // A null $length AND a null $replacement is not the same as supplying null to the call.
        if (is_null($length) && is_null($replacement)) {
            $result = array_splice($data, $offset);
        } else {
            $result = array_splice($data, $offset, $length, $replacement);
        }
        $this->exchangeArray($data);

        return new static($result);
    }

    /**
     * Adding a new value at the beginning of the collection
     *
     * @param mixed $value
     *
     * @return int Returns the new number of elements in the Array
     */
    public function unshift($value): int
    {
        $data = $this->getArrayCopy();
        $result = array_unshift($data, $value);
        $this->exchangeArray($data);

        return $result;
    }

    /**
     * Extract a slice of the array.
     *
     * @see array_slice()
     *
     * @param int $offset
     * @param int|null $length
     * @param bool $preserveKeys
     *
     * @return static
     */
    public function slice(int $offset, int $length = null, bool $preserveKeys = false)
    {
        return new static(array_slice($this->getArrayCopy(), $offset, $length, $preserveKeys));
    }

    /**
     * Sort an array.
     *
     * @see sort()
     *
     * @param int $sortFlags
     *
     * @return bool
     */
    public function sort($sortFlags = SORT_REGULAR)
    {
        $data = $this->getArrayCopy();
        $result = sort($data, $sortFlags);
        $this->exchangeArray($data);

        return $result;
    }

    /**
     * Apply a user supplied function to every member of an array
     *
     * @see array_walk
     *
     * @param callable $callback
     * @param mixed|null $userData
     *
     * @return bool Returns true on success, otherwise false
     *
     * @see array_walk()
     */
    public function walk($callback, $userData = null)
    {
        $data = $this->getArrayCopy();
        $result = array_walk($data, $callback, $userData);
        $this->exchangeArray($data);

        return $result;
    }

    /**
     * Chunks the object into ArrayObject containing
     *
     * @param int $size
     * @param bool $preserveKeys
     *
     * @return ArrayObject
     */
    public function chunk(int $size, bool $preserveKeys = false): ArrayObject
    {
        $data = $this->getArrayCopy();
        $result = array_chunk($data, $size, $preserveKeys);

        return new ArrayObject($result);
    }

    /**
     * @see array_column
     *
     * @param mixed $columnKey
     *
     * @return array
     */
    public function column($columnKey): array
    {
        $data = $this->getArrayCopy();
        $result = array_column($data, $columnKey);

        return $result;
    }

    /**
     * @param callable $mapper Will be called as $mapper(mixed $item)
     *
     * @return ArrayObject A collection of the results of $mapper(mixed $item)
     */
    public function map(callable $mapper): ArrayObject
    {
        $data = $this->getArrayCopy();
        $result = array_map($mapper, $data);

        return new self($result);
    }

    /**
     * Applies the callback function $callable to each item in the collection.
     *
     * @param callable $callable
     */
    public function each(callable $callable)
    {
        foreach ($this as &$item) {
            $callable($item);
        }
        unset($item);
    }

    /**
     * Returns the item in the collection at $index.
     *
     * @param int $index
     *
     * @return mixed
     *
     * @throws InvalidArgumentException
     * @throws OutOfRangeException
     */
    public function at(int $index)
    {
        $this->validateIndex($index);

        return $this[$index];
    }

    /**
     * Validates a number to be used as an index
     *
     * @param int $index The number to be validated as an index
     *
     * @throws OutOfRangeException
     * @throws InvalidArgumentException
     */
    private function validateIndex(int $index)
    {
        $exists = $this->indexExists($index);

        if (!$exists) {
            throw new OutOfRangeException('Index out of bounds of collection');
        }
    }

    /**
     * Returns true if $index is within the collection's range and returns false
     * if it is not.
     *
     * @param int $index
     *
     * @return bool
     *
     * @throws InvalidArgumentException
     */
    public function indexExists(int $index)
    {
        if ($index < 0) {
            throw new InvalidArgumentException('Index must be a non-negative integer');
        }

        return $index < $this->count();
    }

    /**
     * Finding the first element in the Array, for which $callback returns true
     *
     * @param callable $callback
     *
     * @return mixed Element Found in the Array or null
     */
    public function find(callable $callback)
    {
        foreach ($this as $element) {
            if ($callback($element)) {
                return $element;
            }
        }

        return null;
    }

    /**
     * Filtering the array by retrieving only these elements for which callback returns true
     *
     * @param callable $callback
     * @param int $flag Use ARRAY_FILTER_USE_KEY to pass key as the only argument to $callback instead of value.
     *                  Use ARRAY_FILTER_USE_BOTH pass both value and key as arguments to $callback instead of value.
     *
     * @return static
     *
     * @see array_filter
     */
    public function filter(callable $callback, int $flag = 0)
    {
        $data = $this->getArrayCopy();
        $result = array_filter($data, $callback, $flag);

        return new static($result);
    }

    /**
     * Reset the array pointer to the first element and return the element.
     *
     * @return mixed
     *
     * @throws \OutOfBoundsException
     */
    public function first()
    {
        if ($this->count() === 0) {
            throw new \OutOfBoundsException('Cannot get first element of empty Collection');
        }

        return reset($this);
    }

    /**
     * Reset the array pointer to the last element and return the element.
     *
     * @return mixed
     *
     * @throws \OutOfBoundsException
     */
    public function last()
    {
        if ($this->count() === 0) {
            throw new \OutOfBoundsException('Cannot get last element of empty Collection');
        }

        return end($this);
    }

    /**
     * Apply a user supplied function to every member of an array
     *
     * @see array_reverse
     *
     * @param bool $preserveKeys
     *
     * @return static
     */
    public function reverse(bool $preserveKeys = false)
    {
        return new static(array_reverse($this->getArrayCopy(), $preserveKeys));
    }

    public function keys(): array
    {
        return array_keys($this->getArrayCopy());
    }

    /**
     * Use a user supplied callback to reduce the array to a single member and return it.
     *
     * @param callable $callback
     * @param mixed|null $initial
     *
     * @return mixed
     */
    public function reduce(callable $callback, $initial = null)
    {
        return array_reduce($this->getArrayCopy(), $callback, $initial);
    }
}

and

/**
 * Class TypedArray
 *
 * This is a typed array
 *
 * By enforcing the type, you can guarantee that the content is safe to simply iterate and call methods on.
 */
abstract class AbstractTypedArray extends ArrayObject
{
    use TypeValidator;

    /**
     * Define the class that will be used for all items in the array.
     * To be defined in each sub-class.
     */
    const ARRAY_TYPE = null;

    /**
     * Array Type
     *
     * Once set, this ArrayObject will only accept instances of that type.
     *
     * @var string $arrayType
     */
    private $arrayType = null;

    /**
     * Constructor
     *
     * Store the required array type prior to parental construction.
     *
     * @param mixed[] $input Any data to preset the array to.
     * @param int $flags The flags to control the behaviour of the ArrayObject.
     * @param string $iteratorClass Specify the class that will be used for iteration of the ArrayObject object. ArrayIterator is the default class used.
     *
     * @throws InvalidArgumentException
     */
    public function __construct($input = [], $flags = 0, $iteratorClass = ArrayIterator::class)
    {
        // ARRAY_TYPE must be defined.
        if (empty(static
🌐
Delft Stack
delftstack.com › home › howto › php › php array of objects
How to Create Array of Objects in PHP | Delft Stack
February 2, 2024 - We can use the array() function to create an array of objects in PHP. The function will take the object as the arguments and will create an array of those objects. We can create objects by creating a class and defining some properties of the class.
🌐
GeeksforGeeks
geeksforgeeks.org › php › convert-an-object-to-associative-array-in-php
Convert an object to associative array in PHP - GeeksforGeeks
July 11, 2025 - Before conversion: object(sample)#1 ... is simply the explicit conversion of a data type. It can convert a PHP object to an array by using typecasting rules supported in PHP....
Find elsewhere
🌐
TutorialsPoint
tutorialspoint.com › article › php-objects
PHP Objects.
March 15, 2026 - <?php $obj = new stdClass; $obj->name = "Deepak"; $obj->age = 21; $obj->marks = 75; print_r($obj); ?> stdClass Object ( [name] => Deepak [age] => 21 [marks] => 75 ) ... <?php $arr = array("name"=>"Deepak", "age"=>21, "marks"=>75); $obj = ...
🌐
Honar Systems
honarsystems.com › home › php array object
PHP Array Object - Honar Systems
August 10, 2025 - PHP array object allows object to work as array. Array does not object in PHP but PHP gives some ways to make objects that act like arrays.
🌐
W3Schools
w3schools.com › php › php_arrays.asp
PHP Arrays
An array stores multiple values in one single variable: $cars = array("Volvo", "BMW", "Toyota"); Try it Yourself » ... Array items can be of any data type. The most common are strings and numbers, but array items can also be objects...
🌐
Medium
medium.com › @mavelar › convert-array-to-object-object-to-array-in-php-e430ae492951
Convert Array to Object & Object to Array in PHP | by Manuel Avelar | Medium
September 28, 2017 - The above is just an example. You do not need a PHP function to convert an Array into an Object. The (object) function will do that to any PHP Array. If you ever need to change an Object into an Array, then use the (array) type casting function.
Top answer
1 of 2
43

The way I see this, it depends on what you intend to do with the data afterwards. Based on a few simple checks you can determine which of the two data structures is better for you:

  1. Does this data have any logic associated with it?

    For example, is $price stored as an integer number of cents, so a product with a price of $9.99 would have price = 999 and not price = 9.99? (Probably, yes) Or does partNumber need to match a specific regex? Or, do you need to be able to easily check if the itemCount is available in your inventory? Will you need to do these these functions in the future? If so, then your best bet is to create a class now. This means that you can define constraints and logic built into the data structure: private $myPrice is set to 999 but $item->getPriceString() returns $9.99 and $item->inStock() is available to be called in your application.

  2. Are you going to be passing this data to multiple PHP functions?

    If so, then use a class. If you're generating this data once to perform some transformations on it, or just to send as JSON data to another application (JavaScript or otherwise) then an array is an easier choice. But if you have more than two PHP functions which accept this data as a parameter, use a class. If nothing else, that lets you define someFunction(MyProductClass $product) { and it's very clear what your functions expect as input. As you scale out your code and have more functions it will be much easier to know what type of data each function accepts. Seeing someFunction($someArrayData) { is not nearly as clear. Also, this does not enforce type consistency and means that (as you said) the flexible structure of the array can cause development pain later on

  3. Are you building a library or shared code base?

    If so, use a class! Think about some new developer who is using your library, or another developer somewhere else in the company who has never used your code before. It will be much easier for them to look at a class definition and understand what that class does, or see a number of functions in your library which accept objects of a certain class, than to try and guess what structure they need to generate in a number of arrays. Also, this touches on the data consistency issues with #1: if you're developing a library or shared code base, be nice to your users: give them classes which enforce data consistency and protect them from making errors with the design of your data.

  4. Is this a small part of an application or just a transformation of data? Do you not fit into any of the above?

    A class might be too much; use an array if it suits you and you find it easier. As mentioned above, if you're just generating structured data to send as JSON or YAML or XML or whatever, don't bother with a class unless there's a need to. If you are writing a small module in a larger application, and no other modules/teams need to interface with your code, maybe an array is sufficient.

Ultimately, consider the scaling needs of your code and consider than a structured array might be a quick fix, but a class is a much more resilient and scalable solution.

Also, consider the following: if you have a class, and you want to output to JSON, there's no reason you can't define a json_data() method of your class which returns a JSON-ifiable array of the data in the class. This is what I did in my PHP applications where I needed to send class data as JSON. As an example:

class Order {
    private $my_total;
    private $my_lineitems;

    public function getItems() { return $this->my_lineitems; }
    public function addItem(Product $p) { $this->my_lineitems[] = $p; }
    public function getTotal() { return $this->my_total; }

    public function forJSON() {
        $items_json = array();
        foreach($this->my_lineitems as $item) $items_json[] = $item->forJSON();
        return array(
            'total' => $this->getTotal(),
            'items' => $items_json
        );
    }
}

$o = new Order();
// do some stuff with it
$json = json_encode($o->forJSON());
2 of 2
3

You can implement json structure using JsonSerializable interface and use nested array/class in any way. Class is faster in get/set operations and easier to debug. With Array you need no declaration.

class Order implements \JsonSerializable{
    private $my_total;
    private $my_lineitems;

    public function getItems() { return $this->my_lineitems; }
    public function addItem(Product $p) { $this->my_lineitems[] = $p; }
    public function getTotal() { return $this->my_total; }

    public function jsonSerialize(){
        return [
            'total'=>$this->my_total,
            'products'=>$this->my_lineitems;
        ];
    }
}

class Product implements \JsonSerializable{
    private $name;
    private $price;

    public function jsonSerialize(){ 
        return [
            'name'=>$this->name, 
            'price'=>$this->price
        ];
    }
}

$order = new Order();
$order->addProduct(new Product('Product1', 15));
$order->addProduct(new Product('Product2', 35));
$order->addProduct(new Product('Product3', 42));
$json = json_encode(['order'=>$order, 'username'=>'Eughen']);
/*
json = {
    order: {
        total: 92, 
        products: [
            {
                name: 'Product1',
                price: 15
            }, 
            {
                name: 'Product2',
                price: 35
            },
            {
                name: 'Product3',
                price: 42
            }
        ]
    }, 
    username: 'Eughen'
}
*/
🌐
GitHub
gist.github.com › Jeff-Russ › e1f64273a471d440e8b4d9183f9a2667
PHP: ArrayObject, IteratorAggregate , ArrayAccess , Serializable , Countable · GitHub
ArrayObject implements IteratorAggregate , ArrayAccess , Serializable , Countable { // everything gets implemented + things added. } More on the body of that later but for now focus on ArrayAccess.
🌐
EDUCBA
educba.com › home › software development › software development tutorials › php tutorial › php object to array
PHP object to array | How to Convert object to array in PHP with example?
April 18, 2023 - Here, the first method in the method sections is used for converting an object into an array. An associative array is an array that consists of a string index which stores item values linked with key values other than in order of the linear index.
Address: Unit no. 202, Jay Antariksh Bldg, Makwana Road, Marol, Andheri (East),, 400059, Mumbai