php 删除文件夹,及其其下所有文件

 更新时间:2016年11月25日 15:06  点击:1823
在php中删除文件和删除目录我们都用unlink删除实现删除,如果要删除不是空目录主要利用readdir和opendir来遍历目录了。
 代码如下 复制代码

<?php
// 删除文件夹,及其其下所有文件

function deldir($dir) {

  $dh=opendir($dir);
  
  while ($file=readdir($dh)) {
  
    if($file!="." && $file!="..") {
    
    $fullpath=$dir."/".$file;
    
      if(!is_dir($fullpath)) {
      
        unlink($fullpath);
      
      } else {
      
        deldir($fullpath);
      
      }
    
    }
  
  }
  
  closedir($dh);
  
  if(rmdir($dir)) {
  
    return true;
  
  } else {
  
    return false;
  
  }

}
?>

要取得文件后缀名在php中有很多的广告,如php函数pathinfo得出结果后的$extend[\"extension\"]就是一个不错的方法,后面都是民间自定义有需了解的朋友也可以参考一下。

利用 pathinfo函数
<?php

 代码如下 复制代码
function extend_2($file_name)
{
$extend = pathinfo($file_name);
$extend = strtolower($extend["extension"]);
return $extend;
}

定义和用法
pathinfo() 函数以数组的形式返回文件路径的信息。

语法
pathinfo(path,options)

pathinfo() 返回一个关联数组包含有 path 的信息。

包括以下的数组元素:

[dirname]
[basename]
[extension]


//取文件的扩展名

 代码如下 复制代码

function getextension($filename)
{
  return substr(strrchr($filename,”.”),1);
}

用切分方法

 代码如下 复制代码

function GetFiletype($filename){
 $filer=explode(".",$filename);
 $count=count($filer)-1;
 return strtolower(".".$filer[$count]);
}

利用切分法带系统自带函数 array_reverse

 代码如下 复制代码
 
function getfile($filestr){
  // 用点号分隔文件名到数组
    $get = explode('.',$filestr); 
  //把上面数组倒序
    $get = array_reverse($get); 
  //返回倒序数组的第一个值
    return $get[0];
}
$filename =  getfile('nowamagic.doc');
echo $filename;


array_reverse详解
( PHP 4中, PHP 5中)

array_reverse -返回一个数组的内容次序颠倒

描述
阵列array_reverse (数组$阵列[ ,布尔$ preserve_keys =虚假] )
采取一种输入数组并返回一个新数组的命令的内容扭转。

构造函数的声明与其它操作的声明一样,只是其名称必须是__construct( ),封装性就是把对象的属性和服务结合成一个独立的相同单位,并尽可能隐蔽对象的内部细节

构造方法与析构方法
构造方法:
大多数类都有一种称为构造函数的特殊方法。当创建一个对象时,它将自动调用构造函数,也就是使用new这个关键字来实例化对象的时候自动调用构造方法。

构造函数的声明与其它操作的声明一样,只是其名称必须是__construct( )。这是PHP5中的变化,以前的版本中,构造函数的名称必须与类名相同,这种在PHP5中仍然可以用,但现在以经很少有人用了,这样做的好处是可以使构造函数独立于类名,当类名发生改变时不需要改相应的构造函数名称了。为了向下兼容,如果一个类中没有名为__construct( )的方法,PHP将搜索一个php4中的写法,与类名相同名的构造方法。

格式:function __construct ( [参数] ) { ... ... }

在一个类中只能声明一个构造方法,而是只有在每次创建对象的时候都会去调用一次构造方法,不能主动的调用这个方法,所以通常用它执行一些有用的初始化任务。比如对成属性在创建对象的时候赋初值。

 

 代码如下 复制代码

//创建一个人类  
class Person  
{  
    //下面是人的成员属性  
    var $name;  //人的名子  
    var $sex;    //人的性别  
    var $age;    //人的年龄  
 
    //定义一个构造方法参数为姓名$name、性别$sex和年龄$age  
    function __construct($name, $sex, $age)  
    {  
        //通过构造方法传进来的$name给成员属性$this->name赋初使值  
        $this->name=$name;  
        //通过构造方法传进来的$sex给成员属性$this->sex赋初使值  
        $this->sex=$sex;  
        //通过构造方法传进来的$age给成员属性$this->age赋初使值  
        $this->age=$age;  
    }  
 
    //这个人的说话方法  
    function say()  
    {  
        echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."";  
    }  
}  
 
//通过构造方法创建3个对象$p1、p2、$p3,分别传入三个不同的实参为姓名、性别和年龄  
$p1=new Person("张三","男", 20);  
$p2=new Person("李四","女", 30);  
$p3=new Person("王五","男", 40);  
 
//下面访问$p1对象中的说话方法  
$p1->say();  
//下面访问$p2对象中的说话方法  
$p2->say();  
//下面访问$p3对象中的说话方法  
$p3->say();  
 
输出结果为:  
我的名子叫:张三 性别:男 我的年龄是:20  
我的名子叫:李四 性别:女 我的年龄是:30  
我的名子叫:王五 性别:男 我的年龄是:40 

//创建一个人类
class Person
{
    //下面是人的成员属性
    var $name;  //人的名子
    var $sex;    //人的性别
    var $age;    //人的年龄

    //定义一个构造方法参数为姓名$name、性别$sex和年龄$age
    function __construct($name, $sex, $age)
    {
        //通过构造方法传进来的$name给成员属性$this->name赋初使值
        $this->name=$name;
        //通过构造方法传进来的$sex给成员属性$this->sex赋初使值
        $this->sex=$sex;
        //通过构造方法传进来的$age给成员属性$this->age赋初使值
        $this->age=$age;
    }

    //这个人的说话方法
    function say()
    {
        echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."";
    }
}

//通过构造方法创建3个对象$p1、p2、$p3,分别传入三个不同的实参为姓名、性别和年龄
$p1=new Person("张三","男", 20);
$p2=new Person("李四","女", 30);
$p3=new Person("王五","男", 40);

//下面访问$p1对象中的说话方法
$p1->say();
//下面访问$p2对象中的说话方法
$p2->say();
//下面访问$p3对象中的说话方法
$p3->say();

输出结果为:
我的名子叫:张三 性别:男 我的年龄是:20
我的名子叫:李四 性别:女 我的年龄是:30
我的名子叫:王五 性别:男 我的年龄是:40

析构函数:
与构造函数相对的就是析构函数。析构函数是PHP5新添加的内容,在PHP4中没有析构函数。析构函数允许在销毁一个类之前执行的一些操作或完成一些功能,比如说关闭文件, 释放结果集等,析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行,也就是对象在内存中被销毁前调用析构函数。与构造函数的名称类似,一个类的析构函数名称必须是__destruct( )。析构函数不能带有任何参数。
格式:function __destruct ( ) { ... ... }

 

 代码如下 复制代码
//创建一个人类  
class Person  
{  
    //下面是人的成员属性  
    var $name;  //人的名子  
    var $sex;    //人的性别  
    var $age;    //人的年龄  
 
    //定义一个构造方法参数为姓名$name、性别$sex和年龄$age  
    function __construct($name, $sex, $age)  
    {  
        //通过构造方法传进来的$name给成员属性$this->name赋初使值  
        $this->name=$name;  
        //通过构造方法传进来的$sex给成员属性$this->sex赋初使值  
        $this->sex=$sex;  
        //通过构造方法传进来的$age给成员属性$this->age赋初使值  
        $this->age=$age;  
    }  
 
    //这个人的说话方法  
    function say()  
    {  
        echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."";  
    }         
 
    //这是一个析构函数,在对象销毁前调用  
    function __destruct()  
    {  
        echo "再见".$this->name."";  
    }  
}  
 
//通过构造方法创建3个对象$p1、p2、$p3,分别传入三个不同的实参为姓名、性别和年龄  
$p1=new Person("张三","男", 20);  
$p2=new Person("李四","女", 30);  
$p3=new Person("王五","男", 40);  
 
//下面访问$p1对象中的说话方法  
$p1->say();  
//下面访问$p2对象中的说话方法  
$p2->say();  
//下面访问$p3对象中的说话方法  
$p3->say();  
 
输出结果为:  
 
我的名子叫:张三 性别:男 我的年龄是:20  
我的名子叫:李四 性别:女 我的年龄是:30  
我的名子叫:王五 性别:男 我的年龄是:40  
 
再见张三  
再见李四  
再见王五 


封装性
封装性是面象对象编程中的三大特性之一,封装性就是把对象的属性和服务结合成一个独立的相同单位,并尽可能隐蔽对象的内部细节,包含两个含义:1.把对象的全部属性和全部服务结合在一起,形成一个不可分割的独立单位(即对象)。2.信息隐蔽,即尽可能隐蔽对象的内部细节,对外形成一个边界〔或者说形成一道屏障〕,只保留有限的对外接口使之与外部发生联系。

封装的原则在软件上的反映是:要求使对象以外的部分不能随意存取对象的内部数据(属性),从而有效的避免了外部错误对它的"交叉感染",使软件错误能够局部化,大大减少查错和排错的难度。

用个实例来说明吧, 假如某个人的对象中有年龄和工资等属性,像这样个人隐私的属性是不想让其它人随意就能获得到的,如果你不使用封装,那么别人想知道就能得到,但是如果你封装上之后别人就没有办法获得封装的属性, 除非你自己把它说出去,否则别人没有办法得到。在比如说,个人电脑都有一个密码,不想让其它人随意的登陆,在你电脑里面拷贝和粘贴。还有就是像人这个对象, 身高和年龄的属性, 只能是自己来增涨,不可以让别人随意的赋值等等。

 

 代码如下 复制代码

//使用private这个关键字来对属性和方法进行封装:  
//原来的成员:  
var $name;          //声明人的姓名  
var $sex;           //声明人的性别  
var $age;           //声明人的年龄  
function run(){…….}  
 
//改成封装的形式:  
private $name;          //把人的姓名使用private关键字进行封装  
private $sex;           //把人的性别使用private关键字进行封装  
private $age;           //把人的年龄使用private关键字进行封装  
private function run(){……}  //把人的走路方法使用private关键字进行封装 

//使用private这个关键字来对属性和方法进行封装:
//原来的成员:
var $name;   //声明人的姓名
var $sex;   //声明人的性别
var $age;   //声明人的年龄
function run(){…….}

//改成封装的形式:
private $name;    //把人的姓名使用private关键字进行封装
private $sex;   //把人的性别使用private关键字进行封装
private $age;   //把人的年龄使用private关键字进行封装
private function run(){……} //把人的走路方法使用private关键字进行封装注意:只要是成员属性前面有其它的关键字就要去掉原有的关键字”var”. 通过private就可以把人的成员(成员属性和成员方法)封装上了。封装上的成员就不能被类外面直接访问了,只有对象内部自己可以访问;下面的代码会产生错误:


class Person  
{  
    //下面是人的成员属性  
    private $name;  //人的名子,被private封装上了  
    private $sex;    //人的性别, 被private封装上了  
    private $age;    //人的年龄, 被private封装上了  
 
    //这个人可以说话的方法  
    function say()  
    {  
        echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."";  
    }         
 
    //这个人可以走路的方法, 被private封装上了  
    private function run()  
    {  
        echo "这个人在走路";  
    }  
}  
//实例化一个人的实例对象  
$p1=new Person();  
 
//试图去给私有的属性赋值, 结果会发生错误  
$p1->name="张三";  
$p1->sex="男";  
$p1->age=20;  
 
//试图去打印私有的属性, 结果会发生错误  
echo $p1->name."";  
echo $p1->sex."";  
echo $p1->age."" 
 
//试图去打印私有的成员方法, 结果会发生错误  
$p1->run();  
 
输出结果为:  
Fatal error: Cannot access private property Person::$name 
Fatal error: Cannot access private property Person::$sex 
Fatal error: Cannot access private property Person::$age 
Fatal error: Cannot access private property Person::$name 
Fatal error: Call to private method Person::run() from context '' 

class Person
{
    //下面是人的成员属性
    private $name;  //人的名子,被private封装上了
    private $sex;    //人的性别, 被private封装上了
    private $age;    //人的年龄, 被private封装上了

    //这个人可以说话的方法
    function say()
    {
        echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."";
    }  

    //这个人可以走路的方法, 被private封装上了
    private function run()
    {
        echo "这个人在走路";
    }
}
//实例化一个人的实例对象
$p1=new Person();

//试图去给私有的属性赋值, 结果会发生错误
$p1->name="张三";
$p1->sex="男";
$p1->age=20;

//试图去打印私有的属性, 结果会发生错误
echo $p1->name."";
echo $p1->sex."";
echo $p1->age.""

//试图去打印私有的成员方法, 结果会发生错误
$p1->run();

输出结果为:
Fatal error: Cannot access private property Person::$name
Fatal error: Cannot access private property Person::$sex
Fatal error: Cannot access private property Person::$age
Fatal error: Cannot access private property Person::$name
Fatal error: Call to private method Person::run() from context ''

从上面的实例可以看到, 私有的成员是不能被外部访问的, 因为私有成员只能在本对象内部自己访问,比如,$p1这个对象自己想把他的私有属性说出去,在say()这个方法里面访问了私有属性,这样是可以。(没有加任何访问控制,默认的是public的,任何地方都可以访问)


//这个人可以说话的方法, 说出自己的私有属性,在这里也可以访问私有方法  

 代码如下 复制代码

function say()  
{  
    echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age." 
";  
    //在这里也可以访问私有方法  
    //$this->run();  

//这个人可以说话的方法, 说出自己的私有属性,在这里也可以访问私有方法
function say()
{
 echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."
";
 //在这里也可以访问私有方法
 //$this->run();
}因为成员方法say()是公有的, 所以我们在类的外部调用say()方法是可以的,改变上面的代码;


class Person  
{  
    //下面是人的成员属性  
    private $name;  //人的名子,被private封装上了  
    private $sex;    //人的性别, 被private封装上了  
    private $age;    //人的年龄, 被private封装上了  
 
    //定义一个构造方法参数为私有的属性姓名$name、性别$sex和年龄$age进行赋值  
    function __construct($name, $sex, $age)  
    {  
        //通过构造方法传进来的$name给私有成员属性$this->name赋初使值  
        $this->name=$name;  
        //通过构造方法传进来的$sex给私有成员属性$this->sex赋初使值  
        $this->sex=$sex;  
        //通过构造方法传进来的$age给私有成员属性$this->age赋初使值  
        $this->age=$age;  
    }  
 
    //这个人可以说话的方法, 说出自己的私有属性,在这里也可以访问私有方法  
    function say()  
    {  
        echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age." 
";  
    }  
}  
 
//通过构造方法创建3个对象$p1、p2、$p3,分别传入三个不同的实参为姓名、性别和年龄  
$p1=new Person("张三","男", 20);  
$p2=new Person("李四","女", 30);  
$p3=new Person("王五","男", 40);  
 
//下面访问$p1对象中的说话方法  
$p1->say();  
//下面访问$p2对象中的说话方法  
$p2->say();  
//下面访问$p3对象中的说话方法  
$p3->say();  
 
输出结果为:  
我的名子叫:张三 性别:男 我的年龄是:20  
我的名子叫:李四 性别:女 我的年龄是:30  
我的名子叫:王五 性别:男 我的年龄是:40 

class Person
{
    //下面是人的成员属性
    private $name;  //人的名子,被private封装上了
    private $sex;    //人的性别, 被private封装上了
    private $age;    //人的年龄, 被private封装上了

    //定义一个构造方法参数为私有的属性姓名$name、性别$sex和年龄$age进行赋值
    function __construct($name, $sex, $age)
    {
        //通过构造方法传进来的$name给私有成员属性$this->name赋初使值
        $this->name=$name;
        //通过构造方法传进来的$sex给私有成员属性$this->sex赋初使值
        $this->sex=$sex;
        //通过构造方法传进来的$age给私有成员属性$this->age赋初使值
        $this->age=$age;
    }

    //这个人可以说话的方法, 说出自己的私有属性,在这里也可以访问私有方法
    function say()
    {
        echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."
";
    }
}

//通过构造方法创建3个对象$p1、p2、$p3,分别传入三个不同的实参为姓名、性别和年龄
$p1=new Person("张三","男", 20);
$p2=new Person("李四","女", 30);
$p3=new Person("王五","男", 40);

//下面访问$p1对象中的说话方法
$p1->say();
//下面访问$p2对象中的说话方法
$p2->say();
//下面访问$p3对象中的说话方法
$p3->say();

输出结果为:
我的名子叫:张三 性别:男 我的年龄是:20
我的名子叫:李四 性别:女 我的年龄是:30
我的名子叫:王五 性别:男 我的年龄是:40因为构造方法是默认的公有方法(构造方法不要设置成私有的),所以在类的外面可以访问到,这样就可以使用构造方法创建对象, 另外构造方法也是类里面的函数,所以可以用构造方法给私有的属性赋初值。Say()的方法是默认公有的, 所以在外面也可以访问的到, 说出他自己的私有属性。

从上面的例子中我们可以看到, 私有的成员只能在类的内部使用, 不能被类外部直接来存取, 但是在类的内部是有权限访问的, 所以有时候我们需要在类的外面给私有属性赋值和读取出来,也就是给类的外部提供一些可以存取的接口,上例中构造方法就是一种赋值的形式, 但是构造方法只是在创建对象的时候赋值,如果我们已经有一个存在的对象了,想对这个存在的对象赋值, 这个时候,如果你还使用构造方法传值的形式传值, 那么就创建了一个新的对象,并不是这个已存在的对象了。所以我们要对私有的属性做一些可以被外部存取的接口,目的就是可以在对象存在的情况下,改变和存取属性的值,但要注意,只有需要让外部改变的属性才这样做,不想让外面访问的属性是不做这样的接口的,这样就能达到封装的目的,所有的功能都是对象自己来完成,给外面提供尽量少的操作。

如果给类外部提供接口,可以为私有属性在类外部提供设置方法和获取方法,来操作私有属性.例如:

 

 代码如下 复制代码

//私有的属性年龄  
prvate $age;  
 
//为外部提供一个公有设置年龄的方法  
function setAge($age)  
{  
    //在给属性赋值的时候,为了避免非法值设置给属性  
    if($age<0 || $age>130)  
        return;  
    $this->age=$age;  
}  
 
//为外部提供一个公有获取年龄的方法  
function getAge()  
{  
    return($this->age);  

//私有的属性年龄
prvate $age;

//为外部提供一个公有设置年龄的方法
function setAge($age)
{
 //在给属性赋值的时候,为了避免非法值设置给属性
 if($age<0 || $age>130)
  return;
 $this->age=$age;
}

//为外部提供一个公有获取年龄的方法
function getAge()
{
 return($this->age);
}上

面的方法是为一个成员属性设置和获取值, 当然你也可以为每个属性用同样的方法对其进行赋值和取值的操作,完成在类外部的存取工作。

本文章简单的介绍一下关于PHP5面向对象详解 - (10) __set() __get() __isset() __unset()四个方法,有需要发解的朋友可以参考一下。

__set() __get() __isset() __unset() 四个方法的应用
一般来说,总是把类的属性定义为private,这更符合现实的逻辑。但是, 对属性的读取和赋值操作是非常频繁的,因此在PHP5中,预定义了两个函数”__get()”和”__set()”来获取和赋值其属性,以及检查属性的”__isset()”和删除属性的方法”__unset()”。

上一节中,我们为每个属性做了设置和获取的方法,在PHP5中给我们提供了专门为属性设置值和获取值的方法,”__set()”和“__get()”这两个方法,这两个方法不是默认存在的, 而是我们手工添加到类里面去的,像构造方法(__construct())一样, 类里面添加了才会存在,可以按下面的方式来添加这两个方法,当然也可以按个人的风格来添加:

 代码如下 复制代码


//__get()方法用来获取私有属性  
function __get($property_name)  
{  
    if(isset($this->$property_name)) {  
        return($this->$property_name);  
    }else {  
        return(NULL);  
    }  
}   
 
//__set()方法用来设置私有属性  
function __set($property_name, $value)  
{  
    $this->$property_name = $value;  

//__get()方法用来获取私有属性
function __get($property_name)
{
    if(isset($this->$property_name)) {
        return($this->$property_name);
    }else {
        return(NULL);
    }
}

//__set()方法用来设置私有属性
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,通过这个方法的执行,达到赋值的目的, 为了不传入非法的值, 还可以在这个方法给做一下判断。代码如下:

 

 代码如下 复制代码

class Person  
{  
    //下面是人的成员属性, 都是封装的私有成员  
    private $name;  //人的名子  
    private $sex;    //人的性别  
    private $age;    //人的年龄  
 
    //__get()方法用来获取私有属性  
    function __get($property_name)  
    {  
        echo "在直接获取私有属性值的时候,自动调用了这个__get()方法<br>";  
        if(isset($this->$property_name)) {  
            return($this->$property_name);  
        }else {  
            return(NULL);  
        }  
    }   
 
    //__set()方法用来设置私有属性  
    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>"; 

class Person
{
    //下面是人的成员属性, 都是封装的私有成员
    private $name;  //人的名子
    private $sex;    //人的性别
    private $age;    //人的年龄

    //__get()方法用来获取私有属性
    function __get($property_name)
    {
        echo "在直接获取私有属性值的时候,自动调用了这个__get()方法<br>";
        if(isset($this->$property_name)) {
            return($this->$property_name);
        }else {
            return(NULL);
        }
 }

    //__set()方法用来设置私有属性
    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时,自动调用";  
    return isset($this->$nm);  

private function __isset($nm)
{
 echo "当在类外部使用isset()函数测定私有成员$nm时,自动调用";
 return isset($this->$nm);
}

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

 

 代码如下 复制代码

private function __unset($nm)  
{  
    echo "当在类外部使用unset()函数来删除私有成员时自动调用的";  
    unset($this->$nm);  

private function __unset($nm)
{
 echo "当在类外部使用unset()函数来删除私有成员时自动调用的";
 unset($this->$nm);
}我们来看一个完整的实例:


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()函数测定私有成员时,自动调用";  
        return isset($this->$nm);  
    }  
    // __unset()方法  
    private function __unset($nm)  
    {  
        echo "当在类外部使用unset()函数来删除私有成员时自动调用的";  
        unset($this->$nm);  
    }  
}  
$p1 = new Person();  
$p1->name = "this is a person name";  
// 在使用isset()函数测定私有成员时,自动调用__isset()方法帮我们完成,返回结果为true  
echo var_dump(isset($p1->name)) . "";  
echo $p1->name . "";  
// 在使用unset()函数删除私有成员时,自动调用__unset()方法帮我们完成,删除name私有属性  
unset($p1->name);  
// 已经被删除了, 所这行不会有输出  
echo $p1->name; 

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()函数测定私有成员时,自动调用";
  return isset($this->$nm);
 }
 // __unset()方法
 private function __unset($nm)
 {
  echo "当在类外部使用unset()函数来删除私有成员时自动调用的";
  unset($this->$nm);
 }
}
$p1 = new Person();
$p1->name = "this is a person name";
// 在使用isset()函数测定私有成员时,自动调用__isset()方法帮我们完成,返回结果为true
echo var_dump(isset($p1->name)) . "";
echo $p1->name . "";
// 在使用unset()函数删除私有成员时,自动调用__unset()方法帮我们完成,删除name私有属性
unset($p1->name);
// 已经被删除了, 所这行不会有输出
echo $p1->name;输出结果为:

isset()函数测定私有成员时,自动调用  
bool(true)  
this is a person name 

isset()函数测定私有成员时,自动调用
bool(true)
this is a person name当在类外部使用unset()函数来删除私有成员时自动调用的 __set()、__get()、__isset()、__unset()

这四个方法都是我们添加到对象里面的,在需要时自动调用的,来完成在对象外部对对象内部私有属性的操作

PHP中的方法是不能重载的,所谓的方法重载就是定义相同的方法名,通过“参数的个数“不同或“参数的类型“不同,来访问我们的相同方法名的不同方法,继承是php5面象对象程序设计的重要特性之一,它是指建立一个新的派生类,从一个或多个先前定义的类中继承数据和函数,而且可以重新定义或加进新数据和函数,从而建立了类的层次或等级。

重载新的方法


在学习PHP 这种语言中你会发现,PHP中的方法是不能重载的,所谓的方法重载就是定义相同的方法名,通过“参数的个数“不同或“参数的类型“不同,来访问我们的相同方法名的不同方法。但是因为PHP是弱类型的语言,所以在方法的参数中本身就可以接收不同类型的数据,又因为PHP的方法可以接收不定个数的参数,所以通过传递不同个数的参数调用不相同方法名的不同方法也是不成立的。所以在PHP里面没有方法重载。不能重载也就是在你的项目中不能定义相同方法名的方法。另外,因为PHP没有名子空间的概念,在同一个页面和被包含的页面中不能定义相同名称的方法,也不能定义和PHP给我提供的方法的方法重名,当然在同一个类中也不能定义相同名称的方法。

我们这里所指的重载新的方法所指的是什么呢?其实我们所说的重载新的方法就是子类覆盖父类的已有的方法,那为什么要这么做呢?父类的方法不是可以继承过来直接用吗?但有一些情况是我们必须要覆盖的,比如说我们前面提到过的例子里面,“Person”这个人类里面有一个“说话”的方法,所有继承“Person”类的子类都是可以“说话”的,我们“Student”类就是“Person”类的子类,所以“Student”的实例就可以“说话“了,但是人类里面“说话”的方法里面说出的是“Person”类里面的属性,而“Student”类对“Person”类进行了扩展,又扩展出了几个新的属性,如果使用继承过来的“say()”说话方法的话,只能说出从“Person”类继承过来的那些属性,那么新扩展的那些属性使用这个继承过来的“say()”的方法就说不出来了,那有的人就问了,我在“Student”这个子类中再定义一个新的方法用于说话,说出子类里面所有的属性不就行了吗?一定不要这么做,从抽象的角度来讲,一个“学生”不能有两种“说话”的方法,就算你定义了两个不同的说话的方法,可以实现你想要的功能,被继承过来的那个“说话“方法可能没有机会用到了,而且是继承过来的你也删不掉。这个时候我们就要用到覆盖了。

虽然说在PHP里面不能定义同名的方法,但是在父子关系的两个类中,我们可以在子类中定义和父类同名的方法,这样就把父类中继承过来的方法覆盖掉了。

 代码如下 复制代码

//定义一个“人”类做为父类
class Person
{
    //下面是人的成员属性
    var $name;  //人的名子
    var $sex;    //人的性别
    var $age;    //人的年龄

    //定义一个构造方法参数为属性姓名$name、性别$sex和年龄$age进行赋值
    function __construct($name, $sex, $age)
    {
        $this-&gt;name=$name;
        $this-&gt;sex=$sex;
        $this-&gt;age=$age;
    }

    //这个人可以说话的方法, 说出自己的属性
    function say()
    {
        echo "我的名子叫:".$this-&gt;name." 性别:".$this-&gt;sex." 我的年龄是:".$this-&gt;age."&lt;br&gt;";
    }
}

class Student extends Person
{
    var $school;  //学生所在学校的属性

    //这个学生学习的方法
    function study()
    {
        echo "我的名子叫:".$this-&gt;name." 我正在”.$this-&gt;school.” 学习&lt;br&gt;";
    }

    //这个学性可以说话的方法, 说出自己所有的属性,覆盖了父类的同名方法
    function say()
    {
        echo "我的名子叫:".$this-&gt;name." 性别:".$this-&gt;sex." 我的年龄是:".$this-&gt;age."我在".$this-&gt;school."上学.&lt;br&gt;";
    }
}

上面的例子, 我们就在“Student”子类里覆盖了继承父类里面的”say()”的方法,通过覆盖我们就实现了对“方法”扩展。

但是,像这样做虽然解决了我们上面说的问题,但是在实际开发中,一个方法不可能就一条代码或是几条代码,比如说“Person”类里面的“say()”方法有里面有100条代码,如果我们想对这个方法覆盖保留原有的功能外加上一点点功能,就要把原有的100条代码重写一次, 再加上扩展的几条代码,这还算是好的,而有的情况,父类中的方法是看不见原代码的,这个时候你怎么去重写原有的代码呢?我们也有解决的办法,就是在子类这个方法中可以调用到父类中被覆盖的方法, 也就是把被覆盖的方法原有的功能拿过来再加上自己的一点功能,可以通过两种方法实现在子类的方法中调用父类被覆盖的方法:

一种是使用父类的 "类名::" 来调用父类中被覆盖的方法;
一种是使用 "parent::" 的方试来调用父类中被覆盖的方法;

 代码如下 复制代码

class Student extends Person
{
    var $school;  //学生所在学校的属性

    //这个学生学习的方法
    function study()
    {
        echo "我的名子叫:".$this-&gt;name." 我正在”.$this-&gt;school.” 学习&lt;br&gt;";
    }

    //这个学性可以说话的方法, 说出自己所有的属性,覆盖了父类的同名方法
    function say()
    {
        //使用父类的“类名::“来调用父类中被覆盖的方法;
        //Person::say();

        //或者使用“parent::”的方试来调用父类中被覆盖的方法;
        parent::say();

        //加上一点自己的功能
        echo “我的年龄是:".$this-&gt;age."我在".$this-&gt;school."上学.&lt;br&gt;";
    }
}

现在用两种方式都可以访问到父类中被覆盖的方法,我们选那种方式最好呢?用户可能会发现自己写的代码访问了父类的变量和函数。如果子类非常精炼或者父类非常专业化的时候尤其是这样。 不要用代码中父类文字上的名字,应该用特殊的名字 parent,它指的就是子类在 extends 声明中所指的父类的名字。这样做可以避免在多个地方使用父类的名字。如果继承树在实现的过程中要修改,只要简单地修改类中 extends 声明的部分。

同样,构造方法在子类中如果没有声明的话,也可以使用父类中的构造方法,如果子类中重新定义了一个构造方法也会覆盖掉父类中的构造方法,如果想使用新的构造方法为所有属性赋值也可以用同样的方式。

 代码如下 复制代码

class Student extends Person
{
    var $school;  //学生所在学校的属性

    function __construct($name, $sex, $age, $school)
    {
        //使用父类中的方法为原有的属性赋值
        parent::__construct($name, $sex, $age);
        $this-&gt;school=$school;
    }

    //这个学生学习的方法
    function study()
    {
        echo "我的名子叫:".$this-&gt;name." 我正在”.$this-&gt;school.” 学习&lt;br&gt;";
    }

    //这个人可以说话的方法, 说出自己的属性
    function say()
    {
        parent::say();
        //加上一点自己的功能
        echo “我的年龄是:".$this-&gt;age."我在".$this-&gt;school."上学.&lt;br&gt;";
    }
}

类的继承


继承作为面向对象的三个重要特性的一个方面,在面向对象的领域有着及其重要的作用,好像没听说哪个面向对象的语言不支持继承。继承是php5面象对象程序设计的重要特性之一,它是指建立一个新的派生类,从一个或多个先前定义的类中继承数据和函数,而且可以重新定义或加进新数据和函数,从而建立了类的层次或等级。说的简单点就是,继承性是子类自动共享父类数据结构和方法的机制,这是类之间的一种关系。在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并加入若干新的内容。比如你现在已经有一个“人”这个类了,这个类里面有两个成员属性“姓名和年龄”以及还有两个成员方法“说话的方法和走路的方法“,如果现在程序需要一个学生的类,因为学生的也是人,所以学生也有成员属性“姓名和年龄”以及成员方法“说话的方法和走路的方法“,这个时候你就可以让学生类来继承人这个类,继承之后,学生类就会把人类里面的所有的属性都继承过来,就不用你再去重新声明一遍这些成员属性和方法了,因为学生类里面还有所在学校的属性和学习的方法,所以在你做的学生类里面有继承自人类里面的属性和方法之外在加上学生特有的”所在学校属性“和”学习的方法“,这样一个学生类就声明完成了,继函我们也可以叫作“扩展”,从上面我们就可以看出,学生类对人类进行了扩展,在人类里原有两个属性和两个方法的基础上加上一个属性和一个方法扩展出来一个新的学生类。

通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。我们称已存在的用来派生新类的类为基类,又称为父类以及超类。由已存在的类派生出的新类称为派生类,又称为子类。

在软件开发中,类的继承性使所建立的软件具有开放性、可扩充性,这是信息组织与分类的行之有效的方法,它简化了对象、类的创建工作量,增加了代码的可重性。采用继承性,提供了类的规范的等级结构。通过类的继承关系,使公共的特性能够共享,提高了软件的重用性。

在C++语言中,一个派生类可以从一个基类派生,也可以从多个基类派生。从一个基类派生的继承称为单继承;从多个基类派生的继承称为多继承。

 

但是在PHP和Java语言里面没有多继承,只有单继承,也就是说,一个类只能直接从一个类中继承数据, 这就是我们所说的单继承。

 

例如:下面是“人”类的抽象

 代码如下 复制代码

//定义一个“人”类做为父类
class Person
{
    //下面是人的成员属性
    var $name;  //人的名子
    var $sex;    //人的性别
    var $age;    //人的年龄

    //定义一个构造方法参数为属性姓名$name、性别$sex和年龄$age进行赋值
    function __construct($name, $sex, $age)
    {
        $this-&gt;name=$name;
        $this-&gt;sex=$sex;
        $this-&gt;age=$age;
    }

    //这个人可以说话的方法, 说出自己的属性
    function say()
    {
        echo "我的名子叫:".$this-&gt;name." 性别:".$this-&gt;sex." 我的年龄是:".$this-&gt;age."&lt;br&gt;";
    }
}

下面我们做一个”学生类”,如果不是用继承如下:

 代码如下 复制代码

//定义一个“学生类”类做为父类
class Student
{
    //下面是人的成员属性
    var $name;  //人的名子
    var $sex;    //人的性别
    var $age;    //人的年龄
    var $school;  //学生所在学校的属性

    //定义一个构造方法参数为属性姓名$name、性别$sex和年龄$age进行赋值
    function __construct($name="", $sex="", $age="", $school="")
    {
        $this-&gt;name=$name;
        $this-&gt;sex=$sex;
        $this-&gt;age=$age;
        $this-&gt;school=$school;
    }

    //这个人可以说话的方法, 说出自己的属性
    function say()
    {
        echo "我的名子叫:".$this-&gt;name." 性别:".$this-&gt;sex." 我的年龄是:".$this-&gt;age."&lt;br&gt;";
    }  

    //这个学生学习的方法
    function study()
    {
        echo "我的名子叫:".$this-&gt;name." 我正在".$this-&gt;school." 学习&lt;br&gt;";
    }
}


//定义一个子类“学生类“使用”extends”关键字来继承”人”类  
class Student extends Person  
{  
    //学生所在学校的属性  
    var $school;    
 
    //这个学生学习的方法  
    function study()  
    {  
        echo "我的名子叫:".$this->name." 我正在".$this->school." 学习<br>";  
    }  

通过上面“Student“类的定义,Student类通过使用”extends”这个关键字把Person类里的所有成员属性和成员方法都继承过来了,并扩展了一个所在学校成员属性”school”,和一个学习方法“study()”.现在子类”Student”里面和使用这个类实例出来的对象都具有如下的属性和方法:

学生类”Student”里面的成员属性有:
姓名:name;
年龄:age;
性别:sex;
学校:school;
学生类”Student”里面的成员方法有:
说话方法:say();
学习方法:study();

[!--infotagslink--]

相关文章

  • php读取zip文件(删除文件,提取文件,增加文件)实例

    下面小编来给大家演示几个php操作zip文件的实例,我们可以读取zip包中指定文件与删除zip包中指定文件,下面来给大这介绍一下。 从zip压缩文件中提取文件 代...2016-11-25
  • Jupyter Notebook读取csv文件出现的问题及解决

    这篇文章主要介绍了JupyterNotebook读取csv文件出现的问题及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2023-01-06
  • php获取一个文件夹的mtime的程序

    php获取一个文件夹的mtime的程序了,这个就是时间问题了,对于这个问题我们来看小编整理的几个例子,具体的操作例子如下所示。 php很容易获取到一个文件夹的mtime,可以...2016-11-25
  • Photoshop打开PSD文件空白怎么解决

    有时我们接受或下载到的PSD文件打开是空白的,那么我们要如何来解决这个 问题了,下面一聚教程小伙伴就为各位介绍Photoshop打开PSD文件空白解决办法。 1、如我们打开...2016-09-14
  • C#操作本地文件及保存文件到数据库的基本方法总结

    C#使用System.IO中的文件操作方法在Windows系统中处理本地文件相当顺手,这里我们还总结了在Oracle中保存文件的方法,嗯,接下来就来看看整理的C#操作本地文件及保存文件到数据库的基本方法总结...2020-06-25
  • 解决python 使用openpyxl读写大文件的坑

    这篇文章主要介绍了解决python 使用openpyxl读写大文件的坑,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-13
  • C#实现HTTP下载文件的方法

    这篇文章主要介绍了C#实现HTTP下载文件的方法,包括了HTTP通信的创建、本地文件的写入等,非常具有实用价值,需要的朋友可以参考下...2020-06-25
  • SpringBoot实现excel文件生成和下载

    这篇文章主要为大家详细介绍了SpringBoot实现excel文件生成和下载,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-02-09
  • 删除条目时弹出的确认对话框

    复制代码 代码如下: <td> <a href="/member/life/edit_ppt/<?php echo $v->id;?>" class="btn">编辑</a> <a href="javascript:;" onclick="if(confirm('您确定删除这条记录?')){location.href='/member/life/d...2014-06-07
  • php无刷新利用iframe实现页面无刷新上传文件(1/2)

    利用form表单的target属性和iframe 一、上传文件的一个php教程方法。 该方法接受一个$file参数,该参数为从客户端获取的$_files变量,返回重新命名后的文件名,如果上传失...2016-11-25
  • php批量替换内容或指定目录下所有文件内容

    要替换字符串中的内容我们只要利用php相关函数,如strstr,str_replace,正则表达式了,那么我们要替换目录所有文件的内容就需要先遍历目录再打开文件再利用上面讲的函数替...2016-11-25
  • PHP文件上传一些小收获

    又码了一个周末的代码,这次在做一些关于文件上传的东西。(PHP UPLOAD)小有收获项目是一个BT种子列表,用户有权限上传自己的种子,然后配合BT TRACK服务器把种子的信息写出来...2016-11-25
  • AI源文件转photoshop图像变模糊问题解决教程

    今天小编在这里就来给photoshop的这一款软件的使用者们来说下AI源文件转photoshop图像变模糊问题的解决教程,各位想知道具体解决方法的使用者们,那么下面就快来跟着小编...2016-09-14
  • C++万能库头文件在vs中的安装步骤(图文)

    这篇文章主要介绍了C++万能库头文件在vs中的安装步骤(图文),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-23
  • Zend studio文件注释模板设置方法

    步骤:Window -> PHP -> Editor -> Templates,这里可以设置(增、删、改、导入等)管理你的模板。新建文件注释、函数注释、代码块等模板的实例新建模板,分别输入Name、Description、Patterna)文件注释Name: 3cfileDescriptio...2013-10-04
  • php文件上传你必须知道的几点

    本篇文章主要说明的是与php文件上传的相关配置的知识点。PHP文件上传功能配置主要涉及php.ini配置文件中的upload_tmp_dir、upload_max_filesize、post_max_size等选项,下面一一说明。打开php.ini配置文件找到File Upl...2015-10-21
  • ant design中upload组件上传大文件,显示进度条进度的实例

    这篇文章主要介绍了ant design中upload组件上传大文件,显示进度条进度的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-10-29
  • C#使用StreamWriter写入文件的方法

    这篇文章主要介绍了C#使用StreamWriter写入文件的方法,涉及C#中StreamWriter类操作文件的相关技巧,需要的朋友可以参考下...2020-06-25
  • php实现文件下载实例分享

    举一个案例:复制代码 代码如下:<?phpclass Downfile { function downserver($file_name){$file_path = "./img/".$file_name;//转码,文件名转为gb2312解决中文乱码$file_name = iconv("utf-8","gb2312",$file_name...2014-06-07
  • php跨网站请求伪造与防止伪造方法

    伪造跨站请求介绍伪造跨站请求比较难以防范,而且危害巨大,攻击者可以通过这种方式恶作剧,发spam信息,删除数据等等。...2013-10-01