• 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

    • Subscription upon subscription... That old Xzibit Pimp my ride meme comes to mind
    • EA reached out to our reporter that mainly does gaming content and reviewed loads of other games, why would this be shocking to anyone? I admit maybe we were considered this time around because of the extra coverage UFC was getting and they wanted a broader audience for this release? IDK. I can tell you that we aren't paid to do the reviews, the fun part of it is (mostly) being able to keep what we review and giving an honest opinion on what we're reviewing.
    • Save over $430 on Sterling Stock Picker (lifetime subscription) by Steven Parker Today's highlighted Neowin deal comes via our Apps + Software section of the Neowin Deals store, where you can save 88% off on a lifetime subscription to Sterling Stock Picker. Sterling Stock Picker (SSP) is an award-winning platform designed to make stock investing accessible to everyone, regardless of expertise. The software offers multiple methods to identify winning stocks that align with your personal values, investment preferences, and risk tolerance. By handling all the complex calculations, it allows you to focus on making informed investment decisions. The patent-pending North Star technology provides clear guidance on whether to buy, sell, hold, or avoid a particular stock. Ask Finley, your personal AI financial coach Finley is your personal AI financial coach providing real-time data access, strategic investment advice, risk assessment, and educational support to help you make informed decisions. Whether you're a seasoned investor or just starting, Finley is equipped to help you achieve your financial goals. Feel free to ask any questions about your portfolio or the stock market. PERSONALIZED FINANCIAL GUIDANCE Custom Recommendations: Get stock picks tailored to your risk tolerance, portfolio performance, and investment goals. Dynamic Insights: Access detailed financial, technical, earnings, growth, and risk analysis for smarter investing. ENHANCED PORTFOLIO MANAGEMENT Done-For-You Portfolio Builder: Easily construct a diversified portfolio based on your risk tolerance and investment goals. Analysis and Suggestions: Receive data-driven portfolio adjustments to optimize returns based on your risk acceptance score. Risk Assessment Overview: Understand your risk level and receive stock recommendations aligned with your investment strategy. STRATEGIC INVESTMENT ADVICE Stock Rockets: Discover top-performing companies with over 50% quarterly revenue growth and the highest North Star rankings. Concentrated Portfolio Strategy: Focus on high-potential stocks instead of broad diversification to maximize growth. Industry and Sector Insights: Stay ahead with detailed performance narratives and sector-specific trends. EDUCATIONAL SUPPORT & COMMUNITY Verbose Explanations: Break down complex financial concepts with in-depth explanations for beginners. Investment Strategies: Learn and apply various investment strategies with expert-backed insights. Community Chat Forum: Connect with fellow investors to share insights, ask questions, and discuss investment strategies. Build your Stock Portfolio in 3 easy steps! Discover Your Risk Tolerance: Take a quick 5-minute questionnaire to assess your ability to handle risk effortlessly. Search Stocks Aligned With Your Personal Values: Use an intuitive stock-picking interface to confidently find winning stocks. Build Your Portfolio: Utilize the Done-For-You Portfolio Builder to simplify investing and remove the guesswork. Good to know: Length of access: lifetime Redemption deadline: redeem your code within 30 days of purchase Access options: desktop or mobile Only available to new users Updates included A lifetime subscription to Sterling Stock Picker normally has a suggested price of $486, but you can pick it up for just $54.90 for a limited time - that represents a saving of $431.10 (88% off). For a full description, specs, and license info, click the link below. Sterling Stock Picker lifetime subscription for $54.90 (was $486) Although priced in U.S. dollars, this deal is available for digital purchase worldwide. Support queries If you have queries or need support for any of the Neowin Deals, please use the contact form here. Neowin Deals are managed and sold by StackCommerce who represent Neowin on an affiliate basis. Why we post these deals We post these because we earn commission on each sale so as not to rely solely on advertising, which many of our readers block. It all helps toward paying staff reporters, servers and hosting costs. So for those that keep moaning and complaining, be thankful we're still online for you to even do that. Other ways to support Neowin Whitelist Neowin by not blocking our ads Create a free member account to see fewer ads Make a donation to support our day to day running costs Subscribe to Neowin - for $14 a year, or $28 a year for an ad-free experience Disclosure: Neowin benefits from revenue of each sale made through our branded deals site powered by StackCommerce.
  • Recent Achievements

    • Week One Done
      Classifyskilleducation earned a badge
      Week One Done
    • One Month Later
      eurospharma62 earned a badge
      One Month Later
    • Week One Done
      With What earned a badge
      Week One Done
    • Week One Done
      Harris Gilbert earned a badge
      Week One Done
    • One Month Later
      Vincian earned a badge
      One Month Later
  • Popular Contributors

    1. 1
      +primortal
      543
    2. 2
      +Edouard
      171
    3. 3
      PsYcHoKiLLa
      82
    4. 4
      ATLien_0
      64
    5. 5
      neufuse
      64
  • Tell a friend

    Love Neowin? Tell a friend!