I've done a couple of projects recently utilizing a Database Object super class that we use for convenient one-time record query/update, and stretching with appropriate classes, like a User class.

I discovered that lots of classes I had been writing had the identical techniques: query_values(), update(), remove(), etc.

And So I emerged having a class having a constructor that appears such as this:

public function __construct($table, $db_object, $record_id = null){
    $this->db = $db_object; // Database object with query methods

    $this->table = $table; // The name of the database table

    $this->get_column_data();

    if(!is_null($record_id)){
        // This retrieves all column values, 
        // stores into private $fields array property
        $this->query_values($record_id);
    }
}

Along with a child class constructor appears like this:

public function __construct($db_object, $record_id = null){
    parent::__construct($this->table, $db_object, $record_id);
}

In which the $table rentals are defined at the very top, once we ought to know which table this unique object works together with.

Now, all common record management techniques are in one location, and techniques specific towards the class are that's defined within their particular child-classes.

The greatest drawback I see here's that data fields are drawn and therefore are exemplified inside the $fields property, so either generic get and hang techniques have to be defined (that we typically do) which almost negates the encapsulation*, or perhaps a method should be defined particularly for every property you want to expose.

*Example: $user_id = $User->id // NOT USING MY METHOD versus. $user_id = $User->_get('id') // ACCESSES $User->fields['id']

Would you check this out like a drawback, or perhaps a plus? The aim being simplicity of use, object-orientation (encapsulation), and merely being plain awesome!

Well, make your existence simple and easy , use PHP's miracle over-loading __call approach to create generic getters and setters. You could include the next approach to your "Database Object super-class":

/**
 * Create magic getter and setter methods to access private $fields array 
 */
public function __call($method, $args)
{
  $prefix = substr($method, 0, 3);
  $prop   = lcfirst(substr($method, 3));

  if (isset($this->fields[$prop])) {

    if ($prefix == 'get') {
      return $this->fields[$prop];
    } elseif ($prefix == 'set') {
      if ( ! isset($args[0])) {
        $msg = 'Missing argument: ' . get_class($this) . "::$method must specify a value";
        throw new InvalidArgumentException($msg);
      }
      $this->fields[$prop] = $args[0];
      return;
    }
  }

  $msg = 'Invalid method: ' . get_class($this) . "::$method does not exist";
  throw new BadMethodCallException($msg);
}

So allow me to explain what's happening here. The miracle __call method will get calls to any object method that doesn't match among the object's concrete techniques. It receives as parameters the title from the method which was known as and a range of its arguments.

The __call method above does a fast substr determine when the method would be a "getter" or "setter" (while using first three letters from the method title). It needs that the $fields array stores lower-situation "property" names (lcfirst) and uses everything following the setter/getter prefix because the expected property title.

If your property matches the getter method then that property it's came back. Otherwise, the SplException BadMethodCallException is tossed. This can be a best practice because the inclusion from the Spl exceptions in PHP.

Likewise a setter method will even toss the SplException InvalidArgumentException if no argument was specified.

PHP's miracle techniques can change your existence. You may also use __get and __set to assign $fields array values similarly without making faux method calls. Get excited :)