Welcome Guest, Not a member yet? Register   Sign In
unexpected dynamic data behavior when loading views
#1

(This post was last modified: 04-14-2016, 03:55 PM by sneakyimp. Edit Reason: added code output to clarify )

It would appear that data I supply to one view sticks around when I load my second view. This is unexpected. If I supply an array of data when loading a view, I expect that data to dictate which variables are defined when the view gets processed.

For example, I have a controller method:
PHP Code:
    public function somemethod() {
        
$foo = array(
            
"val1" => "one",
            
"val2" => "two",
            
"val3" => "three"
        
);
        
$this->load->view("jtest/scope"$foo);
        
        
$bar = array(
            
"val1" => "changed one",
            
"val2" => "changed two"
        
);
        
$this->load->view("testview"$bar);
    } 
NOTE that I have loaded the same view twice but have supplied entirely different arrays of data each time. In the second case, I do not define val3 at all.
Here is testview:
PHP Code:
<?php
/**
 * view to test scope when loading views in CI
 */
?>
<div>val1=<?php echo $val1?></div>
<div>val2=<?php echo $val2?></div>
<div>val3=<?php echo $val3?></div> 

The output renders the view twice, as expected, but the second time it's rendered, val3 still has the value that was loaded the first time around. The output:
Code:
val1=one
val2=two
val3=three
val1=changed one
val2=changed two
val3=three


This val3 value is also still around if I use an entirely different view the second time:
PHP Code:
    public function scope() {
        
$foo = array(
            
"val1" => "one",
            
"val2" => "two",
            
"val3" => "three"
        
);
        
$this->load->view("jtest/scope"$foo);
        
        
$bar = array(
            
"val1" => "changed one",
            
"val2" => "changed two"
        
);
        
$this->load->view("jtest/scope2"$bar);
    } 

It would appear that somehow these vars are cached. This not at all the behavior I would expect and it does not appear to be described in documentation. It may also present a security issue to have any sensitive values cached.

Is there some feature I don't know about that would 'wipe' the data supplied to my view? Seems to me that if you supply data to a view by using an array, then the view should receive that data and nothing more.
Reply
#2

I think, it is described here: https://www.codeigniter.com/user_guide/l...ader::vars
Reply
#3

If that is the case, and shall test tomorrow, all my carefully constructed arrays passed to multiple views to construct a page was a waste of time. ;-(
May as well dump all data in one array and pass it to the header view only.

Excuse curtness, typing on phone is horrible..
Reply
#4

(04-14-2016, 05:20 PM)ivantcholakov Wrote: I think, it is described here: https://www.codeigniter.com/user_guide/l...ader::vars
Hmmm. I'm not sure that link clearly explains this problem. Also, If you review my code samples, you'll see that I never called the Loader::vars function explicitly.

I don't think CI should behave this way.
Reply
#5

"This method produces the same result as using the second parameter of the $this->load->view() method above." - this phrase reveals that the behavior is intended.

You expect that variable context of different views to be isolated, this is a good expectation. With an addition of "global_vars()" method for serving serving special-purpose variables (intended to be global/cached) this would have been the cleanest implementation. The Twig parser for example supports global variables if they are explicitly registered as such.

But..., the current behavior is not accidental, it is intended, and it is specially implemented using the CI_Loader::_ci_cached_vars property.

A behavior change/improvement here will be a compatibility break. It will probably affect my code, because I am using the Phil Sturgeon's Template library which also reads _ci_cached_vars property.

Your idea in principle is correct, I think it should be considered for CodeIgniter 4.
Reply
#6

(This post was last modified: 04-15-2016, 03:24 AM by ivantcholakov.)

The clear_vars() method https://www.codeigniter.com/user_guide/l...clear_vars could be used if you have a special case.

So, the current state is:
"All view variables are "global", but you can clear the internal cache at will".

The desired behavior should be an inversion, I think
"All variables have isolated view scopes, "global" variables are to be registered explicitly." But this is not an idea for CodeIgniter 3, it will cause a lot of pain. Propose it for CI 4, please.

Edit: I'll post a link there. http://forum.codeigniter.com/thread-64969.html
Reply
#7

In my case, I'm very happy with the way it works right now.
I have a "template" view with this structure:
PHP Code:
$this->load->view('template/header');
$this->load->view($main_content);
$this->load->view('template/footer'); 

In my controller, I populate the $data array with whatever I need in any view.
Then I call the template view:
PHP Code:
$data['title'] = "Page title";
$data['main_content'] = "home";
$this->load->view('template/template',$data); 

The variables that are "packed" in the data array, can be accessed in all views that are loaded inside the template view.
Reply
#8

Well I am very surprised by this.

Not sure what to do now. Do I re-do my self rolled template library, to take advantage of this feature, or given that it is so unexpected, keep on doing it the 'proper' way (by proper I mean what I expected, pass variables to your view so the view can use them).

When I consider the repeated data I have set for no reason I am pulling my hair out a bit to be honest. This is a frustrating realization and a bit strange IMHO. I can see why it is useful, just annoyed I didn't know about this sooner TBH.

The docs should be update immediately to let people know that they only need to pass data once to a view to have it available to all subsequent views.

:-(

+1 to SneakyImp for bringing this up.
Reply
#9

Following a reading of this thread : http://forum.codeigniter.com/thread-6496...31257.html

It looks like this behaviour is going, or at least be a specific option defaulting to 'do not cache' so at least that answers my dilemma.

I shall not be using this feature (even though it happens now) and will continue assuming my vars are view specific.
Reply
#10

Yes many many websites are using a variation of the template pattern that Wouter60 describes which depends on this.
Reply




Theme © iAndrew 2016 - Forum software by © MyBB