Часто сталкиваясь с задачей, что необходимо получать объекты из базы данных, изменять и записывать изменения обратно в базу данных. Мне хотелось, чтобы объект сам знал какие изменения были произведены в нем и при этом объект не имел бы лишние поля, из-за которых запросы на запись к базе выпадали с ошибками о попытке записи несуществующих полей.

Так как мне последнее время было интересно разрабатывать расширения для php, то я и решил написать вспомогательный класс в виде расширения для PHP, который смог бы легко решить проблемы:
  • сделать набор свойств объекта неизменным;
  • при изменении значения свойства, автоматически запоминать что было изменено.


Так как многим знакомым программистам понравилось мое решение, я решил поделиться с хабросообществом своими наработками.

Покажу как работает расширение сразу на примере:

Допустим есть такая сущность пользователя:

class User extends \Entity
{
  public $id = 0;
  public $email = '';
  public $password = '';
  public $permissions = 0;

  public function __construct($data = array())
  {
      if (!isset($data['id'])) {
          $data['id'] = Redis::getInstance()->incr('UserID'); // Redis - простая обертка над nicolasff/phpredis
      }
      parent::__construct($data);
  }
}


Когда мы создаем объект нового пользователя, мы делаем например так:
$User = new User($_POST);


При этом у нас всегда в объекте будет сохранятся только определенные в классе свойства, хотя в переменной POST могло быть намного больше переданно.

Пользователь залогинился и решил поменять пароль:

$User = new User($dataFromDB);
$User->password = 'newpassword';
Db::getInstance->update('users', $User->getChanges(), array('id'=>$User->id));


При этом в метод getChanges() возвращает только массив измененных полей.

Если кому-то понравилась моя идея и есть предложения, как еще можно улучшить и дополнить класс, пишите в комментариях.

Ссылка для скачивания на github: https://github.com/cassej/Entity