Jump to content

2D Array -> Matrix table


fRAiLtY-

Recommended Posts

Hi,

 

I'm unsure on some code logic as to how to create a table, I have attached an image just to make sure you guys understand my interpretation of a matrix:

iPad%202%20Price%20Matrix.png

 

Ok, so using the above as a guide, there's in total 6 products in a 2x3 table. I have 100 products, resulting in a 10x10 table. How in PHP would I fill out a table like the above with my 100 products. I've managed with some code to create a rough table which puts the headings (on above example 16GB, WiFi etc) in on both axis, but don't understand how the table body (on above example, the prices) would be filled out accordingly.

 

Hopefully someone can point me in the right direction?!

 

Cheers.

Link to comment
Share on other sites

Unfortunately the small piece of wrong and not-working code I have is on my work machine local server.

 

It's the logic and the procedure I can't really grasp, I'm using Magento but that's largely irrelevant as I can't get my head round the methodology in producing such a table??

 

Cheers.

Link to comment
Share on other sites

Sorry xyph.

 

For example, I have 10 sizes:

 

CC, A7, A6, A5, A4, A3, SJ, DL, CD, WB

 

And 10 Quantities:

 

25, 50 100, 250, 500, 1000, 2500, 5000, 10000

 

Each product has these attributes assigned to them, a size and a quantity and as such has a price. For example 25 A7's are £25.

 

Therefore, I would have quantities along the top and sizes down the side in a grid style as above.

 

Does this help?

Link to comment
Share on other sites

I realize the kind of data you'll be working with.

 

Is that data going to be stored in a single multi-dimensional array? Is each row going to be in it's own array?

 

Here's an example of what we need.

$data = array(
'A7' => array( 25=>'25',50=>'45',100=>'90',250=>'225' ),
'CC' => array( 25=>'50',50=>'90',100=>'175',250=>'200' )
);

 

Is that how your data will be stored?

 

Now that I've double-read the title, I see you'll be using a 2D array. Is it similar to the one I've provided?

Link to comment
Share on other sites

Hi,

 

It's taken from a database and in it's unchanged form looks like this:

 

A7,25,25.0000

A7,50,25.3000

A7,100,26.2000

A7,250,29.2000

A7,500,37.2000

A7,1000,57.2000

A7,2500,63.2000

A7,5000,70.7500

A7,10000,95.2800

A7,15000,138.8000

A7,20000,175.8500

A7,25000,223.5000

 

In the format size,quantity,price. How can I convert this into the array xyth mentioned or even directly into a matrix. I've got to sort of group on the size and show the quantity->price values somehow?

Link to comment
Share on other sites

Is a database redesign possible? You're storing this information in a very inflexible manner.

 

I can show you an example of how I'd do this, just want to know if I can change your database scheme around to something more normalized.

Link to comment
Share on other sites

Frailty,

 

Could you explain a little more what your looking to do with your data "size", "quantity", "price"?

 

Are you looking to have your "sizes" down your y axis and your quantity along your x axis with the price populating the area between?

 

E.g.

 

        25      50      100      250      500
A7    25.00    25.30   26.20    29.20    37.20

Link to comment
Share on other sites

CKPD: You're spot on, yes. That's exactly what I want to do.

 

xyth: Unfortunately not, I'm working with Magento so it is what is. I can probably mix and match the data a bit to get it how you want it, I understand it's probably not ideal. Basically I have one parent entity which has many child entities. Each of these children has 3 attributes assigned to them; size, quantity and price. I have "got" all these children and listed their attributes so I'm left with a list as of my last post. I now need to convert that into a matrix table.

 

Any ideas?

 

Cheers.

Link to comment
Share on other sites

<?php
$x = array();
$x[] = array('A7',25,25.0000);
$x[] = array('A7',50,25.3000);
$x[] = array('A7',100,26.2000);
$x[] = array('A7',250,29.2000);
$x[] = array('A7',500,37.2000);
$x[] = array('A7',1000,57.2000);
$x[] = array('A7',2500,63.2000);
$x[] = array('A7',5000,70.7500);
$x[] = array('A7',10000,95.2800);
$x[] = array('A7',15000,138.8000);
$x[] = array('A7',20000,175.8500);
$x[] = array('A7',25000,223.5000);

$x[] = array('A8',25,25.0000);
$x[] = array('A8',50,25.3000);
$x[] = array('A8',100,26.2000);
$x[] = array('A8',250,29.2000);
$x[] = array('A8',500,37.2000);
$x[] = array('A8',1000,57.2000);
$x[] = array('A8',2500,63.2000);
$x[] = array('A8',5000,70.7500);
$x[] = array('A8',10000,95.2800);
$x[] = array('A8',15000,138.8000);
$x[] = array('A8',20000,175.8500);
$x[] = array('A8',25000,223.5000);

$rows = array(); // associative array, key index will be A7 A8 etc etc..
$rows[0] = array(); // initial rows would be column names, so the key will just be 0
foreach ($x as $column) { // loop thru the jumbled up mess of information ONE TIME, to calculate the number of columns necessary
	if (!in_array($column[1],$rows[0])) {
		$rows[0][] = $column[1]; // append the column name
	}
}

// sort the column titles now
sort($rows[0],SORT_NUMERIC);

// then get count of this new column title array
$count = count($rows[0]);

// now just loop thru the $x array, and fill in the place values
foreach ($x as $row) {
	$rowTtl = $row[0];
	$rowQty = $row[1];
	$rowVal = $row[2];
	if (!isset($rows[$rowTtl])) $rows[$rowTtl] = array_pad(array(),$count,0);
	$rows[$rowTtl][array_search($rowQty,$rows[0])] = $rowVal;
}

// display table
?><table>
<?php
	foreach ($rows as $rowName => $columns) {
		echo "<tr><td>{$rowName}</td>";
		foreach ($columns as $cell) {
			echo "<td>{$cell}</td>";
		}
		echo "</tr>";
	}
?>
</table>

 

test link: http://myspacechickz.com/tester.php

Link to comment
Share on other sites

Russell,

 

That's awesome, I've got the data in a number of different ways. I've added you to MSN as per your signature, can you pop online and I'll show you what I've got?!

 

I think I can cut down on some code and produce a cleaner script. Here's my function that gets the data:

 

<?php

// get 300gsm flyers only
$childProducts = Mage::getModel('catalog/product_type_configurable')->getFlyers300gsm(null, $_product);

foreach ($childProducts as $_300gsm) {
	$size = $_300gsm->getAttributeText('size');
	$quantity = $_300gsm->getAttributeText('quantity');
	$price = $_300gsm->getPrice();

}

?>

 

The foreach loop iterates through all the 300gsm flyers, I've assigned variables to the crucial parts I need for the matrix, would this cut down on what's necessary in your code Russell making it a bit cleaner? Perhaps I'm trying to format it wrong.

 

Cheers.

Link to comment
Share on other sites

Uhm, add my skype: RussellReal

 

my MSN isn't installed on my new laptop, which I'm currently on, I'm installing it as I write this, but incase its urgent my skype is always available.

 

I have many more clients on skype, so I kinda prioritize :)

 

Thanks, Russell

Link to comment
Share on other sites

Thanks Russel,

 

He's really helped me but I'm a bit stuck now! I've made a mistake and need to swap my axis but I don't think it's as simple as I make it out to be. Here is my code with lots of help from Russell:

 

<?php
// get stock to determine matrix
$childProducts = Mage::getModel('catalog/product_type_configurable')->getFlyers300gsm(null, $_product);

// set array
$x = array();

// loop children and set vars
foreach ($childProducts as $children) {
	$size = $children->getAttributeText('size');
	$quantity = $children->getAttributeText('quantity');
	$price = "£".number_format($children->getPrice(),'2');
	$x[] = array($size,$quantity,$price);
}

$rows = array(); // associative array, key index will be A7 etc..
$rows[0] = array(); // initial rows would be column names, so the key will just be 0

foreach ($x as $column) { 
	if (!in_array($column[1],$rows[0])) {
		$rows[0][] = $column[1]; // append the column name
	}
}

// sort the column titles now
sort($rows[0],SORT_NUMERIC);

// then get count of this new column title array
$count = count($rows[0]);

// now just loop through the $x array, and fill in the place values
foreach ($x as $row) {
	$rowTtl = $row[0];
	$rowQty = $row[1];
	$rowVal = $row[2];
	if (!isset($rows[$rowTtl])) $rows[$rowTtl] = array_pad(array(),$count,0);
	$rows[$rowTtl][array_search($rowQty,$rows[0])] = $rowVal;
}

	// display table
?>
<table class="matrix">
<?php
// set header rows and padder cell
$top = array_shift($rows);
echo "<th></th>";

// display header row x-axis
foreach ($top as $topRow) {
	echo "<th>{$topRow}</th>";
}

// set header columns and populate
foreach ($rows as $rowName => $columns) {
	echo "<tr><th>{$rowName}</th>";

	foreach ($columns as $cell) {
		echo "<td>{$cell}</td>";
	}
	echo "</tr>";
}
?>
</table>

 

And here's the URL: http://dev4.printpartnerships.com/flyer-printing

 

You can see the tables too wide, given we're likely to add more quantities in the future I need some scalability so want to swap the x and y axis round, but can't figure it out. Can anyone help please? I'm so close now!

 

Cheers.

Link to comment
Share on other sites

Here's a solution. I think I've also simplified it

 

<?php

// get stock to determine matrix
//$childProducts = Mage::getModel('catalog/product_type_configurable')->getFlyers300gsm(null, $_product);

// set array
$x = array();

// temporarily define $childProducts for my own testing
$childProducts = array(
	array( 'A7',25,110 ),
	array( 'A7',10,50 ),
	array( 'A7',50,200 ),
	array( 'CC',10,10 ),
	array( 'CC',25,20 ),
	array( 'CC',50,37 )
);

// loop children and set vars
foreach ($childProducts as $children) {
	//$size = $children->getAttributeText('size');
	//$quantity = $children->getAttributeText('quantity');
	//$price = "£".number_format($children->getPrice(),'2');
	$size = $children[0];
	$quantity = $children[1];
	$price = "£".number_format($children[2],'2');
	$x[$quantity][$size] = $price;
}
// sort $x by keys to make sure quanitites are greatest to least
ksort( $x );
// start table, along with blank top left cell
echo '<table><tr><th></th>';
// get our headers from the first set of keys
foreach( array_keys(current($x)) as $size ) {
	echo '<th>'.$size.'</th>';
}
// end the table header
echo '</tr>';
// loop through remaining data
foreach( $x as $quantity => $data ) {
	// create a new row, along with the price header
	echo '<tr><th>'.$quantity.'</th>';
	// loop through prices
	foreach( $data as $price ) {
		echo '<td>'.$price.'</td>';
	}
	echo '</tr>';
}
echo '</table>';

?>

Link to comment
Share on other sites

Hi xyph,

 

That's awesome mate, works great. Code's even shorter too! Only thing that didn't work was your variables assigned to $children[0] so I put mine back on, $children->getPrice() and it works a treat!

 

Thanks guys!

Link to comment
Share on other sites

Here's a quick modification if you needed the sizes sorted as well

<?php

// get stock to determine matrix
//$childProducts = Mage::getModel('catalog/product_type_configurable')->getFlyers300gsm(null, $_product);

// set array
$x = array();

// temporarily define $childProducts for my own testing
$childProducts = array(
	array( 'CC',10,10 ),
	array( 'CC',25,20 ),
	array( 'CC',50,37 ),
	array( 'A7',25,110 ),
	array( 'A7',10,50 ),
	array( 'A7',50,200 )
);

// loop children and set vars
foreach ($childProducts as $children) {
	//$size = $children->getAttributeText('size');
	//$quantity = $children->getAttributeText('quantity');
	//$price = "£".number_format($children->getPrice(),'2');
	$size = $children[0];
	$quantity = $children[1];
	$price = "£".number_format($children[2],'2');
	$x[$quantity][$size] = $price;
}
// sort $x by keys to make sure quanitites are greatest to least
ksort( $x );

echo '<table>';

// This is to keep track of whether we've outputted our header or not
$header = FALSE;
// loop through data
foreach( $x as $quantity => $data ) {
	// sort $data by keys to get sizes in alpha order
	ksort($data);
	if( $header == FALSE ) {
		// start row and output a blank cell for the top left
		echo '<tr><th></th>';
		// loop through an array of $data's keys to output the sizes
		foreach( array_keys($data) as $size ) {
			echo '<th>'.$size.'</th>';
		}
		echo '</tr>';
		// stop header from being outputted again
		$header = TRUE;
	}
	// create a new row, along with the price header
	echo '<tr><th>'.$quantity.'</th>';
	// loop through prices
	foreach( $data as $price ) {
		echo '<td>'.$price.'</td>';
	}
	echo '</tr>';
}
echo '</table>';

?>

 

edit - I always try to create stand-alone code. As such, I'll replace some of your variable definitions with my own, and generally leave yours above it commented out. This is so you can copy and paste the code into an empty PHP file and see how it outputs.

Link to comment
Share on other sites

Hi xyph,

 

Many thanks once again, awesome.

 

One last thing, whilst in the .$price. cell can I get the ID of that child item. Reason is I want to add the product to the cart if they click on the price but I need the child ID to do it. I've tried $children->getId(), $price->getId() but get non-object errors, what's the var for accessing the child in that loop? getId() get's the ID and I can make it get the ID of the main parent product, but can't access the child, even though it's the child price displayed.

 

Cheers

Link to comment
Share on other sites

I've never used Magento, so this becomes harder to help.

 

If your foreach ($childProducts as $children) { loop, what happens when you echo $children->getId()? Is the parent ID echo'd, or the child's?

Link to comment
Share on other sites

Hi xyph,

 

If I do this:

 

foreach ($childProducts as $children) {
	$size = $children->getAttributeText('size');
	$quantity = $children->getAttributeText('quantity');
	$price = "£".number_format($children->getPrice(),'2');
	$x[$quantity][$size] = $price;
	echo $children->getId();
}

 

It echo's all the ID's of the children as expected. How do I move this down into the lower foreach where the price is echo'd?

 

Cheers.

Link to comment
Share on other sites

Mmmm, the power of ARRAYS!

 

I know it's redundant, but since you've already formatted your code this way, I'll follow along. You want to assign $id as the value of $children->getId() within the loop. You then want to add that information to $x. We can store both the ID and price in that value by using an array.

 

$x[$quantity][$size] = array($id, $price);

 

So, in sticking with my example, something like $x[50]['A7'][0] would be it's id, and [1] would be it's price (200.00)

 

That makes it really easy to change our code up.

 

		foreach( $data as $price ) {
		echo '<td>'.$price.'</td>';
	}

 

becomes

 

		foreach( $data as $item ) {
		echo '<td>id:'.$item[0].', price:'.$item[1].'</td>';
	}

 

Numeric arrays can get overwhelming if you're dealing with more than just 2 values, so you can use associative keys instead.

 

$x[$quantity][$size] = array('id'=>$id, 'price'=>$price);

 

And then when you're ready to use the data

 

		foreach( $data as $item ) {
		echo '<td>id:'.$item['id'].', price:'.$item['price'].'</td>';
	}

 

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.