Hello Everyone,

I have a php class like this:

class DatabaseObject {

    protected static $table_name;
}

Then, when I extended this class, I do this:

class User extends DatabaseObject
{
    protected static $table_name = "users";
}

However, I am encountering errors "mysql_fetch_array(): supplied argument is not a valid MySQL" because the $table_name variable has no value.

Can you please give some advise regarding this concern on how to set and get the static variable?

Thanks in advance.

Recommended Answers

All 7 Replies

Seeing as the static variable is protected, you can only access it directly from within the class, or using a public method outside of the class.

To get the variable value from within the class, you can use self::$_table_name and outside of the class, use the static method as defined below.

class User extends DatabaseObject
{
    protected static $_table_name = 'users';

    public static function get_table_name()
    {
        return self::$_table_name;
    }
}

Although he did not post the important parts of the class, what I think is happening is that the table name is set in the derived class, yet the query is executed in the base class. What should be done is instead of reintroducing the variable, the parent's variable should be set:

parent::$_table_name = 'users';

My solution would be to use a regular non-static property and pass the table name in the constructor to the parent class.

If using PHP 5.3 or above, you could also use static::$_table_name to resolve the late static binding issue.

Alternatively, as you say @pritaeas, using a standard instance variable, and inheritance, the value from the child class would be used in the parent when overidden.

Thanks for the reply.

In the class to be extended, I have a function below:

class DatabaseObject {

protected static $table_name;
    public static function find_all() {
    global $database;
    $result_set = $database->get_array_result(self::find_by_sql("SELECT * FROM " . self::$table_name . " WHERE is_deleted = 0"));
    return $result_set;
    }

}

Then, in the other pages, I used the extended class like this:

User::find_by_id(1);

I added the the function below in the DatabaseObject:

public static function get_table_name()
{
return self::$table_name;
}

Then changed the function below from this. However It did not work for me.

public static function find_all() {
    global $database;
    $result_set = $database->get_array_result(self::find_by_sql("SELECT * FROM " . self::get_table_name() . " WHERE is_deleted = 0"));
    return $result_set;
}

I am currently trying pritaeas approach where I am placing a constructor in the DatabaseObject class.

However It did not work for me

Without providing more info about the two classes, it will be hard to help. We'll need to know what is overriden and what isn't.

global $database;

Really, global? Try to avoid that please. Passing it as a parameter is the recommended way.

I really think that in your case, using static is actually making it more difficult. What is the reason you use static in the first place?

I tried writing an ORM layer using static methods and PHP 5.2 and it simply didn't work, because it didn't support late static binding.

In the end, I had to settle for the approach used in the Yii framework, whereby you use a static method to create an instance of the object, so you can then use inherited instance variables instead.

E.g.

class User extends Model
{
    protected $_table = 'users';

    public static function model($class = __CLASS__)
    {
        return parent::model($class);
    }

    public function find($id)
    {
        // Find by id
    }
}

class Model
{
    public static function model($class)
    {
        return new $class;
    }
}

$user = User::model()->find(1);

If you can use PHP 5.3, then you can use late static binding, hence the inherited value static properties can be accessed in the parent class.

Thanks for the replies.

@pritaeas: Actually, this is not my code and I still trying to figure out how it was built. Thanks for the tip for the globals. I'll keep that in mind. I agree with you to pass the variables in the constructors.

@blocblue: the codes works fine with 5.3 however for some reasons, I really don't know why the server downgraded the version of the php to 5.2 so I am currently understanding and might converted the codes. I will try what you have provided.

Thanks again.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.