Question
How can I create an empty object in PHP and assign nested values to it, similar to creating and filling a nested array?
$aVal = array();
$aVal['key1']['var1'] = 'something';
$aVal['key1']['var2'] = 'something else';
Is there equivalent object syntax that lets me write values such as $oVal->key1->var1 and $oVal->key1->var2?
Short Answer
You will learn how to create an empty PHP object with stdClass, why nested objects must be initialized before use, and when an array or a named class is the better data structure.
Concept
PHP arrays and objects both store related data, but they use different access syntax:
- Arrays use keys:
$data['key'] - Objects use properties:
$data->key
For a flexible, empty object, PHP provides stdClass:
$object = new stdClass();
Unlike nested array keys, nested object properties are not created automatically. Before assigning to $object->key1->var1, the key1 property must already contain an object. Otherwise, PHP is trying to set a property on null.
$object = new stdClass();
$object->key1 = new stdClass();
$object->key1->var1 = 'something';
This matters because objects usually represent entities with properties, such as a user, API response, configuration object, or request payload. In larger applications, developers often replace flexible stdClass objects with named classes that document the expected properties and behavior.
Mental Model
Think of an object as a cabinet with labelled compartments.
$oValis the main cabinet.$oVal->key1is a compartment inside it.$oVal->key1->var1is a labelled item stored in that compartment.
You cannot put an item into the key1 compartment until that compartment exists. Therefore, create $oVal->key1 as an object before adding var1 and var2 to it.
Arrays feel different because PHP can create missing nested array keys while you assign to them. Objects require you to explicitly create each nested object.
Syntax and Examples
Create an empty generic object with new stdClass():
<?php
$oVal = new stdClass();
$oVal->key1 = new stdClass();
$oVal->key1->var1 = 'something';
$oVal->key1->var2 = 'something else';
echo $oVal->key1->var1; // something
stdClass is PHP's built-in generic object class. It is useful when the property names are only known at runtime or when you need a lightweight data container.
You can also initialize the nested object inline:
<?php
$oVal = new stdClass();
$oVal->key1 = (object) [
'var1' => 'something',
'var2' => 'something else',
];
For a single empty object, an object cast also works:
$oVal = (object) [];
However, new stdClass() is usually clearer to readers.
If a property name is stored in a variable or contains characters that cannot be written in normal property syntax, use braces:
<?php
$fieldName = 'first-name';
$oVal = new stdClass();
$oVal->{$fieldName} = 'Ada';
echo $oVal->{'first-name'}; // Ada
Step by Step Execution
Consider this code:
<?php
$profile = new stdClass();
$profile->contact = new stdClass();
$profile->contact->email = 'ada@example.com';
$profile->contact->verified = true;
Step by step:
$profile = new stdClass();creates one empty object.$profile->contact = new stdClass();creates a second empty object and stores it in thecontactproperty.$profile->contact->email = ...finds thecontactobject, then adds itsemailproperty.$profile->contact->verified = true;adds another property to the same nested object.
The resulting structure is conceptually similar to:
profile
└── contact
├── email: ada@example.com
└── verified: true
This does not work safely:
<?php
$profile = new stdClass();
$profile->contact->email = 'ada@example.com';
At that point, contact has not been initialized as an object.
Real World Use Cases
Generic objects are useful for small, flexible data structures.
- JSON API payloads: Build a request body with nested fields before encoding it with
json_encode(). - Configuration data: Group settings such as
$config->database->hostand$config->database->port. - Decoded JSON:
json_decode($json)returnsstdClassobjects by default for JSON objects. - View data: Pass simple structured data to a template, such as
$page->seo->title. - Temporary transformations: Assemble a response object from values retrieved from several sources.
Example: building JSON for an API request:
<?php
$payload = new stdClass();
$payload->customer = new stdClass();
$payload->customer->name = 'Ada Lovelace';
$payload->customer->email = 'ada@example.com';
$json = json_encode($payload, JSON_THROW_ON_ERROR);
The JSON result has a nested customer object.
Real Codebase Usage
In production code, choose the structure based on how predictable the data is.
Flexible external data
stdClass is common when handling data from JSON or APIs whose fields may vary.
$response = json_decode($body);
if (!isset($response->user)) {
throw new RuntimeException('Response does not include a user.');
}
Guard clauses before nested access
Check that optional nested data exists before using it:
if (!isset($response->user->email)) {
return null;
}
return $response->user->email;
isset() is useful here because it returns false instead of raising an error when part of the property path is missing or null.
Named classes for known application data
When your application always expects the same fields, use a class rather than attaching arbitrary properties:
<?php
final class Contact
{
public function __construct(
public string $email,
public bool $verified,
) {
}
}
$contact = new Contact('ada@example.com', true);
Named classes provide clearer intent, type declarations, IDE autocomplete, and a place for validation or methods.
Arrays for map-like data
For data indexed by variable keys, arrays are often simpler:
$headers = [];
$headers['X-Request-ID'] = 'abc123';
Common Mistakes
Assigning through an uninitialized nested property
Broken code:
<?php
$oVal = new stdClass();
$oVal->key1->var1 = 'something';
$oVal->key1 has no object assigned to it yet. Initialize it first:
$oVal->key1 = new stdClass();
$oVal->key1->var1 = 'something';
Casting an empty string and expecting nested objects
$oVal = (object) '';
Although casting can produce an object, it does not create $oVal->key1. You still must initialize nested levels. Prefer the clearer form:
$oVal = new stdClass();
Mixing array and object syntax
Broken code:
$oVal = new stdClass();
$oVal['key1'] = 'value';
A standard object is accessed with ->, not array brackets:
$oVal->key1 = 'value';
Assuming a missing property is an object
A missing property reads as null (and may produce a warning when read). Do not chain into it without checking or initializing it.
Using dynamic properties on your own classes without declaring them
Adding undeclared properties to stdClass is intended. However, in PHP 8.2 and later, creating dynamic properties on most user-defined classes is deprecated. Declare class properties instead:
final class User
{
public string $name;
}
$user = new User();
$user->name = 'Ada';
Forgetting that object assignment shares the same instance
$a = new stdClass();
$a->name = 'Ada';
$b = $a;
$b->name = 'Grace';
echo $a->name; // Grace
$a and $b refer to the same object instance. Use clone $a when you specifically need a separate shallow copy.
Comparisons
| Need | Best choice | Access syntax | Notes |
|---|---|---|---|
| Flexible key-value data | Array | $data['key'] | Missing nested keys can be created during assignment. |
| Flexible property-based data | stdClass | $data->key | Initialize each nested object before assigning through it. |
| Predictable application entity | Named class | $user->name | Best for types, validation, methods, and maintainability. |
| Data received from JSON | stdClass or array | -> or [] | Choose with json_decode() options. |
stdClass versus arrays when decoding JSON
$json = '{"user":{"name":"Ada"}}';
$asObject = json_decode($json);
echo $asObject->user->name;
$asArray = json_decode($json, true);
echo $asArray['user']['name'];
Both represent the same JSON data. Use one style consistently within a piece of code where possible.
stdClass versus a named class
Use stdClass for temporary or unknown-shaped data. Use a named class when the object has a known purpose and stable fields. For example, a User class can guarantee that every user has an email address and can provide methods such as isVerified().
Cheat Sheet
// Empty generic object
$data = new stdClass();
// Equivalent empty-object cast
$data = (object) [];
// Add a property
$data->name = 'Ada';
// Create a nested object before using it
$data->address = new stdClass();
$data->address->city = 'London';
// Build a nested object in one expression
$data->address = (object) [
'city' => 'London',
'country' => 'UK',
];
// Dynamic property name
$key = 'display-name';
$data->{$key} = 'Ada Lovelace';
// Safely check nested data
if (isset($data->address->city)) {
echo $data->address->city;
}
Rules to remember:
- Use
new stdClass()for a generic empty object. - Use
->for object properties and[]for array keys. - Create every nested object before assigning into it.
- Use
stdClassfor flexible data; use a declared class for stable domain data. - Dynamic properties are appropriate on
stdClass, but generally avoid them on your own classes in PHP 8.2+.
FAQ
How do I make an empty object in PHP?
Use new stdClass():
$object = new stdClass();
Can I use (object) [] to create an empty object?
Yes. (object) [] creates an empty stdClass object. new stdClass() is often more readable.
Why does $object->a->b = 'value' fail?
Because $object->a has not been initialized as an object. Create it first with $object->a = new stdClass();.
Does PHP automatically create nested object properties?
No. PHP can create nested array keys during assignment, but nested objects must be initialized explicitly.
Should I use an array or an object in PHP?
Use arrays for flexible, key-indexed collections. Use objects when properties describe an entity or when you need behavior, types, and clearer structure.
What object type does json_decode() return?
By default, JSON objects decode to stdClass instances. Pass true as the second argument to receive associative arrays instead.
Can I add any property to stdClass?
Yes. stdClass is designed as a generic object that can receive dynamic properties.
Are object assignments copied in PHP?
Assigning an object variable copies the reference-like handle to the same object. Changes through either variable affect the same instance unless you use clone.
Mini Project
Description
Build a small API-style profile payload using nested stdClass objects. This demonstrates the key rule for nested objects: create each level before assigning properties within it.
Goal
Create a profile object with nested contact and address information, then convert it to JSON.
Requirements
Initialize a root object using stdClass.
Create a nested contact object before setting its properties.
Create a nested address object before setting its properties.
Add a name, email, city, and country.
Encode and print the final structure as JSON.
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.