Using command - DirManager class
Mấy hôm trước lại được làm 1 task liên quan đến thao tác với thư mục bằng PHP :) Thật ra trước đó đã từng làm rồi nhưng giờ vẫn khoái...viết lại, bởi quan trọng nhất là cái class đó...không còn trong máy tính ở cty nữa :)) Ở nhà thì ko tiện remote connect vào (có ai mở hộ máy đâu mà vào :-p) nên quyết định viết lại & phải chạy được cả trên Unix & Windows.
Class DirManager tạm thời có mấy method sau:
class DirManager { public $sourcePath = ''; public $destinationPath = ''; private $operaSystem = ''; static $instance;
public function getInstance() { if (self::$instance == null) { self::$instance = new DirManager(); }
return self::$instance; }
public function __construct() {
}
/** * check opera system * @return bool true if Linux, false if Windows */ private function isLinuxOS() { $this->operaSystem = $_SERVER['SERVER_SOFTWARE'];
if(stripos($this->operaSystem, 'Win32')) { return false; }
return true; }
/** * Create directory * @param string folderName */ public function createDir() { if(!is_dir($this->sourcePath)) { if(!mkdir($this->sourcePath, 0777)) { die('Could not create sub-domain.'); } } else { die($this->sourcePath.' is exist.'); } }
/** * copy using php function * @param string source * @param string dest */ private function windowsCopyDir($source, $dest) { if(!is_dir($dest)) { mkdir($dest, 0777); } if($curdir = opendir($source)) { while($file = readdir($curdir)) { if($file != '.' && $file != '..') { $srcfile = $source . '/' . $file; $dstfile = $dest . '/' . $file;
if(is_file($srcfile)) { copy($srcfile, $dstfile); } else if(is_dir($srcfile)) { $this->windowsCopyDir($srcfile, $dstfile); } } } closedir($curdir); } }
/** * Copy directory and all sub directory in it * @param bool useCommand */ public function copyDir($useCommand=true) { if(is_dir($this->sourcePath)) { if($this->isLinuxOS()) { if($useCommand) { exec("cd {$this->sourcePath}; shopt -s dotglob; cp -pr . {$this->destinationPath}"); } else { $this->WindowsCopyDir($this->sourcePath, $this->destinationPath); } } else { if($useCommand) { exec("xcopy {$this->sourcePath} {$this->destinationPath} /E"); } else { $this->WindowsCopyDir($this->sourcePath, $this->destinationPath); } } } else { die($this->sourcePath.' is not a directory.'); } }
/** * Remove directory and all sub directory in it * @param bool useCommand */ public function removeDir($useCommand=false) { if(is_dir($this->sourcePath)) { if($this->isLinuxOS()) { if($useCommand) { exec("rm -rf {$this->sourcePath} {$this->destinationPath}"); } else { $this->windowsRemoveDir($this->sourcePath); } } else { if($useCommand) { exec("DELLTREE {$this->sourcePath}"); } else { $this->windowsRemoveDir($this->sourcePath); } } } else { die($this->sourcePath.' is not a directory.'); } }
/** * @param string source folder to delete * @param int level */ private function windowsRemoveDir($source, $level=0) { // Trim the trailing slash $source = preg_replace("|^(.+?)/*$|", "\\1", $source);
if(is_dir($source)) { if ( ! $current_dir = @opendir($source)) return;
while(FALSE !== ($filename = @readdir($current_dir))) { if ($filename != "." && $filename != "..") { if (is_dir($source.'/'.$filename)) { $this->windowsRemoveDir($source.'/'.$filename, $level + 1); } else { unlink($source.'/'.$filename); } } }
@closedir($current_dir); @rmdir($source); } else { unlink($source); } } } ?>
Đoạn code trên chắc chắn với những lập trình viên có kinh nghiệm hay nói cách khác là trình độ, họ sẽ khẽ mĩm cười & chẳng nói gì đâu. Còn nhiều vấn đề. Tôi cũng biết điều đó :( Viết OOP không phải cứ quẳng 1 đống hàm vào trong class thì nó là OOP :cry: Nhưng, tạm thời đến lúc này trình độ của tôi chỉ có vậy. Sẽ còn phải cố nhiều đây :clown:
Một điểm thú vị khi viết method copyDir đó là nếu set $useCommand = true, tức là sử dụng command line để copy files & folders (nhanh hơn là dùng PHP để đọc & copy), nếu chạy trên Windows, okie, chạy tốt (trên máy của tôi :p), còn trên Linux thì nó lại copy nguyên cái thư mục nguồn vào bên trong thư mục đích. Cái tôi cần ở đây là chỉ copy các file & folder ở bên trong thư mục nguồn vào thư mục đích.
Và tôi sai ở đây:
exec("cp -pr {$this->sourcePath} {$this->destinationPath}");
Đúng ra phải là:
exec("cd {$this->sourcePath}; shopt -s dotglob; cp -pr . {$this->destinationPath}");
Tức là: - Set thư mục nguồn làm thư mục gốc (nhảy vào bên trong thư mục nguồn). - Hiện tất cả file ẩn. - Copy tất cả file & folder ở thư mục gốc vào thư mục đích
\=> Chạy rất nuột :p
$dirObj = DirManager::getInstance(); $dirObj->sourcePath = 'foo'; $dirObj->destinationPath = 'bar'; $dirObj->copyDir();
Toàn bộ đám bậu sậu trong foo đã nằm trọn trong vòng tay của bar :p