To me, that kind of architecture doesn't look like a Clean Architecture. As you have pointed out, it has many drawbacks, and requires some "work arounds". Something that requires work arounds smells bad to me.
I have been using the Command pattern for most of my Use Cases, and so far it has proven to be quite flexible and easy to use.
The basic layout is something like this:
interface Command{
void execute();
}
class SomeUseCase{
private Request request;
private Receiver receiver;
public SomeUseCase(Request request, Receiver receiver){
this.request = request;
this.receiver = receiver;
}
public void execute(){
doSomethingThatReadsTheRequestAndSendsMessagesToReceiver();
}
...
}
The main difference is that instead of getting a Response object as a return value from the Command.execute() method, you'll receive the response object(s) through callbacks/messages defined in the Receiver interface. (You can call it Receiver, Callback, Responder, whatever fits best)
This way, you can define the Request and Receiver interfaces inside of each UseCase class, because they are UseCase-specific, and so there is no confusion about which type of Request and Receiver to send into the UseCase constructor.
One interesting advantage of the command pattern for use cases is that you can construct it in a context-sensible place (where the request data is known, for instance), and execute it in a completely context-agnostic place. Works wonders for separation of concerns, and logically, testing. :)
About PHP, I guess the same principles are applicable, with or without type hints, but I'll not make any concrete statements since I haven't seen a line of PHP code for a few years now.
I'm basing this on my experience with this exact pattern in Ruby, which does not offer any kind of type specification. It works just as nicely as in Java.
Hope this was helpful.
Kind regards,
Michel