2017 © Pedro Peláez
 

library sorting

image

stratadox/sorting

  • PHP
  • 0 Dependents
  • 0 Suggesters
  • 0 Forks
  • 0 Open issues
  • 2 Versions
  • 0 % Grown

The README.md

Sorting

Build Status Coverage Status Scrutinizer Code Quality, (*1)

The sorting package contains tools to sort data structures like tables or collections of objects., (*2)

Sorting instructions are objects and can therefore easily be passed along as parameters. Multiple instructions can be chained in order to sort by several fields., (*3)

Installation

Install using composer:, (*4)

composer require stratadox/sorting, (*5)

Basic usage

2D Arrays

When sorting a collection of associative arrays, use:, (*6)

<?php
use Stratadox\Sorting\ArraySorter;
use Stratadox\Sorting\Sort;

$table = [
    ['name' => 'Foo', 'rating' => 3],
    ['name' => 'Bar', 'rating' => 1],
    ['name' => 'Baz', 'rating' => 2],
];
$sorter = new ArraySorter();

$table = $sorter->sort($table, Sort::descendingBy('rating'));

assert($table === [
    ['name' => 'Foo', 'rating' => 3],
    ['name' => 'Baz', 'rating' => 2],
    ['name' => 'Bar', 'rating' => 1],
]);

Objects

In case the collection consists of objects, the sorting definition remain the same. Instead of using the ArraySorter, the ObjectSorter picks up the sorting requirements., (*7)

<?php
use Stratadox\Sorting\ObjectSorter;
use Stratadox\Sorting\Sort;

class SomeObject
{
    private $name;
    private $rating;

    public function __construct(string $name, int $rating)
    {
        $this->name = $name;
        $this->rating = $rating;
    }

    public function name(): string
    {
        return $this->name;
    }

    public function rating(): int
    {
        return $this->rating;
    }
}

$objects = [
    new SomeObject('Foo', 3),
    new SomeObject('Bar', 1),
    new SomeObject('Baz', 2),
];
$sorter = new ObjectSorter();

$objects = $sorter->sort($objects, Sort::ascendingBy('rating'));

assert($objects == [
    new SomeObject('Bar', 1),
    new SomeObject('Baz', 2),
    new SomeObject('Foo', 3),
]);

Method mapping

When the names of the methods do not correspond to the fields, or when a custom method is to be used for determining the sorting weight, a mapping can be given to the ObjectSorter:, (*8)

<?php
use Stratadox\Sorting\ObjectSorter;
use Stratadox\Sorting\Sort;

class SomeObject
{
    private $name;
    private $rating;

    public function __construct(string $name, int $rating)
    {
        $this->name = $name;
        $this->rating = $rating;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function getTheRating(): int
    {
        return $this->rating;
    }
}

$objects = [
    new SomeObject('Foo', 3),
    new SomeObject('Bar', 1),
    new SomeObject('Baz', 2),
];
$sorter = new ObjectSorter([
    'name' => 'getName',
    'rating' => 'getTheRating',
]);

$objects = $sorter->sort($objects, Sort::ascendingBy('rating'));

assert($objects == [
    new SomeObject('Bar', 1),
    new SomeObject('Baz', 2),
    new SomeObject('Foo', 3),
]);

Nested arrays

If the structure to be sorted consists of a list of nested arrays, one can use the NestedArraySorter:, (*9)

<?php
use Stratadox\Sorting\NestedArraySorter;
use Stratadox\Sorting\Sort;

$unsorted = [
    ['result' => ['index' => 3, 'label' => 'bar']],
    ['result' => ['index' => 2, 'label' => 'qux']],
    ['result' => ['index' => 1, 'label' => 'baz']],
    ['result' => ['index' => 2, 'label' => 'foo']],
];
$sorter = new NestedArraySorter();
$result = $sorter->sort($unsorted, Sort::ascendingBy('result.index'));

assert($result === [
   ['result' => ['index' => 1, 'label' => 'baz']],
   ['result' => ['index' => 2, 'label' => 'qux']],
   ['result' => ['index' => 2, 'label' => 'foo']],
   ['result' => ['index' => 3, 'label' => 'bar']],
]);

Sorting by multiple fields

<?php
use Stratadox\Sorting\ArraySorter;
use Stratadox\Sorting\Sort;

$table = [
    ['name' => 'Bar', 'rating' => 1],
    ['name' => 'Foo', 'rating' => 3],
    ['name' => 'Baz', 'rating' => 1],
];
$sorter = new ArraySorter();
$table = $sorter->sort($table, 
    Sort::descendingBy('rating', Sort::descendingBy('name'))
);

assert($table == [
    ['name' => 'Foo', 'rating' => 3],
    ['name' => 'Baz', 'rating' => 1],
    ['name' => 'Bar', 'rating' => 1],
]);

Or:, (*10)

<?php
use Stratadox\Sorting\ArraySorter;
use Stratadox\Sorting\Sort;


$table = [
    ['name' => 'Bar', 'rating' => 1],
    ['name' => 'Foo', 'rating' => 3],
    ['name' => 'Baz', 'rating' => 1],
];
$sorter = new ArraySorter();
$table = $sorter->sort($table, 
    Sort::descendingBy('rating')->andThenDescendingBy('name')
);

assert($table == [
    ['name' => 'Foo', 'rating' => 3],
    ['name' => 'Baz', 'rating' => 1],
    ['name' => 'Bar', 'rating' => 1],
]);

Or:, (*11)

<?php
use Stratadox\Sorting\ArraySorter;
use Stratadox\Sorting\Sorted;


$table = [
    ['name' => 'Bar', 'rating' => 1],
    ['name' => 'Foo', 'rating' => 3],
    ['name' => 'Baz', 'rating' => 1],
];
$sorter = new ArraySorter();
$table = $sorter->sort($table, Sorted::by([
    'rating' => false,
    'name' => false,
]));

assert($table == [
    ['name' => 'Foo', 'rating' => 3],
    ['name' => 'Baz', 'rating' => 1],
    ['name' => 'Bar', 'rating' => 1],
]);

Structure

The sorting package consists of two core concepts: - the sorting definition, which is used to declare the sorting requirements, and - the sorter, which sorts the elements according to the given definition, (*12)

This separation is maintained in order to decouple the intention of sorting from the data structure that is being sorted., (*13)

A sorting definition, for instance Sort::ascendingBy('name'), can be applied to a collection of associative arrays or to a collection of objects - the client that asks for the sorting does not need to know the internals of the elements that are to be sorted., (*14)

When designing an interface that allows for sorting, a method might accept a Sorting definition, eg. public function getSorted(Sorting $definition): array. Implementors of this interface may use any sorter they see fit, so long as they produce the expected results., (*15)

Some implementations may not even use any sorter at all, but instead take the sorting definition and produce a sorted list of results in a different way. An example of such usage might be a repository with an in-memory and an sql implementation:, (*16)

<?php
use Stratadox\Sorting\Contracts\Sorting;
use Stratadox\Sorting\ObjectSorter;
use Stratadox\Sorting\OrderByParser;

class SomeEntity
{
    // ...
}

interface SomeRepository
{
    /** @return SomeEntity[] */
    public function all(Sorting $sorting): array;
}

class SomeInMemoryRepository implements SomeRepository
{
    private $sorter;
    private $entities;

    public function __construct(SomeEntity ...$entities)
    {
        $this->sorter = new ObjectSorter();
        $this->entities = $entities;
    }

    public function all(Sorting $sorting): array
    {
        return $this->sorter->sort($this->entities, $sorting);
    }
}

class SomeDatabaseRepository implements SomeRepository
{
    private $connection;
    private $orderByParser;
    private $deserializer;

    public function __construct(PDO $connection, DeserializesObjects $deserializer)
    {
        $this->connection = $connection;
        $this->orderByParser = OrderByParser::allowing('foo', 'bar');
        $this->deserializer = $deserializer;
    }

    public function all(Sorting $sorting): array
    {
        $query = $this->connection->query(
            'SELECT * FROM some_table ' . $this->orderByParser->parse($sorting)
        );
        $entities = [];
        foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $row) {
            $entities[] = $this->deserializer->from($row);
        }
        return $entities;
    }
}

The Versions

12/04 2018
19/12 2017

v0.1

0.1.0.0

  Sources   Download

MIT

The Requires

  • php >=7.1

 

The Development Requires