PHP wishlist

From Woozle Writes Code
Jump to navigation Jump to search

These are features I wish PHP would add. As far as I know, they are not available on PHP 8, though I have only used up through 7.4 as of this writing.

Trait wishlist

  • Where class A uses trait B, where both define function C(), A::C() should be able to call parent::C() to refer to B::C() if it exists.
  • You should be able to define function parameters as traits, the same way you can do for classes or interfaces.
  • Traits should be able to implement one or more interfaces, the way classes can.
    • Traits and interfaces are kind of a perfect match for each other, since they're both independent of class-hierarchy, and it's kind of odd that this isn't being leveraged more.

Virtual fx chaining

Current Behavior

If you have class B which extends class A and they both define function C(), and you call C() in an object of class B, you just get B::C(). The class-structure may be designed, however, in such a way that it's necessary to also run code in the parent class, where B is adding functionality rather than replacing it.

The standard way of accomplishing this is for B::C() to call parent::C() at some point. However it can often be difficult to know whether there is a parent C(), especially where B isn't immediately descended from A (e.g. B extends A3 which extends A2 which extends A1 which extends A) or where there are traits being introduced at any point.

The best way I've found for dealing with that is for the class structure to define a stub C() which does nothing (function C() {}), and to have a rule that all other implementations of C() must call parent::C(). This, however, requires remembering the rule, and also seems a little wasteful in that there may be a lot of calls to an empty function that is really just a placeholder.

Proposal

To fix this, I propose a set of keywords for use in function definitions. This keyword will set the default behavior of offspring functions, and overrides any default if used in offspring functions. Using A, B, and C() as above, this is what will happen if C() is called in an object of class B:

  • replace (or instead): B::C() replaces A::C(), so only B::C() will execute.
    • This is the current behavior.
  • before: A::C() will execute, then B::C().
  • after: B::C() will execute, followed automatically by A::C().