PHP compatibility - markhowellsmead/helpers GitHub Wiki
Updates to PHP 8.3
The following changes need to be made on older Say Hello projects which use the singleton approach for class loading.
Type matching
Ensure that all class variables are correctly type-matched.
/**
* The instance of the object, used for singleton check.
*/
private static ?Theme $instance = null;
Dynamic property creation
Dynamic property creation on PHP classes is deprecated. The dynamically-loaded classes need to be assigned to a container attribute in the main Theme class.
/**
* Container for class groups
*
* @var array
*/
private array $containers = [];
Getter and setter methods
/**
* Magic getter to access the different class instances in the containers, e.g. $this->PostType->Films.
*
* @return mixed
*/
public function __get(string $name): mixed
{
if (!isset($this->containers[$name])) {
$this->containers[$name] = new stdClass();
}
return $this->containers[$name];
}
/**
* Magic setter to set the different class instances in the containers, e.g. $this->PostType->Films = new Films();
*
* @param string $name
* @param mixed $value
*/
public function __set(string $name, mixed $value): void
{
$this->containers[$name] = $value;
}
Load and initialise classes
The exact variables defined by getInstance may vary from project to project.
Theme
/**
* The singleton instance of the Theme object
*
* @var object
*/
private static ?Theme $instance = null;
/**
* Creates an instance if one isn't already available,
* then return the current instance.
*
* @return object The class instance.
*/
public static function getInstance()
{
if (!self::$instance instanceof Theme) {
self::$instance = new Theme;
self::$instance->name = self::$instance->theme->name;
self::$instance->version = self::$instance->theme->version;
self::$instance->prefix = 'sht';
self::$instance->error = 'An unexpected error occurred.';
self::$instance->debug = defined('WP_DEBUG') && WP_DEBUG;
}
return self::$instance;
}
Plugin
use WP_Filesystem_Base;
/**
* The singleton instance of the Plugin object
*
* @var object
*/
private static ?Plugin $instance = null;
…
/**
* Creates an instance if one isn't already available,
* then return the current instance.
*
* @param string $file The file from which the class is being instantiated.
* @return Plugin The class instance.
*/
public static function getInstance($file): Plugin
{
if (!self::$instance instanceof Plugin) {
self::$instance = new Plugin;
if (!function_exists('get_plugin_data')) {
$filesystem = new WP_Filesystem_Base();
include_once $filesystem->abspath() . 'wp-admin/includes/plugin.php';
}
$data = get_plugin_data($file, false, false);
self::$instance->name = $data['Name'];
self::$instance->prefix = 'shp_flugbasis_batchcreate';
self::$instance->version = $data['Version'];
self::$instance->file = $file;
self::$instance->files_path = plugin_dir_path(self::$instance->file);
self::$instance->files_url = plugin_dir_url(self::$instance->file);
self::$instance->run();
}
return self::$instance;
}
/**
* Loads and initializes the provided classes.
*
* @param $classes
*/
private function loadClasses(array $classes): void
{
$instance = self::getInstance();
foreach ($classes as $class) {
$class_parts = explode('\\', $class);
$class_short = end($class_parts);
$class_set = $class_parts[count($class_parts) - 2] ?? 'Global';
// Ensure the parent container exists as an array.
if (!isset($instance->containers[$class_set])) {
$instance->containers[$class_set] = new stdClass();
}
// Prevent duplicate class assignments.
if (property_exists($instance->containers[$class_set], $class_short)) {
error_log(sprintf(
'Duplicate class "%s" detected in "%s". Skipping assignment.',
$class_short,
$class_set
));
continue;
}
// Instantiate and store the class.
$instance->containers[$class_set]->{$class_short} = new $class();
// Run the class if it has a `run()` method.
if (method_exists($instance->containers[$class_set]->{$class_short}, 'run')) {
$instance->containers[$class_set]->{$class_short}->run();
}
}
}