Class method signatures don’t match?

I wrote some code to use a PHP library (for a product called Checkfront, but that’s not important). The library defines a class that has an abstract method:

abstract protected function store($data);

and in my code I subclass it as

Read More
final protected function store($data=array()) {

In my standalone version of the code, that works fine using the implementation from some example code:

/* DUMMY Data store.  This sample stores oauth tokens in a text file...
 * This is NOT reccomened in production.  Ideally, this would be in an encryped 
 * database or other secure source.  Never expose the client_secret or access / refresh
 * tokens.
 *
 * store() is called from the parent::CheckfrontAPI when fetching or setting access tokens.  
 *
 * When an array is passed, the store should save and return the access tokens.
 * When no array is passed, it should fetch and return the stored access tokens.
 *
 * param array $data ( access_token, refresh_token, expire_token )
 * return array
 */
final protected function store($data=array()) {
    $tmp_file = sys_get_temp_dir() . DIRECTORY_SEPARATOR. $this->tmp_file;
    if(count($data)  ) {
        file_put_contents($tmp_file,json_encode($data,true));
    } elseif(is_file($tmp_file)) {
        $data = json_decode(trim(file_get_contents($tmp_file)),true);
    }
    return $data;
}

. But when I tried to use it in a WordPress plugin I got errors. Here’s the function in WordPress land:

final protected function store($data=array()) {
    global $wpdb;
    if (count($data)) {
        $query = "
            INSERT INTO {$wpdb->prefix}pt_store (k, v)
            VALUES      (%s, %s)
            ON DUPLICATE KEY UPDATE v=values(v)";
        foreach ($data as $k => $v) {
            $wpdb->query($wpdb->prepare($query, $k, $v));
        }
    } else {
        $data = $wpdb->get_results("
            SELECT  (k, v)
            FROM    {$wpdb->prefix}pt_store", ARRAY_A);
    }
    return $data;
}

But when I try to activate the plugin, it gives me the error:

Fatal error: Declaration of Checkfront::store() must be compatible with that of CheckfrontAPI::store() in /hsphere/local/home/[blah]/[blah].ixtrial.com/wordpress/wp-content/plugins/pt-checkfront/pt-checkfront.php on line 15

The declarations look the same to me, so what’s wrong? (keep in mind that this is my first time writing PHP so don’t overlook the possibility that I’m being stupid here.)

Related posts

Leave a Reply

3 comments

  1. Under PHP 5.2 and earlier, an optional parameter will cause the signature to be considered different. You can’t really work around that in a nice way, so try upgrading PHP.

    ’Course, it’s possible that you don’t need the default value. In that case, take it out! You can also pass null and do this:

    final protected function store($data) {
        if ($data === null) $data = array();
    
  2. To avoid this error you need to ensure that the method signature is identical in both classes, including optional arguments.

    Alter the abstract class to allow for the default array

    abstract protected function store($data = array());
    

    The PHP manual states

    The signatures of the methods must match, i.e. the type hints and the number of required arguments must be the same. For example, if the child class defines an optional argument, where the abstract method’s signature does not, there is no conflict in the signature.