phpdeprecatedarrayaccessphp-8.1

php 8.1 - return type deprecated in older script


Trying to update to php 8.1 and noticed this deprecated notice showing up in the error logs I'd like to take care of.

[14-Feb-2022 14:48:25 UTC] PHP Deprecated: Return type of TLDExtractResult::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/example/public_html/assets/tldextract/tldextract.php on line 299

I was able to suppress the warning, but would actually like to update the script so there are no issues in the future.

//public function offsetExists($offset) {
//  return array_key_exists($offset, $this->fields);
//}

#[\ReturnTypeWillChange]
public function offsetExists(mixed $offset) {
    return array_key_exists($offset, $this->fields);
}

Here is the section of code in question :

class TLDExtractResult implements ArrayAccess {
    private $fields;

    public function __construct($subdomain, $domain, $tld) {
        $this->fields = array(
            'subdomain' => $subdomain,
            'domain'    => $domain,
            'tld'       => $tld,
        );
    }

    public function __get($name) {
        if ( array_key_exists($name, $this->fields) ) {
            return $this->fields[$name];
        }
        throw new OutOfRangeException(sprintf('Unknown field "%s"', $name));
    }

    public function __isset($name) {
        return array_key_exists($name, $this->fields);
    }

    public function __set($name, $value) {
        throw new LogicException('Can\'t modify an immutable object.');
    }

    public function __toString() {
        return sprintf('%s(subdomain=\'%s\', domain=\'%s\', tld=\'%s\')', __CLASS__, $this->subdomain, $this->domain, $this->tld);
    }

    //public function offsetExists($offset) {
    //  return array_key_exists($offset, $this->fields);
    //}
    
    #[\ReturnTypeWillChange]
    public function offsetExists(mixed $offset) {
        return array_key_exists($offset, $this->fields);
    }

    //public function offsetGet($offset) {
    //  return $this->__get($offset);
    //}

    #[\ReturnTypeWillChange]
    public function offsetGet(mixed $offset) {
        return $this->__get($offset);
    }

    //public function offsetSet($offset, $value) {
    //  throw new LogicException(sprintf('Can\'t modify an immutable object. You tried to set "%s".', $offset));
    //}

    #[\ReturnTypeWillChange]
    public function offsetSet(mixed $offset, $value) {
        throw new LogicException(sprintf('Can\'t modify an immutable object. You tried to set "%s".', $offset));
    }

    //public function offsetUnset($offset) {
    //  throw new LogicException(sprintf('Can\'t modify an immutable object. You tried to unset "%s".', $offset));
    //}

    #[\ReturnTypeWillChange]
    public function offsetUnset(mixed $offset) {
        throw new LogicException(sprintf('Can\'t modify an immutable object. You tried to unset "%s".', $offset));
    }

    /**
     * Get the domain name components as a native PHP array.
     * The returned array will contain these keys: 'subdomain', 'domain' and 'tld'.
     *
     * @return array
     */
    public function toArray() {
        return $this->fields;
    }
}

What exactly does php 8.1 not like here? This is a little above what I typically do with php and not exactly sure of the issue. It sounds like a specific return type needs specified?


Solution

  • Yes, you can specify return types that match those indicated for the various methods of the ArrayAccess interface as shown in the manual. For example, like this for the specific method in the deprecation message in your question:

    public function offsetExists(mixed $offset): bool {
        return array_key_exists($offset, $this->fields);
    }