6

I'm working on a project where I'd like to be able to declare a static member variable inside of an abstract base class. I've got a Model class, an intermediate Post class, and finally a site-specific Post class, something like the following:

abstract class Model {
    protected static $_table    = null;
    protected static $_database = null;

    ...
}

abstract class PostModel extends Model {
    public function __construct() {
        if ( !isset(self::$_table) ) {
            self::$_table = 'some_table';
        }

        parent::__construct();
    }

    ...
}

class SitePostModel extends PostModel {
    public function __construct() {
        if ( !isset(self::$_database) ) {
            self::$_database = 'some_database';
        }

        parent::__construct();
    }

    ...
}

I'd like to make it apparent from the Model class that the $_table and $_database members are required. However, $_table is really static from the point of view of the PostModel class, and $_database is really static from the point of view of the SitePostModel class.

Is this a legitimate way to accomplish my goal? Does declaring the static variables in the Model itself imply that they should exist only once for the abstract base class, or only once for the actual instantiated class?

6
  • 4
    (reference) chapter about the static keyword and chapter about Late Static Binding. Commented Oct 17, 2011 at 18:51
  • 2
    As for whether this is legitimate or implies anything, i'd say this is subject to debate. IMO, you should not use Inheritance here at all. Also, Model does usually not imply database. Commented Oct 17, 2011 at 18:55
  • I appreciated the input @Gordon. I think 'Model does not imply database' is enough to convince me not to treat the members this way. In the immediate future, this Model class will only model database tables, but it may not always be that way. Commented Oct 17, 2011 at 19:31
  • I think Gordon is right - Late Static Bindings are your best bet, and then putting a check wherever needed to ensure the variables have an expected value. Perhaps that's in the Constructor of the SitePostModel, if you are passing those variables in as arguments or defining beforehand. Commented Oct 18, 2011 at 16:52
  • Maybe you should also consider do these variables need to be static? Your entire problem may well go away if you removed that keyword. Commented Oct 20, 2011 at 7:47

2 Answers 2

2

Is this a legitimate way to accomplish my goal?

No. It does not work, so it fails a basic test for legitimacy.

Does declaring the static variables in the Model itself imply that they should exist only once for the abstract base class, or only once for the actual instantiated class?

Static variables are global, they exist once. In your case per each classname. If you have three classnames, you would have three (global) variables. The protected keyword only controls the visibility/scope of the three static variables:

<?php

class A {
   protected static $v = 'red';
   public static function get() { return self::$v . ' - ' . static::$v;}
}

class B extends A {
   protected static $v = 'blue';
}

class C extends B {
   protected static $v = 'green';
}

echo C::get(); # red - green
Sign up to request clarification or add additional context in comments.

2 Comments

Sorry for the (incredibly) late response, but I'd just like to clarify. You've said that my solution would not work. In fact I've taken @Gordon's advice from above, and I've moved the $_table and $_database variables out of the generic Model class; however, if I had left the code as shown above, I could still use static::$_database and static::$_table in the save()/load() functions for the Model and get 'some_table' and 'some_database,' as your example shows. SitePostModel::save() would indeed work correctly and would be unique from SomeOtherSitePostModel::save(), no?
"Is this a legitimate way to accomplish my goal? No. It does not work, so it fails a basic test for legitimacy." -> Brilliant ;)
0

I recently ran into the same problem and came to the same solution - putting settings into static variables and accessing them using the static keyword. It also works in cases where you have default settings (such as number of rows per page) that you might want to override in subclasses. This just seemed like the most intuitive and efficient way.

Alternatives I've considered:

  • Use a static abstract getter function. It requires more lines of code and more function calls.
  • Keep the setting in a non-static member variable and let the child class constructor worry about it. I rejected this option because my child classes didn't otherwise need a constructor.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.