Skip to content

Extended the Widget class is broken from PHP 8.1 onwards #1261

Description

@c0ntax

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"
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions