Reputation: 9658
I'm a relative newcomer to PHP, and I'm figuring out the best way to implement some database access code. I'm trying to create some simple database access objects -- each table gets its own class, each instance of the class represents a row in the table, you know the drill.
I have code that seems to be working, but some of what I've seen online makes me worry that my approach may be wrong-headed somehow. And since "Can I do this?" and "SHOULD I do this?" are two different questions, I was hoping some PHP vets could chime in.
My current strategy is to create a base-level abstract Table class that contains all the common code and then have each class representing an individual table extend it.
My main concern is this code:
abstract class Table {
protected abstract static function get_fields();
protected abstract static function get_primary_key();
protected abstract static function get_table_name();
The idea is that each implementing class will define the field names, the primary key(s), the table name, etc., and then the Table class will use those functions to fill in specific blanks, like so:
static function insert($values) {
$field_list = array();
$value_list = array();
foreach (static::get_fields() as $field_name) {
if (isset($values[$field_name])) {
$field_list[] = $field_name;
$value_list[] = self::escape($values[$field_name]);
}
}
$field_string = join(", ", $field_list);
$value_string = "'" . join("', '", $value_list) . "'";
$sql = "insert into " . static::get_table_name() . " ($field_string) values ($value_string)";
As you can see, the key is that I'm accessing those static abstract
functions by prefacing them with static::
. And as far as I can tell, it's working!
However, the accepted answer to this question indicates that abstract static
functions still aren't allowed in 5.3.
So, I'm trying to figure out what to make of this. Is the answer wrong -- are abstract static
functions now considered perfectly legal PHP code? Am I doing something inadvisable in my code? Is there another approach I ought to consider?
Upvotes: 11
Views: 14578
Reputation: 68810
Here's your example
abstract class Table implements iTable {
public static function insert() {
$class = get_called_class();
$sql = 'INSERT INTO '.$class::get_class_name();
echo $sql;
}
}
interface iTable {
static function get_class_name();
}
class ConcreteTable extends Table
{
public function ConcreteTable() {}
static function get_class_name() {
return 'ConcreteTable';
}
}
$t = new ConcreteTable();
$t::insert();
This example respects object paradigm, and you're sure it'll work even if PHP stop support late static bindings (which is a PHP specificity, I think)
Edit: What both answers show is that it's unknown that an abstract class introduces an interface as well for classes extending from it. Following the template pattern, this is possible in PHP even with static functions (albeit for a good reason that gives you strict standard warnings). The proof of concept:
abstract class Table
{
abstract static function get_class_name();
public static function insert() {
printf('INSERT INTO %s', static::get_class_name());
}
}
class ConcreteTable extends Table
{
public static function get_class_name() {
return 'ConcreteTable';
}
}
ConcreteTable::insert();
If you remove the static keywords here, you actually will get useful (and a standard way of doing things) code:
abstract class Table
{
protected $table = NULL;
public function insert() {
printf('INSERT INTO %s', $this->table);
}
}
class ConcreteTable extends Table
{
protected $table = 'ConcreteTable';
}
$table = new ConcreteTable();
...
$table->insert();
Upvotes: 17
Reputation: 68810
An abstract function will never be static, in any kind of language.
A static function provide a functionality, even if there is no instance.
An abstract function doesn't provide any functionnality.
Logically, you can't use an abstract static function, which would --ALWAYS AND NEVER-- provide a functionnality.
B extends A
When you call a static function in B context, it'll be runned in A context (cause of static state).
But, in A context, this same function is abstract, an you're not allowed to call it.
Upvotes: 7