Using Behaviors in Yii

January 19, 2015 •  oop •  php •  yii



What are Behaviours in Yii ?

behavior is an object whose methods can be 'inherited' by its attached component through the means of collecting functionality instead of specialization (i.e., normal class inheritance). A component can be attached with several behaviors and thus achieve 'multiple inheritance'.

Yii

Typically PHP does not support Multiple Inheritance such as extending Two Classes at the same time only a Multi-Level Inheritance where an extended class inherits another, Yii has a convention of using Multiple Inheritance like, where methods can be attached to classes in form of behaviors with ease and can also be detached.

Creating a Behavior 

Depending on the component you wish to add behaviors to, you can make use of the IBehavior or the CModelBehaviour if working with the CModel or CActiveRecordBehavior but i'll be sticking to the CBehavior which i find easier to use.

BrowserAgent: Behavior Class

We will create a behavior class called browserAgent a simple class that will be attached to the controller to access Navigator information from the Client browser.

Fire up your text editor and create a file called 'BroswerAgent.php' inside the 'protected/behavior' folder you can paste it anyway as you will declare how to map to the file however for clarity sake its better to have a folder called "behaviors".

class BrowserAgent extends CBehavior {

	private $data;
	private $owner;

we created a simple class to extend CBehavior and created to variables, the data will hold browser information while the owner will hold an instance of the component attaching this behavior, which is meant to be a controller,

public function useOwner(){
        //the getOwner returns the owner component that this behavior is attached to in our case "CController" or your Controller that extends CController
	$this->owner=$this->getOwner();
	if(is_subclass_of($this->owner,'CController')){
	//if it is a controller pass an information of browser to it
		$u_agent = $_SERVER['HTTP_USER_AGENT'];
		$bname = 'Unknown';
		$platform = 'Unknown';
		$version= "";

		//First get the platform?
		if (preg_match('/linux/i', $u_agent)) {
			$platform = 'linux';
		}
		elseif (preg_match('/macintosh|mac os x/i', $u_agent)) {
			$platform = 'mac';
		}
		elseif (preg_match('/windows|win32/i', $u_agent)) {
			$platform = 'windows';
		}

		// Next get the name of the useragent yes seperately and for good reason
		if(preg_match('/MSIE/i',$u_agent) && !preg_match('/Opera/i',$u_agent))
		{
			$bname = 'Internet Explorer';
			$ub = "MSIE";
		}
		elseif(preg_match('/Firefox/i',$u_agent))
		{
			$bname = 'Mozilla Firefox';
			$ub = "Firefox";
		}
		elseif(preg_match('/Chrome/i',$u_agent))
		{
			$bname = 'Google Chrome';
			$ub = "Chrome";
		}
		elseif(preg_match('/Safari/i',$u_agent))
		{
			$bname = 'Apple Safari';
			$ub = "Safari";
		}
		elseif(preg_match('/Opera/i',$u_agent))
		{
			$bname = 'Opera';
			$ub = "Opera";
		}
		elseif(preg_match('/Netscape/i',$u_agent))
		{
			$bname = 'Netscape';
			$ub = "Netscape";
		}

		// finally get the correct version number
		$known = array('Version', $ub, 'other');
		$pattern = '#(?' . join('|', $known) .
		')[/ ]+(?[0-9.|a-zA-Z.]*)#';
		if (!preg_match_all($pattern, $u_agent, $matches)) {
			// we have no matching number just continue
		}

		// see how many we have
		$i = count($matches['browser']);
		if ($i != 1) {
			//we will have two since we are not using 'other' argument yet
			//see if version is before or after the name
			if (strripos($u_agent,"Version") < strripos($u_agent,$ub)){
				$version= $matches['version'][0]; }
				else {
				$version= $matches['version'][1];
				}}
				else {
				$version= $matches['version'][0];
				}
// check if we have a number
if ($version==null || $version=="")
{
$version="?";
}

$this->data=array(
				'userAgent' => $u_agent,
				'name'      => $bname,
				'version'   => $version,
				'platform'  => $platform,
				'pattern'    => $pattern
		);

	}else{
	throw new CException("This Component can only be attached to a Controller and not this[".get_class($this->owner)."]");
	}
	}

let me go over it again

    $this->owner=$this->getOwner();
	if(is_subclass_of($this->owner,'CController')){

The getOwner is a function that is derived from CBehavior it gets the components that the behavior is attached to, because we need to make sure that only a controller can attach to this behavior we create a check to determine if the component is indeed a controller or a sub_class of controller and if not we throw CException which Yii's version of Exception.

The rest of the code was gotten from PHP Manual it collects the browser name and the OS used by the client, and assigns the mapped array to its property "data", however which will need to create another function to simply return the information.

    public function getInformation(){
	  $this->useOwner();
	  return $this->data;
	}

Attaching the Behavior to the Controller
in the controller class simple override the behaviors method with:

public function behaviors(){
		return array(
	'BrowserAgent'=>
	array('class'=>'application.behaviours.BrowserAgent'
			)
		);
	}

it returns an array with the classname and the class location the dot in Yii denote DIRECTORY SEPARATOR,

Using the Behavior in the Controller simply call the behavior by doing this:

$data=$this->getInformation();
print_r($data);
//$this->render('index'); //stops the View Rendering

when Yii runs it will load the behavior and attach the methods to the class,you can also use Component::attachBehavior if you need to load behaviors dynamically however it should be noted that it must be added to the config main file.

behaviors'=>array(
                'xyz'=>array(
                    'class'=>'ext.xyz.XyzBehavior',
                    'property1'=>'value1',
                    'property2'=>'value2',
                ),
            ),

with behaviors you can create reusable tools suchs as "Dojo Behavior that loads Dojo from CDN to the View" or a "Class that allows Models to export to various formats" lots and lots of useful tools to be created with behaviors, you can also read on Traits for PHP 5.4


Post Comment