How to override trait function and call it from the overridden function?

Viewed 133013

Scenario:

trait A {
    function calc($v) {
        return $v+1;
    }
}

class MyClass {
    use A;

    function calc($v) {
        $v++;
        return A::calc($v);
    }
}

print (new MyClass())->calc(2); // should print 4

This code doesn't work, and I cannot find a way to call a trait function like it was inherited. I tried calling self::calc($v), static::calc($v), parent::calc($v), A::calc($v) and the following:

trait A {
    function calc($v) {
        return $v+1;
    }
}

class MyClass {
    use A {
        calc as traitcalc;
    }

    function calc($v) {
        $v++;
        return traitcalc($v);
    }
}

Nothing works.

Is there a way to make it work or must I override completely the trait function which is much more complex than this :)

6 Answers

Another variation: Define two functions in the trait, a protected one that performs the actual task, and a public one which in turn calls the protected one.

This just saves classes from having to mess with the 'use' statement if they want to override the function, since they can still call the protected function internally.

trait A {
    protected function traitcalc($v) {
        return $v+1;
    }

    function calc($v) {
        return $this->traitcalc($v);
    }
}

class MyClass {
    use A;

    function calc($v) {
        $v++;
        return $this->traitcalc($v);
    }
}

class MyOtherClass {
    use A;
}


print (new MyClass())->calc(2); // will print 4

print (new MyOtherClass())->calc(2); // will print 3

This is basically a hark, but if the trait is part of your code and not a package, you can have a function that checks if another function exists and return it instead of the current one.

trait A {
    function calc($v) {
        if(method_exists($this, 'calcClass'))
        {
          $this->calcClass($v)
        }
        return $v+1;
    }
}

class MyClass {
    use A;

    function calcClass($v) {
        return $v+2;;
    }
}

print (new MyClass())->calc(2); // prints 4

I hope this helps.

Related