Traits In Php 5.4

I know that Yii 2.0 will support PHP 5.3+ but traits

are making multiple extends possible in PHP 5.4 and this looks very much like what Yii is doing with behaviors.

So I thought it was a good idea to bring it up for discussion since I couldn’t find another topic about it. Except for this one

What are the advantage of using behaviors or ActiveRecordBehavior’s?

What could we do more with behaviors or when we have a server running PHP 5.4 could we just a well use traits?

Would it be a miss when Yii is missing out on some of the new features in PHP 5.4 since it has yet to be released?

And when Yii needs to be 5.3 compatable because setting to high requirements might scare of developers I would like to know if I even SHOULD use behaviors when MY server is running 5.4

I suppose you can make your own choice to either use Traits or Yii Behaviors when you are running PHP 5.4.

:)

Traits are very interesting but a first difference with behaviors is that traits can not be parameterized.

As Giueseppe already stated, behaviors can be parameterized and while there is a way to do the same with traits it breaks the intention of traits IMHO. Imagine a behaviour like the CTimeStamp behaviour which updates "created_at" and "updated_at" fields. You would configure the behaviour like this in Yii 1.x




public function behaviors(){

	return array(

		'CTimestampBehavior' => array(

			'class' => 'zii.behaviors.CTimestampBehavior',

			'createAttribute' => 'create_time_attribute',

			'updateAttribute' => 'update_time_attribute',

		)

	);

}



An approach implementing the same functionality using traits would probably look like this:


trait TimestampBehavior

{

    function setTimestampValue()

    {

        $config = $this->behaviors(); //call MyRecord::behaviors()

        if($this->isNewRecord) {

            $this->{$config['TimestampBehavior']['createAttribute']} = DateTime::getTimestamp();

        } else {

           $this->{$config['TimestampBehavior']['updateAttribute']} = DateTime::getTimestamp();

        }

    }

}


class MyRecord extends CActiveRecord

{

    use TimestampBehavior;


    public function behaviors(){

	return array(

		'TimestampBehavior' => array(

			'createAttribute' => 'create_time_attribute',

			'updateAttribute' => 'update_time_attribute',

		)

	);

    }

}

But the idea of traits is that they should make it easy to reuse generic code; Code that is used independently of the inheritance of the class that uses it. In the example above we are using CActiveRecord’s getIsNewRecord() method which means we are forced to either extend CActiveRecord or write our own getIsNewRecord() method. The same problem is true as soon as using “parent::methodCall()”.

Si in my opinion traits are cool for very generic things like singletons, magic method definitions, conversions (something like toJson() etc.). For everything else behaviours are the better fit I guess.

There is a huge difference between traits and behaviors.

A trait is a way to add generic methods and properties to a class, without any configuration or processing. Therefore a trait is merely a collection of properties and methods to add to a class.

A behavior is a class with its own logic, configuration and processing. It can export methods to its owner class by binding those methods to itself.

An example how these can be simulated in javascript:




	var obj = {

		fname: 'John'

	},

	trait = {

		lname: 'Doe',

		getFullname: function() { return this.fname + ' ' + this.lname }

	},

	behavior = {

		owner: obj,

		lname: 'Doe',

		getFullname: function() { return owner.fname + ' ' + this.lname }

	}


	// add the trait to obj

	// obj now knows about its property lname and has full control over it.

	obj.lname = trait.lname;

	obj.getFullname = trait.getFullname;	// fullname now works on obj


	// add the behavior to obj

	// obj does not know about a property lname and thus has no control over it, but it still works.

	// the behavior has full control over the lname property.

	obj.getFullname = behavior.getFullname.bind(behavior);	// fullname still works on behavior



One thing traits lack when compared to behaviors is runtime attachement. If you want to extend a given (let’s say 3rdParty) class with some special functionality, behaviors give you a chance to attach them to the class (or more specifically to instances of the class). Using traits, you had to to modify the source of the class (please correct me if I’m wrong ;)).

Yup this is quite good explanation of that two features