I’ve been coding in PHP for more than 14 years and worked with different versions of PHP. From 5.4 to 8.3. From very old platforms like WordPress, Joomla, CakePHP, and Zend framework to Symfony and Laravel. But one thing that I see is we are still using PHP the same way we did back a decade ago. It’s as if time has moved on, but our beloved associative arrays refuse to retire.
Today, I’m talking specifically about the widespread use of associative arrays. Back in the day, associative arrays were all the rage. They were one of PHP’s golden advantages, with their flexibility and ease of use. But that was a decade ago. Since then, PHP has introduced an arsenal of new features—Enums, read-only properties, attribute promotion, and more. We should evolve and update our methods, avoiding the use of associative arrays for everything.
Why, you ask? Let me explain, but first, let’s take a trip down memory lane…
The Glory Days of Associative Arrays
In the early days, associative arrays were like the Swiss Army knife of PHP. Need a quick key-value pair? Associative array. Want to pass some data between functions? Associative array. They were everywhere—and I mean everywhere. They offered flexibility, but flexibility came with a cost. That cost was maintenance. As projects grew larger, debugging became harder. Have you ever tried to debug a deeply nested associative array across services? It’s like untangling Christmas lights—except no lights.
Now, PHP has given us better tools, and it’s time to take advantage of them. Today, it’s all about DTOs, value objects, and classes.
What’s Wrong with Associative Arrays in Modern PHP?
Let’s break it down:
Associative Arrays (Old Days) | DTOs/Classes (Modern Approach) |
No type safety | Strict types (string, int, etc.) |
Easy to make typos in keys | IDE support with code completion |
Hard to debug deeply nested arrays | Debug-friendly structured classes |
No built-in validation | Custom validation logic in classes |
No methods—just raw data | Encapsulate behavior & logic |
Associative arrays are loose, dangerous, and are like that friend who never RSVPs but always shows up. Sure, they’re reliable in the sense that they’ll show up (somehow), but in the end, you can’t really plan around them. And if you want maintainable code, it’s time to make a change.
The Rise of Structured Data: DTOs and Classes
With modern PHP, the correct approach is to embrace structured data, like DTOs (Data Transfer Objects) and value objects. These provide clear, predictable data structures that give you:
- Type safety (goodbye, random null or false values!)
- IDE assistance (hello, code completion)
- Consistency (no more hunting for typos in array keys)
- Validation and logic (we can ensure data integrity directly within the class)
Now, PHP doesn’t have structs like some other languages (looking at you, C++), but fear not! We can use DTOs and classes in their place. Let’s dive into the difference between DTOs and regular classes.
DTO vs. Regular Class: What’s the Difference?
It’s easy to confuse DTOs and regular classes, but they serve different purposes. Let’s break down the differences:
DTO | Regular Class |
Purpose: Purely to transfer data | Purpose: Represents an entity or concept, encapsulating data and logic |
Behavior: No business logic, just getters/setters | Behavior: Can include validation, methods, and other behaviors |
Mutable or Immutable: Often immutable (but can be mutable) | Mutable or Immutable: Can be either, depending on design |
Methods: Mostly basic getters, sometimes setters | Methods: Includes logic to manipulate data and interact with other objects |
DTO Example:
class UserDTO {
public function __construct(
private string $name,
private string $email
) {
}
public function getName(): string
{
return $this->name;
}
public function getEmail(): string
{
trturn $this->email;
}
}
This UserDTO
is simple—its sole purpose is to transfer data across layers. There’s no logic, just getters and setters (or sometimes, not even setters if it’s immutable).
Class Example:
class User {
private string $name;
private string $email;
public function __construct(string $name, string $email)
{
$this->setName($name);
$this->setEmail($email);
}
private function setName(string $name): void
{
if (empty($name)) {
throw new InvalidArgumentException('Name cannot be empty.');
}
$this->name = $name;
}
public function getName(): string
{
return $this->name;
}
private function setEmail(string $email): void
{
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new InvalidArgumentException('Invalid email format.');
}
$this->email = $email;
}
public function getEmail(): string
{
trturn $this->email;
}
}
Here, User
is a domain model class. Not only does it hold data, but it also enforces validation rules (e.g., making sure the name isn’t empty and the email is valid). In other words, it has behavior, unlike the DTO.
The Perks of Using Value Objects
Now that you know the difference between DTOs and classes, let’s talk about value objects. They’re perfect when you want to represent small, simple concepts like age, money, or coordinates, but need a bit more control over the data.
For example, a value object for Age might ensure the value is always a positive integer:
class Age {
public function __construct(private int $age)
{
if ($age < 0) {
throw new InvalidArgumentException('Age must be a positive integer.');
}
}
public function getAge(): int {
return $this->age;
}
}
This is great when you want to prevent invalid data (like a negative age) while keeping your code simple and readable.
Conclusion: The Time for Evolution Is Now
So, why are we still using associative arrays everywhere in modern PHP applications? It’s time to embrace change. With features like Enums, attribute promotion, typed properties, and read-only properties, PHP has given us powerful tools to write clean, maintainable, and robust code.
Here’s a quick checklist:
- Use DTOs to transfer data.
- Use value objects to represent domain-specific values.
- Use classes to encapsulate both data and behavior.
- Avoid associative arrays as much as possible in structured applications.
As someone who’s seen PHP evolve from its 5.4 days to 8.3, I can confidently say—we’re no longer living in the world of Christmas lights tangled with associative arrays. Let’s leverage the powerful features PHP has introduced, and make our code easier to read, maintain, and debug.
The future of PHP development is here. Let’s code like it.