最近在肝PHP和Mysql
以我学了四天PHP的感觉来看
PHP的类如果不是考虑前后端彻底分离的话,用class来封装整个网页的Page用来重复利用还是不错的
然后在学习面向对象的时候有些坑爹(高深)的操作让我有些苦恼
1.迭代属性
<?php
class myClass
{
public $a="xiao";
public $b="yu";
public $c="yu";
}
$x=new myClass;
foreach ($x as $key )
{
echo $key."<br />";
}
echo "<br />";
?>
上面这段代码还是很简单的,就是用foreach输出类中的所有属性,然后开始玄学,迭代器……
2.迭代器
为什么要用迭代器呢,如果我们的迭代行为很复杂,用迭代器是不错的操作
然后重点来了迭代器(iterator)需要IteratorAggregate接口,getIterator(返回该迭代器实例)
生命一个类有迭代器接口的方法:
class ObjectIterator implements Iterator //生命ObjectIterator是一个迭代器,可以调用迭代器接口所要求的一系列函数
有哪些函数是需要的呢,如下(不需要析构函数)
class ObjectIterator implements Iterator //生命ObjectIterator是一个迭代器,可以调用迭代器接口所要求的一系列函数
{
private $obj;
private $count;
private $currentIndex;
//构造函数
function __construct($obj)
{
$this->obj=$obj;
$this->count=count($this->obj->data);
}
//重置内部数据指针
function rewind()
{
$this->currentIndex=0;
}
//判断数据指针当前位置是否还存在更多数据
function vaild()
{
return $this->currentIndex<$this->count; //true即为vaild
}
//返回数据指针值
function key()
{
return $this->currentIndex;
}
//返回当前数据指针指向的数据
function current()
{
return $this->obj->data[$this->currentIndex];
}
//向后移动数据指针1step
function next()
{
$this->currentIndex++;
}
}
其实就是要把foreach的操作封装在类里面来应付各种各样的情况,乍一看比较多此一举,但是实际应用还是有价值的,不同的迭代方式我们用这些操作基本都可以搞定
这只是迭代器,我们还需要迭代器的接口IteratorAggregate,我们上面用的data就是接口里的变量,通过这个接口把需要迭代的变量传给迭代器运作(通过getIterator)
class Object implements IteratorAggregate
{
public $data=array();
function __construct($in)
{
$this->data=$in;
}
function getIterator()
{
return new ObjectIterator($this);
}
}
分解开来慢慢分析其实还可以,就是把变量传进data,在把变量的指针传给迭代器,从而进行运作
给个例子
<?php
class ObjectIterator implements Iterator //生命ObjectIterator是一个迭代器,可以调用迭代器接口所要求的一系列函数
{
private $obj;
private $count;
private $currentIndex;
//构造函数
function __construct($obj)
{
$this->obj=$obj;
$this->count=count($this->obj->data);
}
//重置内部数据指针
function rewind()
{
$this->currentIndex=0;
}
//判断数据指针当前位置是否还存在更多数据
function valid()
{
return $this->currentIndex<$this->count; //true即为vaild
}
//返回数据指针值
function key()
{
return $this->currentIndex;
}
//返回当前数据指针指向的数据
function current()
{
return $this->obj->data[$this->currentIndex];
}
//向后移动数据指针1step
function next()
{
$this->currentIndex++;
}
}
class Object implements IteratorAggregate
{
public $data=array();
function __construct($in)
{
$this->data=$in;
}
function getIterator()
{
return new ObjectIterator($this);
}
}
$myObject=new Object(array(2,4,6,8,10)); //data改为一个array
$myIterator= $myObject->getIterator(); //data的地址传入迭代器
for($myIterator->rewind();$myIterator->valid();$myIterator->next())
{
$key=$myIterator->key();
$value=$myIterator->current();
echo $key."=>".$value."<br />";
}
echo "<br />";
?>
结果如下
这个其实还比较容易,但是如果复杂了呢,或者是用了别的迭代方式么,不论内部实现怎么变化,数据接口都是固定的,不用我们多费心,这就是迭代器的作用
3.生成器
生成器怎么说了也算是在迭代中使用的,而且比迭代器简单且容易理解,如果能用生成器的话,我个人倾向于直接while、for之类的,这里就不做介绍了
4.反射API
这个操作有点像爬去类的结构的爬虫?
如果我们手里有一些类的文档,但是不熟悉,变量很复杂,很容易看的一头雾水,这个时候这个操作就很有用了,来个例子比较直观
<?php
class Page
{
public $content;
public $title="TLA Consulting Pty Ltd";
public $keywords="TLA Consulting, Three Letter Abbreviation, some of my best friends are search engines";
public $buttons=["Home"=>"12_home.php",
"Contact"=>"12_contact.php",
"Services"=>"12_services.php",
"Site Map"=>"12_map.php"];
//class Page's operations
public function __set($name,$value)
{
$this->$name=$value;
}
public function Display()
{
echo "<html>\n<head>\n";
$this->DisplayTitle();
$this->DisplayKeywords();
echo "</head>\n<body>\n";
$this->DisplayHeader();
$this->DisplayMenu($this->buttons);
echo $this->content;
$this->DisplayFooter();
echo "</body>\n</html>\n";
}
public function DisplayTitle()
{
echo "<title>".$this->title."</title>";
}
public function DisplayKeywords()
{
//<meta> 标签永远位于 head 元素内部
//元数据总是以名称/值的形式被成对传递的
echo "<meta name='keywords' content='".$this->keywords."'/>";
echo "<title>".$this->title."</title>";
}
public function DisplayHeader()
{
?>
<!-- page header -->
<header>
<img src="./11.jpg" alt="TLA logo" height="200" width="600"/>
<h1>TLA Consulting</h1>
</header>
<?php
}
public function DisplayMenu($buttons)
{
echo "<!--menu-->
<nav>";
while(list($name,$url)=each($buttons))
{
$this->DisplayButton($name,$url,!$this->IsURLCurrentPage($url));
}
echo "</nav>\n";
}
public function IsURLCurrentPage($url)
{
//例如,在地址为 http://example.com/foo/bar.php 的脚本中使用 $_SERVER['PHP_SELF'] 将得到 /foo/bar.php
if(strpos($_SERVER['PHP_SELF'],$url)===false)
{
return false;
}
else
{
return true;
}
}
public function DisplayButton($name,$url,$active=true)
{
if($active)
{
?>
<div class="menuitem">
<a href="<?=$url?>">
<img src="./1.jpg" alt="" height="50" width="50"/>
<!-- ?=?可以在html中表示php的属性值 -->
<span class="menutext"><?=$name?></span>
</a>
</div>
<?php
}
else
{
?>
<div class="menuitem">
<img src="./1.jpg" alt="" height="50" width="50"/>
<span class="menutext"><?=$name?></span>
</div>
<?php
}
}
public function DisplayFooter()
{
?>
<!-- page footer -->
<footer style="background: #ccccff;">
<p>TLA Consulting Pty Ltd.<br />
Please see our legal information page.</p>
</footer>
<?php
}
}
?>
上面这是我们的一个类,东西还是蛮多的对于我这个菜鸡来说,我们接下来用反射API来爬取
<?php
//反射API
require_once("12_page.php");
$class =new ReflectionClass("Page");
echo "<pre>".$class."</pre>";
?>
结果如下
对我这种菜鸟帮助还蛮大的,能一眼看出一个类大概的操作和结构
5.延迟静态绑定
这是继承里的操作,下面这个例子的输出可以很好地解释
<?php
class A
{
public static function whichclass()
{
echo __CLASS__; //使用 self:: 或者 __CLASS__ 对当前类的静态引用,取决于定义当前方法所在的类
}
public static function test()
{
self::whichclass();
}
}
class B extends A
{
public static function whichclass()
{
echo __CLASS__;
}
}
A::test();
echo "<br />";
B::test();
?>
输出结果如下
两个A,而不是A B
我们要解决这个问题很简单,把self改成static就好啦,可以试一下哦
6.多重继承?(Trait)
对不起,PHP没有多重继承,但是可以用别的方法实现,比如Trait,又比如接口
Trait对我来说感觉好的地方就是他强调的代码重用是包含了实现的,因人而异吧,接口的话比较快捷,Triat组合起来我觉得还蛮爽的
<?php
trait fileLogger
{
public function logmessage($message,$level="DEBUG")
{
//code
}
}
trait sysLogger
{
public function logmessage($message,$level="ERROR")
{
//code
}
}
class fileStorage
{
use fileLogger,sysLogger
{
fileLogger::logmessage insteadof sysLogger;
sysLogger::logmessage as logsymessage;
}
function store($data)
{
$this->logmessage($message);
$this->logsymessage($message);
}
}
?>
上述代码就体现Trait的组合特点,而且我们可以看到如果遇到重名的函数,可以用instead和as来轻松解决,这样新的类就可以使用你所需要的Trait了,继承不同Trait,但不是直接继承不同的类的部分,算是一种模拟的多重继承吧,用起来有时候有不错的效果,而且很灵活,可是随时给类“打补丁”