SitePoint Sponsor

User Tag List

Results 1 to 13 of 13
  1. #1
    SitePoint Member
    Join Date
    Apr 2009
    Posts
    2
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    How do you access a child static var from its abstract superclass?

    I have an abstract superclass called Object. Then I have a child class called Comment. Comment has a static variable that I want to be able to access from a static function in Object (obviously without instantiating either).

    In Comment I have

    Code:
    protected static $tableName = "comments";
    Then in Object I have

    Code:
    public static function getTableName()
    {
      return self::$tableName;
    }

    Then I call it like this:

    Code:
    Comment::getTableName();
    This gives me: Fatal error: Access to undeclared static property: Object::$tableName

    It makes sense to a degree, Object doesn't have a static property called $tableName, but Comment does, and I'm calling Comment::getTableName(), so I thought, if it knows enough to execute the parent function, then it should also know that it's a Comment.

    The overall idea that I'm going for is that each object type (like Comment or Blog) will know everything about itself, including its database table name. Sometimes I need to get that table name without creating an instance of a Comment (or Blog) because in my code I do a select statement that also asks the DB if a User has Comments on them, and if they don't it does nothing, but if they do it retrieves all the comments for that user and then makes instances of Comment to load the comments into them.

  2. #2
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Treat a class, even an abstract class, as if it's not going to be extended.

    Any variable accessed by a function in that class, even if its a parent class, should have the variable declared.

    Try adding:
    PHP Code:
    protected static $tableName
    to the 'Object' superclass.
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  3. #3
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,194
    Mentioned
    17 Post(s)
    Tagged
    5 Thread(s)
    Your best bet is to use get_class_vars and read in the properties to a configuration object of some type. Before 5.3 late static binding isn't supported.

  4. #4
    SitePoint Member
    Join Date
    Apr 2009
    Posts
    2
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by arkinstall View Post
    Try adding:
    PHP Code:
    protected static $tableName
    to the 'Object' superclass.
    When I do this the error goes away, *but* the correct $tableName is not accessed. It just accesses Object's $tableName (which is obviously empty), it does not access the child's $tableName which is what I actually want it to do.


    Quote Originally Posted by oddz View Post
    Your best bet is to use get_class_vars and read in the properties to a configuration object of some type. Before 5.3 late static binding isn't supported.
    It appears get_class_vars is the solution. I think I'll make a function in Object that accepts a class name, and then uses get_class_vars on that classname and picks out just the tableName and returns it. Thanks!

  5. #5
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    The best solution is not to use static. get_class_vars does not work on anything but public properties.
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  6. #6
    SitePoint Enthusiast
    Join Date
    Jul 2005
    Location
    Norway
    Posts
    88
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    In php 5.3 one can use the get_called_class to get the name of the child-class and then use the call_user_func_array to call a method on the child class (f.ex getTableName). If you don't use 5.3 there is a hack which can replicate the behaviour of the get_called_class to a certain degree using the debug_backtrace..

  7. #7
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,194
    Mentioned
    17 Post(s)
    Tagged
    5 Thread(s)
    Yeah, you will need to make the properties public.

  8. #8
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,194
    Mentioned
    17 Post(s)
    Tagged
    5 Thread(s)
    Very simple example of what I was referring to doing.

    PHP Code:
    class ModelConfig {

        protected 
    $table;
        
        public function 
    __construct($className) {
        
            if(!
    class_exists($className)) {
            
                throw new 
    Exception('Class '.$className.' doesn\'t exist.');
            
            } else {
            
                
    $this->_init($className);
            
            }
        
        }
        
        protected function 
    _init($className) {
        
            
    $vars get_class_vars($className);
            
            if(
    array_key_exists('table',$vars)) {
                
    $this->table $vars['table'];
            }
        
        }
        
        public function 
    getTable() {
        
            return 
    $this->table;
        
        }



  9. #9
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I don't even want to read the whole thread, I see the mistaken assumption in the subject question and in the first lines of the OP. The answer is: you don't. Classes don't access anything, their instances do. Go learn a bit more about OOP.

  10. #10
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,194
    Mentioned
    17 Post(s)
    Tagged
    5 Thread(s)
    Classes may access static members and objects may access dynamic and static members.

    The problem is summarized here well.

  11. #11
    SitePoint Addict
    Join Date
    Feb 2007
    Posts
    270
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Try

    Child::static_var

    to directly access the variable. It can't be protected, though. If it's protected, then I think you can do it via

    Child::get_static_var()

    so long as the getter is static and not protected.

    In your first example, change "self::" to "Comment::" and it should work. There's no such thing as "self" until the object is instantiated, and you look to be calling for the class, not an instantiated object.

  12. #12
    SitePoint Enthusiast
    Join Date
    May 2007
    Posts
    74
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by blud View Post
    I have an abstract superclass called Object. Then I have a child class called Comment. Comment has a static variable that I want to be able to access from a static function in Object (obviously without instantiating either).

    In Comment I have

    Code:
    protected static $tableName = "comments";
    Then in Object I have

    Code:
    public static function getTableName()
    {
      return self::$tableName;
    }

    Then I call it like this:

    Code:
    Comment::getTableName();
    This gives me: Fatal error: Access to undeclared static property: Object::$tableName

    It makes sense to a degree, Object doesn't have a static property called $tableName, but Comment does, and I'm calling Comment::getTableName(), so I thought, if it knows enough to execute the parent function, then it should also know that it's a Comment.

    The overall idea that I'm going for is that each object type (like Comment or Blog) will know everything about itself, including its database table name. Sometimes I need to get that table name without creating an instance of a Comment (or Blog) because in my code I do a select statement that also asks the DB if a User has Comments on them, and if they don't it does nothing, but if they do it retrieves all the comments for that user and then makes instances of Comment to load the comments into them.
    from title, i know the OP made a design mistake.
    access child from parent is definitely a design error.

    also, static variable bound to class, that why you got error , " Access to undeclared static property".

    by the way, which version of PHP you use? is getTableName() also in Comment class?
    Last edited by ctx2002; Apr 23, 2009 at 13:40. Reason: adding more

  13. #13
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,194
    Mentioned
    17 Post(s)
    Tagged
    5 Thread(s)
    Nope, you can accomplish this using objects.

    PHP Code:
    class Foo {

        protected 
    $test 'foo';
        
        public function 
    getTest() {
            return 
    $this->test;
        }

    }

    class 
    Bar extends Foo {

        protected 
    $test 'bar';

    }

    $foo = new Foo();
    $bar = new Bar();
    echo 
    '<p>',$foo->getTest(),'</p>'// foo
    echo '<p>',$bar->getTest(),'</p>'// bar 
    Notice even though the method resides inside the super class it is intelligent enough to resolve the test property to the current object. However, when made static this is not the case.

    PHP Code:
    class Foo {

        protected static 
    $test 'foo';
        
        public static function 
    getTest() {
            return 
    self::$test;
        }

    }

    class 
    Bar extends Foo {

        protected static 
    $test 'bar';

    }


    echo 
    '<p>',Foo::getTest(),'</p>'// foo
    echo '<p>',Bar::getTest(),'</p>'// foo 


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •