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 typeSomeObj: 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.
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:
SomeObjdefines objects with anameproperty.- The PHPDoc comment tells tools that
$objectsis an array whose elements areSomeObjinstances. - The array is created with two
SomeObjobjects. foreachtakes the first value from$objectsand assigns it to$object.- Based on the annotation, the IDE infers that
$objectis aSomeObj. $object->nameprintsAda.- 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[], orProduct[]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[], orCommand[]instances. - Validation: A validator returns
ValidationError[]so callers can access methods such asgetMessage()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.
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
| Annotation | Meaning | Best use |
|---|---|---|
array | An array with unknown key and value types | Use only when item types genuinely vary or are unknown |
SomeObj[] | An array of SomeObj values | Simple indexed collections |
array<int, SomeObj> | Integer keys and SomeObj values | Explicit indexed collections |
array<string, SomeObj> | String keys and SomeObj values | Lookups keyed by ID, email, or code |
list<SomeObj> | A sequential array of SomeObj values with keys starting at 0 | Static 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:
| Feature | Example | What it provides |
|---|---|---|
| Native property type | private 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.
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 ofSomeObjvalues.array<KeyType, ValueType>describes keys and values.private arrayenforces 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): voidto 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.
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.
Keep learning
Related questions
Are PDO Prepared Statements Enough to Prevent SQL Injection in PHP?
Learn how PDO prepared statements prevent SQL injection in PHP, what they protect, and the mistakes that still leave MySQL apps vulnerable.
Can You Bind an Array to an IN Clause in PHP PDO?
Learn how PDO handles placeholders in IN() clauses, why arrays cannot be bound directly, and the safe PHP pattern to build dynamic queries.
Choosing the Right MySQL Collation for PHP and UTF-8
Learn how MySQL character sets and collations work with PHP, and how to choose a practical UTF-8 setup for web applications.