I'd like to understand why discussions of Traits never seem to include comparison with Require, but always compare with inheritance.
It's my understanding that Require is essentially the same as a copy/paste at runtime, and Require_Once ensures the code is not repeated. Traits are also often referred to as nearly identical to copy/paste.
That said, Require and Include can be used in conditional logic, so in some circumstances they can be a better alternative to a Trait. And Traits have polymorhic and other desirable features that are not available with strict copying of code. For example, the ability to abstract a function in the trait and then optionally override in a container class.
Both of these "code inclusion/import" features have similar behavior when it comes to scope, like with $this.
But a distinct difference is that Include/Require code drops to HTML processing by default, and <?php is optional depending on the context, where with a Trait we know the code must be PHP and must be prefixed with <?php.
So to me, a Trait is more of a higher-level OOP tool while Require is a language-level directive that is not aware of OOP details. And yet, in many cases it seems it would be just as easy and useful to Require code rather than use a Trait to contain the same code.
I'm hoping someone can provide clear-cut examples where one would be chosen over the other, to make it more obvious which one should be used. There are details beyond those that I've cited. Am I already on the right path to making these choices? Is it simpler than this, or more complex? A comparison table would be ideal.
You are correct in that traits are OOP, and require is not, and while I can see how you got there (i.e. both include code) they really aren’t designed for the same use cases at all.
While require does in fact pull in code, I use it almost exclusively like I use an ‘include’ in C++ (my company uses both extensively) – to pull in lists of common defines, and to pull in the parent class for a child. A trait, would not do either of those things. For example, you have to require/include the trait file in order to use it in the desired class def.
A trait is PHP’s way of getting around not having multiple inheritance (as in C++) or a mixin (Java’s ‘fix’ for no multiple inheritance). A trait is typically paired with an interface which is included in the classses that are consumers of the trait.
I’ve used traits extensively (there are strong arguments for and against their use, but I like them), especially with reflection, to provide common behaviours within, and most especially, across class families. For example, in a simple case, I’ve used a trait to provide ‘to html’ functionality for disparate classes – a DB mirror (RDBMS interface), a flat-file mirror that I didn’t wish to force having a common base class. I see no reasonable OOP way to do that with a require. I think sprinkling requires with conditional logic in the body of a class to provide methods, though I guess you could, would be very bad form. If I were interviewing such a programmer I would probably stop at that point.
TLDR – Traits are the PHP OOP method (no pun intended) to provide common methods across classes to avoid artificial common ancestors. Requires pull in defines and parent classes.