简体   繁体   中英

PHP: How to get a class member variable from a static method?

I am trying to create an abstract Model class that has a static fetchAll method. Subclasses need to specify the name/location that will be used in the fetchAll method. However, I can't figure out how to specify the protected $_name method in a way that is accessible from both the static method and non-static methods. This is what I have so far:

abstract class Model
{
    protected $_name;

    public static function fetchAll()
    {
        $request = new ApiRequest();
        return $request->get($this->_name);
    }

    public function save()
    {
        $request = new ApiRequest();
        return $request->put($this->_name, $this->_data);
    }
}

class Email extends Model
{
    protected $_name = 'zEmailz';
}

Did you consider passing the name as an argument to the fetchAll() method?

class Email extends Model
{
    protected $_name = 'zEmailz';

    public function getResults()
    {  
        $rows = parent::fetchAll($this->$_name);
    }    
}

I wouldn't recommend setting the Model::$_name to static, as any possible iterations may override the value and make it difficult to ensure the current value matches what you want. This is one of the many pitfalls of co-mingling static and instantiated members.

-- Update --

You could pass the object into the fetchAll call, sort of (say sort of b/c I never co-mingled DI with static calls) a dependency injection solution:

// Calling code
$email = new Email();

// Do stuff with $email

$results = Model::fetchAll($email);

Then the model class looks like:

abstract class Model
{
    public static function fetchAll($object)
    {
        $request = new ApiRequest();
        return $request->get($object->_name);
    }
}

-- Update #2 --

Based on your comment you are looking for a method to retrieve rows from the database and hydrate the primary objects so you can reference current values via OO API calls. If I were you would take a look at Doctrine , rather than re-invent the wheel. In Doctrine they have what are known as 'table' classes which are directly related to a model class. For example, you would have an EmailTable.php file, and in this class you would add custom methods to return datasets you wanted.

If you still want to stick with your own way of doing this, then you may want to move the fetchAll method into each child class, otherwise if you keep it in the parent class you are going to end up with a nasty switch/case block for all objects you want to hydrate.

Example (demonstrative only):

class Email extends Model
{
    protected $_name = 'zEmailz';

    public static function fetchAll()
    {
        // However you pull rows from DB

        while ($row = get_current_row) {

            $email = new Email();

            $email->setAddress($row['address']);
            ...

            $emails[] = $email;
        }

        return $emails;
    }
}

Just declare the variable as static:

protected static $_name;

And access it using the self or static keyword, depending on whether you want late static binding or not:

return $request->get(static::$_name);

if you want to access your static _name variable from static methods use self::$_name

But it's not a good idea to use static method into base class Realize, that this method will be proccess only static data (common for all descendants). So, if you want to access to the all names of descendants, you must add static array of your models names, also you can store params, classname or link to your descendant objects. Then you can access to all descendants or just select one by name or by classname, or by other some id from stored params.

I can be wrong, but if the model is an abstract class, they not have the responsibility to know who is using them. They only specifies that all class that inherit from him, will have a fetchall method, this method can have implementation or not, but he must exists.

If you have a entity that inherits from Abstract Model Class, should be called using the signature Entity::fetchall().

The Entity::fetchall() can internally call the parent::fetchall($name) or similar, with this way, you can isolate the responsibility of who uses whom.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM