Stut wrote: > Colin Guthrie wrote: >> Stut wrote: >>> Colin Guthrie wrote: >>>> Stut wrote: >>>>> Stut wrote: >>>>>> In that case you need a new foo. That's the only way you're going to >>>>>> reset the internal static if the API doesn't give you a way to do it. >>>>>> >>>>>> $f=new foo(); >>>>>> $f->bar(); >>>>>> $f->bar(); >>>>>> $g=new foo(); >>>>>> $g->bar(); >>>>> Actually, scratch that, won't work. Not even unsetting $f before >>>>> creating the new object works. This kinda sucks since it means PHP >>>>> does >>>>> not support static function-scoped vars. >>>> Yeah I tried that same thing too and then wondered if I had >>>> misinterpreted how function-scoped statics worked. >>>> >>>> I've often used a method like: >>>> >>>> function Init() >>>> { >>>> static $bln_inited = false; >>>> if (!$bln_inited) >>>> { >>>> // Do stuff >>>> $bln_inited = true; >>>> } >>>> } >>>> >>>> >>>> I had always assumed that the static definition here was >>>> function-scoped... I guess I should have tested more but still it >>>> caught >>>> me off guard this morning when I played with it. >>>> >>>> Correct me if I'm wrong but does C++ not do it as both of us initially >>>> thought? e.g. static is function scoped rather than globally scoped >>>> when >>>> used within a class method? >>> Yes it does, which is why I assumed PHP would do it like that too. I >>> knew I should have tried it before sending the reply. >>> >>> I've tried various ways of accessing that variable via a derived class >>> but it doesn't seem to be possible. Again I'm just assuming, but my >>> theory is that the line... >>> >>> static $foobar = false; >>> >>> ...actually is static to the function and therefore cannot be accessed >>> from outside it in any way, shape or form. >>> >>> So using function statics as you have above will work fine. And they >>> also work fine when used in a method of a class. This behaviour is >>> correct because if a function-scoped static is to work correctly there >>> should be absolutely no way to get at it from outside the function. >> >> I completely agree that there should be no way to access it outside the >> function/method it is defined within. The problem is that in PHP the >> static keyword seems to be globally unique but function/class scoped. >> e.g. that if it is used in a class method, regardless of how many >> instances of that method you create with "new" there is only ever one >> "instance" of the variable. >> >> So the case where it wont work fine is when you have the above function >> as a method of a class which can have multiple instances, all of which >> need to be Init()'ed independently. >> >> In such cases, I guess you'd have to use a private member variable >> instead which just isn't quite a neat and tidy. >> >> If you only ever have one instance of the class then all is well but >> still could have unexpected side effects if you later extend the system >> to have more than one instance. I guess if you use a singltron method >> with a private constructor then it's safe enough but then you can just >> do your initialisation in the singletron method in that case so there's >> little point! >> >> Hey ho. >> >> /me scuttles of to grep code for "static" :s > > Nope, not globally unique: http://dev.stut.net/php/funcstatic.php > > So what you have will be fine. No it wont work as I *intended* but that is purely due to my own misinterpretation of how statics in a method works. I've satisfied my own understanding now by testing it in C++ and it behaves the same as in PHP here, so I'm completely in the know (now!). I did however think it worked differently! Like I say it's just my own misunderstanding. Here is what I meant for completeness: Try the following code and note especially the last two lines of the output (change the \n to <br /> if you want if for web output.. I tested on cmdline). <?php $GLOBALS['eol'] = "\n"; class c { public function a($nm) { static $var = 0; print $nm.'a: '.$var.$GLOBALS['eol']; $var++; } public function b($nm) { static $var = 0; print $nm.'b: '.$var.$GLOBALS['eol']; $var++; } } $c = new c(); for ($i = 0; $i < 10; $i++) { $c->a('C'); if ($i % 2) $c->b('C'); } $d = new c(); $d->a('D'); $d->b('D'); ?> Ca: 0 Ca: 1 Cb: 0 Ca: 2 Ca: 3 Cb: 1 Ca: 4 Ca: 5 Cb: 2 Ca: 6 Ca: 7 Cb: 3 Ca: 8 Ca: 9 Cb: 4 Da: 10 Db: 5 i.e. the $d object just carries on where $c left off. This is not what I had in my head how things worked. I had originally thought that the static keyword within a class method was only static in the context of that *instance* of the class. This is clearly mince now I look into it and think about it a bit. e.g. consider the following class. <?php $GLOBALS['eol'] = "\n"; class foo { private $mVar = "Uninitialised"; public function Init() { static $bln_initialised = false; if (!$bln_initialised) { $this->mVar = 'Initialised'; $bln_initialised = true; } } public function Display($nm) { echo $nm.': '.$this->mVar.$GLOBALS['eol']; } } $foo = new foo(); $foo->Init(); $foo->Display('Foo'); $bar = new foo(); $bar->Init(); $bar->Display('Bar'); ?> Foo: Initialised Bar: Uninitialised That's not what I *wanted* to happen, even tho' I now understand that's what *should* happen! I confirmed this with C++ to satisfy me that that's what it does too and it does: #include <iostream> #include <string> using namespace std; class foo { public: foo(); void Init(); void Display(string nm); private: string var; }; foo::foo() :var("Uninitialised") { } void foo::Init() { static bool bln_initialised = false; if (!bln_initialised) { var = "Initialised"; bln_initialised = true; } } void foo::Display(string nm) { cout << nm << ": " << var << endl; } int main() { foo foo, bar; foo.Init(); foo.Display("Foo"); bar.Init(); bar.Display("Bar"); return 0; } Foo: Initialised Bar: Uninitialised So my understanding suitably updated. :) Col PS I know the above examples are contrived and that constructors would be more appropriate for the above - but using constructors is not always possible due to how you deal with failed initialisations where exceptions are not desirable. -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php