1

I'm trying to understand how PHP manages memory and variables with static methods in extended classes. I've got three classes one entitled Model, User1, User2. Hence:

class Model {
    static public $structure;
    static public $name;
    static function get_structure() {
        return self::$structure = file_get_contents(self::$name.'.json');
    }
}
class User1 extends Model {

}
class User2 extends Model {

}
User1::$name = 'User1';
User2::$name = 'User2';
echo User1::get_structure();
echo User2::get_structure();

If I run User1::get_structure(); for some reason it doesn't populate the result accordingly, it seems to be grabbing the value of User2 (the last $name value declared).

I'm operating on the assumption that declaring User2 and extending Model creates a completely separate scope for my $name property. So User1 and User2 are declared as separate classes with the same structure as Model. Then I can statically define values for them in separate scopes.

I'm now however questioning that. If I extend and call the same $name variable do they both point back to the Model class? Or does it only create a separate scope when I declare each class with new User1(); and new User2();?

Thanks.

tereško
  • 58,060
  • 25
  • 98
  • 150
pilotguy
  • 543
  • 1
  • 5
  • 18
  • If you are using static classes, it is not OOP. I am removing the tag. Also, model is a [layer](http://stackoverflow.com/a/5864000/727208) , not a class. – tereško Jul 14 '12 at 17:37

3 Answers3

1

You get this behavior, because you are accessing same variable

class X
{
    public static $data = null;
}

class Foo extends X{};
class Bar extends X{};

Foo::$data = 'lorem ipsum';
echo Bar::$data;
// :: output :: lorem ipsum;

Your $name variable stays tied to the Model class, even in inherited classes.

tereško
  • 58,060
  • 25
  • 98
  • 150
  • Excellent, that confirms precisely what I'm thinking. Thank you. – pilotguy Jul 14 '12 at 17:53
  • @pilotguy, I would actually recommend for you to try to avoid static variable. A static variable in class act like namespaced `global`. While syntax is changed, they both have same behavior and same problem that are associated with [global state](http://www.youtube.com/watch?v=-FRm3VPhseI). – tereško Jul 14 '12 at 17:58
1

Yes, all classes that extends Model will point back to the same $name variable. Sees static variable as a "global" variable.

Maybe this example will clarify you:

class Model 
{
    static public $name;
}

class User1 extends Model 
{
    public function setName( $name )
    {
        parent::$name = $name;
    }

    public function getName()
    {
        return parent::$name;
    }
}

class User2 extends Model 
{
    public function setName( $name )
    {
        parent::$name = $name;
    }

    public function getName()
    {
        return parent::$name;
    }
}

$user1 = new User1();
$user1->setName("User1");

$user2 = new User2();
$user1->setName("User2");

echo $user1->getName();
echo $user2->getName();

// Output : User2User2
jorjdaniel
  • 675
  • 5
  • 11
0

You can work around it with:

<?php
class Model {
    static public $structure;
    static public $name;
    static function get_structure() {
        $class = get_called_class();
        return $class::$structure = file_get_contents($class::$name.'.json');
    }
}
class User1 extends Model {
    static public $structure;
    static public $name;
}
class User2 extends Model {
    static public $structure;
    static public $name;
}
User1::$name = 'User1';
User2::$name = 'User2';
echo User1::get_structure();
echo User2::get_structure();

... but, you might ask yourself the question whether this design is the proper one. atm it for instance looks like they should be instances with separate values & instance methods, but that might be because of the condensed example.

Wrikken
  • 69,272
  • 8
  • 97
  • 136
  • Hmmmm this is a pretty good idea. My goal is to not force the user to instantiate the model layer until they absolutely have to. It's for ease of coding + I bet I can argue that it's good for performance as well. I'm considering a model simply an adapter to the db...all my returned datasets are framework specific "record" objects that point back to the model. – pilotguy Jul 15 '12 at 12:46