Khanh's blog

<- Quay về trang chủ

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

Tags: php