SamC Posted April 23, 2018 Share Posted April 23, 2018 Hi, The array I'm working with (shortened example, the first three items) is: Array ( [0] => Array ( [character] => [credit_id] => 5a26eac792514103360f3e03 [release_date] => 2017-06-13 [vote_count] => 5 [video] => [adult] => [vote_average] => 7.6 [title] => Celtics/Lakers: Best of Enemies [genre_ids] => Array ( [0] => 99 ) [original_language] => en [original_title] => Celtics/Lakers: Best of Enemies [popularity] => 3.191622 [id] => 456788 [backdrop_path] => [overview] => A two-part series exploring the Celtics–Lakers rivalry, focusing mainly on the 1980s era of Larry Bird and Magic Johnson but also examining the entire history of the NBA through the rivalry. [poster_path] => /mF2ccs6AuGUvEIY9lfj8chFu6pW.jpg ) [1] => Array ( [character] => Performer [credit_id] => 5939ea8ec3a36823440029c4 [release_date] => 2017-06-04 [vote_count] => 1 [video] => [adult] => [vote_average] => 1 [title] => Comedy Central's Colossal Clusterfest [genre_ids] => Array ( [0] => 35 ) [original_language] => en [original_title] => Comedy Central's Colossal Clusterfest [popularity] => 1.651011 [id] => 460340 [backdrop_path] => /gsZT6wW4Oo7ApYD4TG5aZWby1Jj.jpg [overview] => Highlights from the inaugural Colossal Clusterfest that took place in San Francisco from June 2-4. [poster_path] => /ui1nZudYxcqJjFIZsiuTyqcV6PL.jpg ) [2] => Array ( [character] => [credit_id] => 589119a092514103f000c00f [release_date] => 2017-03-10 [vote_count] => 4 [video] => [adult] => [vote_average] => 2.6 [title] => G-Funk [genre_ids] => Array ( [0] => 99 ) [original_language] => en [original_title] => G-Funk [popularity] => 5.432522 [id] => 438517 [backdrop_path] => [overview] => G-Funk is the untold story of three childhood friends from East Long Beach who helped commercialize hip hop by developing a sophisticated and melodic new approach – merging Gangsta Rap with elements of Motown, Funk, and R&B. [poster_path] => /lmByKQnHcMch8FkWzNquKtbFueN.jpg ) ) ...and I wanted to sort them by date, newest first. It's small class like this. The problem is outlined in the comments: <?php namespace App\Controllers; // Bring View class into current namespace use \Core\View; // Bring Actor model class into current namespace use App\Models\Actor; /** * About controller */ class Actors extends \Core\Controller { public function list() { // Model 'Actor' just queries API and returns array $movies = Actor::getAll(); // Sort by date - newest first function sortNewestFirst( $a, $b ) { return strtotime($b["release_date"]) - strtotime($a["release_date"]); } /** * ********************************************** * usort() ERRORS IF 'release_date' does not exist * ********************************************** */ usort($movies, "App\Controllers\sortNewestFirst"); View::renderTemplate('Actor/listAll.html', [ 'name' => $this->getFormattedName(), 'movies' => $movies ] ); } /** * Get the current name from URL */ private function getFormattedName() { return ucwords(htmlspecialchars($_GET['name'], ENT_QUOTES | ENT_SUBSTITUTE, "UTF-8")); } } The error: Uncaught exception: 'ErrorException' Message: 'Undefined index: release_date' Unfortunately, the API has no release date for some movies, so my search works perfectly for some actors, but errors for others. I was trying to figure out how to get array_key_exists() into this somehow but I'm totally stuck. Being an array of arrays makes this more tricky. I was thinking of looping each one, if the key exists, add to a new array, but then the movie with the missing key would be completely absent. I was thinking of just chucking it at the bottom of the list. Hopefully this makes sense. Any help, hints or improvements would be awesome, thanks. Link to comment Share on other sites More sharing options...
arjen Posted April 23, 2018 Share Posted April 23, 2018 You could use array_filter to create two arrays: one with and one without release dates. Sort the first one and append the second one. 1 Link to comment Share on other sites More sharing options...
kongondo Posted April 23, 2018 Share Posted April 23, 2018 @SamC, Moderator Note FYI, you posted 3 other copies of this thread. I am guessing you were on mobile, or your computer was a bit wonky. I've deleted the other three. 1 Link to comment Share on other sites More sharing options...
SamC Posted April 23, 2018 Author Share Posted April 23, 2018 56 minutes ago, arjen said: You could use array_filter to create two arrays: one with and one without release dates. Sort the first one and append the second one. I'll give this a try, thanks. 25 minutes ago, kongondo said: @SamC, Moderator Note FYI, you posted 3 other copies of this thread. I am guessing you were on mobile, or your computer was a bit wonky. I've deleted the other three. Thanks, had a problem submitting, 2mins+ with nothing haopening so I refreshed, waited, waited, redreshed, tried again. Third time submitted normally i.e. took seconds. Not sure what went wrong, maybe dodgy internet. 1 Link to comment Share on other sites More sharing options...
SamC Posted April 26, 2018 Author Share Posted April 26, 2018 Did this now, code could most likely be improved, but it works: if ($movies) { // Movies with release date function hasReleaseDate($movies) { return (array_key_exists('release_date', $movies)) ? true : false; } // Movies without release date function noReleaseDate($movies) { return (!array_key_exists('release_date', $movies)) ? true : false; } // Generate arrays of movies with/without release date $movies_with_release_date = array_filter($movies, 'App\Controllers\hasReleaseDate'); $movies_without_release_date = array_filter($movies, 'App\Controllers\noReleaseDate'); // Sort by date - newest first function sortNewestFirst( $a, $b ) { return strtotime($b["release_date"]) - strtotime($a["release_date"]); } usort($movies_with_release_date, "App\Controllers\sortNewestFirst"); // Append movies without release date $movies = array_merge($movies_with_release_date, $movies_without_release_date); View::renderTemplate('Actor/list-all.html', [ 'name' => $this->getFormattedName($name), 'movies' => $movies ] ); } else { View::renderTemplate('Actor/no-results.html'); } The more I move on with this, the more I see the importance of finding some kind of structure. It's starting to confuse myself with where to put code, whether it goes in a model, a controller etc. Def need to work on this. However, all good for now thanks @arjen 1 Link to comment Share on other sites More sharing options...
SamC Posted April 27, 2018 Author Share Posted April 27, 2018 Only just noticed the release_date key is either not there at all, or present, but empty for some movies e.g.: [97] => Array ( [character] => Fred Rogers [credit_id] => 5a709346c3a36847e4012aaa [poster_path] => [id] => 501907 [video] => [vote_count] => 0 [adult] => [backdrop_path] => [genre_ids] => Array ( [0] => 18 ) [original_language] => en [original_title] => You Are My Friend [popularity] => 1 [title] => You Are My Friend [vote_average] => 0 [overview] => The story of Fred Rogers, the honored host and creator of the popular children's television program, Mister Rogers' Neighborhood (1968). [release_date] => ) Had to modify the functions as checking for key existence was not enough: // Movies with release date function hasReleaseDate($movie) { // Has key with value if (array_key_exists('release_date', $movie) && !empty($movie['release_date'])) { return true; } return false; } // Movies without release date function noReleaseDate($movie) { // No key if (!array_key_exists('release_date', $movie)) { return true; } // Has key but no value if (array_key_exists('release_date', $movie) && empty($movie['release_date'])) { return true; } return false; } Seems to work now. 1 Link to comment Share on other sites More sharing options...
Recommended Posts