Reputation: 238727
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';
}
Upvotes: 1
Views: 2324
Reputation: 19989
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;
}
}
Upvotes: 3
Reputation: 727
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.
Upvotes: 1
Reputation: 116
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.
Upvotes: 1
Reputation: 1149
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);
Upvotes: 2