Solved

question about associative arrays...

Posted on 2012-04-09
19
237 Views
Last Modified: 2012-06-27
Hi, my DB structure is as follows:

id           user_id       date                          notes
------------------------------------------------------------------------------
1             12             2012-01-01                A
2             12             2012-01-01                B
3             10             2012-01-14                c
4             12             2012-01-01                D

I run a query and pick up all the fields that have  a date "2012-01-01"

How do  I run a foreach  loop that has date as the key and notes as the value? Thanks for the help.

A
0
Comment
Question by:aej1973
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 5
  • 4
  • +2
19 Comments
 
LVL 35

Expert Comment

by:gr8gonzo
ID: 37825601
The short answer is that you don't. The key of an associative array has to be unique. If you try to put two rows into an associative array that have the same key, the second will overwrite the first.

$x = array();
$x["2012-01-01"] = "A";
$x["2012-01-01"] = "B";
$x["2012-01-14"] = "c";
$x["2012-01-01"] = "D";

In your example data, you have three different rows with the same date value, so if you tried to use the date as the key, you'd end up with a total of two rows - one with a key of 2012-01-1 (with a value of D) and one with 2012-01-14 (with a value of c).

What you CAN do is nest associative arrays, if you want to retain that information:


$x = array();
$x[1] = array("2012-01-01","A");
$x[2] = array("2012-01-01","B");
$x[3] = array("2012-01-14","c");
$x[4] = array("2012-01-01","D");

Now you can do a foreach loop through that array, like this:
foreach($x as $id => $record)
{
   echo $record[0]; // date
   echo $record[1]; // notes
}

Or you could group them like this:

$x = array();
$x["2012-01-01"] = array();
$x["2012-01-01"][] = "A";
$x["2012-01-01"][] = "B";
$x["2012-01-01"][] = "D";

$x["2012-01-14"] = array();
$x["2012-01-14"][] = "c";

foreach($x as $date => $notesPerDate)
{
  echo "For {$date}:\n";
  foreach($notesPerDate as $note)
  {
     echo $note . "\n";
  }
}
0
 
LVL 22

Expert Comment

by:Kim Walker
ID: 37825610
Actually, if you do each row as an associative array, "id", "user_id", "date", and "notes" will be the keys and each row will contain different values for each. More information is needed to understand your objective. Otherwise, the following will cycle through the values:
$result = mysql_query('SELECT date, notes FROM table_name');
while ($row = mysql_fetch_assoc($result) ) {
$target_date = $row['date'];
$target_notes = $row['notes'];
}

Open in new window

0
 

Author Comment

by:aej1973
ID: 37825826
shown below are my code snippets...I have built a calendar application. The calendar shows events for a particular date but with the following code, as you mentioned above only one record shows up for each date event though there are multiple events for a particular date.

//following query is used to check if there is an event on a particular date.
$events = array();
$query_1 = "SELECT patient_id,visit_notes, visit_id,DATE_FORMAT(visit_date,'%Y-%m-%d') AS event_date FROM patient_visitschedule WHERE visit_date LIKE '$year-$month%'";
$result_1 = mysql_query($query_1) or die('cannot get results!');
while($row = mysql_fetch_assoc($result_1)) {
$events[$row['event_date']][] = $row;
//print_r(array_values($row)).'</br>';

}
..........
{
    // Calculate the date and save it to the array
    $date = strtotime("+$count day", $timestamp); //$timestamp = strtotime($startDate) where $startDate = s_date.
      $cell[] = date("Y-m-d", $date);//value to pass to the next page
   
      
      }

.......

$cellDate = $cell[$i];//date to pass to the DB

..........


            //for($n=1; $n<$num_rows; $n++){
            if (isset($events[$cellDate]))
            {
        foreach($events[$cellDate] as $event) {
                  
        $calendar= '<div class="event">'.$event['visit_notes'].'</div></br>';
             }
            
      }
      else {
        $calendar= str_repeat('<p></p>',2);
      }
    $calendar.= '</div></td>';

Thanks for the help.

A
0
Online Training Solution

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action. Forget about retraining and skyrocket knowledge retention rates.

 
LVL 35

Expert Comment

by:gr8gonzo
ID: 37825856
Try doing a print_r($events) right after you build $events
0
 

Author Comment

by:aej1973
ID: 37826049
The output I get is:

Array ( [2012-01-09] => Array ( [0] => Array ( [patient_id] => 6 [visit_notes] => Visit in the morning. [visit_id] => 7 [event_date] => 2012-01-09 ) ) ) Array ( [2012-01-09] => Array ( [0] => Array ( [patient_id] => 6 [visit_notes] => Visit in the morning. [visit_id] => 7 [event_date] => 2012-01-09 ) [1] => Array ( [patient_id] => 6 [visit_notes] => Visit in the evening. [visit_id] => 8 [event_date] => 2012-01-09 ) ) ) Array ( [2012-01-09] => Array ( [0] => Array ( [patient_id] => 6 [visit_notes] => Visit in the morning. [visit_id] => 7 [event_date] => 2012-01-09 ) [1] => Array ( [patient_id] => 6 [visit_notes] => Visit in the evening. [visit_id] => 8 [event_date] => 2012-01-09 ) [2] => Array ( [patient_id] => 6 [visit_notes] => hello [visit_id] => 9 [event_date] => 2012-01-09 ) ) )
0
 
LVL 8

Expert Comment

by:twohawks
ID: 37826265
Hmmm, what's up with that format specifier at the end of this...
'$year-$month%'

I don't understand that... am I missing something?
0
 
LVL 29

Expert Comment

by:Olaf Doschke
ID: 37826589
$events[$row['event_date']][] = $row;

It looks ok,  adding via this code you don't overwrite $events[$row['event_date']] but extend $events[$row['event_date']][], as a 2d array with one dimension being the date and the other being 0..record count-1, the problem just is, the $row is not stored as it's values, but as a reference and in the end all events['2012-01.09'][0...n] are the same last $row added.

Rather use
$events[$row['event_date']][] = unserialise(serialise($row));

Check out print_r($events); after the while() loop, after adding all rows.

Bye, Olaf.
0
 

Author Comment

by:aej1973
ID: 37827147
Hi Olaf, I updated the code as follows;

//following query is used to check if there is an event on a particular date.
$events = array();
$query_1 = "SELECT patient_id,visit_notes, visit_id,DATE_FORMAT(visit_date,'%Y-%m-%d') AS event_date FROM patient_visitschedule WHERE visit_date LIKE '$year-$month%'";
$result_1 = mysql_query($query_1) or die('cannot get results!');
while($row = mysql_fetch_assoc($result_1)) {
$events[$row['event_date']][] = unserialise(serialise($row));

//print_r($events);
}
print_r($events);

With this I get the following error;

Fatal error: Call to undefined function unserialise() in C:\xampp\htdocs\cp\module_p\viewSchedule.php on line 74
0
 
LVL 22

Expert Comment

by:Kim Walker
ID: 37827221
Try using a "z" instead of an "s" in serialize and unserialize.
0
 

Author Comment

by:aej1973
ID: 37827246
Thanks, that works. My output now is;

Array ( [2012-01-09] => Array ( [0] => Array ( [patient_id] => 6 [visit_notes] => Visit in the morning. [visit_id] => 7 [event_date] => 2012-01-09 ) [1] => Array ( [patient_id] => 6 [visit_notes] => Visit in the evening. [visit_id] => 8 [event_date] => 2012-01-09 ) [2] => Array ( [patient_id] => 6 [visit_notes] => hello [visit_id] => 9 [event_date] => 2012-01-09 ) ) )

But, I am still getting only one value as the output from my foreach loop.

Thanks for the help,
A
0
 
LVL 35

Accepted Solution

by:
gr8gonzo earned 400 total points
ID: 37827319
@Olaf - that's incorrect. It is not passing in the array by reference, so there is no need to serialize/unserialize the $row. That is only slowing down the code.

@aej1973 - So in the example output you provided, you had:
Array (
  [2012-01-09] => Array (
    [0] => Array ( [patient_id] => 6 [visit_notes] => Visit in the morning. [visit_id] => 7 [event_date] => 2012-01-09 ) 
    [1] => Array ( [patient_id] => 6 [visit_notes] => Visit in the evening. [visit_id] => 8 [event_date] => 2012-01-09 ) 
    [2] => Array ( [patient_id] => 6 [visit_notes] => hello                 [visit_id] => 9 [event_date] => 2012-01-09 )
  )
)

Open in new window


That data looks correct, since the visit_id is unique. So there should be three rows in $events. I think the problem is that you are looping through your three calendar events, but each time, you are overwriting your $calendar variable, so you only end up with the HTML for one of the events (the last one):
if (isset($events[$cellDate]))
{
  foreach($events[$cellDate] as $event)
  {
    $calendar = '<div class="event">'.$event['visit_notes'].'</div></br>';
  }
}

Open in new window


Maybe it should be something more like:
if (isset($events[$cellDate]))
{
  // Start with a blank calendar
  $calendar = '';
  foreach($events[$cellDate] as $event)
  {
    // Append additional <div>s
    $calendar .= '<div class="event">'.$event['visit_notes'].'</div></br>';
  }
}

Open in new window

0
 
LVL 22

Expert Comment

by:Kim Walker
ID: 37827356
In your original code posted last night at 19:57:03 you have:
        foreach($events[$cellDate] as $event) {
                  
        $calendar= '<div class="event">'.$event['visit_notes'].'</div></br>';
             }
            
      }
      else {
        $calendar= str_repeat('<p></p>',2);
      }

Open in new window

On lines three and eight you need to concatenate the $calendar string each time instead of replace the string:
        foreach($events[$cellDate] as $event) {
                  
        $calendar .= '<div class="event">'.$event['visit_notes'].'</div></br>';
             }
            
      }
      else {
        $calendar .= str_repeat('<p></p>',2);
      }

Open in new window

0
 
LVL 35

Expert Comment

by:gr8gonzo
ID: 37827392
@xmediaman - Don't forget to initialize the variable before trying to append to it. Otherwise he will get a PHP warning.
0
 
LVL 22

Expert Comment

by:Kim Walker
ID: 37827749
gr8gonzo is right. The $calendar variable must be initialized before the loop begins. I assumed it to be initialized elsewhere in your code and should have mentioned that.

I didn't see his comment when I posted mine. His comment is much more detailed than mine and may be more useful for you.
0
 

Author Comment

by:aej1973
ID: 37828486
Dear gr8gonzo, you nailed it! Excellent, thanks a zillion for you help.

A
0
 

Author Closing Comment

by:aej1973
ID: 37828499
Excellent!
0
 
LVL 29

Expert Comment

by:Olaf Doschke
ID: 37831292
Sorry, gr8gonzo;

I had to use unserialize(serialize($row)) all the time using  mysqli, maybe that's related to that. My bad not testing mysql_query() first, to see if that effect plays a role at all.

But we all were rather focused on $events instead of looking at how the final html generated in $calender was not appended to but always overwritten.

Glad it's solved anyway.

Bye, Olaf.
0
 
LVL 35

Expert Comment

by:gr8gonzo
ID: 37831978
@Olaf - Ah, that makes more sense. Yes, PHP does try to pass objects by reference automatically, so using mysqli would explain that. As far as I know, all other values are passed by value unless you explicitly tell PHP to pass by reference with &=.

Just for your own purposes, you can probably make your scripts more speed-and-memory-efficient by populating a new generic object with the values from the original rather than running the serialize/unserialize combo. The serialization process takes some time and memory to construct the temporary value, and the unserialization process takes even longer to parse the string and figure out how to re-construct the original object. If you generate a new generic object, you only take up the memory of the new object and you skip all that extra processing. Just a friendly suggestion.
0
 
LVL 29

Expert Comment

by:Olaf Doschke
ID: 37832441
Thanks, gr8gonzo.

I'll see what I end up with, I've made a new question out of this.

Ray's already at it. Maybe a solution rather is to use PDO than mysqli, especially with bind_result() it seems you get this kind of referencing problems.

So actually the plain straight way via mysql-functions is having lesss problems in this respect. It's just I like to prepare statements and bind parameters to avoid sql injection problems.

Bye, Olaf.
0

Featured Post

Instantly Create Instructional Tutorials

Contextual Guidance at the moment of need helps your employees adopt to new software or processes instantly. Boost knowledge retention and employee engagement step-by-step with one easy solution.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Deprecated and Headed for the Dustbin By now, you have probably heard that some PHP features, while convenient, can also cause PHP security problems.  This article discusses one of those, called register_globals.  It is a thing you do not want.  …
Build an array called $myWeek which will hold the array elements Today, Yesterday and then builds up the rest of the week by the name of the day going back 1 week.   (CODE) (CODE) Then you just need to pass your date to the function. If i…
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…

724 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question