Handling Nested PHP Arrays Using DataBlock

PHP DataBlock is designed to improve the developer experience when working with complex and deeply nested PHP arrays.

If you work with PHP long enough, you will eventually fight an array.

Not because arrays are bad, but because nested, dynamic arrays are everywhere:

  • API responses
  • Configuration files
  • Decoded JSON or YAML
  • Shared data structures with third-party libraries

And they usually come with the same problems:

  • Deep isset() chains
  • Missing keys causing subtle bugs
  • Manual type casting
  • Unclear defaults

This is where DataBlock comes in.

GitHub repo & installation:
https://github.com/Hi-Folks/data-block

What is DataBlock?

DataBlock is a small PHP library that wraps arrays into a safer, more expressive object called a Block.

The DataBlock PHP library doesn’t replace arrays; it improves how you access, read, and handle them.

With DataBlock, you get:

  • Dot-notation access to nested data
  • Typed getters (getInt(), getString(), etc.)
  • Safe defaults
  • Better readability
  • Easy data inspection and export

Let’s see why that matters.

The simple example dataset

For the examples included in this article, we are going to use a small dataset representing fruits:

use HiFolksDataTypeBlock;

$fruitsArray = [
    "avocado" => [
        "name" => "Avocado",
        "fruit" => "🥑",
        "wikipedia" => "https://en.wikipedia.org/wiki/Avocado",
        "color" => "green",
        "rating" => 8,
    ],
    "apple" => [
        "name" => "Apple",
        "fruit" => "🍎",
        "wikipedia" => "https://en.wikipedia.org/wiki/Apple",
        "color" => "red",
        "rating" => 7,
    ],
    "banana" => [
        "name" => "Banana",
        "fruit" => "🍌",
        "wikipedia" => "https://en.wikipedia.org/wiki/Banana",
        "color" => "yellow",
        "rating" => 8.5,
    ],
    "cherry" => [
        "name" => "Cherry",
        "fruit" => "🍒",
        "wikipedia" => "https://en.wikipedia.org/wiki/Cherry",
        "color" => "red",
        "rating" => 9,
    ],
];

$data = Block::make($fruitsArray);

Once the array is wrapped in a Block object, the focus shifts.
Instead of worrying about how the data is structured and whether every key exists, you can concentrate on what you want to read from it.

Safe access without isset()

Accessing nested arrays in plain PHP often ends up looking like this:

$color = $array['avocado']['color'] ?? null;

This works, but it doesn’t scale very well.
As soon as the data becomes more complex or dynamic, these checks start spreading across the codebase, making it harder to read and maintain.

With DataBlock, accessing nested values becomes more direct and expressive:

$data->get("avocado.color");

You can safely retrieve values using dot notation, even when the structure is deeply nested:

var_dump(
    $data->get("avocado.color"),
    $data->get("avocado.rating"),
    $data->get("banana.rating"),
    $data->get("apple.notexists"),
);

Output:

string(5) "green"
int(8)
float(8.5)
NULL

Missing keys are handled gracefully, without triggering warnings or notices.
There’s no need for defensive isset() checks or fallback logic scattered throughout the code, just clear, predictable access to the data you need.

Typed getters and defaults

Arrays, by nature, don’t express intent.
When you read a value from an array, it’s not always clear what type that value is supposed to be, or what should happen if it’s missing.

DataBlock makes this explicit.

Instead of retrieving a value and then casting or validating it later, DataBlock allows you to express your expectations directly at the point of access:

var_dump(
    $data->getInt("avocado.rating"),
    $data->getInt("banana.rating"),
    $data->getFloat("banana.rating"),
    $data->get("apple.notexists", "MY_DEFAULT"),
);

Output:

int(8)
int(8)
float(8.5)
string(10) "MY_DEFAULT"

Here, the method name clearly communicates the expected type.
A numeric value is automatically cast to an integer or a float, while missing fields can fall back to a sensible default, all in a single, readable expression.

Why this matters:

  • getInt() and getFloat() make your intent explicit and self-documenting
  • Type casting happens consistently and close to the data source
  • Default values are handled inline, without extra conditional logic

This approach is especially valuable when working with external or untrusted data, such as API responses, configuration files, or decoded JSON, where types and the presence of fields cannot always be guaranteed.

Working with subsets of data

In some cases, you don’t just need a single value; you want to work with an entire section of the dataset.
DataBlock allows you to retrieve a whole branch of the structure in a straightforward way:

$avocado = $data->get("avocado");

In this case, you receive the underlying array:

[
  "name" => "Avocado",
  "fruit" => "🥑",
  "wikipedia" => "...",
  "color" => "green",
  "rating" => 8
]

This is useful when you want to pass the data to existing code that expects a plain PHP array.

Alternatively, if you want to keep working within the DataBlock API, you can retrieve the same branch as a Block instance:

$avocadoBlock = $data->getBlock("avocado");

By using the getBlock() method, you retain all the benefits of DataBlock, dot notation for nested access, typed getters, and the ability to inspect available keys, while focusing only on the portion of the data you’re interested in.

This makes it easy to navigate complex structures step by step, without losing context or switching mental models.

Discovering what’s inside your data

When dealing with dynamic or loosely defined data structures, simply knowing what keys are available can make a big difference.
DataBlock provides a simple way to inspect the structure of your dataset by listing its keys:

$data->keys();

Result:

["avocado", "apple", "banana", "cherry"]

This provides an immediate overview of the top-level elements, which is especially helpful when working with data from external sources.

The same approach also works for nested data. You can inspect the keys of a specific branch by retrieving it as a Block:

$data->getBlock("avocado")->keys();

Result:

["name", "fruit", "wikipedia", "color", "rating"]

Being able to explore the available keys at each level makes DataBlock particularly useful for debugging, data exploration, and building dynamic behaviors such as conditional rendering or automatic mappings.

Exporting data to YAML (and more)

Beyond reading and navigating data, DataBlock can also help with data representation and serialization.

In addition to JSON (method toJson()), DataBlock allows you to serialize your data into YAML, which is often easier to read and reason about, especially for configuration and inspection purposes:

echo $data->toYaml();

Output:

avocado:
  name: Avocado
  fruit: 🥑
  wikipedia: https://en.wikipedia.org/wiki/Avocado
  color: green
  rating: 8
apple:
  name: Apple
  fruit: 🍎
  wikipedia: https://en.wikipedia.org/wiki/Apple
  color: red
  rating: 7
...

Being able to convert a structured dataset into a human-readable or machine-readable format quickly is helpful in many everyday scenarios.
This includes generating configuration files, producing clear debug output, or sharing data with tools and systems that work naturally with YAML.

When should you use PHP DataBlock?

DataBlock is a great fit when:

  • You consume API responses.
  • You parse JSON/YAML
  • You deal with deeply nested arrays.
  • You want safer, clearer PHP code.

It doesn’t try to replace domain models; it simply makes raw data easier and safer to work with.

Arrays vs DataBlock vs DTOs: which one should you use?

When working with data in PHP, there are usually three common approaches:

  1. Plain PHP arrays
  2. DataBlock
  3. DTOs (Data Transfer Objects)

Each one has a purpose; the key is knowing when to use which.

1) Plain PHP Arrays

The default/first choice.
Arrays are flexible, fast, and built into the language.

$rating = $data['avocado']['rating'] ?? null;

Pros

  • Native PHP feature
  • Zero dependencies
  • Very flexible

Cons

  • No type safety
  • Verbose access for nested data
  • Easy to introduce silent bugs
  • Hard to understand intent
  • Defensive code everywhere

Best for

  • Very small scripts
  • Simple, flat data
  • Performance-critical hot paths

Once data becomes nested or dynamic, arrays tend to leak complexity everywhere.

2) DataBlock

A safer abstraction over arrays.
DataBlock keeps the flexibility of arrays while adding structure and intent.

$rating = $data->getInt("avocado.rating");

Pros

  • Safe nested access (no warnings)
  • Typed getters
  • Defaults built in
  • Highly readable
  • Great for untrusted or dynamic data

Cons

  • Still runtime-typed (not compile-time)
  • Not a domain model
  • Adds a small dependency

Best for

  • API responses
  • Configuration files
  • JSON / YAML parsing
  • Boundary layers (input/output)
  • Rapid prototyping without sacrificing safety

Think of DataBlock as a smart boundary object between raw data and your application logic.

3) DTOs (Data Transfer Objects)

The most explicit and strict option.
DTOs define exactly what your data looks like.

final class FruitDTO
{
    public function __construct(
        public string $name,
        public string $color,
        public float $rating
    ) {}
}

Pros

  • Strong typing
  • IDE autocompletion
  • Self-documenting
  • Great for domain logic
  • Easier to refactor safely

Cons

  • Verbose
  • Requires mapping
  • Rigid structure
  • Overkill for dynamic data

Best for

  • Domain models
  • Business logic
  • Internal application state
  • Long-lived data structures

DTOs shine inside your application, where structure is stable, and rules matter.

The key difference is where you use them

Layer My opinionated recommendation
External input (API, JSON, YAML) DataBlock
Simple scripts Array
Domain logic DTO
Configuration DataBlock
Public interfaces DTO

Recap: why DataBlock exists

DataBlock doesn’t compete with DTOs; it complements them.

It lives in the uncomfortable middle ground where:

  • Data is messy
  • Structure is mostly known
  • Safety matters
  • Full modeling would be too heavy.

If arrays are too loose and DTOs are too strict, DataBlock is the pragmatic middle layer.

Final thoughts

PHP arrays are powerful, but they’re also easy to misuse.

DataBlock is designed to improve the developer experience when working with complex, nested, and structured datasets by providing a fluent and expressive way to access and handle data.

Less boilerplate, fewer bugs, more readable code.

Check it out on GitHub:
https://github.com/Hi-Folks/data-block

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post

Monetzly: Boost Developer Revenue with AI Conversation Ads

Next Post

After 47 Failed Systems, I Built One That Works: The Purpose Stack

Related Posts