You are trying to implement the Active record pattern.
An approach in object persistence is to provide a common ancestor class [e.g. BasicEntity
] every subclass extends, which builds queries based on a given data schema:
class BasicEntity
{
protected $tablename;
protected $schema;
public function update()
{
$fields = "";
$placeholders = "";
foreach($this -> schema as $field => $type)
{
// you join the fields here to get something like ('username', 'email', 'enabled', 'createdAt', 'password')
// then you write your PDO statement providing placeholders like (:?, :?, :?, :?, :?)
// you'll have to bind parameters based on their $type [int, string, date]
}
$query = sprintf(
"UPDATE %s SET VALUES(%s) = %s",
$this -> tablename,
$fields,
$placeholders
);
// execute statement here, handle exceptions, and so...
}
}
So your User
class will be like:
class User extends BasicEntity
{
protected $id;
protected $username;
protected $email;
protected $password;
protected $enabled;
protected $createdAt;
public function __construct()
{
$this -> tablename = '_user';
$this -> schema = array(
'id' => 'int',
'username' => 'string',
'email' => 'string',
'password' => 'string',
'enabled' => 'int',
'createdAt' => 'datetime'
);
}
}
And your Admin
class:
class Admin extends User
{
protected $additionalProperty;
public function __construct()
{
parent::__construct();
$this -> schema['additionalProperty'] = 'string';
}
}
Calling update()
will build the right query based on class schema. This approach works with at a low complexity level, because you'll notice that:
- if you extend your entities [on the same table!], you need to provide empty table fields even for rows that don't have such class fields [in this case,
additionalProperty
];
- if your schema changes [e.g. you change a variable name], you have to hardcode it into class constructor, making it harder to maintain;
- if you want to handle relationship between entities, it will be a big pain to write proper joins in every SELECT statement, unless you just write a lot of separate queries, tearing performance down.
To resolve the first, you need composition of objects, so you don't make your main table grow much [it just gets a reference to an external AdditionalPropertyList
entity, for example].
To resolve the second, you have to keep the schema in external files or using inline annotations.
To resolve the third, you'll have to write your own ORM [Object Relational Mapping], or much better switch to an existing one.
Anyway out of the learning benefits, I'd stand on the shoulder of giants and I'd pick a framework if you plan to build a scalable and maintainable application.