Thinking about it... in #PHP, why are
traits even different things?
Everything you can do with an
This is functionally the same as defining an
abstract public function in a trait.
This is functionally the same as a trait
use-ing another trait.
This is functionally the same as
use-ing a trait that consists entirely of abstract public functions.
This is the one thing a trait cannot do -- but I don't understand why it was done that way.
Note: this seems related to my trait implements wishlist item from earlier. At first I thought that they might be in conflict, but on looking at the syntax in more depth, I don't see how. A trait that uses/extends another trait is also declaring abstract functions in that trait as an implementation requirement.
Putting both of these suggestions together would both simplify the language and make it more powerful, I'd think.
#PHP experts: is there any non-destructive way to tell if a variable contains a reference rather than a literal value?
I keep forgetting to include the keyword
function when declaring functions in #PHP. Does this mean my brain is pining for C++ or something? 🧠
There needs to be a companion to the
final keyword in #PHP.
Background: The "final" keyword indicates that a method cannot be overridden in a child class.
Wish: There needs to be a
first keyword to prevent accidentally creating a method ancestor which might get completely bypassed because a descendant doesn't call
parent::[method] because it doesn't expect one to exist.
Either that, or a way to allow calls to
parent::[method]() even when there's no method ancestor.
...or else a way to define a method such that each generation gets called automatically -- except that takes away sequencing control, which would cause problems.
You can make #PHP throw an error if a function is called without expected arguments, but not if a function is called with more arguments than expected.
I think maybe #PHP8 fixes this by allowing "void" as an argument type? I don't yet have a system with PHP8 on it, though, so I don't actually know.
If it doesn't, then this is a #softwareGripe.
I think I've figured out one of the problems I'm running into with traits in #PHP.
The canonical usage of a trait is to define a set of behaviors that work together -- a feature that classes can use, basically.
That often requires initializing some stuff within the trait.
If it's just a matter of setting initial values for member-variables, you can do that when those members are declared... but if it involves picking up information from the host-object , then some code needs to be executed before trying to access any of the trait's functionality.
There are a couple of ways to handle this.
A. The trait can declare a constructor, if it knows enough about the potential host classes to do that gracefully (i.e. without interfering with their construction processes) to execute the initialization code.
B. The base class can define an initialization event (I usually define
function OnCreate() : void) for the trait to implement.
C. The trait can check itself for initialization every time any of its methods are called. (This probably works, but hurts my optimizing-squirrel's soul.)
It starts to get tricky if the host-class also needs to do some initialization, because if
class A uses
trait B and they both define function X(), A::X() can't call parent::X() to access B::X()... but there's a syntax for hosting traits which allows their functions to be aliased to another name when hosted, so you could rename B::X() to B::Trait_X(), and then call that.
...which means that whenever you host the trait, you also have to remember to do the aliasing.
The real problem is when I have a set of traits that all get hosted together.
...and they all need initialization.
So say you have
class A which needs
D, each of which has its own
OnCreate() function that needs calling.
I guess it can be done by aliasing
OnEvent() in each one (
OnEventD()), then explicitly calling those each individually from
A::OnEvent()... but that seems messy and easy to get wrong. There's too much stuff that needs to be done manually.
I guess it can be slightly tidied by declaring
OnEvent() under a different name in each trait -- basically pre-aliasing them -- so the only messy part is that you have to explicitly call the aliased OnEvent()s from
A::OnEvent()... but it still seems like this kind of breaks how class-inheritance is supposed to work.
You should be able to just use a trait, and not worry about initialization.
I should be able to just call
A::OnEvent() to get
D::OnEvent(), which would then call
parent::OnEvent() to get
C::OnEvent()... and so on, up to
parent::OnEvent() to get A's parent class's
A way to kluge that desired behavior, I suppose, would be to have a series of intermediate classes:
class AB hosts
class AC hosts
trait C and
class AD hosts
trait D and
class A extends AD
...in which case calling up the parent chain would work as needed.... but again, that's kind of messy: more code to manually include.
I'm not sure which of those last two solutions creates the least technical debt, and I keep feeling like there's got to be a better solution, even without changing how PHP handles traits.
I guess I'll try some things and see how deep a pit I end up digging myself into...
(is this a #softwareGripe, or something else?)
used a trait. If class A has
use B;, then A is hosting B. Similarly, a "host object" is an instantiation of a class that is hosting a trait.
Fatal error: Trait method FieldCollective has not been applied, because there are collisions with other trait methods on greenmine\workferret\cCommonTable in /home/htnet/site/git/greenmine/dropins/WorkFerret/lib/base.php on line 25
Ya know, #PHP, it would be reeeally helpful if you could tell me what methods are colliding, rather than just mentioning one that isn't.
a brief review
✅ SSD support in PHP (Xdebug module)
✅ SSD support in KDevelop (native)
🚫 instructions on how to activate SSD in KDevelop when working with an interpreted language
🚫 any information at all about how to use KDevelop with PHP, other than "there's a plug-in!" (which I have installed)
Mood: trying to use #PHP
traits to self-impose coding conventions
Not sure if it's a good mood.
#softwareGripe It's annoying that in #PHP I can't declare an
interface with very general terms (e.g. a class that handles some kind of variable, type unspecified, in various ways) and then implement it with more specific terms (e.g. this class handles strings in the same ways, this other class handles objects of a certain class family...).
Apparently you can do
[ ...code... ]
[ ...code... ]
but you can't do
[ ...code... ]
[ ...code... ]
...or at least not in PHP 7.4.
This isn't mentioned or explained in the documentation, as far as I can tell.
It also leaves open the question of how to turn on strict typing globally. #php
It's annoying the way inheriting traits in #PHP doesn't confer parentage.
trait A which has
function X() which is re-implemented in
B can't call
parent::X(); you have to alias it in the
use statement and call the alias... or else split off the functionality you want them both to have in common into a separate function, and call that from each version of
(The latter technique is kind of good, in a way, since it forces you to be more descriptive and compartmental in your functions... but then why not make class inheritance work the same way?)
#softwareGripe (albeit minor)
The social network of the future: No ads, no corporate surveillance, ethical design, and decentralization! Own your data with Mastodon!