Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP - Using empty interfaces to determine logic

Tags:

oop

php

interface

There are a few places where I've executed logic based on what interfaces a class implements - is there any reason that this may or may not be wrong? (It feels dirty)

The reasoning behind doing this was so you don't have to add any class properties or methods to determine these things, basically in the class definition you can spell out explicitly what it could / could not do.

One use case is ajax calls, some require you to be logged in and some don't:

class ajax_ads extends ajax_controller implements no_login {

}

Also, there are no methods in the interface, it is used soley for this purpose.

interface no_login {}

Then in the base controller:

$controller = controller::factory()
if( !($controller instanceof no_login) && !$controller->LoggedIn()){
    return $controller->redirect(/*login page*/); 
}

It seems lightweight and simple to use instance_of and it works fine, but again it feels like I'm totally abusing the purpose of the interface.

So I ask, is using an interface to determine logic a bad idea, bad oop, or 'okay'?

like image 577
aknosis Avatar asked Oct 12 '12 22:10

aknosis


2 Answers

When you need an if or a switch to determine the state an object should be, it's usually a good sign you are in need of polymorphism.

In your case, there should be one abstract class: Ajax_Ads, and two extending classes: No_Login_Ajax_Ads extends Ajax_Ads, and Login_Ajax_Ads extends Ajax_Ads. And you instantiate the one you require based on the state of the program, this could be done with a factory.

For more information, watch the following lecture: The Clean Code Talks -- Inheritance, Polymorphism, & Testing

like image 140
Madara's Ghost Avatar answered Nov 15 '22 15:11

Madara's Ghost


The accepted answer is from 2012. Laravel uses the empty interface pattern today so I would say it is OK.

<?php

namespace Illuminate\Contracts\Queue;

interface ShouldQueue
{
    //
}

https://github.com/laravel/framework/blob/8.x/src/Illuminate/Contracts/Queue/ShouldQueue.php

protected function sendMailable(MailableContract $mailable)
{
    return $mailable instanceof ShouldQueue
                    ? $mailable->mailer($this->name)->queue($this->queue)
                    : $mailable->mailer($this->name)->send($this);
}

https://github.com/laravel/framework/blob/8.x/src/Illuminate/Mail/Mailer.php#L300 (Lines 300-305)

like image 38
chiliNUT Avatar answered Nov 15 '22 16:11

chiliNUT