PHWinfo banniere

Titres
PORTAIL ANNUAIRE ARTICLES COMPARATEUR HÉBERGEURS DEVIS FORUMS RÉDUCTEUR D'URL
Précédent   PHWinfo > Autres forums > Forum Programmation & Conception > php.general > Strange behaviour of static declared content.
S'inscrire FAQ Membres Recherche Messages du jour Marquer les forums comme lus
Strange behaviour of static declared content.

Réponse
 
LinkBack Outils de la discussion
Vieux 18/10/2007, 12h02   #1
Nathan Nobbe
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: [PHP] Strange behaviour of static declared content.

On 10/18/07, Joshua Bacher <bacher@bash-it.de> wrote:
>
> Hi all,
>
> i faced the following problem.
>
> i am using a API. This API has a class that looks like following:
> <snip>
> class foo{
> public function bar(){
> static $foobar=false;
> if ($foobar === False){
> $foobar='FUBeyondAllR';
> echo "$foobar\n";
> }else{echo "already defined\n";}
> }
> }
> </snip>
> if you call the method of this class twice it will first print
> FUBeyondAllR and at the second time it will echo 'already defined'.
> (examples at the next and the last snippet)
>
> thats fine but what if you have some processing in the first if case? it
> would make sense then to unset this variable, right? No way, you can't
> acces it:
>
> <snip>
> $f=new foo();
> $f->bar();
> $f->bar();
> foo::$foobar=false;
> $f->bar();
> </snip>
>
> will lead to the following (called by `php5 fubar.php`):
>
> <snip>
> FUBeyondAllR
> already defined
>
> Fatal error: Access to undeclared static property: foo::$foobar in xxxxx
> on line 14
> </snip>
>
> I need to recall the expressions encapsulated in the if-statement, but
> this
> fu variable behaves like it is protected, right? Does that make sense? Is
> there
> any way to unset this variable?
>
> I can't touch the API.
>
> Thanks for your suggestions and your time.
>
> josh
>


i have never use static variables inside of functions and likely never will.
go for static class variables instead

<?php
class foo{
public static $foobar = false;
public function bar(){
static $foobar=false;
if (self::$foobar === False){
self::$foobar='FUBeyondAllR';
echo self::$foobar . "\n";
}else{echo "already defined\n";}
}
}

$f=new foo();
$f->bar();
$f->bar();
foo::$foobar=false;
$f->bar();
?>

nathan@devel ~/working/www/siuConference $ php testScript.php
FUBeyondAllR
already defined
FUBeyondAllR

-nathan

  Réponse avec citation
Vieux 18/10/2007, 12h29   #2
Colin Guthrie
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Strange behaviour of static declared content.

Joshua Bacher wrote:

>> nathan@devel ~/working/www/siuConference $ php testScript.php
>> FUBeyondAllR
>> already defined
>> FUBeyondAllR
>>
>> -nathan

>
> thats the solution for the wrong problem. it's not up to me to change
> the API. the API is designed like i noted and i need a way to get around
> this behaviour.
>
> thanks for your idea any further suggestions?


As far as I know you can't change it. The static variable you need to
adjust is inside the function, not the class and thus it is
fundamentally not accessible outside of the function.

Even creating a new foo() class will not allow you to adjust the value
of $foobar inside the bar() method.

Col
  Réponse avec citation
Vieux 18/10/2007, 12h32   #3
Stut
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: [PHP] Strange behaviour of static declared content.

Joshua Bacher wrote:
>> I can't touch the API.
>>
>> i have never use static variables inside of functions and likely never will.
>> go for static class variables instead
>>
>> <?php
>> class foo{
>> public static $foobar = false;
>> public function bar(){
>> static $foobar=false;
>> if (self::$foobar === False){
>> self::$foobar='FUBeyondAllR';
>> echo self::$foobar . "\n";
>> }else{echo "already defined\n";}
>> }
>> }
>>
>> $f=new foo();
>> $f->bar();
>> $f->bar();
>> foo::$foobar=false;
>> $f->bar();
>> ?>
>>
>> nathan@devel ~/working/www/siuConference $ php testScript.php
>> FUBeyondAllR
>> already defined
>> FUBeyondAllR
>>
>> -nathan

>
> thats the solution for the wrong problem. it's not up to me to change
> the API. the API is designed like i noted and i need a way to get around
> this behaviour.
>
> thanks for your idea any further suggestions?


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();

-Stut

--
http://stut.net/
  Réponse avec citation
Vieux 18/10/2007, 12h38   #4
Nathan Nobbe
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: [PHP] Strange behaviour of static declared content.

On 10/18/07, Joshua Bacher <bacher@bash-it.de> wrote:
>
> thats the solution for the wrong problem. it's not up to me to change
> the API. the API is designed like i noted and i need a way to get around
> this behaviour.
>
> thanks for your idea any further suggestions?
>
> josh
>


unfortunately i dont know of a way to modify the value of that variable from
anywhere outside
the function in which it is defined.

-nathan

  Réponse avec citation
Vieux 18/10/2007, 12h40   #5
Nathan Nobbe
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: [PHP] Strange behaviour of static declared content.

On 10/18/07, Stut <stuttle@gmail.com> wrote:
>
> Joshua Bacher wrote:
> >> I can't touch the API.
> >>
> >> i have never use static variables inside of functions and likely never

> will.
> >> go for static class variables instead
> >>
> >> <?php
> >> class foo{
> >> public static $foobar = false;
> >> public function bar(){
> >> static $foobar=false;
> >> if (self::$foobar === False){
> >> self::$foobar='FUBeyondAllR';
> >> echo self::$foobar . "\n";
> >> }else{echo "already defined\n";}
> >> }
> >> }
> >>
> >> $f=new foo();
> >> $f->bar();
> >> $f->bar();
> >> foo::$foobar=false;
> >> $f->bar();
> >> ?>
> >>
> >> nathan@devel ~/working/www/siuConference $ php testScript.php
> >> FUBeyondAllR
> >> already defined
> >> FUBeyondAllR
> >>
> >> -nathan

> >
> > thats the solution for the wrong problem. it's not up to me to change
> > the API. the API is designed like i noted and i need a way to get around
> > this behaviour.
> >
> > thanks for your idea any further suggestions?

>
> 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();



this doesnt work:

nathan@devel ~/working/www/siuConference $ php testScript.php
FUBeyondAllR
already defined
already defined
already defined

-nathan

  Réponse avec citation
Vieux 18/10/2007, 13h08   #6
Nathan Nobbe
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: [PHP] Strange behaviour of static declared content.

On 10/18/07, Nathan Nobbe <quickshiftin@gmail.com> wrote:
>
> On 10/18/07, Joshua Bacher <bacher@bash-it.de> wrote:
> >
> > thats the solution for the wrong problem. it's not up to me to change
> > the API. the API is designed like i noted and i need a way to get around
> > this behaviour.
> >
> > thanks for your idea any further suggestions?
> >
> > josh
> >

>
> unfortunately i dont know of a way to modify the value of that variable
> from anywhere outside
> the function in which it is defined.
>
> -nathan
>



i bet even Robert cant change that one

-nathan

  Réponse avec citation
Vieux 18/10/2007, 13h20   #7
Stut
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: [PHP] Strange behaviour of static declared content.

Stut wrote:
> Joshua Bacher wrote:
>>> I can't touch the API.
>>>
>>> i have never use static variables inside of functions and likely
>>> never will.
>>> go for static class variables instead
>>>
>>> <?php
>>> class foo{
>>> public static $foobar = false;
>>> public function bar(){
>>> static $foobar=false;
>>> if (self::$foobar === False){
>>> self::$foobar='FUBeyondAllR';
>>> echo self::$foobar . "\n";
>>> }else{echo "already defined\n";}
>>> }
>>> }
>>>
>>> $f=new foo();
>>> $f->bar();
>>> $f->bar();
>>> foo::$foobar=false;
>>> $f->bar();
>>> ?>
>>>
>>> nathan@devel ~/working/www/siuConference $ php testScript.php
>>> FUBeyondAllR
>>> already defined
>>> FUBeyondAllR
>>>
>>> -nathan

>>
>> thats the solution for the wrong problem. it's not up to me to change
>> the API. the API is designed like i noted and i need a way to get around
>> this behaviour.
>>
>> thanks for your idea any further suggestions?

>
> 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.

I think you're out of luck. You need to find a way to override this
behaviour. Can you not add a function to the API to reset that static?
That wouldn't break the existing contract but would let you do what you
need.

-Stut

--
http://stut.net/
  Réponse avec citation
Vieux 18/10/2007, 13h41   #8
Jay Blanchard
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut RE: [PHP] Strange behaviour of static declared content.

[snip]
to be honest i meanwhile have a workaround.
[/snip]

How about extending the API class and putting the function within the
extended class that you need?
  Réponse avec citation
Vieux 18/10/2007, 13h50   #9
Joshua Bacher
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Strange behaviour of static declared content.

Hi all,

i faced the following problem.

i am using a API. This API has a class that looks like following:
<snip>
class foo{
public function bar(){
static $foobar=false;
if ($foobar === False){
$foobar='FUBeyondAllR';
echo "$foobar\n";
}else{echo "already defined\n";}
}
}
</snip>
if you call the method of this class twice it will first print
FUBeyondAllR and at the second time it will echo 'already defined'.
(examples at the next and the last snippet)

thats fine but what if you have some processing in the first if case? it
would make sense then to unset this variable, right? No way, you can't
acces it:

<snip>
$f=new foo();
$f->bar();
$f->bar();
foo::$foobar=false;
$f->bar();
</snip>

will lead to the following (called by `php5 fubar.php`):

<snip>
FUBeyondAllR
already defined

Fatal error: Access to undeclared static property: foo::$foobar in xxxxx on line 14
</snip>

I need to recall the expressions encapsulated in the if-statement, but this
fu variable behaves like it is protected, right? Does that make sense? Is there
any way to unset this variable?

I can't touch the API.

Thanks for your suggestions and your time.

josh


--
--------------------------------
joshua bacher
Max Planck Institute for Evolutionary Anthropology
Deutscher Platz 6
04103 LEIPZIG
Germany
web: http://bacher.bash-it.de
--------------------------------
  Réponse avec citation
Vieux 18/10/2007, 14h10   #10
Joshua Bacher
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: [PHP] Strange behaviour of static declared content.

> I can't touch the API.
>
> i have never use static variables inside of functions and likely never will.
> go for static class variables instead
>
> <?php
> class foo{
> public static $foobar = false;
> public function bar(){
> static $foobar=false;
> if (self::$foobar === False){
> self::$foobar='FUBeyondAllR';
> echo self::$foobar . "\n";
> }else{echo "already defined\n";}
> }
> }
>
> $f=new foo();
> $f->bar();
> $f->bar();
> foo::$foobar=false;
> $f->bar();
> ?>
>
> nathan@devel ~/working/www/siuConference $ php testScript.php
> FUBeyondAllR
> already defined
> FUBeyondAllR
>
> -nathan


thats the solution for the wrong problem. it's not up to me to change
the API. the API is designed like i noted and i need a way to get around
this behaviour.

thanks for your idea any further suggestions?

josh

--
--------------------------------
joshua bacher
Max Planck Institute for Evolutionary Anthropology
Deutscher Platz 6
04103 LEIPZIG
Germany
web: http://bacher.bash-it.de
--------------------------------
  Réponse avec citation
Vieux 18/10/2007, 14h48   #11
Colin Guthrie
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Strange behaviour of static declared content.

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?

Col
  Réponse avec citation
Vieux 18/10/2007, 15h19   #12
Nathan Nobbe
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: [PHP] Re: Strange behaviour of static declared content.

On 10/18/07, Colin Guthrie <gmane@colin.guthr.ie> 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?



i didnt see anything in the manual regarding the use of static inside a
class member function.
i would consider the behavior undefined, for php, unless someone can procure
a doc.

-nathan

  Réponse avec citation
Vieux 18/10/2007, 15h35   #13
Joshua Bacher
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: [PHP] Strange behaviour of static declared content.

> >>> I can't touch the API.
> >>>
> >>>i have never use static variables inside of functions and likely
> >>>never will.
> >>>go for static class variables instead
> >>>
> >>><?php
> >>>class foo{
> >>> public static $foobar = false;
> >>> public function bar(){
> >>> static $foobar=false;
> >>> if (self::$foobar === False){
> >>> self::$foobar='FUBeyondAllR';
> >>> echo self::$foobar . "\n";
> >>> }else{echo "already defined\n";}
> >>> }
> >>>}
> >>>
> >>>$f=new foo();
> >>>$f->bar();
> >>>$f->bar();
> >>>foo::$foobar=false;
> >>>$f->bar();
> >>>?>
> >>>
> >>>nathan@devel ~/working/www/siuConference $ php testScript.php
> >>>FUBeyondAllR
> >>>already defined
> >>>FUBeyondAllR
> >>>
> >>>-nathan
> >>
> >>thats the solution for the wrong problem. it's not up to me to change
> >>the API. the API is designed like i noted and i need a way to get around
> >>this behaviour.
> >>
> >>thanks for your idea any further suggestions?

> >
> >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.
>
> I think you're out of luck. You need to find a way to override this
> behaviour. Can you not add a function to the API to reset that static?
> That wouldn't break the existing contract but would let you do what you
> need.
>


to be honest i meanwhile have a workaround. i could suppress the call of
the function for the first time and therefore suppressed the
initializing of $foobar. now it is only running at the time i need it,
with the parameters that i want it to run with.

For me it's just a question of interest. At least, i would say, php
behaves somehow uncool in this situation. But on the other hand it can
also be a nice feature if you want a variable just to be initialized
once and protect it afterwards from arbitrary access. i am unsure how to
feel about it. if you want a protected variable why don't you declare it
as protected?

i thank you very much for all you suggestions. maybe it's a good thing
to ask for this as a feature request.

thank you all

josh

--
--------------------------------
joshua bacher
Max Planck Institute for Evolutionary Anthropology
Deutscher Platz 6
04103 LEIPZIG
Germany
web: http://bacher.bash-it.de
--------------------------------
  Réponse avec citation
Vieux 18/10/2007, 17h49   #14
Joshua Bacher
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: [PHP] Strange behaviour of static declared content.

> [snip]
> to be honest i meanwhile have a workaround.
> [/snip]
>
> How about extending the API class and putting the function within the
> extended class that you need?


it's only partially a solution since the API will change. therefore the
expressions in the if statement maybe will change.

if i extend the class i would have to overwrite the function with my
version. In fact this will solve my problem, but i will not be able to
gain from the updates of newer versions for that function in the API,
right? Thats a solution but it will result in many more problems in the
end. I could merge all the time, but thats sloppy, i don't want that, i
am to lazy for doing that

thanks anyway

josh

--
--------------------------------
joshua bacher
Max Planck Institute for Evolutionary Anthropology
Deutscher Platz 6
04103 LEIPZIG
Germany
web: http://bacher.bash-it.de
--------------------------------


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQFHF45/oQ1PzKVWDx0RAmO0AJ9Drx9sfzdSipkZK6qPIlOOHT8zWgCeMT go
ogCGPJtjKjbN7vU/ywIYfL0=
=p65J
-----END PGP SIGNATURE-----

  Réponse avec citation
Vieux 19/10/2007, 10h21   #15
Stut
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: [PHP] Re: Strange behaviour of static declared content.

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.

-Stut

--
http://stut.net/
  Réponse avec citation
Vieux 19/10/2007, 10h38   #16
Colin Guthrie
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Strange behaviour of static declared content.

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

Col
  Réponse avec citation
Vieux 19/10/2007, 10h43   #17
Stut
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: [PHP] Strange behaviour of static declared content.

Nathan Nobbe wrote:
> On 10/18/07, Nathan Nobbe <quickshiftin@gmail.com> wrote:
>> On 10/18/07, Joshua Bacher <bacher@bash-it.de> wrote:
>>> thats the solution for the wrong problem. it's not up to me to change
>>> the API. the API is designed like i noted and i need a way to get around
>>> this behaviour.
>>>
>>> thanks for your idea any further suggestions?
>>>
>>> josh
>>>

>> unfortunately i dont know of a way to modify the value of that variable
>> from anywhere outside
>> the function in which it is defined.
>>
>> -nathan
>>

>
>
> i bet even Robert cant change that one


Runkit could probably do it, but I wouldn't recommend that to anyone.

-Stut

--
http://stut.net/
  Réponse avec citation
Vieux 19/10/2007, 10h50   #18
Stut
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: [PHP] Re: Strange behaviour of static declared content.

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.

-Stut

--
http://stut.net/
  Réponse avec citation
Vieux 19/10/2007, 11h31   #19
Colin Guthrie
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Strange behaviour of static declared content.

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:isplay(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.
  Réponse avec citation
Vieux 19/10/2007, 11h47   #20
Stut
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: [PHP] Re: Strange behaviour of static declared content.

Colin Guthrie wrote:
> 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.


I see what you mean. You thought that static variables in a member
function of a class would be different for each instance of that class.
Indeed that's not the case, statics are attached to the class not the
object.

As for the problem of dealing with failed initialisations there are two
ways to deal with that. The first is to us a separate initialisation
method - this allows it to return a value. Your constructor would simply
fill the object with sensible defaults.

The second is to have a member variable that stores whether the object
has been successfully initialised. Either of these would be far better
than using a static variable since initialisation status is a property
of the object not the class.

Anyways, glad we both understand some things a bit better now. On to the
next problem!

-Stut

--
http://stut.net/
  Réponse avec citation
Réponse


Outils de la discussion

Règles de messages
Vous ne pouvez pas créer de nouvelles discussions
Vous ne pouvez pas envoyer des réponses
Vous ne pouvez pas envoyer des pièces jointes
Vous ne pouvez pas modifier vos messages

Les balises BB sont activées : oui
Les smileys sont activés : oui
La balise [IMG] est activée : oui
Le code HTML peut être employé : non
Trackbacks are oui
Pingbacks are oui
Refbacks are oui


Fuseau horaire GMT +1. Il est actuellement 17h26.


Édité par : vBulletin® version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0 RC5 Tous droits réservés.
Version française #16 par l'association vBulletin francophone
PHWinfo est un site Éducation Sans Frontières ©2000-2008
Ad Management by RedTyger
©Tous droits réservés par les parties respectives