2

Anyone know if it's possible in PHP to force a class to extend or implement an interface without the child class having to declare it?

Example:

interface Requirements
{
    public function __construct();
    public function kittens();
}

class DingleBerry
{
    public function __construct()
    {
        // yadda yadda yadda    
    }
}

// Example of my initial hope
// of what you could do

$kittens = new DingleBerry implements Requirements;

Obviously that doesn't work, but I need a way of loading in classes that have no predetermined knowledge of the interface requirements but are forced to abide by them.

My overall goal is to check to see if the class implements the Requirements BEFORE its loaded and it's constructor is called.

So I CANNOT use this:

interface Requirements
{
    public function __construct();
    public function kittens();
}

class DingleBerry
{
    public function __construct()
    {
        // DO BAD STUFF (i.e. eat your soul)
    }
}

// Example of what I CANNOT
// do.

$kittens = new DingleBerry;

if( !($kittens instanceof Requirements) )
{
    // eat pizza.    
}

Because then DingleBerry's constructor is called before I can check if it implements the Requirements. Dig?

Jay
  • 195
  • 2
  • 10

2 Answers2

2

You cannot modify an already declared class or interface definition without using a third-party extension (e.g.: runkit).

Runkit has a runkit_class_adopt function that may fulfil that need. Unfortunately I can't test it because the PECL version won't compile on my machine.

For the first part of your question, you can check if a class implements a given interface without instantiating it, and without the Reflection API:

// checks if class Bar implements Foo
if (in_array('Foo', class_implements('Bar'))) {
    $foo = new Bar;
} else {
    throw new Exception('Interface not implemented');
}
netcoder
  • 66,435
  • 19
  • 125
  • 142
  • Note that `class_implements` will try to autoload a class unless you pass `false` as a second param, just like `class_exists` does. – Synchro Jul 29 '13 at 08:52
0

Untested but theoretically this is the API:

<?php
$reflection = new ReflectionClass('DingleBerry');
$reflection->implementsInterface('Requirements');
?>

http://php.net/manual/en/book.reflection.php
http://mark-story.com/posts/view/using-the-php-reflection-api-for-fun-and-profit

Jay
  • 195
  • 2
  • 10
scragz
  • 6,670
  • 2
  • 23
  • 23
  • 1
    This will **check** if the interface is implemented, but will not make the class implement it. – netcoder Jan 26 '11 at 23:53
  • Ah, well that is for the 2nd part of your question, about the DingleBerry's constructor being called before you can check if it implements that. – scragz Jan 26 '11 at 23:56
  • Looks like you're gonna have to rewrite it in Ruby! – scragz Jan 26 '11 at 23:57
  • If I can't force it, this is definitely the next best thing. Thanks scragz, you da man. (Minus your Ruby comment) I edited it to ReflectionsClass => ReflectionClass i.e. remove 's' – Jay Jan 27 '11 at 00:00