Extended the Widget class is broken from PHP 8.1 onwards
Opened this issue · 0 comments
Version
- Carbon Fields: 3.6.5
- WordPress: 6.6.2
- PHP: 8.2
Expected Behavior
I should be able to have two different classes that extend the Widget class that use the same names
Actual Behavior
I just upgraded from PHP 7.4 to 8.2 and I'm now having errors thrown when using register_widget() on two classes that both have a field named image
. It gives the error:
Fatal error: Uncaught Exception: Field name "_image" already registered
in /bla/bla/bla/carbon-fields/core/Exception/Incorrect_Syntax_Exception.php on line 22
Which in the callstack is being thrown from:
Carbon_Fields\Widget\Widget::register_field_name()
bla/bla/carbon-fields/core/Widget/Widget.php:212
Comments
The issue is this bit of code here:
public function register_field_name( $name ) {
static $registered_field_names = array();
if ( in_array( $name, $registered_field_names ) ) {
Incorrect_Syntax_Exception::raise( 'Field name "' . $name . '" already registered' );
return false;
}
$registered_field_names[] = $name;
return true;
}
specifically static $registered_field_names = array();
I believe that this functionality changed in PHP 8.1 such that $registered_field_names
now contains all registered field names from that have ever gone through this method instead of being scoped to only the registered field names for the current class.
The following bit of code can be used to show the difference between PHP versions:
class Base {
public function setThing($thing) {
static $things = [];
$things[] = $thing;
var_dump($things);
}
}
class A extends Base {
public function setSomeThing()
{
$this->setThing('1');
}
}
class B extends Base {
public function setSomeThing()
{
$this->setThing('a');
}
}
$a = new A();
$a->setSomeThing();
$b = new B();
$b->setSomeThing();
If you run this using php 7.4 you get the following output:
array(1) {
[0]=>
string(1) "1"
}
array(1) {
[0]=>
string(1) "a"
}
But with 8.2 (I'm assuming 8.1 as well but I haven't had time to test it)
array(1) {
[0] =>
string(1) "1"
}
array(2) {
[0] =>
string(1) "1"
[1] =>
string(1) "a"
}