Creating a collection from a multidimensional array?

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Creating a Collection from Multidimensional Arrays: Mastering Data Structuring in PHP/Laravel

As senior developers, we often deal with raw data—arrays of arrays, CSV dumps, or database result sets. When we bring this data into a framework like Laravel, the goal is usually to transform it into something highly navigable and expressive. The specific challenge you've encountered—creating a collection from parallel arrays and expecting property-based access—is extremely common. It highlights the difference between holding raw data and holding structured domain objects.

This post will walk you through why your initial approach doesn't work as expected and provide robust, idiomatic solutions using PHP and Laravel Collections to achieve exactly the structure you need.

The Pitfall of Parallel Arrays in Collections

Let's first analyze the code snippet you provided:

$myCollection = collect(
    ['product_id' => 1, 'price' => 200, 'discount' => '50'],
    ['product_id' => 2, 'price' => 400, 'discount' => '50']
);

foreach ($myCollection as $product) {
    // This line will likely cause an error or unexpected behavior
    echo $product->price; 
    echo $product->discount;
}

When you use the two-argument version of collect(), you are essentially creating a collection where each item is an array (or tuple) representing the row data. The collection itself holds these arrays, not objects with named properties. Therefore, when you try to access $product->price, PHP doesn't know what $product is, leading to errors because arrays do not use object property notation.

The key takeaway here is that a Collection is a container for data, but it doesn't inherently define the structure of that data. To get property-based access (->price), we must ensure the elements within our collection are actual objects or associative arrays, not just raw indexed arrays. This concept of structuring your data correctly is fundamental to writing clean code, a core principle emphasized by best practices found on platforms like laravelcompany.com.

Solution 1: Transforming Arrays into Associative Arrays (The Simple Fix)

If you only need simple key-value access without full Object-Oriented programming overhead, the simplest fix is to ensure your input arrays are structured as associative arrays and then use map() to transform them into a more useful structure.

We can combine the two parallel arrays using zip() before mapping over the result:

$data1 = ['product_id' => 1, 'price' => 200, 'discount' => '50'];
$data2 = ['product_id' => 2, 'price' => 400, 'discount' => '50'];

// Use zip to combine the corresponding elements into a single result array
$combinedData = array_map(function($row1, $row2) {
    return array_merge($row1, $row2);
}, $data1, $data2);

$myCollection = collect($combinedData);

// Now, the collection elements are associative arrays:
foreach ($myCollection as $product) {
    echo "Product ID: " . $product['product_id'] . "\n";
    echo "Price: " . $product['price'] . "\n";
    echo "Discount: " . $product['discount'] . "\n";
}

While this solves the immediate access problem, it still results in nested array access ($product['price']). For complex applications, we aim higher.

Solution 2: The Developer's Choice – Mapping to Objects (The Best Practice)

The most robust and scalable solution is to transform your raw data into actual PHP objects or Laravel Eloquent Models before putting them into the Collection. This aligns perfectly with the principles of Object-Oriented design that drive modern frameworks like Laravel.

By mapping each row (or set of parallel arrays) into a dedicated object, you gain full property access and type safety.

$data1 = ['product_id' => 1, 'price' => 200, 'discount' => '50'];
$data2 = ['product_id' => 2, 'price' => 400, 'discount' => '50'];

// Create an array of objects based on the input data
$structuredData = [];

foreach ($data1 as $index => $row1) {
    $structuredData[] = new \stdClass(); // Using stdClass for simple objects
    $structuredData[count($structuredData) - 1] = (object) $row1;
}

foreach ($data2 as $index => $row2) {
    // Assuming data1 and data2 are perfectly aligned in this example
    $structuredData[count($structuredData) - 1] = (object) array_merge($data1[$index], $row2);
}


// Now, create the collection from these structured objects
$myCollection = collect($structuredData);

// Access is now clean and object-oriented:
foreach ($myCollection as $product) {
    echo "Product ID: " . $product->product_id . "\n";
    echo "Price: " . $product->price . "\n";
    echo "Discount: " . $product->discount . "\n";
}

Conclusion

When working with data structures in PHP, the goal should always be to move from raw, unstructured arrays to structured, object-oriented representations. While you can force a collection of arrays using collect(), it forces awkward indexing later on.

The best practice is to use your data transformation step—whether that's using map() or a simple loop—to convert your input into genuine objects. This approach makes your code cleaner, easier to maintain, and aligns perfectly with the philosophy behind building elegant applications, whether you are working with simple PHP structures or complex Eloquent relationships advocated by laravelcompany.com. Always prioritize structure over convenience when handling data!