2

Assuming we have two classes, in the \Base\Form\ namespace:

class Field {
    protected $name;
    protected $value;
}

class DropdownField extends Field {
    protected $options = [];
    // with functions like setOptions(), addOption(), removeOption() etc.
}

Now, in another namespace, a class exists that extends on Field, that has an additional 'layout_position' property:

namespace Integrations;
class IntegrationsField extends \Base\Form\Field {
    const LAYOUT_POSITION_LEFT  = 'left';
    const LAYOUT_POSITION_RIGHT = 'right';
    protected $layoutPosition = self::LAYOUT_POSITION_LEFT;
}

Now, you might see this one coming, but in the event of an IntegrationsField that can also be a dropdown:

namespace Integrations;
class IntegrationsDropdownField extends \Base\Form\DropdownField {}

Of course, this one should also have the $layoutPosition, that should be inherited from IntegrationsField, but since we can't extend two classes, what is the best solution to go for here?

MC Emperor
  • 22,334
  • 15
  • 80
  • 130
Mave
  • 2,413
  • 3
  • 28
  • 54

1 Answers1

5

PHP doesn't support multiple inheritence. You can however rewrite your logic using traits to (sort of) simulate it.

class Field {
    protected $name;
    protected $value;
}

trait Dropdown {
    protected $options = [];
    // with functions like setOptions(), addOption(), removeOption() etc.
}

interface IntegrationPositions { 
    const LAYOUT_POSITION_LEFT  = 'left';
    const LAYOUT_POSITION_RIGHT = 'right';
}

trait Integration {
    protected $layoutPosition = IntegrationPositions::LAYOUT_POSITION_LEFT;
}

class DropdownField extends Field {
     use Dropdown;
}

class IntegrationField extends Field {
     use Integration;
}

class DropdownIntegrationField extends Field {
     use Integration,Dropdown;
}

Update: As @Adambean noted traits cannot have constants. I've therefore updated the example using an enum.

This feels strange to have to declare an enum that's meant to be internal to a trait but PHP does not seem to allow any other mechanism to achieve this as far as I know, I am open to any other ideas.

apokryfos
  • 38,771
  • 9
  • 70
  • 114
  • This exact example wouldn't work because traits cannot have constants. (This throws a fatal error.) – Adambean Dec 06 '17 at 10:14
  • @Adambean I've updated the example with an "enum" of some sort. It doesn't sit well with me but it doesn't seem that PHP is giving us much choice in this. – apokryfos Dec 06 '17 at 10:31
  • 2
    Interfaces can have constants? I wish I knew that 9 hours ago. :D – Adambean Dec 06 '17 at 20:02