Coffeee
Coffeee

Reputation: 143

Laravel Eloquent Array Loop

I have an eloquent query that is returning a 'show', and any 'show_ref's relating to it:

Show::where('show_slug','=',$id)->with('showrefs')->firstOrFail();

This brings back a nested array successfully, as follows:

{
   "show_id":2,
   "show_name":"ShowNo1",
   "show_logo":null,
   "show_facebook_url":null,
   "show_twitter_url":null,
   "show_website_url":null,
   "show_slug":"shown1",
   "created_at":"2014-09-27 11:57:32",
   "updated_at":"2014-09-27 11:57:32",
   "showrefs":[
      {
         "show_ref":1,
         "show_id":2,
         "show_start_date":"2014-05-16",
         "show_end_date":"2014-05-21",
         "show_year":2014,
         "show_common_name":"Mid May",
         "venue_id":null,
         "created_at":"2014-09-27 12:17:40",
         "updated_at":"2014-09-28 06:26:54"
      },
      {
         "show_ref":2,
         "show_id":2,
         "show_start_date":"2014-05-23",
         "show_end_date":"2014-05-28",
         "show_year":2014,
         "show_common_name":"Late May",
         "venue_id":null,
         "created_at":"2014-09-27 12:21:24",
         "updated_at":"2014-09-28 06:26:58"
      },
      {
         "show_ref":4,
         "show_id":2,
         "show_start_date":"2013-02-12",
         "show_end_date":"2013-02-13",
         "show_year":2013,
         "show_common_name":"Early February",
         "venue_id":null,
         "created_at":"2014-09-28 17:50:02",
         "updated_at":"2014-09-28 17:50:02"
      },
      {
         "show_ref":5,
         "show_id":2,
         "show_start_date":"2013-04-27",
         "show_end_date":"2013-04-28",
         "show_year":2013,
         "show_common_name":"Late April",
         "venue_id":null,
         "created_at":"2014-09-28 17:50:42",
         "updated_at":"2014-09-28 17:50:42"
      }
   ]
}

What I am trying to get from my view is the following format:

ShowNo1 (show name)

2014

list of any shows in 2014

2013

List of any shows in 2013

Is there anyway this is possible from what I have coded so far? or have I gone about this the wrong way?

Thanks.

Upvotes: 1

Views: 1880

Answers (2)

Jeff Lambert
Jeff Lambert

Reputation: 24661

You have a showrefs function in your Show model somewhere that is defining this relationship. @Armon's answer will work, but will run on the order of O(n * years) where years is the number of years you want to show. Your example only has 2, but could be many more, and you can instead display your data in O(n) time.

You can orderBy in the methods defining relationships.:

// app/models/Show.php
public function showrefs()
{
    return $this->hasMany('ShowRef')->orderBy('show_start_date', 'DESC');
}

If the tables you are joining together both contain a column which you want to order by, you may need to qualify the order by by appending the table name, as in:

->orderBy('`show_refs`.`show_start_date`', 'DESC')

After that, its just a matter of keeping track of the current year and noticing when it changes when looping over your data:

$show = Show::where('show_slug','=',$id)->with('showrefs')->firstOrFail();
$currentYear = '';
foreach($show->showrefs as $showref) {
    $showRefYear = strtok($showref->show_start_date, '-');
    if($currentYear != $showRefYear) {
        $currentYear = $showRefYear;
        // Output Year heading
    }

    // Output show details
}

Upvotes: 1

Armon
Armon

Reputation: 358

Without knowing anything about Eloquent, you can use a simple function to walk through your nested array and collect your shows for a given year:

function collect_shows_with_year($shows, $year)
{
  $result = array();
  foreach($shows["showrefs"] as $show_ref)
  {
    if($show_ref["show_year"] == $year)
    {
      $result[] = $show_ref;
    }
  }
  return $result;
}

$shows_in_2014 = collect_shows_with_year($shows, 2014);
$shows_in_2013 = collect_shows_with_year($shows, 2013);

Upvotes: 0

Related Questions