This is a documentation for Board Game Arena: play board games online !

Collection

From Board Game Arena
Jump to navigation Jump to search


Game File Reference



Useful Components

Official

  • ItemManager: a PHP component to manage cards or other game items.
  • PlayerCounter and TableCounter: PHP components to manage counters.
  • Draggable: a JS component to manage drag'n'drop actions.
  • Counter: a JS component to manage a counter that can increase/decrease (ex: player's score).
  • ExpandableSection: a JS component to manage a rectangular block of HTML than can be displayed/hidden.
  • Scrollmap: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
  • Zone: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).
  • bga-zoom : a JS component for zoom controls.
  • bga-animations : a JS component for animations.
  • bga-cards : a JS component for cards.
  • bga-dice : a JS component for dice.
  • bga-autofit : a JS component to make text fit on a fixed size div.
  • bga-score-sheet : a JS component to help you display an animated score sheet at the end of the game.
  • bga-jump-to : a JS component to add board shortcuts

Deprecated

  • Deck: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
  • Stock: a JS component to manage and display a set of game elements displayed at a position.

Unofficial



Game Development Process



Guides for Common Topics



Miscellaneous Resources

"Collection" is a PHP helper for working with keyed groups of values. It extends PHP's ArrayObject, so it can be iterated, counted, and accessed with array syntax, while also providing convenient methods for filtering, transforming, grouping, and querying its contents.

Collections are used throughout the BGA framework. In particular, ItemManager methods that return several game objects return a typed Collection keyed by item ID.

With Collection, you can:

  • Keep the keys of a set of items while filtering, sorting, or slicing it.
  • Find, count, and test values with callbacks.
  • Transform or reduce values without writing explicit loops.
  • Query arrays and objects by field, array key, or getter.
  • Group items into nested collections.
  • Convert a collection to either a keyed PHP array or a zero-based list.

Collection overview

Creating a collection

Import the class and pass an array to its constructor:

use Bga\GameFramework\Helpers\Collection;

$cards = new Collection([
    12 => ['type' => 'heart', 'value' => 7],
    18 => ['type' => 'spade', 'value' => 10],
    25 => ['type' => 'heart', 'value' => 3],
]);

The keys can be integers or strings, and the values can be of any type. In PHPDoc, use the generic notation Collection<Card> or Collection<int> to help static analysis and IDE completion:

/** @var Collection<Card> $hand */
$hand = $this->cards->getItemsInLocation(['hand', $playerId]);

Using a collection as an ArrayObject

Because Collection extends ArrayObject, ordinary PHP operations work as expected:

foreach ($cards as $id => $card) {
    // ...
}

$card = $cards[18];
$numberOfCards = count($cards);

$cards[31] = $anotherCard;
unset($cards[12]);

Array access changes that Collection instance. By contrast, Collection methods such as filter(), map(), sort(), and update() return a new Collection and leave the original Collection unchanged.

Keys and native arrays

Collection distinguishes between a keyed array and a list:

$cards->keys();   // [12, 18, 25]
$cards->all();    // [12 => $card1, 18 => $card2, 25 => $card3]
$cards->values(); // [$card1, $card2, $card3]

Most methods preserve existing keys. Use values() when a zero-based PHP array is needed, especially when sending a list to the client. Otherwise, non-consecutive integer keys are encoded by JSON as an object rather than an array.

Callbacks

Predicates and mapping callbacks can receive the value and, optionally, its key:

$highCards = $cards->filter(
    fn(Card $card, int|string $id): bool => $card->value >= 10
);

$labels = $cards->map(
    fn(Card $card): string => $card->type . '-' . $card->value
);

Callbacks may declare only the value when the key is not needed. reduce() is different: its callback receives the accumulator and then the value, without the key.

Reading fields from arrays and objects

The methods pluck(), where(), countWhere(), whereNot(), whereNull(), sortBy(), and groupBy() can read a named value from either an array or an object.

For 'score', Collection looks for:

  1. The 'score' key when the item is an array.
  2. A getScore() method when the item is an object.
  3. A $score property when there is no getter.

Getters therefore take precedence over properties. Object properties used this way should be public.

class PlayerResult
{
    public function __construct(
        public int $playerId,
        private int $points,
    ) {
    }

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

$winners = $results
    ->where('score', 20)
    ->pluck('playerId');

Common examples

Filtering and transforming

// Keep the original item IDs as keys.
$playable = $hand->filter(fn(Card $card): bool => $card->isPlayable());

// Transform each card, still using the original item IDs as keys.
$values = $hand->map(fn(Card $card): int => $card->value);

// Produce a zero-based list for game data or a notification.
$args['cards'] = $playable->values();

Finding and testing

$ace = $hand->find(fn(Card $card): bool => $card->value === 14);
$aceId = $hand->findKey(fn(Card $card): bool => $card->value === 14);

$hasHeart = $hand->some(fn(Card $card): bool => $card->suit === 'heart');
$allVisible = $hand->every(fn(Card $card): bool => $card->visible);
$visibleCount = $hand->count(fn(Card $card): bool => $card->visible);

find() and findKey() return null when no value matches. some() returns false on an empty Collection, while every() returns true on an empty Collection.

Querying fields

$hearts = $cards->where('suit', 'heart');
$redCards = $cards->where('suit', ['heart', 'diamond']);
$notDiscarded = $cards->whereNot('location', 'discard');
$withoutOwner = $cards->whereNull('ownerId');
$numberOfAces = $cards->countWhere('value', 14);

// '%' is a case-insensitive wildcard.
$playerLocations = $cards->where('location', 'hand%');

Field comparisons are strict by default. Pass false as the third argument of where(), whereNot(), or countWhere() to use loose comparison:

$cards->where('value', '10', strict: false);

When the searched value is an array, it is treated as a set of allowed values. When it is a string containing %, the percent signs match any sequence of characters and the match is case-insensitive.

Sorting and grouping

$byValue = $cards->sortBy('value');
$highestFirst = $cards->sortBy('value', 'DESC');

$bySuit = $cards->groupBy('suit');
$hearts = $bySuit['heart']; // A Collection of hearts with their original keys.

$byParity = $cards->groupBy(
    fn(Card $card): string => $card->value % 2 === 0 ? 'even' : 'odd'
);

groupBy() returns a Collection whose values are themselves Collections. A group key must be an integer or string. Both the order of the groups and the original keys inside each group are retained.

Updating object values

update() returns a Collection in which the named field has been changed on every item. Objects are cloned first, so the objects in the original Collection are not modified. Arrays are copied.

$hiddenCards = $cards->update('visible', false);

For an object field named 'visible', Collection calls setVisible(false) when that setter exists. Otherwise it writes to the public $visible property. It throws an exception if the item is scalar or the field cannot be updated.

update() only changes the returned PHP objects; it does not automatically persist ItemManager objects. Use ItemManager's update methods when changes must be stored in the database.

Collection reference

Construction and conversion

new Collection( array|object $array = [], int $flags = 0, string $iteratorClass = ArrayIterator::class )

Creates a Collection from an array or object. The optional flags and iterator class are passed to ArrayObject.

keys(): array

Returns the keys in their current order as a zero-based array of integers and strings.

values(): array

Returns the values as a zero-based native PHP array. Original keys are discarded.

all(): array

Returns a native PHP array containing all values with their keys preserved.

Inspecting values

isEmpty(): bool

Returns true when the Collection contains no items.

first(): mixed

Returns the first value in insertion order, or null for an empty Collection.

last(): mixed

Returns the last value in insertion order, or null for an empty Collection.

has( int|string $key ): bool

Returns whether the supplied key exists. This checks keys, including keys whose value is null.

contains( mixed $value ): bool

Returns whether the supplied value occurs in the Collection. This uses PHP's non-strict in_array() comparison.

random(): mixed

Returns a random value, or null for an empty Collection.

find( callable $fn ): mixed

Returns the first value for which $fn($value, $key) is true, or null if there is no match.

findKey( callable $fn ): int|string|null

Returns the key of the first value for which $fn($value, $key) is true, or null if there is no match.

count( ?callable $fn = null ): int

Without a callback, returns the total number of values. With a callback, returns the number for which $fn($value, $key) is true. The usual count($collection) syntax also returns the total.

some( callable $fn ): bool

Returns whether at least one value satisfies $fn($value, $key).

every( callable $fn ): bool

Returns whether every value satisfies $fn($value, $key).

Creating and combining collections

add( mixed $object, ?int $id = null ): Collection

Returns a new Collection with the object stored under $id. If no ID is supplied, add() reads the object's id array key, getId() method, or $id property. An existing value under the same key is replaced.

diff( Collection $remove, ?callable $compareFn = null ): Collection

Returns a new Collection without values found in $remove. The default comparison is strict identity. An optional comparator receives a value from this Collection and a value from $remove, and returns true when they should be considered equal.

$remaining = $cards->diff(
    $playedCards,
    fn(Card $a, Card $b): bool => $a->id === $b->id,
);

The original keys of retained values are preserved.

merge( Collection $collection ): Collection

Returns a new Collection containing the values from this Collection followed by keys that do not already exist from $collection. If both Collections contain the same key, the value from this Collection wins.

$left = new Collection([1 => 'one', 2 => 'left']);
$right = new Collection([2 => 'right', 3 => 'three']);

$left->merge($right)->all();
// [1 => 'one', 2 => 'left', 3 => 'three']

Transforming collections

pluck( string $property ): Collection

Returns a new Collection containing the named field from each item. Keys are preserved. Fields are resolved as an array key, a getter, or an object property.

map( callable $func ): Collection

Returns a new Collection containing $func($value, $key) for each value. Keys are preserved, but the returned values can have a different type.

reduce( callable $func, mixed $init ): mixed

Reduces the values to a single result. The callback receives the current accumulator and the next value. Collection keys are not passed.

$total = $cards->reduce(
    fn(int $sum, Card $card): int => $sum + $card->value,
    0,
);

filter( callable $func ): Collection

Returns a new Collection containing only the values for which $func($value, $key) is true. Keys are preserved.

slice( int $offset, ?int $length = null ): Collection

Returns a key-preserving slice starting at $offset. When $length is null, all remaining items are returned. Offset and length follow PHP's array_slice() rules.

take( int $n ): Collection

Returns a key-preserving Collection containing the first $n items.

sort( callable $callback ): Collection

Returns a new Collection sorted by a comparator compatible with PHP's uasort(). The comparator receives two values and returns an integer less than, equal to, or greater than zero. Keys are preserved.

Field-based helpers

where( string $field, mixed $value, bool $strict = true ): Collection

Returns the items whose named field matches $value. An array value is treated as an allowed set. A string containing % is treated as a case-insensitive wildcard pattern.

countWhere( string $field, mixed $value, bool $strict = true ): int

Counts the items whose named field matches $value, using the same matching rules as where().

whereNot( string $field, mixed $value, bool $strict = true ): Collection

Returns the items whose named field does not match $value, using the same matching rules as where().

whereNull( string $field ): Collection

Returns the items whose named field is null.

sortBy( string $field, string $direction = 'ASC' ): Collection

Returns a new Collection sorted by the named field. Pass 'DESC' for descending order; any other direction is treated as ascending. Keys are preserved.

groupBy( string|callable $criteria ): Collection

Groups items by a named field or by the result of $criteria($value, $key). It returns a Collection<Collection<T>>. Group keys must be integers or strings, and item keys are preserved inside each group.

update( string $field, mixed $value ): Collection

Returns a new Collection with the field set to $value on every item. Arrays are copied. Objects are cloned and updated through set<Field>() when available, or through a matching public property otherwise. The original items are left unchanged.