How can I make my own custom class be sortable using sort() for example?
I\'ve been scanning the web to find any method of making a class Comparable like in Java but wi
maybe you can use the function "usort":
class Genre {
private $genre;
private $count;
...
public function __construct($g, $c)
{
$this->genre=g;
$this->count=c;
}
public static function compare($a, $b)
{
if ($a->count < $b->count) return -1;
else if($a->count == $b->count) return 0;
else return 1;
}
...
}
$genres= array(
new Genre (1, 5),
new Genre (2, 2),
new Genre (3, 7)
);
usort($genres, array("Genre", "compare"));
Regards Thomas
You can create a custom sort method and use the http://www.php.net/manual/en/function.usort.php function to call it.
Example:
$Collection = array(..); // An array of Genre objects
// Either you must make count a public variable, or create
// an accessor function to access it
function CollectionSort($a, $b)
{
if ($a->count == $b->count)
{
return 0;
}
return ($a->count < $b->count) ? -1 : 1;
}
usort($Collection, "CollectionSort");
If you'd like to make a more generic collection system you could try something like this
interface Sortable
{
public function GetSortField();
}
class Genre implements Sortable
{
private $genre;
private $count;
public function GetSortField()
{
return $count;
}
}
class Collection
{
private $Collection = array();
public function AddItem($Item)
{
$this->Collection[] = $Item;
}
public function GetItems()
{
return $this->Collection;
}
public function Sort()
{
usort($this->Collection, 'GenericCollectionSort');
}
}
function GenericCollectionSort($a, $b)
{
if ($a->GetSortField() == $b->GetSortField())
{
return 0;
}
return ($a->GetSortField() < $b->GetSortField()) ? -1 : 1;
}
$Collection = new Collection();
$Collection->AddItem(...); // Add as many Genre objects as you want
$Collection->Sort();
$SortedGenreArray = $Collection->GetItems();
The simplest way to do this is to simply use usort on a method within the class that accepts as input an array of matching objects. This is example 3 in the documentation linked to above. However, this is somewhat clunky and ugly.
A better way is to create a new type of array class specific to the desired objects using ArrayAccess. This will enable you to use the custom array like you'd expect but then also be able to run arbitrary sorting methods on the array.
Under the hood, you'd likely still want to use usort, but you'd be hiding that fact behind a much nicer interface that might look like this:
$array = new GenreCollection();
$array[] = new Genre(1); // Genre's constructor is a factory that can load genres via an ID
$array[] = new Genre(2);
$array[] = new Genre(3);
$array[] = new Genre(4);
$array[] = new Genre(5);
// Example Sorts
$array->SortByName();
$array->SortByDateInvented();
$array->SortByID();
$array->SortBySubGenres(); // Arranges Genres into a hierarchy where 'Death Metal' comes with other metal after 'Heavy Metal' - Add in a nest-level value for making dropdowns and other nested lists.
__toString()
works for me:
class Genre
{
private $genre;
private $count;
public function __construct( $genre, $count = 0 )
{
$this->genre = $genre;
$this->count = $count;
}
public function __toString()
{
return $this->count . ' ' . $this->genre;
}
}
$collection = array(
new Genre( 'alternative', 3 ),
new Genre( 'jazz', 2 ),
new Genre( 'hiphop', 1 ),
new Genre( 'heavy metal', 1 )
);
natsort( $collection );
foreach( $collection as $genre )
{
echo $genre . "\n";
}
Produces:
1 heavy metal
1 hiphop
2 jazz
3 alternative