Reputation: 633
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
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
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