Ruby-like mixins in PHP5

Hi,

yesterday I was experimenting with mixins idea in PHP. Ruby mixins were used as an example. Code is so simple that at first I was shamed to post it.

Here are tests
http://johno.jsmf.net/knowhow/mixins/tests/unit_tests.phps and code http://johno.jsmf.net/knowhow/mixins/mixins.phps

It was just a coding exercise, but I have some ideas how to use it.

Imagine models for a simple application.

class Photo {
	protected $id;
	protected $title;
	
	protected $position;
	// ...
	
	public function moveUp() { ... }
	public function moveDown() { ... }
}


class PhotoCollection {
	protected $id;
	protected $title;
	
	protected $parentId;
	protected $children;
	
	public function addChild() { ... }
	public function removeChild() { ... }
}

class Article {
	protected $id;
	protected $title;
	protected $body;
	
	protected $position;
	protected $parentId;
	protected $children;
	
	public function moveUp() { ... }
	public function moveDown() { ... }
	public function addChild() { ... }
	public function removeChild() { ... }
}

There is some code duplication, that’s hard to refactor. At least for me. :confused: So I came up with this.

class OrderingBehavior() {
	public function moveUp() { ... }
	public function moveDown() { ... }
}

class TreeBehavior() {
	public function addChild() { ... }
	public function removeChild() { ... }
}

class Photo extends Mixer {
	// ...
	public function __construct() {
		$this->inject(new OrderingBehaviour());
	}
}

class PhotoCollection extends Mixer {
	// ...
	public function __construct() {
		$this->inject(new TreeBehaviour());
	}
}

class Article extends Mixer {
	// ...
	public function __construct() {
		$this->inject(new TreeBehaviour());
		$this->inject(new OrderingBehaviour());
	}
}

Maybe I could use Decorators instead. This whole thing is just an idea.

So what do you think? Any better ideas how to use this?

Time to break out runkit?

http://uk.php.net/manual/en/function.runkit-method-copy.php

REN: Yes, I know about that.

If you want mixins I think it is better to use Ruby

BONEFRY: Please, I don’t want this to be a flame about Ruby vs PHP. I like both: Ruby and PHP.

I just want to discuss about other usages for mixins or how to refactor code mentioned as example.

There are several other ways to factor it. The best way tends to depend on more detail than you’ve presented so far.

PhotoCollection and Article have the behavior of a Composite, which can be implemented in more than one way.

Apart from that, your code suggests Strategy to me. With Null Object implementations, you could do something that would work like this:

$photo = new Resource(new NullTreeBehavior, new OrderingBehavior);
$photocollection = new Resource(new TreeBehavior, new NullOrderingBehavior);
$article = new Resource(new TreeBehavior, new OrderingBehavior);

You probably don’t want object creation to be this cryptic, so you need creation methods or a factory class just to make it more readable.

It’s probably not the best way to solve this particular kind of problem, but it’s really useful to know how to do this kind of thing.

Great a post to the point, but I am a bit sceptical. Imagine adding new behaviours. You will probably end up with many NullStrategy<->Strategy class pairs. How are you going to call methods of these strategies? I assume

class Resource {
   //...
   function moveUp() {
       $this->orderingStrategy->moveUp();
   }
}

So in the end you will have a Resource with many methods that mostly don’t do anything. Because of null strategies.

Yes. Actually, the first part of my reply was more realistic. For the challenge you’re presenting, I would start by considering the Composite pattern. And would you want to implement Composite as a mixin? I don’t know.

It’s just an example, I don’t know if it’s a good idea. Whole point of this thread is to find out, what it actually is good for. :blush:

I don’t currently program in PHP5, but I had a similar idea recently; You could have an array of objects (say, called $behaviors), and then you program __call, __get and __set to loop through the array to find the first object that implements the function/property you called. These behavior objects would contain a reference to the parent object, which they would use instead of $this for method calls and properties. Not quite a replacement for mixins, but could be feasible.

In my implementation the mixin/behaviour has only access to parents public/protected properties, but besides that does the same.

Probably should have looked at your code before posting, sorry :blush:

There was a thread a while back that parsed the class text, combined text to mixin and the used eval to create new object from the combined text. More of a hack certainly. Anyone remember where that thread was – as there was working code.

this one; http://www.sitepoint.com/forums/showthread.php?t=292954&highlight=php+mixins

Interesting approach.

It seemed to me at the time that what was needed was some sort of builder that would convert “example.class.php” into “example.mixin.php” that was prepped and formatted for the runtime mixin code to use efficiently. I guess you could have the run-time autobuild the mixin files ala template cache systems.

While that’s certainly an interesting approach to mixin-like behaviour, I see the requirement to extend a base “mixin” class as a big drawback.

IMHO, one of the strongest uses for mixins is to bring classes from different codebases together and make them play nice together, which is very hard when you introduce a mandatory base class.

I understand, that I’m bumping up an old thread, but I just wanted to inroduce my small mixin library for PHP, that supports bot inheritance and composition approach to creating mixins.

<snip/>

Both approaches are very easy to implement and reuse.

PHP trunk has traits.

http://wiki.php.net/rfc/horizontalreuse

Though from toying with the current state of implementation there feels like its still abit incomplete. As traits only deal with code and not state.

Mixins and traits are something different.