Mark worked with the kind of programmer who understood the nuances and flexibility of PHP on a level like none other. This programmer also wanted to use all of those features.
This resulted in the Base
class, from which all other classes descend.
Mark, for example, was trying to understand how the status
field on a Widget
got set. So, he pulled up the Widget
code:
class Widget extends Base {
public function getOtherWidgets(){return $this->widgetPart->otherWidgets;}
public function getStatus(){
$this->otherWidgets;
if(isset($this->status))return $this->status;
}
}
So, getStatus
doesn't always return a value. That's fun, but I guess it doesn't return a value when $this->status
doesn't have a value, we can let that slide.
The line above that return is odd, though. $this->otherWidgets
. That sure as heck looks like a property access, not a function call. What's going on there?
I'll let Mark explain:
if it can't find a property called "otherWidgets", it uses PHP's magic
__get
,__set
, and__call
to create a call to getOtherWidgets.
Which, as we can see, getOtherWidgets
calls into a WidgetPart
, which also does the same magic, and calls its own getOtherWidgets
.
class WidgetPart extends Base {
public function getOtherWidgets() {
$part = $this->name;
$widgets = array();
$statuses = self::checkPartStatusForWidget($part,self::$widgetPartList);
foreach($statuses[$widget] as $part=>$status){
$widgets[] = Widget::find($part)->self($w)->inline($w->status = $status);
}
return $widgets;
}
}
This starts out pretty normal. But this line has some oddness to it:
$widgets[] = Widget::find($part)->self($w)->inline($w->status = $status);
Okay, find
makes sense; we're doing some sort of database lookup. What is self
doing, though? Where did $w
come from? What the heck is inline
doing?
That's certainly what Mark wanted to know. But when Mark put in debugging code to try and interact with the $w
variable, he got an undefined variable warning. It was time to look at the Base
class.
class Base {
// <snip>
/**
* Attach variable name to current object
*/
public function self(&$variable) {
$variable = $this;
return $this;
}
/**
* Allows you to preform a statement and maintain scope chain
*/
## Widget::find('myWidget')->self($widget)->inline(echo $widget->name)->part->...
public function inline(){
return $this;
}
}
self
accepts a variable by reference, and sets it equal to this
, and then returns this
.
inline
doesn't do anything but return this.
Somehow, inline
doesn't take parameters, but a statement in the parentheses gets evaluated. I can't accurately explain how this works. I can't even try getting these snippets to behave anything like this- clearly, there's more "magic" happening around the inline
function to allow the inline execution of a statement, which Mark didn't provide.
Honestly, that's for the best- I'm not sure I want to see that. (Actually, I'd love to see that, but I'm a glutton for punishment)
But this is a whole lot of magic to allow us to play code golf. Without the magic, you could just… write a few lines.
$w = Widget::find($part);
$w->status = $status;
You don't need to do any of this. It certainly doesn't make the code cleaner or easier to understand. And I certainly can't explain what the code is doing, which is always a problem.
It's the worst kind of code: clever code. May the programming gods save us from clever programmers.