M-N
M-N

Reputation: 633

How to abstract php database object class to work with variable columns

I have a PHP class whose instances are rows in my database table. The class has methods that allow one to create, read, update, and delete rows corresponding to the given instance of the class. It works well as it stands, but I currently name each of the database columns explicitly in my code. As a result, when I add or delete columns (an occasional, but not trivially infrequent action), I must update the class to include those column names. I would like to abstract my code so that it queries the database first to determine what the columns it needs to fill in. (Incidentally, I'm working with PHP 7.2)

The code below is what I've got now, but I'm at a loss as to how to abstract it so that it is not tied to spelling out each specific column name.

<?php
class Example extends DatabaseObject {
    static protected $table_name = "data";
    static protected $db_columns = ['id','column1', 'column2', 'column3', 'column4'];

    public $id;
    public $column1;
    public $column2;
    public $column3; 
    public $column4;

    public function __construct($args=[]) {
        $this->column1 = $args['column1'] ?? '';
        $this->column2 = $args['column2'] ?? '';
        $this->column3 = $args['column3'] ?? '';
        $this->column4 = $args['column4'] ?? '';
    }

    public function attributes() {
      $attributes = [];
      foreach (static::$db_columns as $column) {
        if ($column === "id") { continue; }
        $attributes[$column] = $this->$column;
      }
      return $attributes;
    }

    public function save() {
        // calls private methods to validate, sanitize, then create or update, acc. to context
        // to create, it preps an sql statement based on a call to attributes()
    }

}
?>

Upvotes: 0

Views: 511

Answers (2)

ryantxr
ryantxr

Reputation: 4219

I'm not sure how far you want to take this. This is one way that you can abstract the data for a row.

You will notice that I use set and get functions to access the data.

class Example extends DatabaseObject {
    static protected $table_name = "data";
    static protected $db_columns = ['id', 'column1', 'column2', 'column3', 'column4'];

    public $id;
    protected $data = [];

    public function __construct($args=[]) {
        foreach(self::$db_columns as $columnName) {
            if ( isset($args[$columnName]) ) {
                $this->data[$columnName] = $args[$columnName];
            }
        }
    }

    public function set($columnName, $value)
    {
        if ( in_array($columnName, $this->data) && isset($this->data[$columnName]) ) {
            $this->data[$columnName] = $value;
        }
    }

    public function get($columnName)
    {
        if ( isset($this->data[$columnName]) ) {
            return $this->data[$columnName];
        }
        return null;
    }

    public function attributes() {
      $attributes = [];
      foreach (static::$db_columns as $columnName) {
        if ($column === "id") { continue; }
        $attributes[$columnName] = $this->data[$columnName];
      }
      return $attributes;
    }

    public function save() {
        // calls private methods to validate, sanitize, then create or update, acc. to context
        // to create, it preps an sql statement based on a call to attributes()
    }
}

Upvotes: 1

Roberto Maldonado
Roberto Maldonado

Reputation: 1595

You may need to look at the magic methods __get() and __set(). Basically, they are class methods that are triggered when trying to access a property that doesn't exist in your class, so you can have a fallback for them.

Please take a look at the documentation: https://www.php.net/manual/en/language.oop5.overloading.php#object.set

Upvotes: 0

Related Questions