$this->bga->notify
Send changes to the front end after updating the game data. Register matching handlers through the front-end notifications API.
API
all(string $notifName, string|NotificationMessage $message = '', array $args = []): void
Send a public notification to players and spectators. $notifName selects the front-end handler. $message is the log text; wrap nonempty messages in clienttranslate. An empty message updates the interface without a log entry.
player(int $playerIdOrNo, string $notifName, string|NotificationMessage $message = '', array $args = []): void
Send a notification to one player. Targets are player IDs by default.
Both methods accept Bga\GameFramework\NotificationMessage in place of the message string. Put the arguments in that object and leave the separate $args parameter empty.
setUseNo(bool $useNo): void
Use player numbers for player targets and _private keys when true. This does not convert IDs inside your custom arguments.
addDecorator(callable $fn)
Register a function with signature function(string $message, array $args): array that returns the decorated arguments. A decorateNotifArgs method on Game is registered automatically.
alwaysMergePrivate()
Merge private data directly into each recipient’s arguments instead of placing it under args._private. Call this in the Game constructor to apply it to notifications and state arguments. To enable it for one argument array, add '_merge_private' => true.
Public and private data
For all, put information visible to everyone in the main argument array. Put each player’s private information under _private, keyed by their ID or number according to setUseNo. Other recipients do not receive those private values.
$this->bga->notify->all('cardDrawn', clienttranslate('${player_name} draws a card'), [
'player_name' => $this->getPlayerNameById($playerId),
'player_id' => $playerId,
'_private' => [
$playerId => ['card' => $card],
],
]);
A private entry can itself be a NotificationMessage to give that recipient different log text and arguments.
Undo notifications
The public flag doNotWriteNextNotificationsToDatabase suppresses persistence of subsequent notifications for the current request. The logs API sets it when removing undone moves.
When notifications are sent
Notifications are queued during an action and normally delivered when the action completes successfully, including its state transitions. An exception rolls back the move and prevents delivery of its queued notifications.
Send notifications from action methods, onEnteringState, or setupNewGame after initializing the players. Constructors and methods that only read data, such as state getArgs, must not send notifications.
Framework state changes already generate their own notifications. Register handlers for your game’s custom notifications; use the exposed APIs for built-in updates.
The framework limits each serialized notification packet to 128 KiB during normal play. Several notifications can share one packet, so send only the changes needed by the interface. Keep log messages as text and perform HTML rendering on the client.
Public notifications give a move its identifier. An action containing only private notifications has no associated move ID. If the action needs one, include a public notification, even with an empty message. Private and public channels are stored separately: private entries precede public entries in the restored log, so avoid relying on interleaved ordering between the two channels.
Log arguments and translations
Use single-quoted PHP strings for ${...} placeholders so PHP does not interpolate them. Supply every referenced argument.
$this->bga->notify->all('tilePlaced', clienttranslate('${player_name} places ${tile_name}'), [
'player_id' => $playerId,
'player_name' => $this->getPlayerNameById($playerId),
'tile_name' => clienttranslate('Garden'),
'i18n' => ['tile_name'],
'tile' => $tile,
]);
i18n lists argument names whose values need translation. Player names must not be included in it. To format player names in their colors, pass matching pairs such as player_name and player_id, or player_name2 and player_id2 for a second player. These fields contain player IDs even when notification targets use player numbers.
Nested log fragments
An argument can contain its own log and args, which the client formats recursively:
$this->bga->notify->all('tileScored', clienttranslate('${tile_label} scores ${points} points'), [
'tile_label' => [
'log' => clienttranslate('${kind} (${number})'),
'args' => [
'kind' => clienttranslate('Garden'),
'number' => $tileNumber,
'i18n' => ['kind'],
],
],
'points' => $points,
]);
Restoring log history
On a page reload, old notifications rebuild the log without calling your normal notification handlers. Most arguments not needed by the log message are removed from history. If your custom log formatter needs additional fields, list their names in preserve:
$this->bga->notify->all('tilePlaced', clienttranslate('${player_name} places a tile'), [
'player_id' => $playerId,
'player_name' => $this->getPlayerNameById($playerId),
'tileType' => $tileType,
'preserve' => ['tileType'],
]);
Preserve only fields needed to render the historical log. Rebuild the current board from getAllDatas, rather than relying on history handlers.
Different private log text
Use NotificationMessage inside _private when a player should see different log text as well as private data. With the default merge setting, refer to private fields using ${_private.field}:
use Bga\GameFramework\NotificationMessage;
$this->bga->notify->all('tileDrawn', clienttranslate('${player_name} draws a tile'), [
'player_id' => $playerId,
'player_name' => $this->getPlayerNameById($playerId),
'_private' => [
$playerId => new NotificationMessage(clienttranslate('You draw ${_private.tile_name}'), [
'tile' => $tile,
'tile_name' => clienttranslate('Garden'),
'i18n' => ['tile_name'],
]),
],
]);
With private merging enabled, the field is ${tile_name} instead. For a private update with no public counterpart, use player:
The recipient must be a player at the table. Use public notifications for information spectators need to receive.
Decorator example
Register decorators in the Game constructor, after parent::__construct(). They can supply commonly repeated arguments:
$this->bga->notify->addDecorator(function (string $message, array $args): array {
if (isset($args['player_id']) && !isset($args['player_name'])
&& str_contains($message, '${player_name}')) {
$args['player_name'] = $this->getPlayerNameById($args['player_id']);
}
return $args;
});
Then an action can omit the repeated player-name lookup:
$this->bga->notify->all('pass', clienttranslate('${player_name} passes'), [
'player_id' => $playerId,
]);
Decorators run for the bga->notify methods, including private argument arrays. Calls to the deprecated Game methods notifyAllPlayers and notifyPlayer bypass them.
Player-number example
Configure the mode once in the Game constructor and use it consistently for all targets:
In an action, use a player number both for player and for _private keys: