Search/filter Custom Column On Cgridview

hi to all, i just wanna ask how can i search or filter on my cgrid using my custom column

this is my view:

array(

‘header’=>‘average’

‘value’=>’$data->getAverage()’

}

this is my model where i can get the value of average

public function getAverage

{

$average = Yii::app()->db->createCommand(‘select AVG(column) FROM your_table’)->queryScalar();

return $average;

}

note code above is for example only

my proble is how can i create a search or filter on my cgrid view?

Hi raiethan

The caclulation occurs for each record at the moment that CGridview displays the records.

So, it is no possible to sort or filter this column in this way

The best way to achieve that is by adding a column in your databse table and assign with the $averange value on before save event. Because you have already records with no calculated average value, make a method that initializes the new column for all old records.

Another way is by CArrayDataProvider

http://www.yiiframework.com/doc/api/1.1/CArrayDataProvider

but you have to caclulates the extra average column for all records for each request (make your webapp slow when a lot of records exist) So the first way is the best

Hi raiethan,

As KonApaz says, CActiveDataProvider (and also CSqlDataProvider) uses SQL to search, filter and sort by some value. The value must be accessible from SQL.

We usually use a column in db for that, but if you can express the value in SQL then you can use it.

A getter method of AR can’t be used for that purpose, because the value should be calculated in SQL, before Yii constructs the AR objects as the result.

i will try the first way sir… thank you so much…

thank you so much… in short sir the proper way is to create another column on my db and will add before save that will compute and save my average on my db…

For instance, let’s assume a model called Point.

The table that implements Point is something like this:




id ... PK

point_a ... decimal

point_b ... decimal

point_c ... decimal



Now you can think of the average value of point_a, point_b and point_c.

KonApaz’s suggestion is to add a new column, something like point_avg.




id ... PK

point_a ... decimal

point_b ... decimal

point_c ... decimal

point_avg ... decimal



You can calculate the average point in beforeSave().




// in Point.php

...

public function beforeSave()

{

	$this->point_avg = ($this->point_a + $this->point_b + $this->point_c ) / 3;

	return parent::beforeSave();

}



In this way, you can calculate and save the average every time you create or update Point.

in my case sir i follow your suggestion, but when i try to create it will save 0 and blank on my average and interpretation




            public function beforeSave()

        {

            $this->average =

                        $divider = 0;

                        if($this->rating1 != 0 || $this->rating1 != null) $divider += 1;

                        if($this->rating2 != 0 || $this->rating2!= null) $divider += 1;

                        if($this->rating3 != 0 || $this->rating3 != null) $divider += 1;


                        if($this->rating4 != 0 || $this->rating4 != null) $divider += 1;

                        if($this->rating5 != 0 || $this->rating5!= null) $divider += 1;

                        if($this->rating6 != 0 || $this->rating6 != null) $divider += 1;

                        if($divider == 0) $divider = 1;

                        $avg = ($this->rating1 + $this->rating2 + $this->rating3+ $this->rating4 + $this->rating5 + $this->rating6) / $divider;


          $this->interpretation = 

                 $avg = ($this->interpretation);

          

	if ($avg >= 96) 

	  	 {

          $remarks = "<font color='blue'>Outstanding</font>";

        }

		 else if ($avg >= 91) 

	  	 {

          $remarks = "<font color='green'>Superior</font>";

        }

		 else if ($avg >= 86) 

	  	 {

          $remarks = "<font color='indigo'>Very Satisfactory</font>";

        }

		 else if ($avg >= 81) 

	  	 {

          $remarks = "<font color='orange'>Satisfactory</font>";

        }

		else if ($avg >= 76) 

	  	 {

          $remarks = "<font color='violet' >Minimally Santisfactory<font>";

        }

		else if ($avg <= 75) 

	  	 {

          $remarks = "<font color='red' >Needs Improvement</font>";

                 }

                 

   

                

                return parent::beforeSave();

     }



You are not saving the value of $avg to your AR object. :)




    // $avg = ($this->rating1 + $this->rating2 + $this->rating3+ $this->rating4 + $this->rating5 + $this->rating6) / $divider;

    $this->avg = ($this->rating1 + $this->rating2 + $this->rating3+ $this->rating4 + $this->rating5 + 



And review your code for another local variable named $remarks.

opps… sorry my bad… thank you so much…