仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1388|回复: 20
打印 上一主题 下一主题

[学习教程] PHP编程:PHP 5.0 中的对象重载手艺研讨

[复制链接]
深爱那片海 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-2-3 23:57:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
接触MYSQL,开始设计数据库程序     1、简介

  很侥幸,PHP 5.0中引入了对象重载手艺。本文将切磋关于办法__call(),__set()和__get()停止重载的能够性。在对重载实际作复杂引见后,咱们将经由过程两个例子直奔主题:第一例,完成延续存储类;第二例,找到一种完成静态的getter/setter的办法。

  2、甚么是对象重载?

  在PHP中谈到对象重载时,咱们要区分两品种型:

  ・办法重载

  ・属性重载

  在办法重载的情形下,咱们要界说一个魔术般的办法__call(),它将完成一个在响应类中对不决义办法的笼统挪用。只要当你想存取类中不决义的办法时,这类笼统办法才会被挪用。在没无方法重载的情形下,上面的例子将招致PHP显示一条致命毛病信息:Call to undefined method ThisWillFail::bar() in/some/directory/example.php on line 9并流产法式的履行:

<?php
 class ThisWillFail {
  public function foo() {
   return "Hello World!";
  }
 }
 $class = new ThisWillFail;
 $class->bar();
?>

  借助办法重载的匡助,代码可以捕捉到这类挪用且可以面子地赐与处置。

  属性重载与办法重载差不多。这类情形下,类把读/写操作重定向(亦可称代办署理)到类的属性,这些属性在类中没有显式界说。这里的专门办法是__set()和__get()。依附于毛病呈报品级,PHP翻译器凡是在存取一个不决义的属性时,或收回一个告诉,或推延一下并潜伏地界说这个变量。而假如利用属性重载,翻译器却可以在设置一个不决义的属性时挪用__set(),而在存取一个不决义的属性值时挪用__get()。
综上所述,使用重载手艺可以完成在象用PHP如许的静态言语停止时软件开辟工夫的大大延长。

  实际引见至此,上面剖析详细编码。

  3、延续性存储类举例

  以下代码,经由过程利用属性重载手艺,用少于50行的PHP代码完成了下面所提到的延续性存储类。术语persistable意味着类可以从一个数据布局中描写一个元素,并坚持与底端存储体系的同步。用编码的注释就是,内部代码可使用类来完成从一个数据库表当选定一行。如许,在法式运转时,可以直接存取类的属性来把持该行中的元素(读/取)。在剧本停止时,PHP将担任把更新的行数据回送到数据库中去。

  精心研读上面代码将有助于你了解甚么是属性重载。

<?php
 //装入PEAR的 <a href="http://pear.php.net/package/DB/">DB package</a>
 require_once "DB.php";
 class Persistable {
  private $data = array();
  private $table = "users";
  public function __construct($user) {
   $this->dbh = DB::Connect("mysql://user:password@localhost/database");
   $query = "SELECT id, name, email, country FROM " .
   $this->table . " WHERE name = ?";
   $this->data = $this->dbh->getRow($query, array($user),
   DB_FETCHMODE_ASSOC);
  }
  public function __get($member) {
   if (isset($this->data[$member])) {
    return $this->data[$member];
   }
  }
  public function __set($member, $value) {
   // dataset的ID是只读的
   if ($member == "id") {
    return;
   }
   if (isset($this->data[$member])) {
    $this->data[$member] = $value;
   }
  }
  public function __destruct() {
   $query = "UPDATE " . $this->table . " SET name = ?,
   email = ?, country = ? WHERE id = ?";
   $this->dbh->query($query, $this->name, $this->email,
   $this->country, $this->id);
  }
 }
 $class = new Persistable("Martin Jansen");
 $class->name = "John Doe";
 $class->country = "United States";
 $class->email = "john@example.com";
?>

  你碰到的第一个成绩多是__construct(),这是PHP 5中引入的新的机关器办法。在PHP 4时期,机关器老是与它们的类名相婚配。在PHP 5中已不再是如许。你不需求对机关器办法有过量的懂得,除挪用它可以创立一个类的实破例;并注重到,这里利用了一个参数 - 履行一个基于此参数的数据库。此机关器把查询了局赋值给类属性$data。

  接上去,法式界说了两个出格的办法__get()和__set()。你应当对它们早已熟习:__get()用于读取不决义的属性值,__set()用于修正不决义的属性值。

  这意味着不管甚么时分从延续性存储类中读取/写入一个不决义的属性,由这些专门办法来担任办理在属性数组变量$data中的信息,而不是直接改动类的属性(切记:变量$data包括着来自于数据库中的一行!)。

  类中的最初一个办法是__construct()的对峙者- 析构器__destruct()。PHP在"剧本封闭阶段"挪用析构器,典范地这是在PHP剧本履行将近停止的时分。析构器把来自于$data属性的信息写回到数据库中去。这恰是后面同步(synchronization )术语的寄义。

  你能够早已注重到,这里的代码利用了PEAR的数据库笼统层包(database abstraction layer package)。其实这无所谓,经由过程其余体例与数据库通信也一样能申明本文的主题。

  假如你仔细察看,会发明该延续性存储类的描写对照复杂。例子中仅触及了一个数据库表,而没有思索更庞杂的数据模子,如利用LEFT JOIN和其它庞杂的数据库操作手艺。但是你不用受此束缚,借助于属性重载,你可使用你本人幻想的数据库模子。只需求到场少量代码,你便可以在该延续性存储类中应用庞杂的数据库特征。

  还存在一个小成绩 - 当在析构器中查询掉败时并没有引入毛病处置机制。是析构器的天分招致在这类情形下不成能显示响应的毛病信息,由于构建HTML标记经常在PHP挪用构析器之前就已停止了。

  为处理这个成绩,你可以把__destruct()重定名为象saveData()如许的名字并在挪用剧本的某处手工履行这一办法。这关于类的延续性存储的概念并没有任何改动;仅是多写几行代码罢了。作为选择,你还可以在析构器中利用函数error_log()来纪录上司于体系局限的毛病纪录文件中的毛病信息。

  属性重载的任务机制就是如许。上面咱们会商一下办法重载。
<P>  4、办法重载举例

  1. 静态的Getter/Setter办法

  以下代码完成了"静态"getter/setter办法以借助于办法重载的匡助来掌握类。上面咱们联合源代码停止剖析:

<?php
 class DynamicGetterSetter {
  private $name = "Martin Jansen";
  private $starbucksdrink = "Caramel Cappuccino Swirl";
  function __call($method, $arguments) {
   $prefix = strtolower(substr($method, 0, 3));
   $property = strtolower(substr($method, 3));
   if (empty($prefix) || empty($property)) {
    return;
   }
   if ($prefix == "get" && isset($this->$property)) {
    return $this->$property;
   }
   if ($prefix == "set") {
    $this->$property = $arguments[0];
   }
  }
 }
 $class = new DynamicGetterSetter;
 echo "Name: " . $class->getName() . "\n";
 echo "Favourite Starbucks flavour: " . $class->getStarbucksDrink() . "\n\n";
 $class->setName("John Doe");
 $class->setStarbucksDrink("Classic Coffee");
 echo "Name: " . $class->getName() . "\n";
 echo "Favourite Starbucks flavour: " . $class->getStarbucksDrink() . "\n\n";
?>

  很分明,这里的两个属性$name和$starbucksdrink都是公有的,就是说从类的内部是不克不及够存取这些属性的。在面向对象的编程中,完成公共的getter/setter办法来存取或修正非公共属性的值是很常常的工作。完成这些是单调的工作,且相当消耗工夫和精神。

  借助于办法重载可以轻易得处理这个成绩。不是为每一个属性完成getter/setter办法,下面只完成了一个通用的__call()办法。这意味着当挪用一个不决义的getter/setter办法如setName()或getStarbucksdrink()时,PHP不会发生一个致命毛病而流产,而是履行(或代办署理到)魔术般的__call()办法。

  这是些复杂引见,上面咱们对__call()作一下深切剖析。

  2. 具体剖析__call()办法

  __call()的第一个参数是原始的且还没有肯定的办法(如setName),第二个参数是一个数字索引的一维数组,它包括了原始办法的一切参数。用两个参数("Martin"和42)挪用一个不决义的办法将发生上面数组:

$class->thisMethodDoesNotExist("Martin", 42);
/导向__call()的第二个参数
Array
(
[0] => Martin
[1] => 42
)

  在办法__call()外部,假如原始办法以get或set开首,则要停止某种盘算以肯定是不是代码挪用的是一个getter/setter办法。并且,这类办法还要进一步剖析办法名的别的一构成局部(除去入手下手的三个字符),由于前面这局部字符串正代表getter/setter参照的属性的名字。

  假如办法名中唆使有一个getter/setter,那末该办法或前往响应的属性值,或设置原始办法的第一个参数的值。假如没有的话,它不做任何工作,持续履行法式,好象没有工作产生。

  3. 完成方针

  本色上,响应于恣意的属性,存在一种办法答应代码静态地挪用恣意的getter/setter办法,这类算法是存在的。这在短时间内开辟一个法式原型的情形下是很便利的:不是消费大批工夫来完成getters/setters,开辟人员可以专注于建模API并包管使用法式的基本准确。把__call()办法归入到一个笼统类中乃至有能够使你在未来的PHP工程开辟中完成代码的重用!

  4. 缺乏以外

  有长处就出缺点。以上办法也有几个缺乏:较大些的项目可以会利用象phpDocumentor如许的东西来跟踪API布局。用下面引见的静态办法,一切的getter/setter办法固然不会呈现在主动生成的文档中,这是无需多作注释的。

  别的一个缺乏是,类里面的代码可以存取类内的每个公有属性。当利用真实的getter/setter办法时,有能够区分开内部代码可以存取的公有属性和对类内部不成见的"真实的"公有属性 - 由于咱们无方法重载,并且有虚拟的getter和setter办法可以使用。

  5、结论

  本文经由过程两个例仔细致剖析了PHP 5.0中对象重载的两种情况。很但愿本文的办法匡助你进步PHP编程的任务效力!同时,你也应苏醒地看到这类办法的缺乏。
多去关于PHP的网站,尤其有很多经典的文章,多读读这些文章显然是有好处的。
愤怒的大鸟 该用户已被删除
沙发
发表于 2015-2-4 07:19:39 | 只看该作者
这些都是最基本最常用功能,我们这些菜鸟在系统学习后,可以先对这些功能深入研究。
小妖女 该用户已被删除
板凳
发表于 2015-2-6 19:48:02 | 只看该作者
环境搭建好,当你看见你的浏览器输出“it works\\\\\\\"时你一定是喜悦的。在你解决问题的时候,我强烈建议多读php手册。
老尸 该用户已被删除
地板
发表于 2015-2-9 23:44:07 | 只看该作者
你很难利用原理去编写自己的代码。对于php来说,系统的学习我认为还是很重要的,当你有一定理解后,你可你针对某种效果研究,我想那时你不会只是复制代码的水平了。
5#
发表于 2015-2-16 06:48:40 | 只看该作者
不禁又想起那些说php是草根语言的人,为什么认得差距这么大呢。
第二个灵魂 该用户已被删除
6#
发表于 2015-2-28 05:45:33 | 只看该作者
至于模板嘛,各位高人一直以来就是争论不休,我一只小菜鸟就不加入战团啦,咱们新手还是多学点东西的好。
爱飞 该用户已被删除
7#
发表于 2015-3-1 02:18:55 | 只看该作者
在学习的过程中不能怕麻烦,不能有懒惰的思想。学习php首先应该搭建一个lamp环境或者是wamp环境。这是学习php开发的根本。虽然网络上有很多集成的环境,安装很方便,使用起来也很稳定、
小魔女 该用户已被删除
8#
发表于 2015-3-7 21:01:23 | 只看该作者
你很难利用原理去编写自己的代码。对于php来说,系统的学习我认为还是很重要的,当你有一定理解后,你可你针对某种效果研究,我想那时你不会只是复制代码的水平了。
柔情似水 该用户已被删除
9#
发表于 2015-3-15 13:39:18 | 只看该作者
php里的数组为空的时候是不能拿来遍历的;(这个有点低级啊,不过我刚被这个边界问题墨迹了好长一会)
admin 该用户已被删除
10#
发表于 2015-3-19 17:40:51 | 只看该作者
曾经犯过一个很低级的错误,我在文件命名的时候用了一个横线\\\\\\\'-\\\\\\\' 号,结果找了好几个小时的错误,事实是命名的时候 是不能用横线 \\\\\\\'-\\\\\\\' 的,应该用的是下划线  \\\\\\\'_\\\\\\\' ;
只想知道 该用户已被删除
11#
发表于 2015-3-24 16:29:00 | 只看该作者
最后祝愿,php会给你带来快乐的同时 你也会给他带来快乐。
分手快乐 该用户已被删除
12#
发表于 2015-4-5 20:52:57 | 只看该作者
小鸟是第一次发帖(我习惯潜水的(*^__^*) 嘻嘻……),有错误之处还请大家批评指正,另外,前些日子听人说有高手能用php写驱动程序,真是学无止境,人外有人,天外有天。
莫相离 该用户已被删除
13#
发表于 2015-4-11 00:09:05 | 只看该作者
最后祝愿,php会给你带来快乐的同时 你也会给他带来快乐。
若相依 该用户已被删除
14#
发表于 2015-4-12 22:52:23 | 只看该作者
至于模板嘛,各位高人一直以来就是争论不休,我一只小菜鸟就不加入战团啦,咱们新手还是多学点东西的好。
飘灵儿 该用户已被删除
15#
发表于 2015-4-14 12:02:17 | 只看该作者
装在C盘下面可以利用windows的ghost功能可以还原回来(顺便当做是重转啦),当然啦我的编译目录要放在别的盘下,不然自己的劳动成果就悲剧啦。
精灵巫婆 该用户已被删除
16#
发表于 2015-4-17 21:42:46 | 只看该作者
建数据库表的时候,int型要输入长度的,其实是个摆设的输入几位都没影响的,只要大于4就行,囧。
不帅 该用户已被删除
17#
发表于 2015-4-20 22:44:49 | 只看该作者
首推的搜索引擎当然是Google大神,其次我比较喜欢 百度知道。不过搜出来的结果往往都是 大家copy来copy去的,运气的的概率很大。
再见西城 该用户已被删除
18#
发表于 2015-4-22 19:51:43 | 只看该作者
基础有没有对学习php没有太大区别,关键是兴趣。
简单生活 该用户已被删除
19#
发表于 2015-4-26 22:21:40 | 只看该作者
开发工具也会慢慢的更专业,每个公司的可能不一样,但是zend studio是个大伙都会用的。
金色的骷髅 该用户已被删除
20#
发表于 2015-6-12 06:04:28 | 只看该作者
写的比较杂,因为我也是个新手,不当至于大家多多指正。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-12-23 13:26

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表