[PHP-DEV] Optional interfaces

Hey all,

If you try to implement an interface that does not exist, you get the ‘Interface “%s” not found’ error. Usually that’s useful as it points to a code error.

However, sometimes we want our code to be compatible with an optional library. For example, my Expression class might be compatible with some ORM, but it would also usable without it or with another ORM. This can already be accomplished, but the solutions seems very workaroundish: https://stackoverflow.com/questions/57996429/implements-interface-only-if-exists

Maybe the PHP itself should allow marking some interfaces as optional — such that they are discarded from the list if the interface class does not exist? Here’s one way the syntax could look like:

class Expression implements MyInterface, ?OptionalInterface {}

interface EventDispatcherInterface extends ?PsrEventDispatcherInterface {}

BR,

Juris

On Sat, Nov 16, 2024, at 00:34, Juris Evertovskis wrote:

Hey all,

If you try to implement an interface that does not exist, you get the ‘Interface “%s” not found’ error. Usually that’s useful as it points to a code error.

However, sometimes we want our code to be compatible with an optional library. For example, my Expression class might be compatible with some ORM, but it would also usable without it or with another ORM. This can already be accomplished, but the solutions seems very workaroundish: https://stackoverflow.com/questions/57996429/implements-interface-only-if-exists

Maybe the PHP itself should allow marking some interfaces as optional — such that they are discarded from the list if the interface class does not exist? Here’s one way the syntax could look like:

class Expression implements MyInterface, ?OptionalInterface {}

interface EventDispatcherInterface extends ?PsrEventDispatcherInterface {}

BR,

Juris

Hey Juris,

Is there some reason you cannot do this:

https://3v4l.org/hF1vr

— Rob

On 15 Nov 2024, at 20:42, Rob Landers rob@bottled.codes wrote:

On Sat, Nov 16, 2024, at 00:34, Juris Evertovskis wrote:

Hey all,

If you try to implement an interface that does not exist, you get the ‘Interface “%s” not found’ error. Usually that’s useful as it points to a code error.

However, sometimes we want our code to be compatible with an optional library. For example, my Expression class might be compatible with some ORM, but it would also usable without it or with another ORM. This can already be accomplished, but the solutions seems very workaroundish: https://stackoverflow.com/questions/57996429/implements-interface-only-if-exists

Maybe the PHP itself should allow marking some interfaces as optional — such that they are discarded from the list if the interface class does not exist? Here’s one way the syntax could look like:

class Expression implements MyInterface, ?OptionalInterface {}

interface EventDispatcherInterface extends ?PsrEventDispatcherInterface {}

BR,

Juris

Hey Juris,

Is there some reason you cannot do this:

https://3v4l.org/hF1vr

— Rob

That seems to match what he shared on SO link?

I think I opened this email with a strong negative feeling towards what would be optional interface, but to be honest a syntax sugar where implements ?MyInterface becomes something pretty close to what Rob shared doesn’t sound bad, it’s just convenience. Unfortunately PHP is not keen on being open to those.

Overall, I dig it.

Is there some reason you cannot do this:

https://3v4l.org/hF1vr

Unless I’m missing something, you can’t patch-define a namespaced OptionalInterface that easily.

Anyway, I was not implying this is something impossible to accomplish. My point is that it would be beneficial to have syntax for expressing “if your app has this interface, our class implements it”.

Juris

On Sat, Nov 16, 2024, at 01:27, Marco Aurélio Deleu wrote:

On 15 Nov 2024, at 20:42, Rob Landers rob@bottled.codes wrote:

On Sat, Nov 16, 2024, at 00:34, Juris Evertovskis wrote:

Hey all,

If you try to implement an interface that does not exist, you get the ‘Interface “%s” not found’ error. Usually that’s useful as it points to a code error.

However, sometimes we want our code to be compatible with an optional library. For example, my Expression class might be compatible with some ORM, but it would also usable without it or with another ORM. This can already be accomplished, but the solutions seems very workaroundish: https://stackoverflow.com/questions/57996429/implements-interface-only-if-exists

Maybe the PHP itself should allow marking some interfaces as optional — such that they are discarded from the list if the interface class does not exist? Here’s one way the syntax could look like:

class Expression implements MyInterface, ?OptionalInterface {}

interface EventDispatcherInterface extends ?PsrEventDispatcherInterface {}

BR,

Juris

Hey Juris,

Is there some reason you cannot do this:

https://3v4l.org/hF1vr

— Rob

That seems to match what he shared on SO link?

Thanks Marco,

I don’t visit stackoverflow because I loath “features locked behind internet points”. Thanks for letting me know what is behind the link!

I think I opened this email with a strong negative feeling towards what would be optional interface, but to be honest a syntax sugar where implements ?MyInterface becomes something pretty close to what Rob shared doesn’t sound bad, it’s just convenience. Unfortunately PHP is not keen on being open to those.

Overall, I dig it.

I maintain a PHP SDK that needs to be compatible with Symfony and Laravel and any other framework. The shenanigans are all bound in one file that I very rarely touch. So, I do kinda like the idea of having optional interfaces, but I feel like it is rather niche. As an application developer, I can’t think of one time I’ve ever needed this.

However, the single biggest advantage comes from IDEs that can somehow show that there is an optional interface on a type. I think that would be the most useful bit to come from this, honestly. It also prevents IDEs or static analysis from giving a warning that there are multiple definitions of an interface if you have the appropriate libraries installed.

It’s also rather simple to implement, so I think it is worth pursuing, IMHO.

— Rob

On Sat, Nov 16, 2024, at 10:02, Juris Evertovskis wrote:

Is there some reason you cannot do this:

https://3v4l.org/hF1vr

Unless I’m missing something, you can’t patch-define a namespaced OptionalInterface that easily.

Anyway, I was not implying this is something impossible to accomplish. My point is that it would be beneficial to have syntax for expressing “if your app has this interface, our class implements it”.

Juris

Yeah, I get it now (see my reply to Marco).

Even with namespaces, it is pretty straightforward, though: https://3v4l.org/dmXoB

— Rob

On Sat, 16 November 2024 at 13:42 Rob Landers rob@bottled.codes wrote:

On Sat, Nov 16, 2024, at 10:02, Juris Evertovskis wrote:

Is there some reason you cannot do this:

https://3v4l.org/hF1vr

Unless I’m missing something, you can’t patch-define a namespaced OptionalInterface that easily.

Anyway, I was not implying this is something impossible to accomplish. My point is that it would be beneficial to have syntax for expressing “if your app has this interface, our class implements it”.

Juris

Yeah, I get it now (see my reply to Marco).

Even with namespaces, it is pretty straightforward, though: https://3v4l.org/dmXoB

— Rob

This is a nice solution.

However, interface_exists should be used for interfaces.


Valentin

On Sat, Nov 16, 2024, at 12:43, Valentin Udaltsov wrote:

On Sat, 16 November 2024 at 13:42 Rob Landers rob@bottled.codes wrote:

On Sat, Nov 16, 2024, at 10:02, Juris Evertovskis wrote:

Is there some reason you cannot do this:

https://3v4l.org/hF1vr

Unless I’m missing something, you can’t patch-define a namespaced OptionalInterface that easily.

Anyway, I was not implying this is something impossible to accomplish. My point is that it would be beneficial to have syntax for expressing “if your app has this interface, our class implements it”.

Juris

Yeah, I get it now (see my reply to Marco).

Even with namespaces, it is pretty straightforward, though: https://3v4l.org/dmXoB

— Rob

This is a nice solution.

However, interface_exists should be used for interfaces.

Valentin

Actually, you’d probably want to check for both (as well as traits) for a better developer experience.

For example, using interface_exists results in the error “Cannot declare interface, because the name is already in use” if a class with the same name is used instead of an interface. This is a nonsensical error message because the library is not responsible for declaring it.

Instead, you’d want the error message to be more actionable: “cannot implement class – it is not an interface”

— Rob