• 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

    • Excuse me for having an opinion, fella'... (Why am I not surprised?...) Congrats on your very informative post however...
    • By the sounds of that wall of Fox News propaganda gibberish attacking the Democratic Party you've already had plenty of "juices" flowing this morning. You've ruined what could have been a productive comment thread.
    • (Topic to get the juices flowing this Sunday morning!...) Actually, the situation has almost nothing to do with "lack of skills", especially since assembly-line skills can be taught to anyone, including Americans, certainly. Rather, the inadequacy-to-impossibility of large-scale tech manufacturing in America today, and the reasons why America finds tech manufacturing completely onerous in the 21st century, has to do with politically driven laws amid a plethora of non-scientific, utterly politicized "science-fact" that is patently false, punitive business taxation at every turn, an array of judicial fines of unimaginable scope and complexity, and, last but not least, American unionization strictures that serve to actually slay job creation and hobble all such manufacturing endeavors in America before they can get off the ground. Globalism emerged, they tell us, as the needed answer to American hubris and an unholy American drive to excel. Unless one is buried under mounds of political propaganda, it's easy to see the absurdity of labeling the employees of SpaceX, for instance, as "unskilled labor"... Etc. ad infinitum. At one time in the recent past, American manufacturing prowess was the envy of the world in a wide variety of technical fields! The current federal and state government roadblocks against America becoming competitive globally in tech manufacturing are considerable, it's true, as anyone with a working brain knows. But remarkably, that is only half the story! The other half of the story is, of course, the corporations themselves... Chinese tech manufacturing is simply unassailable in terms of profits, because the Chinese government wants to see its tech manufacturing second-to-none globally so that no companies/nations can compete in terms of ROI, and China has completely succeeded in that goal. Let's tic-off a few things: *Chinese tariff policies are set according to what is considered best for Chinese business, Chinese employees, and the Chinese people. Huge difference with how things are done with tariffs in the US--as the US government (SCOTUS in this case, Congress in others) plainly feels that tariffs are "unfair" for the limited number of citizens who may pay them, whereas nothing is "unfair" when Congress considers the Personal Income Tax rates to be infinitely hike-able, along with infinitely enlarging annual budget deficits. *The Chinese government boldly subsidizes Chinese companies to artificially amplify their profits. *The Chinese government deliberately refuses to avidly demonize Chinese businesses and does not consider Chinese businesses "the enemy", so very unlike American (D)s these days. *Chinese labor laws and businesses are allowed to set their own labor policies according to what Chinese companies consider is best for companies and their employees... Simply put, American workers in tech manufacturing are not allowed to set their own labor policies! It is the height of hypocrisy for Americans to decry working conditions in China while simultaneously ensuring that American products are manufactured in China, not in the US, simply to maximize profits. There is nothing wrong with making a profit, of course, absolutely nothing. But there is plenty wrong with attempts to normalize hypocrisy of this kind! But rank hypocrisy and the (D) party in the US are longtime bedfellows... The current government in Washington is working overtime to see if it can toss out the horribly poor, failed economic policies of the past, while the (D)s still in Washington work very hard to bring back the stupidity whenever possible. With the right policies in place, America can be an infinitely competitive manufacturer.
  • Recent Achievements

    • Conversation Starter
      jessse3334 earned a badge
      Conversation Starter
    • Reacting Well
      JuvenileDelinquent earned a badge
      Reacting Well
    • One Month Later
      Excellence2025 earned a badge
      One Month Later
    • Week One Done
      Excellence2025 earned a badge
      Week One Done
    • Week One Done
      flexorcist earned a badge
      Week One Done
  • Popular Contributors

    1. 1
      +primortal
      508
    2. 2
      +Edouard
      198
    3. 3
      PsYcHoKiLLa
      152
    4. 4
      Steven P.
      73
    5. 5
      FloatingFatMan
      64
  • Tell a friend

    Love Neowin? Tell a friend!