Bill in Kansas City
Bill in Kansas City

Reputation: 360

PHP: Dealing with function case-insensitivity

I have a situation where there are similar functions in different classes, let's call them "Execute" and "execute."

class oldVersion {
    public function Execute($x){
        echo 'This does the same thing as newVersion->execute(1)';
        echo 'but the class contains a lot of garbage that PHP7 doesn\'t like.';
        echo 'and the app dies if it\'s included';
    }
}

class newVersion {
    public function execute($x, $y = 0, $z = 0){
        if($y == 1){
            echo 'do thing one';
        } else {
            echo 'do thing zero';
        }
        return 'bar';
    }
}
$obj1 = new oldVersion();
$obj1->Execute('foo');

$obj2 = new newVersion();
$obj2->execute('bar', 1);

The class oldVersion has a lot of things wrong with it and won't function at all under PHP7, so what I'd really love to be able to do is move Execute into newVersion and do this:

class oldVersion_deprecated {
    // no longer included so PHP7 doesn't break
}

class newVersion {
    public function Execute($x){
        return $this->execute($x, 1);
    }
    public function execute($x, $y = 0, $z = 0){
        if($y == 1){
            echo 'do thing one';
        } else {
            echo 'do thing two';
        }
        return 'bar';
    }
}

$obj1 = new newVersion();
$obj1->Execute('foo');

$obj2 = new newVersion();
$obj2->execute('bar', 1);

But naturally I get

FATAL ERROR: cannot redefine execute

Is there a fancy workaround, or am I stuck finding and rewriting every call?

Upvotes: 1

Views: 62

Answers (2)

iainn
iainn

Reputation: 17417

It's a bit messy, and I wouldn't normally recommend it, but you can simulate case-sensitive methods with PHP's "magic" __call method. This gets called whenever a method can't be found in the given class. You can then check the supplied method name, and run whatever logic is appropriate.

class Foo
{
    public function __call($name, $args)
    {
        switch ($name) {
            case 'Execute':
                return $this->oldExecute(...$args);
            case 'execute':
                return $this->newExecute(...$args);
        }
    }

    private function oldExecute($x)
    {
        echo 'Running old function with arg: ', $x, PHP_EOL;
    }

    private function newExecute($x, $y, $z)
    {
        echo 'Running new function with args: ', implode(',', [$x, $y, $z]), PHP_EOL;
    }
}

See https://eval.in/926262

Upvotes: 1

Joshua
Joshua

Reputation: 29

Just remove the first execute function that calls the "real" one. Functions are case insensitive so you dont have to have two

class newVersion {
 public function execute($x, $y = 0, $z = 0){
    if($y == 1){
        echo 'do thing one';
    } else {
        echo 'do thing two';
    }
    return 'bar';
   }
 }
 /* All the same */
 echo newv->Execute('foo');
 echo newv->ExEcUTe('foo');  
 echo newv->execute('bar', 1);

Upvotes: 1

Related Questions