CGridView Footer Summary

I need a little feedback on why an approach didn’t work. Ultimately, I did something else that worked out, but this is still bugging me.

I have a CGridView with dynamic columns starting with the current year (2011) through some maximum year. It’s basically a sparse pivot table. To compute the cell values, I created a helper function in the view. I also created an array in the view called $agg to store the sum based on the year. (e.g. $agg[2011], $agg[2012],…). I tried to pass the array by reference to the helper function, and within the function, I’d update the array. In the footer, I called a separate function to retrieve the appropriate $agg. I couldn’t get it to work. No errors and no values. In reviewing it, I’m wondering if creating $agg within the controller and passing it to the view would have made a difference. It is also very possible that I screwed up something and just didn’t see it.


$agg = array();


function computeStuff($year, $plans, &$aggr) {

...

...

   $aggr[$year]=...

...

}



Note: Because I generated $columns dynamically and passed it to the CGridView, I ended up extending CDataColumn so that footer cells would accept single quoted expressions (similar to a column’s ‘value’=>‘expression’).

Any thoughts, insights, etc. are greatly appreciated.

A view file doesn’t represent any class or struct. It’s a code fragment which a corresponding controller includes in some method(s). So your $agg in your view file is a local variable that has a limited scope in the method that includes the view file.

Creating a variable and a calculating function in the controller would do the job.

Thanks for the input. From your response, I’m not sure if you misread my post. You mention the method that includes the view file. $agg and the method are both in the view file. In fact, the method works as far as setting a computed value for columns. It only fails on the part where it references $agg. Passing by reference “should” bypass the scope issue. I guess in the scheme of things, it doesn’t matter. It’s just going to bug me.

Ultimately, I decided to keep the controller slimmed down, so I created a class called Aggregate with static functions and a static variable ($agg).

I would like to nhelp you but ill need to see some code, and a not working example if possible, otherwise I could only guess.

I apologize you if I’ve misread your post.

I thought that you called the calculating function through the ‘value’ property of the CDataColumn.

But you called it in the view script and stored the results to $agg, and couldn’t retrieve the value of it for the grid’s footer. Am I right?

I did something like that in one of my CGridView, though it was not for the footer.




$columns = array(

....

	array(

		'name' => 'foo',

		'type' => 'raw',

		'value' => '$this->grid->controller->calc_bar($row, $data)',

	),

....



I thought that when ‘value’=>‘expression’ is eval()ed somewhere in the codes for CDataColumn, the only variables that I can directly make use of are just 3: i.e. $this(CDataColumn instance), $row(row number), and $data(row contents). So I had to write ‘$this->grid->controller->’ and access the method in the controller.

Am I missing something?


$columns = array(

....

        array(

                'name' => 'foo',

                'type' => 'raw',

                'value' => 'computeStuff($data)',

        ),

The above works where computeStuff is a function defined locally within the view. You can also use: ‘MyController::mymethod($data)’. Since I can use a locally defined function, my assumption was that I could also use a locally defined variable.

I use this to set the value of the column and after extending CDataColumn, I also do the same thing in the footer. The class for extending CDataColumn is also included in the view file, since I don’t plan on using it anywhere else. If that changes, I’ll pull it out and put it in components.

Oh, and no apology necessary. :)

Oh, I didn’t know that.

Thank you a lot.

Asgaroth, I’d have to recreate it to get the exact code. It really boils down to a question: Is it possible to define a local variable within a view file, and then pass that variable by reference to a local function being called in a column value? (i.e. ‘value’=>‘computeStuff(&$agg)’, )

I second softark in that only $this(CDataColumn instance), $row(row number), and $data(row contents). are available when evaluating the expression,

Anyway what you want might work, But having a function defined in the view is not very clear and correct IMO.

Since you don’t have a Model for this (which you should even if it is dynamic, thats what models are for, representing things) then you are better off creating the array in the controller, computing everything there including what you want to show in your footer and then send just variables to the view, remember that the view is only used for presentation purposes, and should no contain logic.

You might want to read this:

http://www.yiiframework.com/doc/guide/1.1/en/basics.best-practices

Asgaroth, I appreciate your input. I originally wanted the function in the view because in addition to computing a numeric value it wraps it in a DIV and other markup. It’s fairly small as functions go. As I mentioned, I actually ended up with an alternative solution that pulled everything out into a helper class for the calculations. There is a Model, but I don’t see the point in moving the construction of the dynamic columns (which are all computed values) into it. I do that in the controller and pass it to the view. You’d have to see the whole thing to get a good understanding. Remember, my original question was only asking about passing the variable by reference and why that didn’t work. The rest is just background.

I think there is a grey area when you’re returning markup from a function whether it is in the view, Model, or wherever. But that’s just my interpretation. You’ve probably done more of this than I have. I work for myself and this project is something I’ve wanted to build for a while. Part of what I’m doing is testing the limits of what I can and can’t do with the framework. If I need to refactor a bit later to clean things up, that’s fine.

– Sorry. Not true. See my earlier post. It’s easy enough to test.

Anyway, I think we’ve exhausted this discussion. Thanks again.

if you use $this in a view it refers to the controller