11

我是 PHP 的新手,我正在寻找实现一些数据库访问代码的最佳方法。我正在尝试创建一些简单的数据库访问对象——每个表都有自己的类,类的每个实例都代表表中的一行,你知道的。

我的代码似乎可以正常工作,但是我在网上看到的一些内容让我担心我的方法可能会以某种方式出错。自从“我可以这样做吗?” “我应该这样做吗?” 是两个不同的问题,我希望一些 PHP 兽医能加入进来。

我目前的策略是创建一个包含所有公共代码的基本抽象 Table 类,然后让每个代表单个表的类扩展它。

我主要关心的是这段代码:


abstract class Table {
    protected abstract static function get_fields();
    protected abstract static function get_primary_key();
    protected abstract static function get_table_name();

这个想法是每个实现类将定义字段名、主键、表名等,然后 Table 类将使用这些函数来填充特定的空白,如下所示:


    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)";

如您所见,关键是我static abstract通过在它们前面加上static::. 据我所知,它正在工作!

但是,这个问题的公认答案表明abstract static5.3 中仍然不允许使用函数。

所以,我想弄清楚该怎么做。答案是否错误——现在abstract static函数是否被认为是完全合法的 PHP 代码?我在我的代码中做了一些不可取的事情吗?我应该考虑另一种方法吗?

4

2 回答 2

17

这是你的例子

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();

这个例子尊重对象范式,即使 PHP 停止支持后期静态绑定(我认为这是 PHP 的特殊性),您也确信它会工作

编辑:两个答案都表明,抽象类引入接口以及从它扩展的类是未知的。遵循模板模式,这在 PHP 中即使使用静态函数也是可能的(尽管有充分的理由给您提供严格的标准警告)。概念证明:

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();

如果您在此处删除静态关键字,您实际上将获得有用的(和标准的做事方式)代码:

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();
于 2012-05-24T17:10:07.500 回答
6

在任何语言中,抽象函数都不会是静态的。

静态函数提供功能,即使没有实例。

抽象函数不提供任何功能。

从逻辑上讲,您不能使用抽象的静态函数,它会 -- 总是 -- 永远不会 -- 提供功能。


B 扩展 A

当您在 B 上下文中调用静态函数时,它将在 A 上下文中运行(由于静态)。

但是,在 A 上下文中,这个相同的函数是抽象的,你不能调用它。

于 2012-05-24T14:59:53.290 回答