Solução para resolver o problema com rename no windows
Estes dias me deparei com um problema chato pra dedéu enquando desenvolvia uma nova aplicação para a empresa que trabalho!
O PHP no meu apache rodando em Windows não executava a função rename() correntamente.
Então resolvi o problema criando uma classe utilizando alguns recursos nativos da SPL do PHP 5 e misturando um pouco com recursos que já são até barbudos do PHP e que se não cuidar enrosca no servidor quando estiver rodando (riso, tudo bem não teve graça ).
Gostaria de compartilhar com os amigos que desenvolvem aplicações de alto nível e que precisam gerenciamento de diretórios no windows e estão sofrendo com alguns bits a menos neste OS, entretanto a classe roda em outros sistemas Operacionais também, testei no CentOS 5.4 e Ubuntu 9.10, ainda não comprei um Mac, então se alguém testar e quiser me informar, comenta este Post que eu atualizo as informações.
O script foi publicado no site www.phpclasses.org com o nome de DirectoryHandler (do inglês, manipulador de diretório) e está disponível em http://www.phpclasses.org/browse/package/5924.html; se você for cadastrado no site, faça login e baixe os arquivos incluindo um teste que disponibilizei.
Basicamente, o que o script faz são três operações:
- Copiar o diretório para um novo local (incluindo subdiretórios e arquivos)
- Apagar um diretório completamente
- Renomear um diretório usando a método de copiar e deletar
A idéia é simples, a princípio, e graças aos novos recursos do PHP 5.2, foi possível reduzir consideravelmente a quantidade de código:
<?php class DirectoryHandler { public function renameDirectory($startDir, $endDir) { $this->copyDirectory($startDir, $endDir); $this->deleteDirectory($startDir); } public function copyDirectory($startDir, $endDir) { if (is_dir($startDir)) { if (!is_dir($endDir)) { mkdir($endDir); } for ( $source = new DirectoryIterator($startDir); $source->valid(); $source->next() ) { if ($source->getFilename() == '.' || $source->getFilename() == '..') { continue; } else { if ($source->getType() == 'dir') { mkdir( $endDir . DIRECTORY_SEPARATOR . $source->getFilename() ); $this->copyDirectory( $startDir . DIRECTORY_SEPARATOR . $source->getFilename(), $endDir . DIRECTORY_SEPARATOR . $source->getFilename()); } else { $content = @file_get_contents( $startDir . DIRECTORY_SEPARATOR . $source->getFilename() ); $openedfile = fopen( $endDir . DIRECTORY_SEPARATOR . $source->getFilename(), "w" ); fwrite($openedfile, $content); fclose($openedfile); } } } } } public function deleteDirectory($target) { if (is_dir($target)) { chmod($target, 0777); for ( $source = new DirectoryIterator($target); $source->valid(); $source->next() ) { if ($source->getFilename() == '.' || $source->getFilename() == '..') { continue; } else { if ($source->getType() == 'dir') { $this->deleteDirectory( $target . DIRECTORY_SEPARATOR . $source->getFilename() ); if (is_dir($target . DIRECTORY_SEPARATOR . $source->getFilename())) { rmdir($target . DIRECTORY_SEPARATOR . $source->getFilename()); } } else { unlink($target . DIRECTORY_SEPARATOR . $source->getFilename()); } } } rmdir($target); } } }
Para utilizar é simples, veja os exemplos abaixo comentados:
<?php require_once 'DirectoryHandler.php'; /** * Cria um novo diretório para testes */ if(!is_dir( 'inicio' )) { mkdir( 'inicio' ); } $dir = new DirectoryHandler(); /** * Faz uma cópia de "inicio" com o nome de "novo" */ $dir->copyDirectory ( 'inicio', 'novo' ); /** * Copia "novo" e cria "outro" */ $dir->copyDirectory ( 'novo', 'outro' ); /** * Delete o diretorio "novo" * Para provar que de fato foi deletado, * Você verá "outro" que foi criado a partir de "novo" */ $dir->deleteDirectory ( 'novo' ); /** * Renomeia "outro" para "final" * E terminamos com "inicio" e "fim" */ $dir->renameDirectory ( 'outro', 'final' );
Abraços, e espero que lhes sejam muito útil.