CodeIgniter Forums

Full Version: HELP! regarding variable scope in a library I created
You're currently viewing a stripped down version of our content. View the full version with proper formatting.

El Forum

[eluser]steveh[/eluser]
Hi all...
In summary, I need some pointers/corrections regarding how to handle variable scope within a library I created. The problem seems to be that when I call (methods in) my library from a controller/view/etc, some data that I stored in an array in the library only appears when I later access the array library from the same view/controller.
What I was wanting to achieve is a generic library into which I can place various home grown utility functions, and data... not the least of which would be generalised handling of headers, footers and menus, etc... so I'd like to call the lib from various places during the processing of a Request... and use any data stored in an array in that lib for example later when I build a menu with the items I then know are needed (irrespective of which view/controller put it there).
I've called the library "Llib" (for Local Library), and I include 'llib' in the autoload[libraries] of autoload.php. I also included a __construct in Llib in which I call write_message(), which dutifully displays "Llib Class Initialized" at the same point that the other libraries are being loaded.
I hadn't progressed the app prototype far before I encountered this issue. Basically, I'd provided for a login_authentication controller/view - that, when submitted and successfully processed (using the CI session library), will redirect() to a main_page controller/view. I noticed that data stored in an array in Llib by the login_auth view (e.g. summary user details and state) was not available when accessed from the main_page view (only data I'd set via method calls from the main_page view was there).
I set and get the data via a couple of methods in Llib that access a var array ... declared similar to "class Llib { var $myArray = array(); ...
...the set and get functions a pretty basic, e.g. function set_item($item, $value) { $myArray[$item] = $value; }
...and to debug/verify what's in the array at any given time, I simply: foreach ( $myArray as $name => $val ) { log_message(debug...) }
Hence, I think I've encountered some sort of data scoping issue. I've read quite a lot about data scoping in PHP, however I seem to have lost the plot insofar as how it is managed within CI (for the Request, the different controllers/views, CI's super object.... arrrrrgh!). (I am way more familiar with Perl than PHP, so it may even be some basic PHP 101 thing that I'm just not used to).
I'd just like the array data to be considered Global to my Llib methods called from any controller/view during processing a particular request (i.e. the instance of Llib loaded that request).
Please let me know if I need to provide any more info.
Thanks in advance for any 'how to' on this one,
Steve

El Forum

[eluser]InsiteFX[/eluser]
PHP.net - Variable Scope

InsiteFX

El Forum

[eluser]danmontgomery[/eluser]
Code:
class Llib {
    var $myArray = array();

    function set_item($item, $value) {
        $this->myArray[$item] = $value;
    }

    function get_item($item) {
        return $this->myArray[$item];
    }
}

// ...

$this->load->library('llib');
$this->llib->set_item('foo','bar');
echo $this->llib->get_item('foo'); // bar

El Forum

[eluser]steveh[/eluser]
Thanks for the replies thus far.

noctrum -- Thanks very much for taking the time to provide some sample code... I had already done what you indicated... however, my understanding of "$this->load->library('llib');" is that it would need to be done in each controller/view. I'd done the autoload to ensure the Llib was available without needing specific loading per controller/view. Am I right in thinking I can autoload it? and that your example requires loading per controller/view? Also, in your example, what is the magic of referring to $this->myArray[...] as I'd have thought that myArray is already scoped local to Llib? or am I expecting too much here? or is '$this->" just a very explicit way of referring to something scoped in the embodying class? (is $this explicitly documented somewhere?) arrrgh!
(and also as I understand it, I need to do some other scoping stuff in my Llib to access CI libraries, per: "$CI =& get_instance();" ... hence my thinking there is various other scoping magic that I can't discern from generic documentation.)

InsiteFX -- I'd noticed the Global terms... however wasn't sure how they might apply in the context of CI libraries. At face value, it reads as though I should be declaring "var $myArray = array();" outside the class then have a "global $myArray" inside any of the class methods that utilise it?

In any event, is it apparent from what I'd written as to what my underlying issue is, and the (code) solution? to reiterate:
- autoloading
- global scope to that Request to its variables and methods callable from any controller/view during the Request
(- perhaps even callable later from a hook... e.g. to produce hdr/ftr/menu based on context provided by calls made during controller/view processing)

thanks, Steve

El Forum

[eluser]InsiteFX[/eluser]
You should use public, private etc, gor you variables.

var is depreciated.

InsiteFX

El Forum

[eluser]danmontgomery[/eluser]
[quote author="steveh" date="1303798642"]my understanding of "$this->load->library('llib');" is that it would need to be done in each controller/view. I'd done the autoload to ensure the Llib was available without needing specific loading per controller/view. Am I right in thinking I can autoload it? and that your example requires loading per controller/view?[/quote]

You can, generally speaking you only want to autoload what you're using on every page, or close to it, otherwise it's wasting resources. If you don't autoload, you would have to explicitly load it per controller (or, per method, however), when you needed it.

[quote author="steveh" date="1303798642"]Also, in your example, what is the magic of referring to $this->myArray[...] as I'd have thought that myArray is already scoped local to Llib? or am I expecting too much here? or is '$this->" just a very explicit way of referring to something scoped in the embodying class? (is $this explicitly documented somewhere?) arrrgh![/quote]

$this indicates a member of the current class. You are expecting too much Wink Class or not, unless otherwise specified, variables are local to their current function.

[quote author="steveh" date="1303798642"](and also as I understand it, I need to do some other scoping stuff in my Llib to access CI libraries, per: "$CI =& get_instance();" ... hence my thinking there is various other scoping magic that I can't discern from generic documentation.)[/quote]

get_instance() returns the CI superobject, which is the Controller object. This is used when you need to access controller members from outside the scope of the controller.

[quote author="steveh" date="1303798642"]I should be declaring "var $myArray = array();" outside the class then have a "global $myArray" inside any of the class methods that utilise it?[/quote]

No... These are two different variables.

El Forum

[eluser]steveh[/eluser]
It seems as there may not have been a scope issue after all... at least not of the type I'd originally considered.
Further to my above/original mention of "...will redirect() to a main_page...", I think I've pinned the prob to the actual redirect()... and on closer investigation, it is a HTTP redirect rather than a redirection of CI processing... hence it will be processing as a new Request and thus a new $myArray by the time it gets to call the other controller.
What I was doing with redirect() was trying to achieve the effect of $this->load->view() albeit to a controller. Is there any way I can transfer processing to a different controller that stays within the same request? (if there isn't, then perhaps my way around it is to shift the majority of my processing to views to enable use of load->view() merely as a means to call them).
In any event, thanks very much for your efforts in responding to my help request.
regards
Steve

El Forum

[eluser]danmontgomery[/eluser]
Nope. You would have to use a modular solution, like modular extensions, modular ci, etc.