Salvando objetos com ID definido no Data Mapper (CI)

Desde que comecei a estudar e utilizar o Code Igniter eu recomendo o uso do ORM Data Mapper, que facilita a vida nas consultas ao banco de dados (leia: tutorial do Data Mapper no Code Igniter), esta semana ele mais uma vez se mostrou muito útil enquanto eu fazia a migração do banco antigo do And After para o novo.

Depois de dominar (yeaaaah) relacionamento de tabelas com o Code Igniter (usando o Data Mapper) e finalizar o sistema do And After neste framework estou fazendo a migração de todo o conteúdo para a nova plataforma: textos, comentários, cadastro de usuários, logs, tags, blogs…

Achei que seria extremamente trabalhoso, pois toda a estrutura de banco foi alterada – recomecei o sistema do zero sem pensar na migração, fiz isso para evitar "puxadinhos" e gambiarras (que com o crescimento de sistema, estava cheio) e desenvolver tudo direito, do zero, um sistema novo.

No ônibus voltando para São Paulo fiz em alguns minutos a migração dos usuários e iniciei a dos textos (que será um pouco mais complicada devido aos relacionamentos), mas tive um problema com o Data Mapper: não perder os ID"s dos objetos que estão sendo migrados.

Como salvar um objeto com um ID existente?

O Data Mapper usa o atributo ID do objeto para verificar se ele deve fazer um insert ou um update, se o objeto ID existe ele fará um UPDATE, portanto você não consegue setar o ID de um objeto e usar o $object->save();, pois ele fará um update mesmo que o objeto não exista (e não vai acontecer nada no seu banco).

Para isso o Data Mapper tem a função save_as_new, segue um exemplo abaixo:

$user = new User();
$user->id = 1;
$user->login = "Admin";
$user->password = "password";
$success = $user->save_as_new();

Se não deu nenhum problema no seu banco (neste caso ele deveria estar limpo) você acabou de criar um usuário "Admin" com o id 1na sua tabela.

Problemas comuns

Após fazer a migração pode acontecer problemas ao tentar salvar novos objetos na tabela, isso pode acontecer porque o auto_increment (do ID) não foi atualizado – e está tentando inserir um novo objeto na tabela com um ID que já foi registrado "na mão".

Para facilitar o entendimento vamos a ao exemplo do caso da migração do And After. Existem aproximadamente 1.500 usuários cadastrados no site, após a migração o último ID utilizado na tabela de usuários foi o 1600 (devido a usuários excluídos, testes no banco, etc).

Preciso avisar a minha tabela que o próximo auto_increment (ID) é 1601, e não 1 (que seria o primeiro inserido de forma "natural", sem ID setado). O código abaixo executa esta atualização no banco:

// Update MySQL AUTO_INCREMENT:
$user->db->query("ALTER TABLE `users` AUTO_INCREMENT = 1601;");

Agora a migração da tabela users está completa e é possível utilizar ela normalmente.

Para mais dúvidas sobre o save leia a documentação do data mapper (EN).

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *