After reading the comments on the question, my take on the answer is this:
Traits allow the extending of a class without it being part of the class hierarchy. There's no need for something like class Book extends Loggable
, as Book itself is not a Loggable, we just want the Loggable functionality. The functionality within the Loggable could be stuffed in a trait, therefore being able to use the Loggable methods within Book as though you were extending from it.
The advantage of using traits above the use of static methods within classes (or namespaced functions) is that the trait has access to the full class scope, also private members.
The downside of using static functions instead of traits, is tight coupling (dependencies) between the classes, which hurts reusability and can hurt unit testing (for instance when using mock services). Dependencies should be injected at runtime, which indeed increases the effort of instantiating a class/method, but allow better flexibility over the full app. This was a new insight for me.