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

PHP 8 upgrade: Difference between revisions

From Board Game Arena
Jump to navigation Jump to search
No edit summary
 
(6 intermediate revisions by 2 users not shown)
Line 2: Line 2:
[[Category:Studio]]
[[Category:Studio]]


Starting December 2023, BGA is upgrading game servers from PHP 7.4 to PHP 8.2. See https://boardgamearena.com/forum/viewtopic.php?t=33940 for more information.
Starting in 2023-12, BGA began upgrading game servers from PHP 7.4 to PHP 8.2. See https://boardgamearena.com/forum/viewtopic.php?t=33940 for more information.


== Current Status ==
As of 2024-08-09, the BGA upgrade to PHP 8.2 is '''complete'''. Your game can now use PHP 8-specific features. 🎉
BGA studio and production are both currently running in a <b>mixed environment</b>, with some servers on PHP 7 and others on PHP 8. Until this upgrade is fully completed, your game code must be compatible with both versions of PHP. You <b>cannot</b> use any PHP 8-specific features yet.


The following servers are currently running PHP 8.2:
As of 2025-10-06, the BGA upgrade to PHP 8.8 is '''complete'''. Your game can now use PHP 8.4-specific features. 🎉
* <b>PHP 8 gameservers in Studio:</b> 2
* <b>PHP 8 gameservers in Production:</b> 5, 7, 8, 12
 
== Control your game's PHP version ==
 
In studio, you can switch between PHP 7.4 and PHP 8.2 using the [https://studio.boardgamearena.com/studio Managed Game] page. You can also change the gameserver portion of the URL between "/1" and "/2" (although this doesn't test your game setup code). For example, https://studio.boardgamearena.com/1/nowboarding?table=575275 is PHP 7 and https://studio.boardgamearena.com/2/nowboarding?table=575275 is PHP 8.
 
In production, you can add the <b>PHP8</b> tag using the [https://boardgamearena.com/controlpanelgames Game Metadata Manager] page. This allows (but does not guarantee) new real-time tables for your game to be created on one of the PHP 8 servers. All turn-based tables continue to run on the PHP 7 servers.


== Fix your game's code ==
== Fix your game's code ==
Line 29: Line 20:
=== Static calls to non-static methods ===
=== Static calls to non-static methods ===


See https://php.watch/versions/8.0/non-static-static-call-fatal-error and https://www.php.net/manual/en/language.oop5.basic.php
📖 See https://php.watch/versions/8.0/non-static-static-call-fatal-error and https://www.php.net/manual/en/language.oop5.basic.php


PHP 8 no longer allows non-static class methods to be called statically. This may affect your game if you've created a class which <code>extends APP_GameClass</code> and you call various BGA framework functions statically using <code>self::</code>.
PHP 8 no longer allows non-static class methods to be called statically. This may affect your game if you've created a class which <code>extends APP_DbObject</code> and you call various BGA framework functions statically using <code>self::</code>.


If possible, the simplest change is to replace <code>self::</code> with <code>$this-></code> (which refers to the current instance of your game class). This works if your function is non-static.
If possible, the simplest change is to replace <code>self::</code> with <code>$this-></code> (which refers to the current instance of your game class). This works if your function is non-static.
Line 37: Line 28:
Non-compliant example:
Non-compliant example:


     class NMap extends APP_GameClass {
     class NMap extends APP_DbObject {
         public function getPossibleMoves($playerId) {
         public function getPossibleMoves($playerId) {
             $planeHasNervous = intval(self::getUniqueValueFromDB("SELECT COUNT(1) FROM `pax` WHERE `player_id` = $playerId AND `status` = 'SEAT' AND `vip` = 'NERVOUS'")) > 0;
             $planeHasNervous = intval(self::getUniqueValueFromDB("SELECT COUNT(1) FROM `pax` WHERE `player_id` = $playerId AND `status` = 'SEAT' AND `vip` = 'NERVOUS'")) > 0;
Line 43: Line 34:
Fix:
Fix:


     class NMap extends APP_GameClass {
     class NMap extends APP_DbObject {
         public function getPossibleMoves($playerId) {
         public function getPossibleMoves($playerId) {
             $planeHasNervous = intval($this->getUniqueValueFromDB("SELECT COUNT(1) FROM `pax` WHERE `player_id` = $playerId AND `status` = 'SEAT' AND `vip` = 'NERVOUS'")) > 0;
             $planeHasNervous = intval($this->getUniqueValueFromDB("SELECT COUNT(1) FROM `pax` WHERE `player_id` = $playerId AND `status` = 'SEAT' AND `vip` = 'NERVOUS'")) > 0;
Line 51: Line 42:
Non-compliant example:
Non-compliant example:


     class PlayerMgr extends APP_GameClass {
     class PlayerMgr extends APP_DbObject {
         public static function getMaxScore() {
         public static function getMaxScore() {
             return self::getUniqueValueFromDB("SELECT MAX(player_score) FROM player WHERE player_eliminated = 0 AND player_zombie = 0");
             return self::getUniqueValueFromDB("SELECT MAX(player_score) FROM player WHERE player_eliminated = 0 AND player_zombie = 0");
Line 64: Line 55:
             self::$instance = $this;
             self::$instance = $this;


     class PlayerMgr extends APP_GameClass {
     class PlayerMgr extends APP_DbObject {
         public static function getMaxScore() {
         public static function getMaxScore() {
             return hardback::$instance->getUniqueValueFromDB("SELECT MAX(player_score) FROM player WHERE player_eliminated = 0 AND player_zombie = 0");
             return hardback::$instance->getUniqueValueFromDB("SELECT MAX(player_score) FROM player WHERE player_eliminated = 0 AND player_zombie = 0");
         }
         }

Latest revision as of 09:55, 6 October 2025


Game File Reference



Useful Components

Official

  • Deck: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
  • 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).
  • Stock: a JS component to manage and display a set of game elements displayed at a position.
  • 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-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.

Unofficial



Game Development Process



Guides for Common Topics



Miscellaneous Resources

Starting in 2023-12, BGA began upgrading game servers from PHP 7.4 to PHP 8.2. See https://boardgamearena.com/forum/viewtopic.php?t=33940 for more information.

As of 2024-08-09, the BGA upgrade to PHP 8.2 is complete. Your game can now use PHP 8-specific features. 🎉

As of 2025-10-06, the BGA upgrade to PHP 8.8 is complete. Your game can now use PHP 8.4-specific features. 🎉

Fix your game's code

Here are a few common scenarios that may make your game incompatible with PHP 8 and how to fix them:

implode argument order

📖 See https://www.php.net/manual/en/function.implode.php

The signature of this function is implode(string $separator, array $array): string. PHP 7 accepted the arguments in either order, but PHP 8 requires the string argument first and the array argument second.

Static calls to non-static methods

📖 See https://php.watch/versions/8.0/non-static-static-call-fatal-error and https://www.php.net/manual/en/language.oop5.basic.php

PHP 8 no longer allows non-static class methods to be called statically. This may affect your game if you've created a class which extends APP_DbObject and you call various BGA framework functions statically using self::.

If possible, the simplest change is to replace self:: with $this-> (which refers to the current instance of your game class). This works if your function is non-static.

Non-compliant example:

   class NMap extends APP_DbObject {
       public function getPossibleMoves($playerId) {
           $planeHasNervous = intval(self::getUniqueValueFromDB("SELECT COUNT(1) FROM `pax` WHERE `player_id` = $playerId AND `status` = 'SEAT' AND `vip` = 'NERVOUS'")) > 0;

Fix:

   class NMap extends APP_DbObject {
       public function getPossibleMoves($playerId) {
           $planeHasNervous = intval($this->getUniqueValueFromDB("SELECT COUNT(1) FROM `pax` WHERE `player_id` = $playerId AND `status` = 'SEAT' AND `vip` = 'NERVOUS'")) > 0;

Otherwise, if your own function is static and $this-> doesn't exist, you can create a static variable like $instance in your game class, populate the variable in your game's constructor, and call the BGA framework functions through this variable.

Non-compliant example:

   class PlayerMgr extends APP_DbObject {
       public static function getMaxScore() {
           return self::getUniqueValueFromDB("SELECT MAX(player_score) FROM player WHERE player_eliminated = 0 AND player_zombie = 0");
       }

Fix:

   class hardback extends Table {
       public static $instance = null;
       function __construct() {
           parent::__construct();
           self::$instance = $this;
   class PlayerMgr extends APP_DbObject {
       public static function getMaxScore() {
           return hardback::$instance->getUniqueValueFromDB("SELECT MAX(player_score) FROM player WHERE player_eliminated = 0 AND player_zombie = 0");
       }