• 0

Breaking my head on a multi-dimensional array


Question

Hi people! I've been trying to get a receipt # from a database and building up an array with it.

I've modified the code, at least 5 times to make it work, but I need a last push, and I can't seem to get it:


private function array_key_exists_r($needle, $haystack)
{
$result = array_key_exists($needle, $haystack);
if ($result) return $result;
foreach ($haystack as $v) {
if (is_array($v)) {
$result = $this->array_key_exists_r($needle, $v);
}
if ($result) return $result;
}
return $result;
}


while($row = $this->stmt->fetch())
{

$factura = $row['factura']; /*This is how I get the receipt's number*/
print($factura);
$result = $this->array_key_exists_r($factura,$this->factura);
if(!$result)
{
if(!in_array($factura,$this->trigger)) $this->trigger[] = $factura;
$this->factura = array($factura => array('producto_id' => array($row['producto_id']),
'producto' => array($row['producto']),
'cantidad' => array($row['cantidad']),
'price_i' => array($row['price_i']),
'tax' => array($row['tax'])
)
);

}

else
{

$this->factura[$factura]['producto_id'][] =$row['producto_id'];
$this->factura[$factura]['producto'][] =$row['producto'];
$this->factura[$factura]['cantidad'][]= $row['cantidad'];
$this->factura[$factura]['price_i'][] =$row['price_i'];
$this->factura[$factura]['tax'][] = $row['tax'];
}

}
[/CODE]

Explaining:

The code is trying to do the following:

Create an array which first keys are the receipt number, and to that receipt number add all the products that were fetched from the database.

What I'm getting:

The array is being currently overwrote by the last receipt #. I know that the root of all this evil is this portion of the code:

[CODE]
if(!in_array($factura,$this->trigger)) $this->trigger[] = $factura;
[b] $this->factura = [/b]array($factura => array('producto_id' => array($row['producto_id']),
'producto' => array($row['producto']),
'cantidad' => array($row['cantidad']),
'price_i' => array($row['price_i']),
'tax' => array($row['tax'])
)
);

[/CODE]

The bold part should actually be:

[CODE]
$this->factura[] =
[/CODE]

But by doing so, the whole schema breaks, and the receipts are not appended in order.

Now, in English:

The result I'm getting without any mods:

[CODE]
Array
(
[4] => Array
(
[producto_id] => Array
(
[0] => E5030
[1] => E5060
[2] => E0094
[3] => E7485
)

[producto] => Array
(
[0] => Product # 1
[1] => Product # 2
[2] => Product # 3
[3] => Product # 4
)

[cantidad] => Array
(
[0] => 1
[1] => 1
[2] => 1
[3] => 1
)

[price_i] => Array
(
[0] => 286.62
[1] => 301.92
[2] => 153
[3] => 481
)

[tax] => Array
(
[0] => 1
[1] => 1
[2] => 1
[3] => 1
)

)

)

[/CODE]

WHICH IS GOOD, but the other receipts are overwritten.

But if I made the change I was talking about before, I'd get:

[CODE]
Array
(
[0] => Array
(
[1] => Array
(
[producto_id] => Array
(
[0] => A4318
)

[producto] => Array
(
[0] => Product name
)

[cantidad] => Array
(
[0] => 1
)

[price_i] => Array
(
[0] => 771.12
)

[tax] => Array
(
[0] => 0
)

)

)

[1] => Array
(
[producto_id] => Array
(
[0] => 102992
)

[producto] => Array
(
[0] =>Product name
)

[cantidad] => Array
(
[0] => 1
)

[price_i] => Array
(
[0] => 1128.12
)

[tax] => Array
(
[0] => 0
)

)

[2] => Array
(
[2] => Array
(
[producto_id] => Array
(
[0] => A5816
)

[producto] => Array
(
[0] => Product name
)

[cantidad] => Array
(
[0] => 1
)

[price_i] => Array
(
[0] => 630.36
)

[tax] => Array
(
[0] => 0
)

)

)

[3] => Array
(
[4] => Array
(
[producto_id] => Array
(
[0] => E5030
)

[producto] => Array
(
[0] => Product name
)

[cantidad] => Array
(
[0] => 1
)

[price_i] => Array
(
[0] => 286.62
)

[tax] => Array
(
[0] => 1
)

)

)

[4] => Array
(
[producto_id] => Array
(
[0] => E5060
[1] => E0094
[2] => E7485
)

[producto] => Array
(
[0] => Product name
[1] => Product name
[2] => Product name
)

[cantidad] => Array
(
[0] => 1
[1] => 1
[2] => 1
)

[price_i] => Array
(
[0] => 301.92
[1] => 153
[2] => 481
)

[tax] => Array
(
[0] => 1
[1] => 1
[2] => 1
)

)

)
Array

[/CODE]

What I'm really after:

[CODE]
Array
(
[1] => Array
(
[producto_id] => Array
(
[0] => E5030

)

[producto] => Array
(
[0] => Product # 1

)

[cantidad] => Array
(
[0] => 1

)

[price_i] => Array
(
[0] => 286.62

)

[tax] => Array
(
[0] => 1

)

)

)

Array
(
[2] => Array
(
[producto_id] => Array
(
[0] => E5030
[1] => E5060
)

[producto] => Array
(
[0] => Product # 1
[1] => Product # 2
)

[cantidad] => Array
(
[0] => 1
[1] => 1
)

[price_i] => Array
(
[0] => 286.62
[1] => 301.92
)

[tax] => Array
(
[0] => 1
[1] => 1
)

)

)

Array
(
[4] => Array
(
[producto_id] => Array
(
[0] => E5030
[1] => E5060
[2] => E0094
[3] => E7485
)

[producto] => Array
(
[0] => Product # 1
[1] => Product # 2
[2] => Product # 3
[3] => Product # 4
)

[cantidad] => Array
(
[0] => 1
[1] => 1
[2] => 1
[3] => 1
)

[price_i] => Array
(
[0] => 286.62
[1] => 301.92
[2] => 153
[3] => 481
)

[tax] => Array
(
[0] => 1
[1] => 1
[2] => 1
[3] => 1
)

)

)
[/CODE]

**Note that the 3 is missing on purpose because the receipt's number does not belong to the user I'm currently fetching on the database.

I know this post is looooooooooooooooooooooooooooooooooooong, but if someone could give me a little help I'd appreciate it a lot! Thanks :D

2 answers to this question

Recommended Posts

  • 0

The array is being currently overwrote by the last receipt #. I know that the root of all this evil is this portion of the code:

>
if(!in_array($factura,$this->trigger)) $this->trigger[] = $factura;
[b] $this->factura = [/b]array($factura => array('producto_id' => array($row['producto_id']),
'producto' => array($row['producto']),
'cantidad' => array($row['cantidad']),
'price_i' => array($row['price_i']),
'tax' => array($row['tax'])
)
);

[/CODE]

The bold part should actually be:
[CODE]
$this->factura[] =
[/CODE]

But by doing so, the whole schema breaks, and the receipts are not appended in order.

Its broken (with the above fix implemented) primarily because of your array_key_exists_r() function. I'm assuming that you do understand what that function does... When processing a new row from the database, you're scanning recursively through all nested arrays within $this->factura looking for [b][u]any[/u][/b] existence of a key with a value matching the receipt number! I.e. it's checking for the existence of the receipt number amongst all existing receipt number keys, and all item number keys!!
Let me walk you through the incorrect output you printed having made your suggested fix (from the perspective of processing each row in the result set returned by the database):</pre>
<ul>Row#1: The array is empty, so array_key_exists_r() returns false and the if statement passes. You therefore create a new array containing the receipt number, and the details of the first item, which is stored in a new array entry in the format of $this-&gt;factura[0][1][itemdata], where key [0] was automatically created and [1] is the receipt number.
Row#2: A second item for receipt 1 is being processed. array_key_exists_r() finds an existing array key with a value of 1, so attempts to add the new item data to the receipt, but the receipt is at $this-factura[0][1] not $this-&gt;factura[1], so inadvertently makes a new top level array entry.
Row#3: We are now processing the first item of receipt 2. There is no array entry anywhere in $this-&gt;factura, so array_key_exists_r() returns false, and as with row #1, a new array entry is to be created. The next numerical array key is [2], which coincidentally happens to be the same as the receipt number. We end up creating $this-&gt;factura[2][2][itemdata], with the first [2] being automatically created and the second representing the receipt number.
Row#4: We are now processing receipt 4. An array key with value 4 does not exist anywhere in $this-&gt;factura (as a key representing a receipt number, and item number, or anything else), so same situation as the previous row, we create the new entry $this-&gt;factura[3][4][itemdata].
Row#5: Still on receipt 4, an array key with value 4 does now exist, so we therefore do an update as with row #2. But similarly, since receipt 4 is at $this-&gt;factura[3][4] not $this-&gt;factura[4] we inadvertently create $this-&gt;factura[4].
</ul>
<p></p>
<p>Now, try this:</p>
<div>[code]while($row = $this-&gt;stmt-&gt;fetch())
{
	$factura = $row['factura']; /*Receipt number*/
	print($factura);
	if(! array_key_exists($factura, $this-&gt;factura))
	{
		if(! in_array($factura, $this-&gt;trigger)) $this-&gt;trigger[] = $factura;
		$this-&gt;factura[$factura] = array(
			'producto_id' =&gt; array($row['producto_id']),
			'producto' =&gt; array($row['producto']),
			'cantidad' =&gt; array($row['cantidad']),
			'price_i' =&gt; array($row['price_i']),
			'tax' =&gt; array($row['tax'])
		);
	}
	else
	{
		$this-&gt;factura[$factura]['producto_id'][] =$row['producto_id'];
		$this-&gt;factura[$factura]['producto'][] =$row['producto'];
		$this-&gt;factura[$factura]['cantidad'][]= $row['cantidad'];
		$this-&gt;factura[$factura]['price_i'][] =$row['price_i'];
		$this-&gt;factura[$factura]['tax'][] = $row['tax'];
	}
}<

  • 0

Its broken (with the above fix implemented) primarily because of your array_key_exists_r() function. I'm assuming that you do understand what that function does... When processing a new row from the database, you're scanning recursively through all nested arrays within $this->factura looking for any existence of a key with a value matching the receipt number! I.e. it's checking for the existence of the receipt number amongst all existing receipt number keys, and all item number keys!!

First of all, thank you... thank you thank you...! It did the trick!!!!!!!!! :D :D :D :D:D

Before using the array_keys_r function, which I got from stackoverflow, I was using array_key_exists to verify the array, but it wasn't working as I wanted since the last receipt overwrote the previous one. I thought it was a multi-dimensional array problem so I looked up on Google and thought using that custom function. In the end it yielded the previous results I was having!

But clearly, the main problem was this little row:

$this-&gt;factura = array($factura =&gt; array('producto_id' =&gt; array($row['producto_id']),

Which you change to:

$this->factura[$factura] = array(

And through the explanation it does make a lot of sense...

I'm kind of slapping my face right now...

Really, really, really, thanks a million!

(Y)

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • Hello, Also known for https://www.theguardian.com/technology/2009/jan/29/adware-internet.   Regards, Aryeh Goretsky    
    • Hello, I have used a few TEAM Group SSDs, USB flash drives, and Micro SDXC cards in the past. They all seemed to work fine. Regards, Aryeh Goretsky
    • "just $100 per TB"? Just? Are we trying to make this seem like the new normal? Kinda weird to make it sound like that is not a ridiculously expensive asking price.
    • The reviews you refer to mean nothing. Where there is no journalism there is no reason to call the gaming media's opinion pieces "reviews". For GP games there is indeed a metric for success - increasing subscriptions. Which turns in revenue. The only circumstance in which subs do not rise when great is being released is a Game Pass system where the company is close to fully saturated with customers in a subscription. However, in that case as the theory goes you spend aplenty in all kind of games - from shady live service cash cows and customer offending agitprop crap in purple colours to robust and entertaining single player games. And keep a solid level of profitability. Ignoring the simply innocuous but mid games MGS has released primarily of the second kind.
    • Report: Microsoft to use AWS to help GitHub deal with a major surge in demand by Pradeep Viswanathan Thanks to the surge of coding AI agents, GitHub's usage has skyrocketed over the past 12 months. To meet this demand, GitHub started with a plan in October 2025 to increase capacity by 10x. However, by early this year, the company realized that it needed 30x scale. This rapid growth has caused severe strain on the platform's reliability, resulting in several small outages over the past few months. In April, GitHub published a long blog post explaining the steps it is taking to resolve these reliability issues. In the post, the company also confirmed that it is working toward a multi-cloud architecture for better resilience. Today, Business Insider reported that GitHub is turning to Amazon Web Services to help deal with a major surge in AI-driven coding activity. It is important to note that GitHub is still in the process of moving completely to the Azure cloud. The current plan is to move the platform fully to Azure by 2027 so that it can scale better as per developer demand. Therefore, the current decision to utilize AWS might be part of a short-term plan to meet immediate demand. A Microsoft spokesperson confirmed that GitHub is using multiple cloud providers with the following statement: For Microsoft, the decision highlights the operational pressure behind the AI boom. GitHub has to stay reliable for developers at a time when rivals such as Codex, Cursor, Claude Code, and other AI coding tools are gaining attention. And the decision to use AWS for computing capacity seems practical given the circumstances.
  • Recent Achievements

    • Collaborator
      vjlex earned a badge
      Collaborator
    • Reacting Well
      Dys Topia earned a badge
      Reacting Well
    • Conversation Starter
      NovaEdgeX earned a badge
      Conversation Starter
    • One Year In
      Console General earned a badge
      One Year In
    • Week One Done
      Twozo Technologies earned a badge
      Week One Done
  • Popular Contributors

    1. 1
      +primortal
      518
    2. 2
      +Edouard
      182
    3. 3
      PsYcHoKiLLa
      106
    4. 4
      Steven P.
      88
    5. 5
      ATLien_0
      68
  • Tell a friend

    Love Neowin? Tell a friend!