Let's say I have an entity (a stone) and I have a few more specific entities, that extend the basic enity - a talking stone for example, which have a few different properties and methods. All the properties of a stone are stored in the database in the same table. All the specific properties of a specific object are stored serialized in the field "specific_options" of the table. I have the class "Stone", and the class "Talking_Stone", which extends the basic stone class. I need to create a stone object based on the data I get from the database.
What is the best practice to emplement such thing?
What I've got so far:
class Stone_Data {
...
public static function get_item( $id ) {
$sql = 'SELECT * FROM `' . self::$table . '` WHERE `id`=' . ( int ) $id;
$item = self::$db->get_row( $sql );
return $item;
}
...
}
class Stone_Factory {
...
public static function create( $id = null ) {
// if the stone's type is set
if ( !is_null( $id ) && !is_null( $data = Stone_Data::get_item( $id ) ) && !empty( $data['type'] ) ) {
// create a stone of this type
$class_name = ucfirst( $data['type'] ) . '_Stone';
return new $class_name( $data );
}
// otherwise create a basic stone
return new Stone;
}
...
}
class Stone {
private $data = array(
...
'specific_options' => '',
...
);
...
public function __construct( $data = array() ) {
$this->set( $data );
}
...
public function __set( $name, $value ) {
if ( array_key_exists( $name, $this->data ) ) {
// serialize if the value is an array or an object
if ( is_array( $value ) || is_object( $value ) ) {
$value = serialize( $value );
}
$this->data[$name] = $value;
}
}
public function set( $data = array() ) {
foreach ( $data as $key => $value ) {
// serialize if the value is an array or an object
if ( is_array( $value ) || is_object( $value ) ) {
$data[$key] = serialize( $value );
}
}
$this->data = array_merge( $this->data, $data );
return $this;
}
...
}
class Talking_Stone extends Stone {
...
public function __construct( $data = array() ) {
parent::__construct( $data );
// $this->type = 'talking'
$this->specific_options->language = 'French';
...
}
...
}
But somehow, it doesn't feel quite right..