Question

PHPDoc Array of Objects Type Hints in PHP

phpidephpdocvarhint

Question

How can I use PHPDoc to declare that a class property contains an array of SomeObj instances so that an IDE can provide autocompletion and type information when I iterate over the array?

<?php

class Test
{
    /** @var SomeObj */
    private $someObjInstance;
}

@var SomeObj works for one object, but @var array does not tell the IDE what type each array element contains. Is there valid PHPDoc syntax for an array of SomeObj objects?

Short Answer

You will learn how to document collections of objects in PHPDoc using SomeObj[] and generic array syntax. You will also see how those annotations help IDEs and static-analysis tools infer the type of each item inside a foreach loop.

Concept

PHP arrays can contain values of any type, including objects. At runtime, an array does not automatically remember or enforce that every value is a SomeObj.

PHPDoc adds metadata for tools such as IDEs, PHPStan, and Psalm. For an array whose values are SomeObj instances, the most common annotation is:

/** @var SomeObj[] */
private $objects;

SomeObj[] means “an array of SomeObj values.” When code iterates over that property, a compatible tool can infer that each element is a SomeObj and offer methods and properties from that class.

A more explicit modern form is:

/** @var array<int, SomeObj> */
private $objects;

This describes both parts of the array:

  • int: the key type
  • SomeObj: the value type

These annotations improve editor assistance and static checking, but PHPDoc alone does not stop invalid values from being inserted into the array. Your code must still validate inputs when necessary.

Mental Model

Think of an array as a box containing many labelled folders. Writing array on the box only says that it contains folders; it does not say what is inside them.

Writing SomeObj[] adds a label: “Every folder in this box should be a SomeObj.” An IDE can read that label. Therefore, when you take one folder out during foreach, it knows which SomeObj methods should be available.

PHPDoc is the label, not a physical lock. Someone can still put the wrong item into the box unless your program checks it.

Take Quiz

Syntax and Examples

Use ClassName[] for a simple array of objects:

<?php

class SomeObj
{
    public function getName(): string
    {
        return 'Example';
    }
}

class Test
{
    /** @var SomeObj[] */
    private array $objects = [];

    public function add(SomeObj $object): void
    {
        $this->objects[] = $object;
    }

    public function printNames(): void
    {
        foreach ($this->objects as $object) {
            echo $object->getName() . PHP_EOL;
        }
    }
}

The property has a native PHP type of array, which guarantees only that the property is an array. The PHPDoc annotation adds the missing element type: SomeObj.

For an explicit key and value declaration, use generic array syntax:

/** @var array<int, SomeObj> */
private array $objects = [];

For an associative array keyed by strings, write:

/** @var array<string, SomeObj> */
private array $objectsById = [];

Both SomeObj[] and array<int, SomeObj> are commonly understood by modern PHP tools. The second form is especially useful when the key type matters.

Step by Step Execution

Consider this example:

<?php

class SomeObj
{
    public function __construct(public string $name)
    {
    }
}

/** @var SomeObj[] $objects */
$objects = [
    new SomeObj('Ada'),
    new SomeObj('Linus'),
];

foreach ($objects as $object) {
    echo $object->name . PHP_EOL;
}

Execution proceeds as follows:

  1. SomeObj defines objects with a name property.
  2. The PHPDoc comment tells tools that $objects is an array whose elements are SomeObj instances.
  3. The array is created with two SomeObj objects.
  4. foreach takes the first value from $objects and assigns it to $object.
  5. Based on the annotation, the IDE infers that $object is a SomeObj.
  6. $object->name prints Ada.
  7. The loop repeats for the second object and prints Linus.

The annotation does not change PHP's loop behavior. It gives development tools enough information to understand the value held by $object.

Real World Use Cases

Arrays of objects appear throughout PHP applications:

  • Database repositories: A repository returns User[], Order[], or Product[] objects.
  • API clients: A decoded API response is converted into an array of DTOs such as WeatherReport[].
  • Framework collections: A service may build an array of Middleware[], EventListener[], or Command[] instances.
  • Validation: A validator returns ValidationError[] so callers can access methods such as getMessage() safely.
  • Caching: A cache layer stores CacheItem[] or domain objects grouped by identifier.

In each case, documenting the element type prevents a common ambiguity: knowing that a variable is an array but not knowing what each item can do.

Take Quiz

Real Codebase Usage

In real codebases, developers usually combine an element-type PHPDoc annotation with APIs that make invalid values difficult to add.

Type the property and the method parameter

<?php

class Team
{
    /** @var User[] */
    private array $members = [];

    public function addMember(User $user): void
    {
        $this->members[] = $user;
    }

    /** @return User[] */
    public function getMembers(): array
    {
        return $this->members;
    }
}

The User parameter ensures addMember() receives a User. The User[] annotations tell tools the type of array elements, including for callers of getMembers().

Use associative keys deliberately

/** @var array<string, User> */
private array $usersByEmail = [];

This signals that email addresses are keys and User objects are values.

Add a local annotation when type information is lost

Some older libraries return a plain array without useful PHPDoc. Add a local annotation after you validate or otherwise know the contents:

$results = $repository->findAll();

/** @var User[] $results */
foreach ($results as $user) {
    $user->sendWelcomeEmail();
}

Use this carefully: it should describe a fact your code can rely on, not hide an uncertain type. Static analyzers can then report mismatches elsewhere.

Common Mistakes

Using only array

/** @var array */
private array $objects = [];

This says nothing about the values inside the array. An IDE may treat $object in a loop as mixed.

Avoid it: use SomeObj[] or array<int, SomeObj>.

Using nonstandard array(SomeObj) syntax

/** @var array(SomeObj) */
private array $objects = [];

This is not the standard PHPDoc generic-array notation and may not be understood by tools.

Avoid it: write SomeObj[] or array<int, SomeObj>.

Assuming PHPDoc enforces runtime types

/** @var SomeObj[] */
private array $objects = [];

public function add(mixed $value): void
{
    $this->objects[] = $value;
}

The annotation does not prevent a string, integer, or unrelated object from being appended.

Avoid it: accept a typed parameter such as add(SomeObj $object): void, or validate a dynamic value before storing it.

Omitting a return element type

public function getObjects(): array
{
    return $this->objects;
}

The native array return type is useful, but callers still do not know the element type.

Avoid it: add /** @return SomeObj[] */ above the method.

Confusing array keys with values

/** @var array<string, SomeObj> */
private array $objects = [];

This means string keys and SomeObj values. It does not mean that SomeObj is a string.

Avoid it: read array<KeyType, ValueType> from left to right.

Comparisons

AnnotationMeaningBest use
arrayAn array with unknown key and value typesUse only when item types genuinely vary or are unknown
SomeObj[]An array of SomeObj valuesSimple indexed collections
array<int, SomeObj>Integer keys and SomeObj valuesExplicit indexed collections
array<string, SomeObj>String keys and SomeObj valuesLookups keyed by ID, email, or code
list<SomeObj>A sequential array of SomeObj values with keys starting at 0Static analysis when order and list-like keys matter

SomeObj[] is concise and usually sufficient. array<TKey, TValue> is clearer when keys are meaningful. list<SomeObj> is supported by tools such as PHPStan and Psalm, but it expresses a stricter expectation than a general PHP array.

Native PHP type declarations and PHPDoc serve different roles:

FeatureExampleWhat it provides
Native property typeprivate array $objects = [];Runtime enforcement that the property is an array
PHPDoc element type/** @var SomeObj[] */Tooling information about values within that array

Using both is often the clearest approach.

Take Quiz

Cheat Sheet

// Array containing SomeObj values
/** @var SomeObj[] */
private array $objects = [];

// Explicit integer keys and SomeObj values
/** @var array<int, SomeObj> */
private array $objects = [];

// String-keyed lookup table
/** @var array<string, SomeObj> */
private array $objectsById = [];

// Method returning objects
/** @return SomeObj[] */
public function getObjects(): array
{
    return $this->objects;
}

// Method receiving an array of objects
/** @param SomeObj[] $objects */
public function replaceObjects(array $objects): void
{
    $this->objects = $objects;
}
  • SomeObj[] means an array of SomeObj values.
  • array<KeyType, ValueType> describes keys and values.
  • private array enforces only “this is an array,” not its element type.
  • PHPDoc improves IDE and static-analysis results; it is not runtime validation.
  • Prefer typed methods such as add(SomeObj $object): void to protect the collection.

FAQ

What is the PHPDoc syntax for an array of objects?

Use /** @var SomeObj[] */. This means that the array values are instances of SomeObj.

Can I use array<SomeObj> in PHPDoc?

Many modern tools accept array<SomeObj> as shorthand. However, SomeObj[] and array<int, SomeObj> are broadly clear and explicit. Use array<int, SomeObj> when you want to document the key type too.

Does SomeObj[] enforce that every value is a SomeObj?

No. PHPDoc is documentation and tooling metadata. Use typed parameters, validation, and static analysis to catch invalid values.

Should I use both array and SomeObj[]?

Yes, when your PHP version supports typed properties. For example, use private array $objects = []; for runtime array enforcement and /** @var SomeObj[] */ for element-type information.

How do I document a method that returns an array of objects?

Add /** @return SomeObj[] */ above a method whose native return type is array.

How do I document an associative array of objects?

Use array<string, SomeObj> when keys are strings, such as user IDs or emails. Use the actual key type that your code expects.

Why does my IDE still not infer the type in foreach?

Check that the annotation is attached to the correct property, variable, parameter, or return value. Also verify that the IDE recognizes the class name and supports the PHPDoc syntax you used.

Take Quiz

Mini Project

Description

Build a small in-memory product catalog. The catalog stores Product objects in an associative array keyed by SKU. PHPDoc records the key and value types so tools can infer the type returned from the catalog and the type used in foreach.

Goal

Create a catalog that adds products, finds one product by SKU, and prints every product in the catalog.

Requirements

Define a Product class with an SKU and name. Store products in a Catalog class using the SKU as the array key. Document the catalog property as an array with string keys and Product values. Add a method that accepts only Product objects. Add methods to find a product and return all products. Loop through all products and print their details.

Take Quiz

Keep learning

Related questions

View more