If we assume for now that models in general will be objects that read/write data from/to a data source, it's reasonable to expect that any classes which basically represent things stored in that data source might share a lot of attributes and methods. Therefore, why not make one class that provides the "standard" parts of any models, which the more specific classes can extend and re-use?
It may get a bit fuzzy determining how much specific stuff can actually be coded in the model class, and how much you might want to make abstract -- essentially making those aspects of the Model class more of an interface. (Which, of course, brings up the whole issue of interfaces, which I probably don't use enough -- and then there are always "traits", a new feature of the latest PHP releases that let's you sort of emulate multiple inheritance, but let's not go there now.
)
At a minimum, a model class might include properties/methods that handle connection to the database, logging of database errors, and then perhaps abstract methods for CRUD operations (create, read, update, delete). Then your User class would extend that, perhaps adding new methods specific to user objects, and then your classes for specific user types would add/modify things unique to those special types.
Here's a simplified example just dealing with a read() method (and is by no means the only or even best way to do this, just some ideas to chew on):
<?php
class Model
{
private $pdo;
public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}
abstract public function read(Array $keys);
}
class User extends Model
{
protected $userData;
public function read(Array $keys)
{
if(!isset($keys['username']) or !isset($keys['password'])) {
throw new Exception("Invalid keys");
}
$hashedPassword = sha1($keys['password']);
$sql = "SELECT * FROM users WHERE username=:username and password=:password";
$stmt = $this->pdo->prepare($sql);
$stmt->execute(
array(
':username' => $keys['username'],
':password' => $hashedPassword
)
);
$this->userData = $stmt->fetch(PDO::FETCH_ASSOC);
return (bool) $this->userData;
}
}
class AdminUser extends User {
public function read(Array $keys)
{
parent::read($keys);
if(!empty($this->userData)) {
if($this->userData['admin'] == false) {
$this->userData = null;
}
}
return (bool) $this->userData;
}
}