PHP中简单工厂模式实例讲解

 更新时间:2016年11月25日 16:23  点击:2106
PHP中简单工厂模式实例讲解,简单的讲述了一下大家可参考一下。

简单工厂模式:
①抽象基类:类中定义抽象一些方法,用以在子类中实现
②继承自抽象基类的子类:实现基类中的抽象方法
③工厂类:用以实例化对象

看完文章再回头来看下这张图,效果会比较好

采用封装方式

 代码如下 复制代码
<?php
    class Calc{
        /**
         * 计算结果
         *
         * @param int|float $num1
         * @param int|float $num2
         * @param string $operator
         * @return int|float
         */
        public function calculate($num1,$num2,$operator){
            try {
                $result=0;
                switch ($operator){
                    case '+':
                        $result= $num1+$num2;
                        break;
                    case '-':
                        $result= $num1-$num2;
                        break;
                    case '*':
                        $result= $num1*$num2;
                        break;
                    case '/':
                        if ($num2==0) {
                            throw new Exception("除数不能为0");
                        }
                        $result= $num1/$num2;
                        break;
                    return $result;
                }
            }catch (Exception $e){
                echo "您输入有误:".$e->getMessage();
            }
        }
    }
    $test=new Calc();
//    echo $test->calculate(2,3,'+');//打印:5
    echo $test->calculate(5,0,'/');//打印:您输入有误:除数不能为0
?>

优点:以上代码使用了面向对象的封装特性,只要有了include这个类,其他页面就可以随便使用了

缺点:无法灵活的扩展和维护
比如:想要增加一个“求余”运算,需要在switch语句块中添加一个分支语句,代码需要做如下改动
添加分支语句

 代码如下 复制代码
<?php
    class Calc{
        public function calculate($num1,$num2,$operator){
            try {
                $result=0;
                switch ($operator){
                    //......省略......
                    case '%':
                        $result= $num1%$num2;
                        break;
                    //......省略......
                }
            }catch (Exception $e){
                echo "您输入有误:".$e->getMessage();
            }
        }
    }
?>

代码分析:用以上方法实现给计算器添加新的功能运算有以下几个缺点

①需要改动原有的代码块,可能会在为了“添加新功能”而改动原有代码的时候,不小心将原有的代码改错了
②如果要添加的功能很多,比如:‘乘方’,‘开方’,‘对数’,‘三角函数’,‘统计’,或者添加一些程序员专用的计算功能,比如:And, Or, Not, Xor,这样就需要在switch语句中添加N个分支语句。想象下,一个计算功能的函数如果有二三十个case分支语句,代码将超过一屏,不仅令代码的可读性大大降低,关键是,为了添加小功能,还得让其余不相关都参与解释,这令程序的执行效率大大降低
解决途径:采用OOP的继承和多态思想
简单工厂模式的初步实现
 

 代码如下 复制代码
<?php
     /**
      * 操作类
      * 因为包含有抽象方法,所以类必须声明为抽象类
      */
     abstract class Operation{
         //抽象方法不能包含函数体
         abstract public function getValue($num1,$num2);//强烈要求子类必须实现该功能函数
     }
     /**
      * 加法类
      */
     class OperationAdd extends Operation {
         public function getValue($num1,$num2){
             return $num1+$num2;
         }
     }
     /**
      * 减法类
      */
     class OperationSub extends Operation {
         public function getValue($num1,$num2){
             return $num1-$num2;
         }
     }
     /**
      * 乘法类
      */
     class OperationMul extends Operation {
         public function getValue($num1,$num2){
             return $num1*$num2;
         }
     }
     /**
      * 除法类
      */
     class OperationDiv extends Operation {
         public function getValue($num1,$num2){
             try {
                 if ($num2==0){
                     throw new Exception("除数不能为0");
                 }else {
                     return $num1/$num2;
                 }
             }catch (Exception $e){
                 echo "错误信息:".$e->getMessage();
             }
         }
     }
 ?>

里采用了面向对象的继承特性,首先声明一个虚拟基类,在基类中指定子类务必实现的方法(getValue())

分析:通过采用面向对象的继承特性,我们可以很容易就能对原有程序进行扩展,比如:‘乘方’,‘开方’,‘对数’,‘三角函数’,‘统计’等等。

求余类

 代码如下 复制代码

<?php
    /**
     * 求余类(remainder)
     *
     */
    class OperationRem extends Operation {
        public function getValue($num1,$num2){
            return $num1%$num12;
        }
    }
?>

我们只需要另外写一个类(该类继承虚拟基类),在类中完成相应的功能(比如:求乘方的运算),而且大大的降低了耦合度,方便日后的维护及扩展

现在还有一个问题未解决,就是如何让程序根据用户输入的操作符实例化相应的对象呢?
解决办法:使用一个单独的类来实现实例化的过程,这个类就是工厂
代码如下:

工厂类

 代码如下 复制代码

<?php
    /**
     * 工程类,主要用来创建对象
     * 功能:根据输入的运算符号,工厂就能实例化出合适的对象
     *
     */
    class Factory{
        public static function createObj($operate){
            switch ($operate){
                case '+':
                    return new OperationAdd();
                    break;
                case '-':
                    return new OperationSub();
                    break;
                case '*':
                    return new OperationSub();
                    break;
                case '/':
                    return new OperationDiv();
                    break;
            }
        }
    }
    $test=Factory::createObj('/');
    $result=$test->getValue(23,0);
    echo $result;
?>

我们经常会在php的面向对象中可以看到位__set __get __isset __unset这些东西的用法,但很不明白为什么会要用这些东西,下面我们来一一介绍一下他们哥四的用法吧。

 一般来说,总是把类的属性定义为private,这更符合现实的逻辑。但是,对属性的读取和赋值操作是非常频繁的,因此在PHP5中,预定义了两个函数“__get()”和“__set()”来获取和赋值其属性,以及检查属性的“__isset()”和删除属性的方法“__unset()”。
上一节中,我们为每个属性做了设置和获取的方法,在PHP5中给我们提供了专门为属性设置值和获取值的方法,“__set()”和“__get()”这两个方法,这两个方法不是默认存在的,而是我们手工添加到类里面去的,像构造方法(__construct())一样, 类里面添加了才会存在,可以按下面的方式来添加这两个方法,当然也可以按个人的风格来添加:

//__get()方法用来获取私有属性

 代码如下 复制代码

private function __get($property_name)


{

 


if(isset($this->$property_name))


{


return($this->$property_name);


}else


{


return(NULL);


}


}


//__set()方法用来设置私有属性


private function __set($property_name, $value)


{


$this->$property_name = $value;


}

__get()方法:这个方法用来获取私有成员属性值的,有一个参数,参数传入你要获取的成员属性的名称,返回获取的属性值,这个方法不用我们手工的去调用,因为我们也可以把这个方法做成私有的方法,是在直接获取私有属性的时候对象自动调用的。因为私有属性已经被封装上了,是不能直接获取值的(比如:“echo $p1->name”这样直接获取是错误的),但是如果你在类里面加上了这个方法,在使用“echo $p1->name”这样的语句直接获取值的时候就会自动调用__get($property_name)方法,将属性name传给参数$property_name,通过这个方法的内部执行,返回我们传入的私有属性的值。如果成员属性不封装成私有的,对象本身就不会去自动调用这个方法。
__set()方法:这个方法用来为私有成员属性设置值的,有两个参数,第一个参数为你要为设置值的属性名,第二个参数是要给属性设置的值,没有返回值。这个方法同样不用我们手工去调用,它也可以做成私有的,是在直接设置私有属性值的时候自动调用的,同样属性私有的已经被封装上
 
了,如果没有__set()这个方法,是不允许的,比如:$this->name=‘zhangsan’, 这样会出错,但是如果你在类里面加上了__set($property_name, $value)这个方法,在直接给私有属性赋值的时候,就会自动调用它,把属性比如name传给$property_name, 把要赋的值“zhangsan”传给$value,通过这个方法的执行,达到赋值的目的。如果成员属性不封装成私有的,对象本身就不会去自动调用这个方法。为了不传入非法的值,还可以在这个方法给做一下判断。代码如下:

 代码如下 复制代码

<?php


class Person


{


//下面是人的成员属性, 都是封装的私有成员


private $name;          //人的名子


private $sex;           //人的性别


private $age;           //人的年龄


//__get()方法用来获取私有属性


private function __get($property_name)


{


echo "在直接获取私有属性值的时候,自动调用了这个__get()方法<br>";


if(isset($this->$property_name))


{


return($this->$property_name);


}


else


{


return(NULL);


}


}


//__set()方法用来设置私有属性


private function __set($property_name, $value)


{


echo "在直接设置私有属性值的时候,自动调用了这个__set()方法为私有属性赋值<br>";

 


$this->$property_name = $value;


}


}


$p1=new Person();


//直接为私有属性赋值的操作, 会自动调用__set()方法进行赋值


$p1->name="张三";


$p1->sex="男";


$p1->age=20;


//直接获取私有属性的值, 会自动调用__get()方法,返回成员属性的值


echo "姓名:".$p1->name."<br>";


echo "性别:".$p1->sex."<br>";


echo "年龄:".$p1->age."<br>";


?>

程序执行结果:
在直接设置私有属性值的时候,自动调用了这个__set()方法为私有属性赋值
在直接设置私有属性值的时候,自动调用了这个__set()方法为私有属性赋值
在直接设置私有属性值的时候,自动调用了这个__set()方法为私有属性赋值
在直接获取私有属性值的时候,自动调用了这个__get()方法
姓名:张三
在直接获取私有属性值的时候,自动调用了这个__get()方法
性别:男
在直接获取私有属性值的时候,自动调用了这个__get()方法
年龄:20
 
以上代码如果不加上__get()和__set()方法,程序就会出错,因为不能在类的外部操作私有成员,而上面的代码是通过自动调用__get()和__set()方法来帮助我们直接存取封装的私有成员的。
__isset() 方法:在看这个方法之前我们看一下“isset()”函数的应用,isset()是测定变量是否设定用的函数,传入一个变量作为参数,如果传入的变量存在则传回true,否则传回false。那么如果在一个对象外面使用“isset()”这个函数去测定对象里面的成员是否被设定可不可以用它呢?分两种情况,如果对象里面成员是公有的,我们就可以使用这个函数来测定成员属性,如果是私有的成员属性,这个函数就不起作用了,原因就是因为私有的被封装了,在外部不可见。那么我们就不可以在对象的外部使用“isset()”函数来测定私有成员属性是否被设定了呢?可以,你只要在类里面加上一个“__isset()”方法就可以了,当在类外部使用”isset()”函数来测定对象里面的私有成员是否被设定时,就会自动调用类里面的“__isset()”方法了帮我们完成这样的操作,“__isset()”方法也可以做成私有的。你可以在类里面加上下面这样的代码就可以了:

 代码如下 复制代码

private function __isset($nm)


{


echo "当在类外部使用isset()函数测定私有成员$nm时,自动调用<br>";


return isset($this->$nm);


}

__unset()方法:看这个方法之前呢,我们也先来看一下“unset()”这个函数,“unset()”这个函数的作用是删除指定的变量且传回true,参数为要删除的变量。那么如果在一个对象外部去删除对象内部的成员属性用“unset()”函数可不可以呢,也是分两种情况,如果一个对象里面的成员属性是公有的,就可以使用这个函数在对象外面删除对象的公有属性,如果对象的成员属性是私有的,我使用这个函数就没有权限去删除,但同样如果你在一个对象里面加上“__unset()”这个方法,就可以在对象的外部去删除对象的私有成员属性了。在对象里面加上了“__unset()”这个方法之后,在对象外部使用“unset()”函数删除对象内部的私有成员属性时,自动调用“__unset()”函数来帮
我们删除对象内部的私有成员属性,这个方法也可以在类的内部定义成私有的。在对象里面加上下面的代码就可以了:

 代码如下 复制代码

private function __unset($nm)


{


echo "当在类外部使用unset()函数来删除私有成员时自动调用的<br>";


unset($this->$nm);


}

我们来看一个完整的实例:

<?php


class Person


{


//下面是人的成员属性


private $name;        //人的名子


private $sex;         //人的性别


private $age;         //人的年龄


//__get()方法用来获取私有属性


private function __get($property_name)


{


if(isset($this->$property_name))


{


return($this->$property_name);


}else {


return(NULL);


}


}


//__set()方法用来设置私有属性


private function __set($property_name, $value)


{

 


$this->$property_name = $value;


}


//__isset()方法


private function __isset($nm)


{


echo "isset()函数测定私有成员时,自动调用<br>";


return isset($this->$nm);


}


//__unset()方法


private function __unset($nm)


{


echo "当在类外部使用unset()函数来删除私有成员时自动调用的<br>";


unset($this->$nm);


}


}


$p1=new Person();


$p1->name="this is a person name";


//在使用isset()函数测定私有成员时,自动调用__isset()方法帮我们完成,返回结果为true


echo var_dump(isset($p1->name))."<br>";


echo $p1->name."<br>";


//在使用unset()函数删除私有成员时,自动调用__unset()方法帮我们完成,删除name私有属性


unset($p1->name);


//已经被删除了, 所这行不会有输出


echo $p1->name;


?>

输出结果为:
isset()函数测定私有成员时,自动调用
bool(true)
this is a person name
当在类外部使用unset()函数来删除私有成员时自动调用的
__set()、__get()、__isset()、__unset() 这四个方法都是我们添加到对象里面的,在需要时自动调用的,来完成在对象外部对对象内部私有属性的操作

文章从最简单的cookie操作(增加,删除,修改)到我们的cookie队列操作类的操作,有需要了解的同学可以参考本实例。

1、设置Cookie

1. PHP 的COOKIE

    cookie 是一种在远程浏览器端储存数据并以此来跟踪和识别用户的机制。
    PHP 在http 协议的头信息里发送cookie,因此  setcookie()     函数必须在其它信息被输出到浏览器
前调用,这和对  header()    函数的限制类似。

1.1 设置cookie:

   可以用 setcookie()或 setrawcookie()函数来设置 cookie。也可以通过向客户端直接发送http  头来
设置。
    1.1.1  使用 setcookie()函数设置cookie:
bool setcookie ( string name [, string value [, int expire [, string path [, string domain [, bool secure [, bool
httponly]]]]]] )
   name: cookie 变量名
   value: cookie 变量的值
   expire: 有效期结束的时间
   path: 有效目录
   domain: 有效域名,顶级域唯一
   secure: 如果值为 1,则cookie 只能在https 连接上有效,如果为默认值 0,则http 和 https 都可
以。

来看几个例子:

简单的:

SetCookie("MyCookie", "Value of MyCookie");

 

带失效时间的:

 代码如下 复制代码

SetCookie("WithExpire", "Expire in 1 hour", time()+3600);//3600秒=1小时

什么都有的:

 代码如下 复制代码

SetCookie("FullCookie", "Full cookie value", time()+3600, "/forum", ".phpuser.com", 1);

我们需要用到队列。

 代码如下 复制代码

class QueueSvc
{/*{{{*/
    private $length; // 队列的长度
    private $server_arr;
   
    public function __construct($length,$server_arr)
    {
        $this->length = $length;
        $this->server_arr = $server_arr;
    }
   
    public function getServerArr()
    {
        return $this->server_arr;
    }
   
    public function set($server_name)
    {
        self::push($server_name);
    }
   
    private function push($server_name)
    {
        //有重复的记录,把重复的删掉
        if(self::isServerExist($server_name)){
            self::removeRepeat($server_name);
        }else{
            if(self::isFull()){
                //如果已经满了,要把队列最后一个记录删掉
                array_pop($this->server_arr);
            }
        }
        //如果队列为空,先置为空数组
        if(empty($this->server_arr))
            $this->server_arr = array();
        //向队列头添加数据
        array_unshift($this->server_arr,$server_name); 
    }
   
    private function isFull()
    {
        if(is_array($this->server_arr) && (count($this->server_arr) >= $this->length))
            return true;
        return false;
    }
   
    private function isServerExist($server_name)
    {
        if(is_array($this->server_arr) && in_array($server_name,$this->server_arr))
            return true;
        return false;
    }
   
    private function removeRepeat($server_name)
    {
        if(is_array($this->server_arr) && in_array($server_name,$this->server_arr))
        {
            foreach($this->server_arr as $key=>$value)
            {
                if($server_name == $value)
                {
                    $this->array_remove($this->server_arr,$key);
                }
            }  
        }
    }
   
    private function array_remove(&$arr, $offset) {    
        array_splice ( $arr, $offset, 1 );
    }
}/*}}}*/require_once('queue_svc.php');
class CookieSvc
{/*{{{*/
    const   COOKIE_KEY = "GAME_SERVER";
   
    const   SEPARATE   = "|";

    const   COOKIE_LENGTH = "2";
   
    public function getCookieArr()
    {/*{{{*/
        $server_str =  $_COOKIE[self::COOKIE_KEY];
        $server_str =  $_COOKIE['GAME_SERVER'];
        if($server_str == ''){
            $result =  array();
        }else{
            $result = explode(self::SEPARATE,$server_str);
        }
        return $result;
    }/*}}}*/
   
    public function set($cookie_id)
    {/*{{{*/
        $server_arr = self::getCookieArr();
        if($cookie_id != false)
        {
            $que = new QueueSvc(self::COOKIE_LENGTH,$server_arr);
            $que->set($cookie_id);
            $server_new = $que->getServerArr();
            if(is_array($server_new))
            {
                $cookie_str = implode(self::SEPARATE,$server_new);
                setcookie(self::COOKIE_KEY,$cookie_str,time()+3600,'/');
            }
        }
    }/*}}}*/
}/*}}}*/

不多解释了,这个别人用的不多,昨天因为需要写的,留一下吧,也许以后还用得到。。
调用的代码很简单:

 代码如下 复制代码

require_once("queue_svc.php");

require_once("cookie_svc.php");

$cookie_id = '4';

CookieSvc::set($cookie_id);

这样就可以了。呼。。大家可以每次把$cookie_id换做不同的值,来检验此操作。
检验的代码可以用如下代码:

 代码如下 复制代码
var_dump($_COOKIE);

常见问题解决:

    1) 用 setcookie()时有错误提示,可能是因为调用setcookie()前面有输出或空格。也可能你的文
       档是从其他字符集转换过来,文档后面可能带有 BOM 签名(就是在文件内容添加一些隐藏
       的BOM 字符)。解决的办法就是使你的文档不出现这种情况。还有通过使用ob_start()函数
       也能处理一点。
    2) $_COOKIE 受magic_quotes_gpc 影响,可能自动转义。
    3) 使用的时候,有必要测试用户是否支持cookie

文章简单的介绍了关于PHP中ZipArchive压缩文件并下载打包好的文件介绍 ,有需要了解php中文件打包的朋友可参考五下。

分析下技术要点:

将文件打包成zip格式
下载文件的功能
要点解析:

这里我采用的是php自带的ZipArchive类
    a) 我们只需要new一个ZipArchive对象,然后使用open方法创建一个zip文件,接着使用addFile方法,将要打包的文件写入刚刚创建的zip文件中,最好还得记得关闭该对象。

    b) 注意点:使用open方法的时候,第二个参数$flags是可选的,$flags用来指定对打开的zip文件的处理方式,共有四种情况

                    i.     ZIPARCHIVE::OVERWRITE 总是创建一个新的文件,如果指定的zip文件存在,则会覆盖掉

                      ii.    ZIPARCHIVE::CREATE     如果指定的zip文件不存在,则新建一个

              iii.  ZIPARCHIVE::EXCL      如果指定的zip文件存在,则会报错   

               iv.  ZIPARCHIVE::CHECKCONS

 


--------------------------------------------------------------------------------

 下载文件的流程:

服务器端的工作:
-------------------------------------------
客户端的浏览器发送一个请求到处理下载的php文件。
注意:任何一个操作都首先需要写入到内存当中,不管是视频、音频还是文本文件,都需要先写入到内存当中。
换句话说,将“服务器”上的文件读入到“服务器”的内存当中的这个操作时必不可少的(注意:这里我将服务器三个字加上双引号,主要是说明这一系类的操作时在服务器上完成的)。<br>
既然要将文件写入到内存当中,就必然要先将文件打开
所以这里就需要三个文件操作的函数了:
一:fopen($filename ,$mode)
二:fread ( int $handle , int $length )
三:fclose ( resource $handle )

---------------------------------------
客户端端的工作:
---------------------------------------
那么,如何将已经存在于服务器端内存当中的文件信息流,传给客户端呢?
答案是通过header()函数,客户端就知道该如何处理文件,是保存还是打开等等

最终的效果如下图所示:

 代码如下 复制代码

<?php
 require'./download.php';
 /**
  * 遍历目录,打包成zip格式
  */
     class traverseDir{
         public $currentdir;//当前目录
         public $filename;//文件名
         public $fileinfo;//用于保存当前目录下的所有文件名和目录名以及文件大小
         public function __construct(){
             $this->currentdir=getcwd();//返回当前目录
         }       
         //遍历目录
         public function scandir($filepath){
             if (is_dir($filepath)){
                     $arr=scandir($filepath);
                     foreach ($arr as $k=>$v){
                         $this->fileinfo[$v][]=$this->getfilesize($v);
                     }
                 }else {
                     echo "<script>alert('当前目录不是有效目录');</script>";
                 }
         }
         /**
          * 返回文件的大小
          *
          * @param string $filename 文件名
          * @return 文件大小(KB)
          */
         public function getfilesize($fname){
             return filesize($fname)/1024;
         }
        
         /**
          * 压缩文件(zip格式)
          */
         public function tozip($items){
             $zip=new ZipArchive();
             $zipname=date('YmdHis',time());
             if (!file_exists($zipname)){
                 $zip->open($zipname.'.zip',ZipArchive::OVERWRITE);//创建一个空的zip文件
                 for ($i=0;$i<count($items);$i++){
                     $zip->addFile($this->currentdir.'/'.$items[$i],$items[$i]);
                 }
                 $zip->close();
                 $dw=new download($zipname.'.zip'); //下载文件
                 $dw->getfiles();
                 unlink($zipname.'.zip'); //下载完成后要进行删除   
             }
         }
     }
 ?>

 代码如下 复制代码

<?php
 /**
  * 下载文件
  *
  */
     class download{
         protected $_filename;
         protected $_filepath;
         protected $_filesize;//文件大小
         public function __construct($filename){
             $this->_filename=$filename;
             $this->_filepath=dirname(__FILE__).'/'.$filename;
         }
         //获取文件名
         public function getfilename(){
             return $this->_filename;
         }
        
         //获取文件路径(包含文件名)
         public function getfilepath(){
             return $this->_filepath;
         }
        
         //获取文件大小
         public function getfilesize(){
             return $this->_filesize=number_format(filesize($this->_filepath)/(1024*1024),2);//去小数点后两位
         }
         //下载文件的功能
         public function getfiles(){
             //检查文件是否存在
             if (file_exists($this->_filepath)){
                 //打开文件
                 $file = fopen($this->_filepath,"r");
                 //返回的文件类型
                 Header("Content-type: application/octet-stream");
                 //按照字节大小返回
                 Header("Accept-Ranges: bytes");
                 //返回文件的大小
                 Header("Accept-Length: ".filesize($this->_filepath));
                 //这里对客户端的弹出对话框,对应的文件名
                 Header("Content-Disposition: attachment; filename=".$this->_filename);
                 //修改之前,一次性将数据传输给客户端
                 echo fread($file, filesize($this->_filepath));
                 //修改之后,一次只传输1024个字节的数据给客户端
                 //向客户端回送数据
                 $buffer=1024;//
                 //判断文件是否读完
                 while (!feof($file)) {
                     //将文件读入内存
                     $file_data=fread($file,$buffer);
                     //每次向客户端回送1024个字节的数据
                     echo $file_data;
                 }
                
                 fclose($file);
             }else {
                 echo "<script>alert('对不起,您要下载的文件不存在');</script>";
             }
         }
     }
 ?>

页面中的显示代码如下

 代码如下 复制代码

<script type="text/javascript" src="jquery-1.7.2.js"></script>
 <script type="text/javascript" src="ajax.js"></script>
 <?php
     header("Content-type:text/html;charset=utf8");
     require('./getfile.php');
     $scandir=new traverseDir();
     $scandir->scandir($scandir->currentdir);
     $scandir->currentdir;
    
     if (isset($_POST['down_load'])){
         $items=$_POST['items'];
         $scandir->tozip($items);//将文件压缩成zip格式
     }
     echo "当前的工作目录:".$scandir->currentdir;
     echo "<br>当前目录下的所有文件";
 ?>
 
 <form action="list.php" method="POST">
 <table>
     <tr>
         <td></td>
         <td>名称</td>
         <td>大小(KB)</td>
     </tr>
 <?php
     $res=$scandir->fileinfo;
     foreach ($res as $k=>$v){
         if (!($k=='.' || $k=='..'))    {//过滤掉.和..
 ?>
     <tr>
         <td><input type="checkbox" name="items[]" class="filename" value="<?php echo $k;?>"></td>
         <td><?php echo $k; ?></td>
         <td><?php echo number_format($v[0],0); ?></td>
     </tr>
 <?php
         }
     }
 ?>
     <tr>
         <td><input type="checkbox" id="selall"><label for="selall">全选</label></td>
         <td><input type="submit" name="down_load" value="打包并下载" id="tozip_tetttt"></td>
     </tr>
 </table>
 </form>

总结:


--------------------------------------------------------------------------------

使用PHP下载文件的操作需要给出四个header(),可以参考我的另一篇博文:PHP如何实现下载功能超详细流程分析
计算文件的大小的时候,并不需要先打开文件,通过filesize($filename)就可以看出,如果需要先打开文件的话,filesize可能就会是这样的形式了filesize($filehandle)
向客户端回送数据的是,记得要设置一个buffer,用来指定每次向客户端输出多少数据,如:$buffer=1023。如果不指定的话,就会将整个文件全部写入内存当中,再一次性的讲数据传送给客户端
通过feof()函数,可以判断要读取的文件是否读完,如果还没读完,继续读取文件($file_data=fread()),并将数据回送给客户端(echo $file_data)
每次下载完成后,在客户端都会刷新下,说明了,其实每次都将数据写入到一个临时文件中,等全部下载完成后,再将所有的数据重新整合在一起
这里我使用的是绝对路径,绝对路径有个好处,就是适应性比较强,而且相对于相对路径,效率更高(免去了查找文件的过程)

本文章来介绍一下如何在windows中与php实现任何计划这个东西,有需要的同学可以参考一下下哈。

一、让PHP定时运行吧!
1、 编辑如下代码,并保存为test.php:

 代码如下 复制代码
<?php
$fp = @fopen("test.txt", "a+");
fwrite($fp, date("Y-m-d H:i:s") . " 让PHP定时运行吧!n");
fclose($fp);
?>

打开文本输入:D:php4php.exe -q D:php4test.php
保存为.bat格式。
D:php4php.exe 是php安装路径,D:php4test.php是要定时运行的程序的路径。

2、添加一个任务计划,选择那个.bat文件

3、时间设置为每隔1分钟运行一次,然后运行这个任务。

4、现在我们来看看d:php4test.txt文件的内容时候是否成功。如果内容为如下所示,那么恭喜你成功了。

2003-03-03 11:08:01 让PHP定时运行吧!
2003-03-03 11:09:02 让PHP定时运行吧!
2003-03-03 11:10:01 让PHP定时运行吧!
2003-03-03 11:11:02 让PHP定时运行吧!

二、让MYSQL实现自动备份变成可能!
1、编辑如下代码,并保存为backup.php,如果要压缩可以拷贝一个rar.exe:

 代码如下 复制代码

<?php
if ($argc != 2 || in_array($argv[1], array('--help', '-?'))) {
?>
backup   Ver 0.01, for Win95/Win98/WinNT/Win2000/WinXP on i32
Copyright (C) 2000 ptker All rights reserved. This is free software,and you are welcome to modify and redistribute it
under the GPL license

PHP Shell script for the backup MySQL database.

Usage: <?php echo $argv[0]; ?> <option>

   <option> can be database name you would like to backup.
   With the --help, or -? options, you can get this help and exit.
<?php
} else {
$dbname = $argv[1];
$dump_tool = "c:\mysql\bin\mysqldump";
$rar_tool = "d:\php4\rar";
@exec("$dump_tool --opt -u user -ppassword $dbname > ./$dbname.sql");
@exec("$rar_tool a -ag_yyyy_mm_dd_hh_mm $dbname.rar $dbname.sql");
@unlink("$dbname.sql");
echo "Backup complete!";
}
?>

2、添加一个任务计划,在(如图2所示)这一步输入命令:
D:php4php.exe -q D:php4backup.php databasename
3、时间设置为每天运行一次,然后运行这个任务。
4、最后会在d:php4目录下生成一个以数据库名和当前时间组成的rar文件。
5、恭喜你!大功告成了!
当然备份方式有很多种,读者可按照自己喜欢的去做!

 

以上是原著.结合本人实贱,补充说明如下:

1. 如果出现错误:
           在试着设置任务帐户信息时出现错误
   指定的错误是:
   0x80070005:拒绝访问
   您没有运行所请求的操作的权限

在上面'"4.接下来系统将会要求用户设置适当的用户名及密码(如图5所示),以便系统今后能自动加以运行".这里最好用"system"用户,密码可为空.

这个system的权限非常之高,比你的administrator还要高,所以你在运行命令的时候千万不要乱来,这个可是什么提示都没有就会无条件执行的,这个权限下你kill核心进程都行

[!--infotagslink--]

相关文章

  • php简单数据操作的实例

    最基础的对数据的增加删除修改操作实例,菜鸟们收了吧...2013-09-26
  • javascript设计模式之解释器模式详解

    神马是“解释器模式”?先翻开《GOF》看看Definition:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。在开篇之前还是要科普几个概念: 抽象语法树: 解释器模式并未解释如...2014-06-07
  • Postgresql 如何选择正确的关闭模式

    这篇文章主要介绍了Postgresl 如何选择正确的关闭模式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-18
  • 学习JavaScript设计模式之装饰者模式

    这篇文章主要为大家介绍了JavaScript设计模式中的装饰者模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
  • 如何开启mysql中的严格模式

    很多集成的PHP环境(PHPnow WAMP Appserv等)自带的MySQL貌似都没有开启MySQL的严格模式,何为MySQL的严格模式,简单来说就是MySQL自身对数据进行严格的校验(格式、长度、类型等),比如一个整型字段我们写入一个字符串类型的数...2013-10-04
  • c#标准idispose模式使用示例

    下面将把C#里实现IDispose模式的代码展现出来,大家一起来学习一下,它的使用场合也很多的,当我们手动对网站,数据库作封装时,都会用的到...2020-06-25
  • C# MVC模式中应该怎样区分应用程序逻辑(Controller层)和业务逻辑(Model层)?

    这篇文章主要介绍了C# MVC模式中应该怎样区分应用程序逻辑(Controller层)和业务逻辑(Model层)?,这也小编做.NET项目时经常思考和让人混乱的一个问题,这篇文章写的挺好,一下清晰了许多,需要的朋友可以参考下...2020-06-25
  • JavaScript设计模式之职责链模式

    这篇文章主要介绍了JavaScript设计模式之职责链模式,对设计模式感兴趣的同学,可以参考下...2021-04-25
  • 学习JavaScript设计模式之状态模式

    这篇文章主要为大家介绍了JavaScript设计模式中的状态模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-12
  • 快速理解MySQL中主键与外键的实例教程

    主键与外键的关系,通俗点儿讲,我现在有一个论坛,有两张表,一张是主贴 thread,一张是回帖 reply先说说主键,主键是表里面唯一识别记录的字段,一般是帖子id,体现在访问的时候,例如是 thread.php&#63;id=1 表示我要访问的是帖子...2015-11-24
  • php Observer观察者模式之学习笔记

    当我们在星际中开地图和几家电脑作战的时候,电脑的几个玩家相当于结盟,一旦我们出兵进攻某一家电脑,其余的电脑会出兵救援。 那么如何让各家电脑知道自己的盟友被攻击了...2016-11-25
  • 关于MySQL外键的简单学习教程

    在MySQL中,InnoDB引擎类型的表支持了外键约束。 外键的使用条件: 1.两个表必须是InnoDB表,MyISAM表暂时不支持外键(据说以后的版本有可能支持,但至少目前不支持); 2.外键列必须建立了索引,MySQL 4.1.2以后的版本在建立外键时...2015-11-24
  • Java接口DAO模式代码原理及应用详解

    这篇文章主要介绍了Java接口DAO模式代码原理及应用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-11-03
  • C#中的IDisposable模式用法详解

    这篇文章主要介绍了C#中的IDisposable模式用法,讲述了垃圾资源回收机制的实现,并对比分析了Dispose()方法、~DisposableClass()析构函数、虚方法Dispose(bool disposing)的原理,需要的朋友可以参考下...2020-06-25
  • 阿里云OpenSearch在php版sdk开启调试模式

    版本:php_v2.0.6 在CloudsearchClient的类中,开启debug模式,设置为true 如:$opts = array(&#39;host&#39;=>$host,&#39;debug&#39;=>true); 注意true不能加引号...2016-05-19
  • c# 接口使用实例

    这篇文章主要介绍了c#接口使用的实例,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-07-17
  • yii添删改查实例

    一、数据访问对象 (DAO)YiiDAO 基于 PHP Data Objects (PDO) 构建。它是一个为众多流行的DBMS提供统一数据访问的扩展,这些 DBMS 包括MySQL, PostgreSQL 等等。因此,要使用 Yii DAO,PDO 扩展和特定的 PDO 数据库驱动(例如...2015-11-24
  • C#使用Dispose模式实现手动对资源的释放

    这篇文章主要介绍了C#使用Dispose模式实现手动对资源的释放,涉及C#采用Dispose模式操作资源的技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • 学习JavaScript设计模式之单例模式

    这篇文章主要为大家介绍了JavaScript设计模式中的单例模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
  • MIUI儿童模式如何开启 小米手机儿童模式开启教程

    您是否遇到过孩子想要玩手机又不好拒绝,或者是您想要给孩子配一个联系用的手机有担心孩子玩手机上瘾?如果您购买的是小米手机,那么MIUI的儿童模式就能很好地解决这个问题...2016-12-21