1

我正在用 PHP 为 MySQL 编写一个数据库交互层。但我认为这是一个一般的 OOP 问题(见最后一行)。

我有一个基本的 dbTables 类。它有一个

public static function getBy($method='name', $value) {
        // Gets flat table array of db Tables matching by $method == $value
        // later could implement some lookup tables.
        $allowed = array('name');
        $query_format = SHOW TABLES LIKE '%s'";
        if(in_array($method,$allowed)) {
            dbConnection::connect(MAIN_DB); // makes db connection
            $safe_value = mysql_real_escape_string($value);
            // MAY want to change this query to a SCHEMA query in CHILD classes
            $sql = sprintf($query_format,$safe_value);
            // e.g. $sql = "SHOW TABLES LIKE '$safe_value'";
            $result = mysql_query($sql);
            if($result === false) {
                debug::add('errors', __FILE__, __LINE__, __METHOD__,"Query Error for query '$sql'. MySQL said: " . mysql_error());
            }
            while($row = mysql_fetch_row($result)) {
                $db_table = new static($row[0]); // creates instance of $this class
                $object_array[] = $db_table; // add to $object_array for return value
            }
        } else {
            debug::add('errors',__FILE__, __LINE__, __METHOD__, ' - Wrong method: ' . $method . '. Currently allowed: ' . print_r($allowed,true));
            return false;
        }
    return $object_array;
    // END public static function getBy($method='name', $value)
    }

但是子类会通过不同的查询来获取信息。他们将有其他允许的 $methods 进行搜索。

这是我的解决方案,但我不知道这是否是好的做法,以及以后是否会导致更多的痛苦。我可以创建一组私有静态属性,而不是在每个子类中重写这个函数,作为函数的修饰符。

像这样:

    protected static $get_by_methods = array('name'); // array('name','id','frontend_name'…) in CHILDREN
    protected static $get_by_query_format = "SHOW TABLES LIKE '%s'"; // for sprintf. Changes in children
    protected static $get_by_handles_arrays = false; // true in CHILDREN
    protected static $get_by_query_format_array = " SELECT * FROM %s` WHERE `$method` IN ($safe_values)"; // used in CHILDREN ONLY

    public static function getBy($method, $value) {
        $allowed = self::$get_by_methods;
        $query_format = self::$get_by_query_format;
        $handle_arrays = self::$get_by_handles_arrays; // false here,,, true in children
        $query_format_array = self::$get_by_query_format_array; // used in children
        if(is_array($value) && $handle_arrays === true) {
            return false; // in child class, $handle_arrays can be set to true outside of function
                // without rewriting function. just change the static property
        }
        if(in_array($method,$allowed)) {
            dbConnection::connect(MAIN_DB);
            if(!is_array($value)) { // handle string values
                $safe_value = mysql_real_escape_string($value);
                $sql = sprintf($query_format,$safe_value);
            } else {
                // arrays used only in children
e.g. 
$safe_values = mysql_real_escape_string(implode(',',$value)); // convert to string
                $sql = sprintf($query_format_array,$safe_values); // used in children
            }
            $result = mysql_query($sql);
            if($result === false) {
                debug::add('errors', __FILE__, __LINE__, __METHOD__,"MySQL Error num " . mysql_errno() . " for query [$sql] - MySQL said: " . mysql_error());
            }
            while($row = mysql_fetch_row($result)) {
                $db_table = new dbTables($row['name']);
                $object_array[] = $db_table;        
            }
        } else { // if bad method chosen above
            debug::add('errors',__FILE__, __LINE__, __METHOD__, ' Wrong method: ' . $method . '. Must use one of these: ' . print_r($allowed,true));
            return false;
        }
    return $object_array;
    // END public static function getBy($method='name', $value)
    }

总而言之,这样做可以让我永远不会覆盖 getBy() 方法。我只需要覆盖它附带的受保护的静态属性。对于 DRY(不要重复自己),这似乎很好。我只需要编写 4 行代码,而不是一遍又一遍地编写 20 多行代码。但我对此很陌生,不知道这是否是一个可怕的错误,因为其他原因。

将继承覆盖从方法中取出并将其放入辅助属性中是否安全且良好的做法?

4

1 回答 1

0
 $allowed = array('name');
 $query_format = SHOW TABLES LIKE '%s'";

似乎属于类属性,因为您需要在子类中访问它来覆盖行为。

在您的子类中,您可以覆盖行为,也可以通过使用 parent 关键字来使用相同的行为

$allowed = parent::$allowed;

现在 $allowed 将具有从父级继承的值。

该方法也是如此。如果要调用父方法,请使用 parent 关键字。

父::getBy(); 在你的孩子班上。永远记住 DRY(不要重复自己)原则。在您的情况下,您正在重复父类和子类中的代码。所以改为使用 parent 来调用子类中的父方法。例如在你的孩子班

public function getBy()
{
    parent::getBy();
}

现在孩子 getBy() 将从父母那里继承。您唯一应该覆盖的是类属性。

于 2012-05-09T08:06:59.627 回答