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从入门到精通——读书笔记(第14—15章:面向对象、加密技术)_第1张图片

说明:默认情况,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;

 

你可能感兴趣的:(面向对象)