Joss Posted November 21, 2013 Share Posted November 21, 2013 Okay, so, like I have said many times before, I ain't no coder! I am currently taking an old and tired static angling site and turning it into a singing and dancing, Bootstrap 3, Mobile first, Processwire site - which seemed a good idea at the time! The reason is that the bloke wot did the website is retiring and the "committee" will need to update it. Now, the problem I need to create a very basic events page that will be laid out more or less like the original http://www.harlestonanglingclub.co.uk/Bookings.php So, I create a small handful of fields and bung them in a repeater - they will never display many events in one go, so this does not need to be more complicated. I have a event_start_date and an event_end_date field with the output format set at none - so it spits out the time format. What I need to do is: 1. Split the resulting array up by month so that I have several new arrays, each one being a specific month in a specific year. (I have no idea what the months or years will be; this will be defined by what is in the array) 2. Loop through each of those resulting arrays to produce a table - probably using the "month" from the result displayed at the top of the table, then the rest of the results as shown. However, I have not the slightest idea HOW to take my repeater field array and split it into new arrays by month and ... well you get the idea. HELP!!!! Loads of Love Joss Link to comment Share on other sites More sharing options...
Macrura Posted November 22, 2013 Share Posted November 22, 2013 this is my ghetto way of doing it, but wrote this in browser so more to give some ideas, i think there are still some issues with doing it this way... <?php // get all of the events $events = $page->events; $years = array(); // find the array of years for all events foreach ($events as $event) { $years[]= date("Y", $event->getUnformatted("event_start_date")); // change the format of the year in memory for later comparison $event->event_start_date = date("Y", $event->getUnformatted("event_start_date")); } $years = array_unique($years); asort($years); foreach($years as $key => $year) { // find the array of events this year $year_events = $events->find("event_start_date=$year"); $months = array(); // loop through the events for this year and add the months to the array foreach ($year_events as $year_event) { $months[]= date("m", $event->getUnformatted("event_start_date")); $event->event_start_date = date("m", $event->getUnformatted("event_start_date")); } $months = array_unique($months); asort($months); foreach($months as $key => $month) { $month_events = $events->find("event_start_date=$month"); foreach($month_events as $e) { // output the table here } // end foreach events for this month } // end foreach months } // end foreach years ?> Link to comment Share on other sites More sharing options...
Joss Posted November 22, 2013 Author Share Posted November 22, 2013 Hi Macrura - thanks for that, I will try it later once I have finished with some barbershop I have to arrange. Strange life! Joss Link to comment Share on other sites More sharing options...
Joss Posted November 22, 2013 Author Share Posted November 22, 2013 Okay, I output just the following (where you say to output the table) to see what is happening $out .="<p>{$e->event_start_time} - {$e->event_who}</p>"; (event_who is just a field with a name in it so I can see what is outputing) But all I got was: "12 Mickey" I have no idea what the 12 is - the Mickey event is in February 2014. What am I missing? Thanks, Macrura Joss Link to comment Share on other sites More sharing options...
Macrura Posted November 22, 2013 Share Posted November 22, 2013 hi joss - sorry - i think one reason why this isn't going to work yet is because we reset the variable in memory for $event->event_start_date so it probably has to be unset after each of the foreach statements that obtain the arrays of years and months... Link to comment Share on other sites More sharing options...
Joss Posted November 22, 2013 Author Share Posted November 22, 2013 Hi Macrura how do we do that? (showing my complete ignorance here!) Link to comment Share on other sites More sharing options...
diogo Posted November 22, 2013 Share Posted November 22, 2013 If I understand correctly, you can also simply store these values on a new property instead: foreach ($events as $event) { $years[]= date("Y", $event->getUnformatted("event_start_date")); // <del>change</del> format of the year in memory for later comparison $event->event_start_date_for_comparing_later = date("Y", $event->getUnformatted("event_start_date")); } Link to comment Share on other sites More sharing options...
Joss Posted November 22, 2013 Author Share Posted November 22, 2013 I wondered that, but didn't ask in case I was being idiotic. How does that then get used in the rest of the thing? (my head is spinning slowly...) Link to comment Share on other sites More sharing options...
Macrura Posted November 22, 2013 Share Posted November 22, 2013 wow - thanks diogo i didn't know you could do that, i.e. set a new property for the page array... so this would be an altered version based on that.. <?php // get all of the events $events = $page->events; $years = array(); // find the array of years for all events foreach ($events as $event) { $years[]= date("Y", $event->getUnformatted("event_start_date")); // change the format of the year in memory for later comparison $event->event_year = date("Y", $event->getUnformatted("event_start_date")); } $years = array_unique($years); asort($years); foreach($years as $key => $year) { // find the array of events this year $year_events = $events->find("event_year=$year"); $months = array(); // loop through the events for this year and add the months to the array foreach ($year_events as $year_event) { $months[]= date("m", $year_event->getUnformatted("event_start_date")); $event->event_month = date("m", $event->getUnformatted("event_start_date")); } $months = array_unique($months); asort($months); foreach($months as $key => $month) { $month_events = $events->find("event_month=$month"); foreach($month_events as $e) { // output the table here } // end foreach events for this month } // end foreach months } // end foreach years ?> 1 Link to comment Share on other sites More sharing options...
Joss Posted November 22, 2013 Author Share Posted November 22, 2013 Okay, nearly there! Actually, now you have given unique variable names, it is much less confusing! I can almost get the workflow, despite my aged brain. In the code below I am outputing the year as an H2, then the month as an H3 (just for convenience). The code is happilly listing the years and the associated months. However, when it comes to outputting the actual event, it is only outputting the most recent event for the most recent month and not the others in the other months. Note: This code is set up as a function and I have corrected the variable names since I accidentally gave the wrong ones in the original post - sorry! Thanks guys, we are definitely getting there! <? function events() { // get all of the events $events = wire("page")->events; //gets the repeater field $years = array(); $out =""; // find the array of years for all events foreach ($events as $event) { $years[]= date("Y", $event->getUnformatted("event_start_time")); // change the format of the year in memory for later comparison $event->event_year = date("Y", $event->getUnformatted("event_start_time")); } $years = array_unique($years); asort($years); foreach($years as $key => $year) { // Output the year $out .="<h2>{$year}</h2>"; // find the array of events this year $year_events = $events->find("event_year=$year"); $months = array(); // loop through the events for this year and add the months to the array foreach ($year_events as $year_event) { $months[]= date("m", $year_event->getUnformatted("event_start_time")); $event->event_month = date("m", $event->getUnformatted("event_start_time")); } $months = array_unique($months); asort($months); foreach($months as $key => $month) { // Output the month as a number $out .="<h3>{$month}</h3>"; // Set up a variable for the next loop of events $month_events = $events->find("event_month=$month"); foreach($month_events as $e) { $out .="<p>{$e->event_who}</p>"; // output the table here } // end foreach events for this month } // end foreach months } // end foreach years echo $out; } ?> 1 Link to comment Share on other sites More sharing options...
Pete Posted November 22, 2013 Share Posted November 22, 2013 ryan did once tell me a long time ago that, if they have at least one event per month, it's actually less intensive to just generate all months and years from a given start date to today with just PHP and not iterating through every single event (the way it's being approached above doesn't scale infinitely basically, but would be fine for most sites). What you could do is get the single event with teh date that's furthest in the future, then iterate through all the months and years between the current month and that event and create links for each month and year that way. EDIT: Silly me, you want to print all the event details anyway so this is irrelevant in this case, but useful to bear in mind for someone who might just want to have a menu for months and years that click through to an events list (or blog or some such thing where you might want to have links to all past years etc with potentially thousands of pages behind them). But yeah, not relevant in this case at all! 1 Link to comment Share on other sites More sharing options...
Joss Posted November 23, 2013 Author Share Posted November 23, 2013 Pete, so nice to see you are awake and sober! Joss 1 Link to comment Share on other sites More sharing options...
Macrura Posted November 23, 2013 Share Posted November 23, 2013 Joss - maybe try echoing the count of month_events echo count($month_events); and make sure it is the right # of events being returned by the selector $events->find("event_month=$month"); also maybe echo all the other variables to make sure nothing is going wrong somewhere, check the debug also? Link to comment Share on other sites More sharing options...
Joss Posted November 24, 2013 Author Share Posted November 24, 2013 Hi Macrura I have been putting the count right at the end of the function. Counting the $years variable is returning the right number - 2 (2013 and 2014) Counting the $months variable is returning 1 - this is not right. I have three events in three different months, so it should be returning 3 However, if I put count($months) BEFORE the last foreach (the events one), it returns the right number - so something is breaking with that last foreach. I have tried debug, but it is happy with everything, which doesn't surprise me as I cant see any code errors. Joss Link to comment Share on other sites More sharing options...
Joss Posted November 24, 2013 Author Share Posted November 24, 2013 Okay, just noticed another oddity. I put an event in november 2014. It is displaying that under november 2014 (good!) However, although no other events are showing, the Nov 2014 event is also showing under Nov 2013 .... ummm! It does not seem to be relating to the year. Joss Link to comment Share on other sites More sharing options...
Joss Posted November 24, 2013 Author Share Posted November 24, 2013 Okay, I think I have worked out the year confusion - I have changed the last find to $month_events = $events->find("event_month=$month, event_year=$year"); However, that has not solved the original problem of only one actual event showing. Link to comment Share on other sites More sharing options...
Joss Posted November 24, 2013 Author Share Posted November 24, 2013 Right, I think I have a vague idea about the problem. This line: foreach ($year_events as $year_event) { $months[]= date("m", $year_event->getUnformatted("event_start_time")); $event->event_month = date("m", $event->getUnformatted("event_start_time")); } If I add $Out .= $event->event_month to the loop it just returns 11, which is the month associated with the very last event. If I move that event to october, it returns 10. Now, if I change the loop so that the last line is: $event->event_month = date("m", $year_event->getUnformatted("event_start_time")); Then my check outputs all the correct months. However, I am still not getting my events. Closer, perhaps? Link to comment Share on other sites More sharing options...
Macrura Posted November 24, 2013 Share Posted November 24, 2013 hey Joss - maybe see if this is better... still untested: <? function events() { // get all of the events $events = wire("page")->events; //gets the repeater field $years = array(); $out =""; // find the array of years for all events foreach ($events as $event) { $years[]= date("Y", $event->getUnformatted("event_start_time")); // add properties event_year and event_month to the $event object $event->event_year = date("Y", $event->getUnformatted("event_start_time")); $event->event_month = date("m", $event->getUnformatted("event_start_time")); } $years = array_unique($years); asort($years); // for testing // print_r($years); // print_r($events); foreach($years as $key => $year) { // Output the year $out .="<h2>{$year}</h2>"; // find the array of events this year and put into new array $year_events $year_events = $events->find("event_year=$year"); // print_r($year_events); // loop through the events for this year and add the months to the array $months = array(); foreach ($year_events as $year_event) { $months[]= date("m", $year_event->getUnformatted("event_start_time")); } $months = array_unique($months); asort($months); // print_r($months); // loop through the months and find events for the month foreach($months as $key => $month) { // Output the month as a number $out .="<h3>{$month}</h3>"; // filter only the events for this month, from the $year_events array. $month_events = $year_events->find("event_month=$month"); // print_r($month_events); foreach($month_events as $e) { $out .="<p>{$e->event_who}</p>"; } // end foreach events for this month } // end foreach months } // end foreach years echo $out; } ?> *maybe joss or a moderator could mark this as best answer? 2 Link to comment Share on other sites More sharing options...
Joss Posted November 24, 2013 Author Share Posted November 24, 2013 Yee-haw!!! Okay, looks like that works ... now I have just got to work out how (and throw some extra bits in to test properly) ...... er, so you just removed one line? Thanks a million! Link to comment Share on other sites More sharing options...
Macrura Posted November 24, 2013 Share Posted November 24, 2013 there were a bunch of mistakes in the first code, with the wrong var names in the nested loops, that's why it wasn't working, and i moved one line; the comments should tell the story though 1 Link to comment Share on other sites More sharing options...
Joss Posted November 24, 2013 Author Share Posted November 24, 2013 Well, it seems to be working fine now! This sort of thing is REALLY REALLY useful! Why don't you do it up as a little tutorial, explaining in more detail exactly how you are extracting data using processwire and how to use nested loops? There are a lot of people like me on here that would appreciate it! All the best Joss Link to comment Share on other sites More sharing options...
Macrura Posted November 24, 2013 Share Posted November 24, 2013 yeah - should probably do that - cheers! also - once you start setting up your markup for output, there are some things you can do to get the month names to output how you want (instead of numbers), usually done using php built in strtotime http://php.net/manual/en/function.strtotime.php , so you can pass the month as a string and then format it any way you want once you tell php that it's a date; http://www.php.net/manual/en/datetime.formats.date.php; since you are sorting by the month number, so those will appear in the right order; the last project i did i needed to customize the output of the day names, so i used a switch statement in the loop, something similar for this, in case you don't want to use the php date: <?php switch ($month) { case 01: $monthName = "January"; break; case 02: $monthName = "February"; break; // etc.. } Link to comment Share on other sites More sharing options...
Joss Posted November 24, 2013 Author Share Posted November 24, 2013 The way I did that was to use the date() function, eg: $start_date = date("l jS", $e->getUnformatted("event_start_time")); $out .="<td><strong>{$start_date}</strong></td>"; to give me the day name and the day number (with a th or nd on the end) - Saturday 19th Link to comment Share on other sites More sharing options...
Macrura Posted November 24, 2013 Share Posted November 24, 2013 yes - that would work for the events themselves; but before you start foreaching through the month's events, if you wanted to for example output headers for each month, you could also use the existing $month variable and then strtotime it to get your month name, or use the switch.. Link to comment Share on other sites More sharing options...
Joss Posted November 24, 2013 Author Share Posted November 24, 2013 Yes, I have already used a similar solution for all the display - that was just an example. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now