Back-End

25 ago, 2015

Modernizando a serialização de objetos PHP com class_alias()

Publicidade

Algum tempo atrás, um correspondente apresentou uma situação legada com a qual nunca tive de lidar. Ele estava trabalhando com Modernizção de aplicações legadas em PHP, e percebeu que a base de código estava armazenando objetos PHP serializados em um banco de dados. Ele não poderia refatorar os nomes de classe sem quebrar seriamente a aplicação.

Eu estava andando entre minhas aulas para uma estrutura PSR-0/4 quando me deparei com isso. O aplicativo salva a saída de serialize ($shoppingCart) em uma coluna BLOB, e remove a serialização mais tarde para recriar o objeto ShoppingCart. A cadeia de objeto serializado se parece com isto:

O:12:"ShoppingCart":17:{s:13:"\00Basket\00items";a:25:{...}; ...}

Veja como o nome da classe é incorporado na sequência serializada. Se eu mudar o nome da classe ShopppingCart para PSR-0/4, então a velha classe não será encontrada quando o aplicativo tentar utilizar a função unserialize() na representação serializada. Como posso começar a refatoração disso sem quebrar o aplicativo inteiro?

Antes eu seria capaz de responder, mas meu correspondente terminou por mudar a estratégia de serialização ao usar JSON, o que foi uma grande mudança. Ele acabou bem, mas o que acontece lá fora é uma solução menos intrusiva: usar class_alias().

Se você estiver em uma situação serializada e precisa alterar um nome de classe, poderá usar a função class_alias() para apontar o nome de classe antigo para um novo (a chamada class_alias() no início da execução, possivelmente antes de registrar seu autoloader). Em seguida, você pode renomear e mover a classe de acordo com as regras PSR-0/4, e o PHP irá lidar com o resto para você.

Por exemplo, se você renomeou ShoppingCart para Domain\Orders\Cart, você pode fazer isto:

class_alias('ShoppingCart', 'Domain\Orders\Cart');

Agora, quando você chamar a função unserialize($shoppingCart) para criar um objeto, o PHP irá criá-la como uma instância de Domain\Orders\Cart em vez de ShoppingCart. Representações reserializadas do objeto recriado irá manter o novo nome da classe, não o antigo: O:18:”Domain\Orders\Cart”:…..

Assim como não existem representações mais serializadas usando o antigo nome da classe, você pode remover o class_alias() e chamá-la inteiramente.

***

Paul M. Jones faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: http://paul-m-jones.com/archives/6158