PHP面向对象核心(一)——序列化与魔术方法

PHP面向对象核心(一)

(原创内容,转载请注明来源,谢谢)

一、对象存储——serialize与unserialize

对象是存储类的属性的键值对,类似于数组的键值对。

对象在进行serialize(序列化)时,会连带类名、属性值、属性占用长度一并存储,当使用unserialize(反序列化)时可以还原对象。但是反序列化需要包含类原先定义的代码,否则还原后无法执行对象所属类的方法。

作用:将对象序列化,以便于将对象以字符串的形式存储在文件或数据库中。

示例如下:

//定义一个水果类
class fruit{
         private $shape;
         private $color;
         public function __construct($shape,$color){
         $this->shape =$shape;
         $this->color =$color;
}
         public function eatMethod($hasPeel){
                   echo ‘反序列化成功’;
}
}
//定义苹果对象
$apple = newfruit(‘round’, ‘red’);
$strApple =serialize($apple);
echo $strApple;
//运行结果:O:5:"fruit":2:{s:12:"fruitshape";s:5:"round";s:12:"fruitcolor";s:3:"red";}
//还原apple对象方式:反序列化
$objApple =unserialize($strApple);//$objApple==$apple

二、魔术方法

魔术方法是PHP的“语法糖”,都是以两个下划线开头的方法,在面向对象中具有重要作用。魔术方法在类中定义,当对于把类实例化的对象进行一些特定操作时,会触发相应的魔术方法。

1、__construct与__destruct

__construct称为构造函数,在每个类被实例化的时候,该函数会自动被调用。PHP不同于java,构造函数无法被重写。

构造函数通常用于实例化类时对类的属性进行赋值,还有进行数据库连接等操作。具体用法在上面水果类的定义中已经提到。

__destruct称为析构函数,与构造函数相对应,这个函数是在某个对象的所有引用被删除,或者对象被显示销毁时,自动调用的。该函数也不能重写。

析构函数通常用于释放存储空间、断开数据库连接等操作。

2、__get与__set

当要对一个类定义的private属性进行获取或者赋值的操作时,如果没有在类中定义__get、__set,PHP会爆出Fatal错误。但是,如果定义了方法,会自动执行方法。

这两个方法主要是对于操作类的私有方法时,可以进行更为灵活的处理,再避免报错增强程序健壮性的同时,又可以根据设置得到想要的结果,保证程序是可控的。

根据面向对象的封装性的思想,通常是不建议对象直接操控类的属性。这两个方法就可以对操作属性进行把控。

示例如下:

class testControlProp{
         private $propArray;
         public function__get($name){
                   if(!property_exists($this,$name)){
                            return'无此属性<br />';
                   }else{
                            return$this->$name.'<br />';
                   }
         }       
         public function__set($name, $val){
                   if(!property_exists($this,$name)){
                            echo'无此属性<br />';
                   }else{
                            if(!is_array($val)){
                                     echo'对属性的设置不合法<br />';
                            }else{
                                     $this->$name= $val;
                                     echo'success<br />';
                            }
                   }
         }
}
$test = new testControlProp();
$test->propArray = 'a1';//返回结果是对属性设置不合法
$test->propArray = array(1, 2);//返回success
echo $test->prop;//返回无此属性
echo $test->propArray;//返回array      

上述方法实现把控对象对其属性的操作,保证设置的属性都是想要的格式或内容,保证获取的属性都是有效的经过处理的。

3、__toString

当echo类的实例时,会自动调用该方法,如果没有定义该方法,则会报错。

__toString方法可以自定义echo的内容,让输出更人性化。

因此,可以使用此方法自定义需要输出的结果,以起到自定义serialize的作用,更加节约存储空间。

4、__call、__callStatic

当调用类没有定义的方法时,如果类中没有定义__call则会报错(__callStatic则是调用没有定义的static方法)。

__call方法具有重要作用,可以实现动态创建和延迟绑定功能。

下面实现数据库查询条件where的动态绑定功能。

结果如下:

PHP源码如下:

<?php
class Db{
         private$server; //数据库服务器名称
   private $username; // 连接数据库用户名
   private $password; // 连接数据库密码
   private $database; // 数据库的名字
         private$conn;//数据库连接
         private$sql;
         publicfunction __construct($server='localhost', $username='root', $password='root',$database='test'){
                   $this->server= $server;
                   $this->username= $username;
                   $this->password= $password;
                   $this->database= $database;
                   $dbConnection= new PDO('mysql:host=127.0.0.1;dbname=test','root','root');
                   //$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
                   //$dbConnection->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);             
                   $this->conn= $dbConnection;
         }
         //动态查询数据:
         //格式:get_tablename_by_condintions1_conditions2(val1,val2)
         publicfunction __call($name, $args){
                   $arrName= explode('_', $name);
                   $this->sql= ' select * from '.$arrName[1];
                   if(count($arrName)<3){
                            return$this->conn->query($this->sql);
                   }else{
                            $this->sql.= ' where ';
                            $arrCond= array();
                            for($i=3;$i<count($arrName);$i++){
                                     $this->sql.= ' '.$arrName[$i].' = :'.$arrName[$i].' ';
                                     if($i<count($arrName)-1){
                                               $this->sql.= ' and ';
                                     }
                                     $arrCond[$arrName[$i]]= $args[$i-3];
                            }
                            $pre= $this->conn->prepare($this->sql);
                            $pre->execute($arrCond);
                            return$pre;//注意:需要return pre,而不是execute的结果,否则报错
                   }
         }
}
$db = new DB();
$result = $db->get_mytable();
echo '不带查询条件:<br />';
foreach($result as $val){ 
         print_r($val); 
         echo'<br /        >';
}
echo '<br />带查询条件<br/>' ;
$result =$db->get_mytable_by_name_status('a', 1);
//var_dump($result);die();
foreach ($result as $val) {
         print_r($val); 
         echo'<br /        >';
}

——written by linhxx 2017.06.20

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2017-06-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java学习

工程师笔试题2(答案解析)

一、单项选择题 1.二进制数 11101 转化为十进制数是( )。 A.23 B.17 C.26 D.29 2.以下可以对对象加互斥锁的关键字是( )。 ...

3126
来自专栏程序员互动联盟

【专业知识】初学者需要知道的10个Java字符串问题

下面我为大家总结了10条Java开发者经常会提的关于Java字符串的问题,如果你也是Java初学者,仔细看看吧: ? 1、如何比较字符串,应该用”==”还是eq...

3497
来自专栏Jack的Android之旅

疯狂Java笔记之对象及其内存管理

类体内定义的变量被称为成员变量〔英文是Field)。如果定义该成员变量时没有使用static 修饰,该成员变量又被称为非静态变量或实例变量;如果使用了stat...

653
来自专栏用户2442861的专栏

C++ STL源码实现以及分析之vector

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/haluoluo211/article/d...

441
来自专栏Java学习网

开发中最常见的Java字符串问题总结

开发中最常见的Java字符串问题总结  1.怎样比较字符串?用”==”还是用equals()?   简单地说,”==”测试两个字符串的引用是否相同,equals...

20810
来自专栏.Net Core 开发记录

JavaScript权威指南 - 函数

函数本身就是一段JavaScript代码,定义一次但可能被调用任意次。如果函数挂载在一个对象上,作为对象的一个属性,通常这种函数被称作对象的方法。用于初始化一个...

563
来自专栏决胜机器学习

《Redis设计与实现》读书笔记(六) ——Redis中的压缩列表

《Redis设计与实现》读书笔记(六) ——Redis中的压缩列表 (原创内容,转载请注明来源,谢谢) 一、概述 压缩列表(ziplist)是列表键(list)...

3517
来自专栏Java架构师进阶

Java程序员实现完美代码的十大要素

对于方法的注释应该包含详细的入参和结果说明,有异常抛出的情况也要详细叙述;类的注释应该包含类的功能说明、作者和修改者。

652
来自专栏Python小屋

Python类中公开方法、私有方法和特殊方法的继承原理

在Python中,对象的私有成员在类外部、派生类或程序中无法直接访问,但是可以通过“对象名._类名__私有成员名”这样一种特殊的形式来访问。 基类的构造方法和公...

3485
来自专栏技术博客

C#基础知识系列五(构造函数)

  2、不带参数的构造函数称为“默认构造函数”。 无论何时,只要使用 new 运算符实例化对象,并且不为 new 提供任何参数,就会调用默认构造函数。除非类是s...

603

扫描关注云+社区