魔术方法/序列化/对象遍历/重载

Posted on Posted in php
Tips: 本文创建于2014年4月13日,已超过 2 年,内容或图片可能已经失效!

魔术方法,当某个情况发生时候,会自动调用魔术方法
1、把对象转成字符串。对象转不成字符串会自动调用__toString方法

[code lang="php"]
<?php
class C {
private $id;
private $name;
public function __construct($id, $name) {
$this->id = $id;
$this->name = $name;
}
public function __toString() {
$str = '';
// get_object_vars(对象),该函数获得对象的所有属性
$arr = get_object_vars ( $this );
foreach ( $arr as $k => $v ) {
$str .= $k . ':' . $v . '<br>';
}
return $str;
}
}
$c1 = new C ( '1', 'c1' );
echo $c1;
?>
[/code]

2、把对象当作函数调用。__invoke方法:PHP实现匿名函数机制的一个重要步骤
其实:调用对象就是调用对象的__invoke()方法。

[code lang="php"]
<?php
$sayHello = function ($name) {
echo 'Hello ', $name;
};
$sayHello ( 'PHP' ); // 将对象当作函数调用
echo '<br>';
var_dump ( $sayHello ); // 查看下匿名函数类型
echo '<br>';
class C {
public function __invoke($name) {
echo 'Hi ', $name;
}
}
$o = new C ();
$o ( 'ITCAST' );//将对象当作函数调用
?>
[/code]

3、序列化&&反序列化
函数:把数据存储在一个文件中
file_put_contents(文件地址,写入内容);//写入文件
file_get_contents(文件地址);//获得文件内容

序列化

[code lang="php"]
<?php
//存
require './MySQLDB.class.php';
$data = MySQLDB::getInstance(array('pass'=>'123456'));
//serialize函数:数据 转成特殊字符串
var_dump($data_ser = serialize($data));
file_put_contents('./data', $data_ser);
?>
[/code]

反序列化

[code lang="php"]
<?php
//取
$data = file_get_contents('./data');
//反序列化对象时,找不到类的定义,这里把类包含上,即OK
//require './MySQLDB.class.php';
var_dump($db = unserialize($data));

echo '<hr>';
var_dump($db->fetchAll('show databases'));

function __autoload($c) {
require './' . $c . '.class.php';
}
?>
[/code]

序列化时控制哪些属性需要被序列化,__sleep()
该方法返回一个数组,数组内的每个元素,就是一个需要被序列化的属性名

[code lang="php"]
<?php
//序列化时执行
public function __sleep(){
return array('host','port','user','pass','dbname','charset');
}
?>
[/code]

反序列化时重新初始化对象部分成员,自动解决上面找不到类的问题。
可以利用魔术方法, __wakeup()完成。

[code lang="php"]
<?php
//反序列化过程中执行的魔术方法,重新链接并初始化信息
public function __wakeup(){
//数据库链接
$this->connect();
//设定字符集
$this->setCharset();
//选择默认数据
$this->selectDefaultDb();
}
?>
[/code]

4、对象遍历:遍历的是对象的属性
常规遍历,收到访问修饰符限制

[code lang="php"]
<?php
$p = new person('001','张三');
foreach($p as $p_id => $p_name){
var_dump($p_id,$p_name);
}
?>
[/code]

自定义对象的遍历:利用foreach的5个步骤流程

foreach-step

[code lang="php"]
<?php
class team implements Iterator {
private $t_id;
private $t_name;
private $p_count = 0; // 球员数量
private $players = array (); // 球员
public function __construct($id, $name) {
$this->t_id = $id;
$this->t_name = $name;
}
public function addPlayer(player $p) {
$this->players [] = $p;
$this->p_count ++;
}
public function rewind() {
reset ( $this->players );
}
public function valid() {
static $i = 0; // 遍历计数器
if ($i < $this->p_count) {
// 还合法
++ $i;
return true;
} else {
// 已经非法
$i = 0;
return false;
}
}
public function current() {
return current ( $this->players );
}
public function key() {
return key ( $this->players );
}
public function next() {
return next ( $this->players );
}
}
class player {
private $p_id;
public $p_name;
private $p_no;
public function __construct($id, $name, $no) {
$this->p_id = $id;
$this->p_name = $name;
$this->p_no = $no;
}
}
$t = new team ( '13', '皇马' );
$p1 = new player ( 1, 'C罗', 7 );
$p2 = new player ( 2, '贝尔', 10 );
$p3 = new player ( 3, '本泽马', 11 );
$t->addPlayer ( $p1 );
$t->addPlayer ( $p2 );
$t->addPlayer ( $p3 );
echo '<pre>';
// var_dump($t);

foreach ( $t as $p_name => $p ) {
// $p;//队员
exam ( $p );
submit ( $p );
}
function exam(player $p) {
echo $p->p_name, '在考试中,请勿打扰...<br>';
}
function submit(player $p) {
echo $p->p_name, '交卷,考试结束<hr>';
}
?>
[/code]

5、重载
成员重载:对不可访问的成员的访问处理

  • __set():设置/增加修改
  • __get():获取
  • __isset():判断是否存在
  • __unset():删除

[code lang="php"]
<?php
class student {
private $name;
private $age; // 可以设置
private $height = 170;
private $class_id; // 设置
public function getName() {
}
public function getHeight() {
}
public function setClassId($id) {
}
public function seAge($age) {
}
public function __set($p_name, $p_value) {
$allow_set = array (
'age',
'class_id'
);
if (in_array ( $p_name, $allow_set )) {
$this->$p_name = $p_value; // 可变属性
} else {
// 不可重载的属性
trigger_error ( $p_name . '属性你没有资格动他', E_USER_WARNING );
}
}
public function __get($p_name) {
$allow_get = array (
'age',
'name',
'height'
);
if (in_array ( $p_name, $allow_get )) {
return $this->$p_name; // /可变属性
} else {
trigger_error ( $p_name . '不对你开放', E_USER_WARNING );
}
}
public function __isset($p_name) {
$allow_get = array (
'age',
'name',
'height'
);
if (in_array ( $p_name, $allow_get )) {
return true;
} else {
return false;
}
}
public function __unset($p_name) {
trigger_error ( $p_name . '不能删除', E_USER_WARNING );
}
}

$o = new student ();

var_dump ( isset ( $o->height ) );

echo $o->height;

unset ( $o->height );

// $o->class_id = 18;
// var_dump($o);
// $o->name = '王力宏';

// $o->gender = 'male';
// echo $o->gender;
// echo $o->name;

echo '<hr>';
class Table {
private $name; // 表名
private $fields = array (); // 字段列表
private $values = array ();
public function __construct($name) {
$this->name = $name;
// 获得该表的字段列表 desc $name
$this->field ();
}
private function field() {
$this->fields = array (
'id',
'name',
'length'
);
}
public function __set($p, $v) {
if (in_array ( $p, $this->fields )) {
$this->values [$p] = $v;
}
}
public function __get($p) {
if (in_array ( $p, $this->fields )) {
return $this->values [$p];
}
}
}

$row = new Table ( 'student' );
$row->id = 10;
$row->height = 178;
echo $row->id;
echo '<hr>';
echo $row->height;
?>
[/code]

方法重载:当调用一个不可访问的方法时,会自动执行

  • __call();
  • static __callStatic()

当静态调用一个方法是,如果该方法是不可访问的,则会自动触发上面的魔术方法tip:方法是静态的

[code lang="php"]
<?php
class Team {
private $t_name = '拜仁';
private $p_count = 23;
public function getCount() {
return $this->p_count;
}
}
class Player {
private $p_name;
private $p_gender;
private $belong_team; // 所属球队
public function __construct($n, $g) {
$this->p_name = $n;
$this->p_gender = $g;
}
public function selectTeam(Team $t) {
$this->belong_team = $t;
}
public function __call($m_name, $m_args) {
// var_dump($m_name, $m_args);
// echo '你所请求的方法不存在请确定后再次访问<br>';
// $this->defaultAction();
if (method_exists ( $this->belong_team, $m_name )) {
return '我帮你问了球队:' . $this->belong_team->$m_name (); // 可变方法
} else {
echo '伙计我尽力啦';
}
}
public function defaultAction() {
echo 'Hello, 我是', $this->p_name, '<br>';
}
}

$p = new Player ( '罗本', 'male' );
$team = new Team ();
$p->selectTeam ( $team );

echo $p->getCount ();
echo $p->getXYZ ();
?>
[/code]

Leave a Reply

Your email address will not be published. Required fields are marked *

twenty + 15 =