E.g.
trait ConfigProvider {
private $_configProviderConfig;
public function setConfigProvider($cfg) {
}
public function getConfigProviderValue($key) {
// lazy load and setConfigProvider the default
}
}
Then any class that needs to know about system-wide config settings can use
the trait. But unit tests can setConfigProvider to test different config settings.
So, for example, class Lplt_Form_Element_Text
extends Zend_Form_Element_Text
extends Zend_Form_Element
. I need some extra/different/whatever behaviour in Zend_Form_Element
, but don't want to actually patch library code.
trait MyCustomFormBehaviour {
public function doTheThing () {
}
}
class Lplt_Form_Element Text extends Zend_Form_Element_Text {
use MyCustomFormElementBehaviour;
}
class Lplt_Form_Element_Select extends Zend_Form_Element_Select {
use MyCustomFormElementBehaviour;
}
So I don't have to patch library code but can add behaviour to all subclasses of Zend_Form_Element
, with only copying and pasting the use
statement.
Composing a complicated (but essentially Single Responsibility) class from easier to manage components
In Lamplight, Group_Select
is a class that constructs (rather complicated) SQL statements in an OOP kind of way:
$sel = new Group_Select();
$sel->bodysOfType("user")
->attended("work", "2011-01-01", "2012-01-01")
->withAttribute("gender", "male")
->arePublished();
or something: this will eventually generate a 8-table (say, sometimes many more) SQL statement.
One refactoring might be:
class Group_Select {
public function attended($type) {
$this->_attendance = new Attendance_Select();
return $this->_attendance;
}
public function attribute() {
$this->_attribute = new Attribute_Select();
return $this->_attribute;
}
public function buildSQL () {
// put $this->_attendance, $this->_attribute etc together
// to make a nice SQL statement
}
}
class Attendance_Select {
public function type($type) {
return $this;
}
public function dates($from, $to) {
return $this;
}
}
// and then...
$sel = new Group_Select();
$sel->attended()->type("work")->dates($date1, $date2);
$sel->attribute()->field("gender")->values("male");
$sql = $sel->buildSQL();
With traits it might be
trait Attendance_Select {
// all the logic around attendance things
}
trait Attribute_Select {
// all the logic around attributes
}
class Group_Select {
use Attendance_Select, Attribute_Select;
// small amount of general logic
}
Need to think about the pros and cons of these two, not sure which I prefer...