How to handle inheritance of a function with many

2019-05-30 13:48发布

问题:

I am writing a database interaction layer in PHP for MySQL. But I think this is a general OOP question (see last line).

I have a basic dbTables class. And it has a

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)
    }

But child classes will different queries to get information. They will have other allowed $methods for searching.

Here is my solution, but I don't know if it is good practice and if it will lead to more pain later. Rather than override this function in every child class, I can create a set of private static properties that will act as modifiers for the function.

Like so:

    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)
    }

To sum up, doing this will allow me to never override the getBy() method. I will only have to override the protected static properties that go with it. For DRY (don't repeat yourself), this seems good. I will only have to write 4 lines of code instead of 20+ over and over again. But I am new at this and don't know if this might be a horrible mistake for some other reason.

Is it safe and good practice to take the inheritance overriding out of the methods and put it into helper properties?

回答1:

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

seems to belong to class property, since you need to access this in your child classes to, to overwrite the behavior.

and in your child classes you can overwrite the behavior or can use the same by using parent keyword like

$allowed = parent::$allowed;

now $allowed will have the value inherited from the parent.

same goes for the method. if you want to call the parent method then use the parent keyword.

parent::getBy(); in your child classes. always remember the DRY(don't repeat yourself) principle. in your case you are repeating the code in your parent and child class. so instead use parent to call the parent method in child class. for example in your child class

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

now the child getBy() will inherit from parent. the only thing you should override is class property.