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