mysqli_fetch_array and foreach: unexpected solution

Hi all -
I have been hacking with Chapter 4 in
Build Your Own Database Driven Web Site Using PHP & MySQL, 4th Edition

I made the joke database into an event database, and was wanting to format the output in the include file so the event dates would appear under the event and location.

Some searching indicated I might have to make a multidimensional array to accomplish this. Setting up my code to try that, I tried this and it kind of works.


while ($row = mysqli_fetch_array($result))
{
	$event[] = "* " . $row['event'] . " - " . $row['location'] ;
	$event[] .= "  " . $row['startdate'] . " through " . $row['enddate'] ;
}

I am still getting more blockquotes and paragraphs than I need, but I never expected the include file would see the concatenated array as separate entities.


		<p>Here are all the shows in the database:</p>
		<?php foreach ($event as $event): ?>
			<blockquote>
				<p><?php echo htmlspecialchars($event, ENT_QUOTES, 'UTF-8'); ?></p>
			</blockquote>
		<?php endforeach; ?>

html source snip


		<p>Here are all the shows in the database:</p>
					<blockquote>

				<p>* The Great Alaska Sportsman Show - Sullivan Arena</p>
			</blockquote>
					<blockquote>
				<p>  2010-04-08 through 2010-04-11</p>
			</blockquote>
					<blockquote>
				<p>* Comfish Alaska - Kodiak Convention Center</p>

			</blockquote>
					<blockquote>
				<p>  2010-04-15 through 2010-04-17</p>
			</blockquote>
					<blockquote>
				<p>* Alaska Women's Show - Sullivan Arena</p>
			</blockquote>

					<blockquote>
				<p>  2010-04-23 through 2010-04-25</p>
			</blockquote>


The empty operator creates a new entry in the array. You use it twice, creating two entries each time through your loop.

Concatenate your string first, then put the whole concatenated string in the array.

thanks Dan,
controller snip


while ($row = mysqli_fetch_array($result))
{
	$event[] = array( "sholoc" => "* " . $row['event'] . " - " . $row['location'], "dates" => $row['startdate'] . " through " . $row['enddate']) ;
}

include snip


		<p>Here are all the shows in the database:</p>
		<?php foreach ($event as $event): ?>
			<blockquote>
				<p><?php echo htmlspecialchars($event['sholoc'], ENT_QUOTES, 'UTF-8'); ?><br/>
				   <?php echo $event['dates']; ?>
				</p>
			</blockquote>
		<?php endforeach; ?>

That works, and shows a multidimensional array is not needed.

That IS a multidimensional array. You created an array, $event, where each value in the array is another array having two values.

You can do it with zero extra arrays if you want, just loop through the result set as needed. You can always reset the row pointer in the result set back to 0 with mysql_data_seek

I get it. Ok I just made the array even more multidimensional
in the controller:


while ($row = mysqli_fetch_array($result))
{
	$event[] = array( "sholoc" => $row['event'] . " - " . $row['location'], 
	"dates" => $row['startdate'] . " through " . $row['enddate'], 
//	"filename" => $row['filenames']) ;
	"filename" => explode(",",$row['filenames'])) ;
}

in the template:


		<?php foreach ($event as $event): ?>
			<ul>
				<li><?php echo htmlspecialchars($event['sholoc'], ENT_QUOTES, 'UTF-8'); ?></li>
				<ul>
				<li><?php echo $event['dates']; ?></li>
<!--			<li><?php echo htmlspecialchars($event['filename'], ENT_QUOTES, 'UTF-8'); ?></li>    -->
				<li><?php foreach ($event['filename'] as $name)
				{echo htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . "&nbsp;&nbsp;";} ?></li>
				</ul>
			</ul>
		<?php endforeach; ?>

I am getting the desired output, along with an html commented warning:

htmlspecialchars() expects parameter 1 to be string, array given

I know there’s one more index, but I don’t know how to pass it at

foreach ($event[‘filename’] as $name)

thanks

Just to share what worked for me - and so anyone searching on GROUP_CONCAT, explode and array_combine might find one way that works
the query:


$result = mysqli_query($link, 'SELECT events.event, events.location, 
DATE_FORMAT(events.startdate, "%a %b %e %Y") as startdate, 
DATE_FORMAT(events.enddate, "%a %b %e %Y") as enddate, 
GROUP_CONCAT(filestore.id) as file_id,
GROUP_CONCAT(filestore.description) as filedesc
FROM events 
LEFT JOIN filestore ON events.id = filestore.event_id 
GROUP BY events.id ORDER BY events.startdate ASC
LIMIT 0 , 30 ');

build the array:


$event = array();
while ($row = mysqli_fetch_array($result))
{
	$event[] = array( "sholoc" => $row['event'] . " - " . $row['location'], 
	"dates" => $row['startdate'] . " through " . $row['enddate'], 
	"files" => array_combine(explode(",",$row['file_id']), explode(",",$row['filedesc'])));	
}