zoukankan      html  css  js  c++  java
  • PHP从入门到精通——读书笔记(第14—15章:面向对象、加密技术)

    第十四章:面向对象

    1:面向对象的基本概念
    这里指的面向对象,准确的说应该叫面向对象编程(OOP),是面向对象的一部分。面向对象包括3部分:面向对象分析(Object Oriented Analysis,OOA)、面向对象设计(Object Oriented Design,OOD)以及面向对象编程(Object Oriented Programming,OOP)

    1.1-1.2:类、对象

    1.3:OOP三大特点:封装性、继承性、多态性

    2:PHP与对象

    2.1:类的定义—— class
    class SportObject {....}

    2.2:成员方法——类中的函数被称为成员方法。区别:函数实现的是某个独立的功能,而成员方法是实现类的一个行为,是类的一部分

    2.3:类的实例化—— 实例化通过new关键字类声明一个对象。然后使用 "对象名 -> 成员方法" 的格式来调用要使用的方法

    2.4:成员变量——类中的变量(也有称为属性或字段的)。用来保存信息数据,或与成员方法进行交互来实现某项功能: "对象名 -> 成员变量"

    注意:无论是使用 "$this-> " 还是使用 "对象名 -> " 的格式,后面的变量是没有$符合的。

    2.5:类常量—— const关键字声明

    2.6:构造方法和析构方法
    1)构造方法——当一个类实例化一个对象时,可能会随着对象初始化一些成员变量。构造方法是生成对象时自动执行的成员方法,作用就是初始化对象。格式如下:
    void __construct ([mixed args [,...]] ) //注意是两条下划线

    2)析构方法——与构造方法相反,是对象被销毁时被调用的,作用是释放内存
    void __destruct (void)

    说明:PHP使用的是一种”垃圾回收“机制,自动清除不再使用的对象,释放内存。

    2.7:继承和多态的实现——根本的作用就是完成代码的重用

    1)继承—— extends 关键字声明

    2)多态——同一种方法,产生了不同的形态。多态存在两种形式:覆盖和重载
    A:覆盖——在子类中重写父类的方法
    B:重载——函数重载是指一个标识符被用作多个函数名,且能通过函数的参数的个数或参数类型将这些同名的函数区分开来

    2.8: ”$this ->“ 和 ”::“ 的使用
    1)$this ->  调用成员方法:”对象名 -> 方法名“,但在定义类时,根本无法得知对象的名称是什么。此时要想调用类中的方法,就要用伪变量 $this -> 。$this的意思就是本身,所以它只能在类的内部使用

    注意:get_class()函数返回对象所属类的名字,如果不是对象,则返回false

    2)操作符”::“——相比伪变量$this 只能在类的内部使用,操作符”::“更为强大,操作符"::"可以在没有声明任何实例的情况下访问类中的成员方法或成员变量。通用格式:

    关键字::变量名/常量名/方法名
    这里关键字分为3种情况:
    parent关键字:可以调用父类中的成员变量、成员方法和常量
    self 关键字:可以调用当前类中的静态成员和常量
    类名:可以调用本类中的变量、常量和方法

    2.9:数据隐藏——面向对象编程的特点之一就是封装性,即数据隐藏。注意,对于成员方法,如果没写关键字,默认是public
    关键字:public、private、protected、static和final

    2.10:静态变量(方法)—— 不是所有的变量(方法)都要通过创建对象来调用。可以通过给变量(方法)加上 static 关键字类直接调用:
    关键字::静态成员
    关键字可以是self,或者静态成员所在的类名

    说明:静态成员不用实例化对象,当类第一次加载时就已经分配了内存空间,所以直接调用静态成员的速度要快一些。但如果静态成员声明过多,空间一直被占用,反而会影响系统的功能。

    3:PHP对象的高级应用

    3.1:final关键字——被final修饰过的类不能被继承,也不能有子类。被final修饰过的方法不可以进行重写,也不可以被覆盖

    3.2:抽象类—— abstract 关键字声明,格式: abstract class ClassName{...}
    抽象类与普通类的区别:抽象类至少要包含一个抽象方法。抽象方法没有方法体,其功能的实现只能在子类中完成。abstract function functionName();

    3.3:接口的使用——PHP只支持单继承。要想实现多重继承,就要使用接口。使用关键字 interface。子类通过implements来实现接口

    3.4:克隆对象
    1)克隆对象—— clone 关键字
    $obj1 = new ClassName();
    $obj2 = clone $obj1;

    2)__clone() 方法——有时除了单纯的克隆对象外,还需要克隆出来的对象可以拥有自己的属性和行为。__clone()方法的作用是:在克隆对象的过程中,调用__clone()方法,可以使克隆出来的对象保持自己的一些行为及属性

    View Code
    class SportObject{
    
             //声明私有变量,并赋初值为 book
             private $object_type = 'book';
    
             //声明成员方法setType,为变量$object_type 赋值
             public function setType($type){
                      
                      $this->object_type = $type;
             }
    
             //声明成员方法getType,返回变量$object_type 的值
             public function getType(){
                      
                      return $this->object_type;
             }
    
             //声明__clone()方法,修改变量$object_type的值
             public function __clone(){
    
                      $this -> object_type = "computer";
             }
    }
    
    //实例化对象$book1
    $book1 = new SportObject();
    
    //使用普通数据类型的方法给对象$book2 赋值
    $book2 = clone $book1;
    
    echo '对象$book1 的变量值为:'.$book1->getType();
    echo '<br>';
    echo '对象$book2 的变量值为:'.$book2->getType();

    3.5:对象比较——判断两个对象之间的关系是克隆还是引用,可以使用比较运算符"=="和"==="。两个等号是比较两个对象的内容,3个等号是比较对象的引用。

    3.6:对象类型检测—— instanceof 操作符可以检测当前对象是属于哪个类
    ObjectName instanceof ClassName。如:if ($cBook instanceof MyBook)

    3.7:魔术方法——以两个下划线开头的方法。注意php中保留了所有以"__"开头的方法,所以不要创建这样的方法

    1)__set()和__get()方法:
    当程序试图写入一个不存在或不可见的成员变量时,PHP就会执行__set()方法。方法包含两个参数,分别表示变量名称和变量值,不可省略
    当程序调用一个未定义或不可见得成员变量时,可以通过__get()方法来读取变量值,它有一个参数,表示要调用的变量名

    注意:如果希望PHP调用这些魔术方法,首先必须在类中进行定义。否则PHP不会执行未创建的魔术方法

    View Code
    class SportObject{
            
            //私有变量type
            private $type = '';
    
            //声明魔术方法__get()
            private function __get($name){
    
                    //判断变量是否被声明
                    if (isset ($this->$name)){
                           echo '变量'.$name.'的值为:'.$this->$name.'<br>';
    
                    }else{
    
                            echo '变量'.$name.'未定义,初始化为 0 <br>';
                            
                            //如果未被声明,则对变量初始化
                            $this->$name = 0;
    
                    }
            }
    
            private function __set($name, $value){
                    
                    if (isset($this->$name)){
                            $this->$name = $value;
                            echo '变量'.$name.'赋值为:'.$value.'<br>';
    
                    }else{
            
                            $this->$name = $value;
                            echo '变量'.$name.'被初始化为:'.$value.'<br>';
                    }
            }
    
    }
    
    $MyComputer = new SportObject();
    $MyComputer -> type = 'DIY'; //给变量赋值
    $MyComputer -> type;   // 调用变量$type
    $MyComputer -> name; //调用变量$name

    2)__call()方法——当程序试图调用不存在或不可见的成员方法时,PHP会先调用__call() 方法来存储方法名及参数。包含两个参数:方法名和方法参数。方法参数以数组方式存在

    View Code
    class SportObject{
     
            public function myDream(){
                    echo '调用的方法存在,直接执行此方法。';
            }
    
            public function __call ($method, $parameter ){
                    
                    echo '如果方法不存在,则执行__call()方法。<br>';
                    
                    echo '方法名为:'.$method.'<br>';
    
                    echo '参数有:';
    
                    var_dump($parameter);//$parameter是一个数组
            }
    }

    3)__sleep()和__wakeup()方法——使用 serialize()函数可以实现序列化对象。就是将对象中的变量全部保存下来,对象中的类则只保存类名。在使用serialize()函数时,如果实例化的对象包含__sleep()方法,则会先执行__sleep()方法。该方法可以清除对象并返回一个该对象中所有变量的数组。使用__sleep()方法的目的是关闭对象可能具有的数据库连接等类似的善后工作

    unserialize()函数可以重新还原一个被 serialize() 函数序列化的对象, __wakeup()方法则是恢复在序列化中可能丢失的数据库连接及相关工作

    View Code
    class SportObject{
            
            private $type = "DIY";
    
            //声明getType()方法,用来调用私有变量$type
            public function getType(){
                    return $this -> type;
            }
    
            public function __sleep(){
                    
                    echo '使用serialize()函数将对象保存起来,可以存放到文本文件、数据库等地方<br>';
    
                    return $this;
            }
    
            public function __wakeup(){
    
                    echo '当需要该数据时,使用 unserialize() 函数对已序列化的字符串进行操作,将其转换回对象<br>';
    
            }
    
    }
    
    $myBook = new SportObject();
    $i = serialize($myBook); //序列化对象
    echo '序列化后的字符串:'.$i.'<br>';
    
    $reBook = unserialize($i); // 将字符串$i 重新转换为对象$reBook
    echo '还原后的成员变量:'.$reBook -> getType();

    4)__toString()方法——当使用 echo 或 print 输出对象时,将对象转化为字符串

    View Code
    class SportObject{
    
            private $type = "DIY";
    
            public function __toString(){
                    return $this->type;
            }
    }
    
    $myComputer = new SportObject();
    
    echo '对象$myComputer 的值为:';
    
    echo $myComputer;
    
    /*
    注意:如要没有 __toString() 方法,会发生致命错误(fatal error)
    echo或print 函数后面要直接跟输出对象
    */

    5)__autoload()方法——将一个独立、完整的类保存到一个PHP页中,并且文件名和类名保持一致。
    如果要在一个页面中引进很多类,需要使用 include_once()函数或require_once()函数一个个引入,PHP5解决了这个问题,__autoload()方法可以自动实例化需要使用的类。当程序要用到一个类,但该类还没有被实例化,PHP5将使用__autoload()方法,在指定的路径下自动查找和该类名称相同的文件。如果找到,程序继续执行,否则报告错误。

    View Code
    //类文件SportObject.class.php 代码
    
    class SportObject{
    
            private $cont;
    
            public function __construct($cont){
                    $this -> cont = $cont;
            }
    
            public function __toString(){
                    return $this -> cont;
            }
    }
    
    //index.php文件的代码:
    
    function __autoload($class_name){
    
            //类文件路径
            $class_path = $class_name.'.class.php';
    
            //判断类文件是否存在
            if (file_exists($class_path)){
            
                    //动态包含类文件
                    include_once($class_path);
    
            }else{
                    echo '类路径错误';
            }
    }
    
    $myBook = new SportObject("江山代有人才出    各领风骚数百年");

    4:面向对象的应用——中文字符串的截取类

    View Code
    class MsubStr {
    
            function csubstr ($str, $start, $len){
                    //字符串的总长度
                    $strlen = $start + $len;
    
                    //for循环,读取字符串
                    for ($i = 0; $i < $strlen; $i++){
                    
              //如果字符串中首个字节的ASCII序数值大于0xa0,则表示为汉字
              //ord()函数返回ASCII值
                            if( ord ( substr ($str, $i, 1)) > 0xa0){
                                    //每次取出两位字符(一个汉字)赋给变量
                                    $tmpstr .= substr ($str, $i, 2);
                                    $i ++;
    
                            }else{
                            
                                    $tmpstr .= substr ($str, $i, 1);
                            }
                    }
                    
                    return $tmpstr;
            }
    }

    第十五章:PHP加密技术

    1:php加密函数—— crypt()、md5()、sha1(),还有加密扩展库 Mcrypt 和 Mass

    1)使用 crypt() 函数进行加密
    string crypt(string str [, string salt]);
    str是要加密的字符串,salt是加密时使用的干扰串。如果省略第二个参数,则会随机生成一个干扰串。crypt()函数支持4中算法和长度:

    说明:默认情况,PHP使用一个或两个字符的DES干扰串,如果系统使用的是MD5,则会使用12个字符。可以通过CRYPT_SALT_LENGTH变量来查看干扰串的长度

    crypt()函数是单向加密的,密文不可能还原成明码,而每次加密后的数据还不相同,如何对加密后的数据进行判断比较?这就是salt要解决的问题。crypt()函数用salt参数对明文进行加密,判断时,对输出的信息再次使用相同的salt加密,对比两次加密后的结果来进行判断

    2)使用md5()函数进行加密——使用MD5算法(Message-Digest Algorithm 5:信息-摘要算法),它的作用是把不同长度的数据信息经过一系列的算法计算成一个128位的数值,就是把任意长度的字节串变换成一定长的大整数。注意这里是”字节串“而不是”字符串“,因为这种变换只与字节的值有关,与字符集或编码方式无关

    string md5 ( string str [, bool raw_output] );
    str是要加密的明文,raw_output参数如果设置为true,则函数返回一个二进制形式的密文,该参数默认为false

    View Code
    class chkinput{
             
             var $name; 
             var $pwd;
    
             function chkinput($x, $y){
                      
                      $this->name = $x;
                      $this->pwd = $y;
             }
    
             //定义方法,完成用户注册
             function checkinput(){
    
                      include "conn/conn.php";
    
                      $info = mysql_query("insert into tb_user(user,password)value(' ".$this->name." ', ' ".$this->pwd. ' " )" );
    
                      if ($info == false){
                               echo "<script language='javascript'>alert('会员注册失败'); history.back();</script>";
    
    /*exit()函数输出一条信息并退出当前脚本。是die()函数的别名*/
                               exit();
    
                      }else{
    
                               $_SESSION[admin_name] = $this->name;
    
                               echo "<script language='javascript'>alert('注册成功');window.location.href='index.php';</script>";
    
                      }
             }
    }
    
    
    $obj = new chkinput ( trim ($_POST[name], trim (md5($_POST[pwd])));
    
    $obj->checkinput();

    3)使用sha1()函数进行加密——SHA算法和md5算法类似。SHA:Secure Hash Algorithm(安全哈希算法)
    string sha1 ( string str [,bool raw_output] )
    函数返回一个40位的十六进制数,如果参数raw_output 为true,则返回一个20位的二进制数。默认为false

    2:PHP加密扩展库——Mcrypt扩展库可以实现加密解密功能。Mhash库则包含了MD5在内的多种hash算法实现的混编函数

    注意:这两个在PHP最新版本已经默认安装和开启!

    安装:PHP的主目录下包含了 libmcrypt.dll 和 libmhash.dll 文件,首先将文件复制到系统目录 windows\system32下,然后在php.ini中找到”;extension=php_mcrypt.dll“ 和 ”;extension=php_mhash.dll“,取消注释,重启服务器

    1)Mcrypt 库常量——支持20多种加密算法和8种加密模式,分别通过函数mcrypt_list_algorithms() 和 mcrypt_list_modes() 查看。这些算法和模式在实际应用中要用常量来表示,写的时候分别要加上前缀:MCRYPT_ 和 MCRPT_MODED_来表示

    View Code
    //使用Mcrypt进行加密解密不像使用MD5、sha1 等函数,直接调用即可
    
    $str = "被加密的内容";
    
    $key = "key:111"; //密钥
    
    $cipher = MCRYPT_DES; //密码类型
    
    $modes = MCRYPT_MODE_ECB; //密码模式
    
    //初始化向量
    $iv = mcrypt_create_iv ( mcrypt_get_iv_size($cipher, $modes), MCRYPT_RAND);
    
    echo "加密前:".$str."<br>";
    
    //加密。mcrypt_encrypt是加密函数
    $str_encrypt = mcrypt_encrypt ($cipher, $key, $str, $modes, $iv);
    
    echo "加密后:".$str_encrypt."<p>";
    
    $str_decrypt = mcrypt_decrypt ($cipher, $key, $str_encrypt, $modes, $iv);
    
    echo "还原:".$str_decrypt."<p>";

    (1)加密函数:string mcrypt_create_iv ( int size [, int source] );
    使用Mcrypt 进行数据加密、解密之前,首先要创建一个初始化向量(iv)。创建初始化向量需要两个参数:size指定了iv的大小,source为iv的源。source可以取如下值:
    MCRYPT_RAND:系统随机数
    MCRYPT_DEV_RANDOM:读取目录/dev/random 中的数据(UNIX系统)
    MCRYPT_DEV_URANDOM:读取目录/dev/urandom 中的数据(UNIX系统)

    (2)int mcrypt_get_iv_size ( string cipher, string mode):该函数返回初始化向量(iv)的大小。cipher:加密算法;mode:算法模式

    (3)string mcrypt_encrypt ( string cipher, string key, string data, string mode [,string iv]) : data为要加密的数据

    (4)string mcrypt_decrypt ( string cipher, string key, string data, string mode [, string iv] ) :解密函数

    2)Mhash扩展库——支持MD5、SHA、CRC32等多种散列算法。使用mhash_count()和 mhash_get_hash_name() 函数输出支持的算法名称

    View Code
    $num = mhash_count();   //函数返回最大的 hash id
    
    echo "Mhash 库支持的算法有:";
    
    for ($i=0; $i <= $num; $i++)
    {
              //输出每一个hash id的名称
              echo $i."=>".mhash_get_hash_name($i)." ";
    }

    如果在实际应用中使用上面的常量,需要在算法名称前面加上MHASH_前缀。
    相比Mcrypt库的30多个函数,Mhash库只有5个函数,除了上面使用到的两个函数外,下面介绍其他3个函数:

    (1)mhash_get_block_size() 函数: int mhash_get_block_size( int hash )
    该函数用来获取hash的区块大小,如mhash_get_block_size(MHASH_CRC32)

    (2)mhash()函数: string mhash ( int hash, string data [, string key] )
    该函数返回一个哈希值,参数hash为要使用的算法,data是要加密的数据,key是加密密钥

    (3)mhash_keygen_s2k()函数: string mhash_keygen_s2k ( int hash, string password, string salt, int bytes)
    该函数将根据password和salt返回一个长度为字节的key值,hash是使用的算法。其中salt固定8字节,如果给出的值小于8字节,将用0补齐

    View Code
    $filename = '08.txt';
    
    $str = file_get_contents($filename);
    
    $hash = 2;   //设置hash值
    
    $password = '111';
    
    $salt = '1234';
    
    $key = mhash_keygen_s2k (1, $password, $salt, 10);//生成key
    
    //使用$key、$hash对字串$str加密
    $str_mhash = bin2hex(mhash($hash,$str,$key));
    
    echo "文件08.txt的校检码是:".$str_mhash;
  • 相关阅读:
    BZOJ3212 Pku3468 A Simple Problem with Integers(线段树区间求和、区间加模板)
    BZOJ2208 [Jsoi2010]连通数
    洛谷P3952 时间复杂度
    BZOJ1051 [HAOI2006]受欢迎的牛
    BZOJ4318 OSU!
    BZOJ1798 [Ahoi2009]Seq 维护序列
    BZOJ1483 [HNOI2009]梦幻布丁
    洛谷P1439 最长公共子序列(O(nlogn)最长公共子序列模板)
    BZOJ2429 [HAOI2006]聪明的猴子
    BZOJ3714 [PA2014]Kuglarz
  • 原文地址:https://www.cnblogs.com/mumue/p/2844711.html
Copyright © 2011-2022 走看看