Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
202 views
in Technique[技术] by (71.8m points)

php - How to prevent sharing of static variables in inherited classes?

Consider Model.php:

class Model {
    protected static $class_name;
    protected static $table_name;

    protected $id;

    public static function initialize() {
        static::$class_name = get_called_class();
        static::$table_name = strtolower(static::$class_name).'s';
    }
}

and its children, User.php and Product.php:

class User extends Model {
    protected $username;
    protected $password;
}
User::initialize();

class Product extends Model {
    protected $name;
    protected $price;
}
Product::initialize();

Since every User or Product will have the same $class_name and $table_name, it makes sense to make them static. The actual values are assigned when initialize() method is called on the child model (e.g. User::initialize(); and Product::initialize();).

Problem

I would expect to end up with the following:

User    -> $class_name -> 'User',    $table_name -> 'users'
Product -> $class_name -> 'Product', $table_name -> 'products'

Yet I get the following:

User    -> $class_name -> 'User',    $table_name -> 'users'
Product -> $class_name -> 'User',    $table_name -> 'users'

How is this possible given that I am using late static binding with static::? And how can this be fixed? My goal is for User and Product to have independent class_name and table_name, but still keep both variables static, hopefully without redeclaring them on each model, be it User, Product or any other!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

When Product::initialize is called, Model::$class_name is set to "Product" and Model::$table_name to "products". When User::initialize is called, Model::$class_name and Model::$table_name are overwritten with "User" and "users".

The static in initialize would only make a difference, if those attributes were defined in the sub classes.

The second part of your question you answered yourself, either redeclare them or make them non-static.

Edit

You could use a map in combination with accessors to fake sub-class local inherited static properties (I hope I just made that up).

class Foo {
        private static $class_names = [];
        private static $table_names = [];

        public static function getClassName() {
                return self::$class_names[static::class];
        }

        public static function getTableName() {
                return self::$table_names[static::class];
        }

        public static function initialize() {
                self::$class_names[static::class] = static::class;
                self::$table_names[static::class] = strtolower(static::class).'s';
        }
}

class Bar extends Foo {
}
Bar::initialize();

class Baz extends Foo {
}
Baz::initialize();

echo Bar::getTableName() . " " . Bar::getClassName() . "
";
echo Baz::getTableName() . " " . Baz::getClassName() . "
";

Declaring dynamic static properties does sadly not work in PHP 7.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...