仓酷云

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

[学习教程] PHP网页编程之php5进修笔记(转)

[复制链接]
柔情似水 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-2-4 00:30:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

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

x
大家如果能懂得“熟能生巧”的道理也就明白了这并不是浪费时间,同时这也可以减轻板主的负担,让他们有时间去处理更难的问题。php5|笔记   作者: whhwq
在phpv.net看到的感到不错
/*
+-------------------------------------------------------------------------------+
| = 本文为Haohappy读<<Core PHP Programming>>
| = 中Classes and Objects一章的笔记
| = 翻译为主+团体心得
| = 为防止能够产生的不用要的费事请勿转载,感谢
| = 接待品评斧正,但愿和一切PHP喜好者配合前进!
+-------------------------------------------------------------------------------+
*/

PHP5进修笔记
第一节--面向对象编程
面向对象编程被设计来为大型软件项目供应处理计划,特别是多人协作的项目. 当源代码增加到一万行乃至更多的时分,每个更动都能够招致不但愿的反作用. 这类情形产生于模块间结成奥密同盟的时分,就像第一次世界大战前的欧洲.
//haohappy注:喻手印块间的联系关系渡过高,互相依附性太强.更动一个模块招致其它模块也必需随着更动.
想像一下,假如有一个用来处置登录的模块答应一个信誉卡处置模块来分享它的数据库毗连. 固然起点是好的,节俭了停止另外一个数据库毗连的收入.但是有时,登录处置模块改动了个中一个变量的名字,便可能切断了二者间的协定.招致信誉卡模块的处置失足,进而招致处置发票的模块失足. 很快地,系统中一切有关的模块都能够由此失足.
因而,我感觉有点戏剧性地,绝大多半法式员都对耦合和封装心存感谢. 耦合是两个模块间依附水平的量度. 耦合越少越好.咱们但愿可以从已有的项目中抽走一个模块并在另外一个新项目中利用.
咱们也但愿在某个模块外部大范围的更动而不必忧虑对其他模块的影响. 封装的准绳可以供应这个处理计划.模块被对待成绝对自力,而且模块间的数据通讯经由过程接口来停止. 模块欠亨过彼此的变量名来窥测另外一个模块,它们经由过程函数来礼貌地发送恳求.
封装是你可以在任何编程言语中利用的一个准绳. 在PHP和很多面向进程的言语中,可以偷懒是很有引诱的.没有甚么可以禁止你经由过程模块来构建一个设想的WEB. 面向对象编程是使法式员不会违反封装准绳的一种办法.
在面向对象编程中,模块被组织成一个个对象. 这些对象具有办法和属性. 从笼统的角度来看,办法是一个对象的所做的举措,而属性是对象的特征.从编程角度来看,办法就是函数而属性是变量. 在一个幻想化的面向对象系统中,每一个部分都是一个对象. 系统由对象及对象间经由过程办法来构成的接洽组成.
一个类界说了对象的属性. 假如你在烘烤一组甜饼对象,那末类将会是甜饼机. 类的属性和办法是被挪用的成员. 人们可以经由过程说出数据成员或办法成员来表达.
每种言语供应了分歧的路子来会见对象. PHP从C++中借用概念,供应一个数据类型用来在一个标识符下包括函数和变量。最后设计PHP的时分,乃至PHP3被开辟出时,PHP其实不盘算供应开辟超越10万行代码的大型项目标才能。跟着PHP和Zend引擎的开展,开辟大型项目变得有能够,但不管你的项目范围多大,用类来书写你的剧本将可让代码完成重用。这是一个好主张,出格当你情愿与他人分享你的代码的时分。
有关对象的设法是盘算机迷信上最使人高兴的概念之一。入手下手很难把握它,但我可以包管,一旦你把握了它,用它的思惟来思虑将会十分天然。
第二节--PHP5 的对象模子
PHP5有一个单重承继的,限制会见的,可以重载的对象模子. 本章稍后会具体会商的”承继”,包括类间的父-子关系. 别的,PHP撑持对属性和办法的限制性会见. 你可以声明成员为private,不答应内部类会见. 最初,PHP答应一个子类从它的父类中重载成员.
//haohappy注:PHP4中没有private,只要public.private关于更好地完成封装很有优点.
PHP5的对象模子把对象当作与任何其它数据类型分歧,经由过程援用来传递. PHP不请求你经由过程援用(reference)显性传递和前往对象. 在本章的最初将会具体论述基于句柄的对象模子. 它是PHP5中最主要的新特征.
有了更直接的对象模子,基于句柄的系统有附加的优势: 效力进步, 占用内存少,而且具有更大的天真性.
在PHP的前几个版本中,剧本默许复制对象.如今PHP5只挪动句柄,需求更少的工夫. 剧本履行效力的提拔是因为防止了不用要的复制. 在对象系统带来庞杂性的同时,也带来了履行效力上的收益. 同时,削减复制意味着占用更少的内存,可以留出更多内存给其它操作,这也使效力进步.
//haohappy注:基于句柄,就是说两个对象可以指向统一块内存,既削减了复制举措,又削减对内存的占用.
Zand引擎2具有更大的天真性. 一个使人乐意的开展是答应析构--在对象烧毁之前履行一个类办法. 这关于使用内存也很有优点,让PHP清晰地晓得甚么时分没有对象的援用,把空出的内存分派到其它用处.
第三节--界说一个类
当你声明一个类,你需求列出对象应有的一切变量和一切函数―被称为属性和办法. 3.1.1中显示了一个类的组成. 注重在大括号({})内你只能声明变量或函数. 3.1.2中显示了若何在一个类中界说三个属性和两个办法.
3.1.1
class Name extends Another Class
{
Access Variable Declaration
Access Function Declaration
}
<?php
//界说一个跟踪用户的类
class User
{
//属性
public $name;
private $password, $lastLogin;

//办法
public function __construct($name, $password)
{
$this->name = $name;
$this->password = $password;
$this->lastLogin = time();
$this->accesses++;
}

// 获得最初会见的工夫
function getLastLogin()
{
return(date("M d Y", $this->lastLogin));
}
}

//创立一个对象的实例
$user = new User("Leon", "sdf123");

//获得最初会见的工夫
print($user->getLastLogin() ."<br>\n");

//打印用户名
print("$user->name<br>\n");
?>
当你声明属性,你不需求指明数据类型. 变量多是整型,字符串或是另外一个对象,这取决于实践情形.在声明属性时增添正文是一个好主张,标志上属性的寄义和数据类型.

当你声明一个办法,你所做的和在类内部界说一个函数是一样的. 办法和属性都有各自的定名空间. 这意味着你可以平安地创立一个与类内部函数同名的办法,二者不会抵触. 例如,一个类中可以界说一个名为date()的办法. 然而你不克不及将一个办法定名为PHP的关头字,如for或while.

类办法能够包括PHP中所谓的type hint. Type hint 是另外一个传递参数给办法的类的名字. 假如你的剧本挪用办法并传递一个不是类的实例的变量,PHP将发生一个”致命(fatal)毛病” . 你能够没有给其它类型给出type hint,就像整型,字符串,或布尔值. 在书写的时分, type hint是不是应该包括数组类型仍存在争议.

Type hint是测试函数参数或运算符的实例的数据类型的捷径. 你能够老是前往这个办法. 确认你强迫让一个参数必需是哪一种数据类型,如整型. 3.2.1 确保编译类只发生Widget的实例.

3.2.1
PHP代码:

<?php
//组件
class Widget
{
public $name='none';
public $created=FALSE;
}

//拆卸器
class Assembler
{
public function make(Widget $w)
{
print("Making $w->name<br>\n");
$w->created=TRUE;
}
}

//创立一个组件对象
$thing = new Widget;
$thing->name = 'Gadget';

//拆卸组件
Assembler::make($thing);
?>
除传递参数的变量外,办法含有一个特别的变量. 它代表类的一般实例. 你应该用这个来指向对象的属性和其它办法.一些面向对象的言语假定一个不及格的变量提交给当地属性,但在PHP中办法的任何变量只是在办法的必定局限内. 注重在User类的机关函数中这个变量的利用(3.1.2).

PHP在属性和办法声明前界说一个会见限制语,如public,private和protected. 别的,你可以用”static”来标志一个成员. 你也能够在类中声明常量. 本章稍后会有分歧会见体例的相干会商.

你可以在一行中列出不异会见体例的几个属性,用逗号来分隔它们. 在3.1.2中,User类有两个private属性--$password和$lastLogin.

第四节--机关函数和析构函数

假如你在一个类中声明一个函数,定名为__construct,这个函数将被当做是一个机关函数并在创立一个对象实例时被履行. 清晰地说,__是两个下划线. 就像其它任何函数一样,机关函数能够有参数或默许值. 你可以界说一个类来创立一个对象并将其属性全放在一个语句(statement)中.

你也能够界说一个名为__destruct的函数,PHP将在对象被烧毁前挪用这个函数. 它称为析构函数.

承继是类的一个壮大功效. 一个类(子类/派生类)可以承继另外一类(父类/基类)的功效. 派生类将包括有基类的一切属性和办法,并可以在派生类中加上其他属性和办法. 你也能够覆写基类的办法和属性. 就像3.1.2中显示的,你可以用extends关头字来承继一个类.

你能够想晓得机关函数是若何被承继的. 当它们和其它办法一同被承继时,他们不会在创立对象时被履行.
假如你需求这个功效,你需求用第二章提到的::运算符. 它答应你指向一块定名空间. parent指向父类定名空间,你可以用parent::__construct来挪用父类的机关函数.

一些面向对象言语在类以后定名机关函数. PHP的前几个版本也是如斯,到如今这类办法依然无效.也就是:假如你把一个类定名为Animal而且在个中创立一个定名也是Animal的办法,则这个办法就是机关函数.假如一个类的同时具有__construt机关函数和与类名不异的函数,PHP将把__construct看做机关函数.这使得用之前的PHP版本所写的类依然可使用. 但新的剧本(PHP5)应该利用__construct.

PHP的这类新的声明机关函数的办法可使机关函数有一个举世无双的称号,不管它地点的类的称号是甚么. 如许你在改动类的称号时,就不需求改动机关函数的称号.

你能够在PHP中给机关函数一个像其它类办法一样的会见体例. 会见体例将会影响从必定局限内实例化对象的才能. 这答应完成一些固定的设计形式,如Singleton形式.

析构函数,相反于机关函数. PHP挪用它们来将一个对象从内存中烧毁. 默许地,PHP仅仅释放对象属性所占用的内存并烧毁对象相干的资本. 析构函数答应你在利用一个对象以后履行恣意代码来排除内存.

当PHP决意你的剧本不再与对象相干时,析构函数将被挪用. 在一个函数的定名空间内,这会产生在函数return的时分. 关于全局变量,这产生于剧本停止的时分. 假如你想明白地烧毁一个对象,你可以给指向该对象的变量分派任何其它值. 凡是将变量赋值勤为NULL或挪用unset .

上面的例子中,盘算从类中实例化的对象的个数. Counter类从机关函数入手下手增值,在析构函数减值.

一旦你界说了一个类,你可以用new来创立一个这个类的实例. 类的界说是设计图,实例则是放在拆卸线上的元件. New需求类的称号,并前往该类的一个实例. 假如机关函数需求参数,你应该在new后输出参数.
PHP代码:
<?php
class Counter
{
private static $count = 0;

function __construct()
{
self::$count++;
}

function __destruct()
{
self::$count--;
}

function getCount()
{
return self::$count;
}
}

//创立第一个实例
$c = new Counter();

//输入1
print($c->getCount() . "<br>\n");

//创立第二个实例
$c2 = new Counter();

//输入2
print($c->getCount() . "<br>\n");

//烧毁实例
$c2 = NULL;

//输入1
print($c->getCount() . "<br>\n");
?>
当你新建了一个实例,内存会被筹办来存储一切属性. 每一个实例有本人独有的一组属性. 但办法是由该类的一切实例同享的.

第五节--克隆

PHP5中的对象模子经由过程援用来挪用对象, 但有时你能够想创立一个对象的正本,并但愿本来的对象的改动不影响到正本 . 为了如许的目标,PHP界说了一个特别的办法,称为__clone. 像__construct和__destruct一样,后面有两个下划线.

默许地,用__clone办法将创立一个与原对象具有不异属性和办法的对象. 假如你想在克隆时改动默许的内容,你要在__clone中覆写(属性或办法).

克隆的办法可以没有参数,但它同时包括this和that指针(that指向被复制的对象). 假如你选择克隆本人,你要当心复制任何你要你的对象包括的信息,从that到this. 假如你用__clone来复制. PHP不会履行任何隐性的复制,

上面显示了一个用系列序数来主动化对象的例子:
PHP代码:
<?php
class ObjectTracker //对象跟踪器
{
private static $nextSerial = 0;
private $id;
private $name;

function __construct($name) //机关函数
{
$this->name = $name;
$this->id = ++self::$nextSerial;
}

function __clone() //克隆
{
$this->name = "Clone of $that->name";
$this->id = ++self::$nextSerial;
}

function getId() //获得id属性的值
{
return($this->id);
}

function getName() //获得name属性的值
{
return($this->name);
}
}

$ot = new ObjectTracker("Zeev's Object");
$ot2 = $ot->__clone();

//输入: 1 Zeev's Object
print($ot->getId() . " " . $ot->getName() . "<br>");

//输入: 2 Clone of Zeev's Object
print($ot2->getId() . " " . $ot2->getName() . "<br>");
?>
第六节--会见属性和办法

一个对象实例的属性是变量,就像PHP的其他变量一样. 然而你必需利用->运算符来援用它们. 不需求在属性前利用美元符$. 例如, 6.1中打印User对象的name属性那一行.

可以联用->,假如一个对象的属性包括了一个对象,你可使用两个->运算符来失掉外部对象的属性. 你乃至可以用两重援用的字符串来放置这些表达式. 看6.5中的例子,对象House中的属性room包括了一组Room对象.

会见办法和会见属性相似. ->运算符用来指向实例的办法. 在例子6.1中挪用getLastLogin就是. 办法履行起来和类外的函数几近不异.

假如一个类从另外一类中承继而来,父类中的属性和办法将在子类中都无效,即便在子类中没有声明. 像之前提到过的,承继长短常壮大的. 假如你想会见一个承继的属性,你只需求像会见基类本人的属性那样援用便可,利用::运算符.
PHP代码:
<?php
class Room
{
public $name;

function __construct($name="unnamed")
{
$this->name = $name;
}
}

class House
{
//array of rooms
public $room;
}

//create empty house
$home = new house;

//add some rooms
$home->room[] = new Room("bedroom");
$home->room[] = new Room("kitchen");
$home->room[] = new Room("bathroom");

//show the first room of the house
print($home->room[0]->name);
?>
PHP有两个特别的定名空间arent定名空间指向父类,self定名空间指向以后的类. 例子6.6中显示了若何用parent定名空间来挪用父类中的机关函数. 同时也用self来在机关函数中挪用另外一个类办法.
<?php
class Animal //植物
{
public $blood; //热血or冷血属性
public $name;
public function __construct($blood, $name=NULL)
{
$this->blood = $blood;
if($name)
{
$this->name = $name;
}
}
}

class Mammal extends Animal //哺乳植物
{
public $furColor; //外相色彩
public $legs;

function __construct($furColor, $legs, $name=NULL)
{
parent::__construct("warm", $name);
$this->furColor = $furColor;
$this->legs = $legs;
}
}

class Dog extends Mammal
{
function __construct($furColor, $name)
{
parent::__construct($furColor, 4, $name);

self::bark();
}

function bark()
{
print("$this->name says 'woof!'");
}
}

$d = new Dog("Black and Tan", "Angus");
?>
第四章中引见了若何挪用函数. 关于对象的成员来是如许挪用的:假如你需求在运转时肯定变量的称号,你可以用$this->$Property如许的表达式. 假如你想挪用办法,可以用$obj->$method().

你也能够用->运算符来前往一个函数的值,这在PHP之前的版本中是不答应的. 例如,你可以写一个像如许的表达式: $obj->getObject()->callMethod(). 如许防止了利用一个两头变量,也有助于完成某些设计形式,如Factory形式.
第七节--类的静态成员

类的静态成员与普通的类成员分歧: 静态成员与对象的实例有关,只与类自己有关. 他们用来完成类要封装的功效和数据,但不包含特定对象的功效和数据. 静态成员包含静态办法和静态属性.

静态属性包括在类中要封装的数据,可以由一切类的实例同享. 实践上,除属于一个固定的类并限制会见体例外,类的静态属性十分相似于函数的全局变量

咱们鄙人例中利用了一个静态属性Counter::$count. 它属于Counter类,而不属于任何Counter的实例.你不克不及用this来援用它,但可以用self或其它无效的定名表达. 在例子中,getCount办法前往self::$count,而不是Counter::$count.

静态办法则完成类需求封装的功效,与特定的对象有关. 静态办法十分相似于全局函数. 静态办法可以完整会见类的属性,也能够由对象的实例来会见,不管会见的限制语是不是是甚么.

在6.3例中,getCount是一个通俗的办法,用->来挪用. PHP创立一个this变量,虽然办法没有利用到.然而,getCount不属于任何对象.在有些情形下,咱们乃至但愿在不存在无效的对象时挪用它,那末就应当利用静态办法. PHP将不在静态办法外部创立this变量,即便你从一个对象中挪用它们.

例子6.7由6.3改动getCount为静态办法而来. Static关头字不克不及禁止一个实例用->运算符来挪用getCount,但PHP将不在办法外部创立this变量.假如你利用this->来挪用,将会失足.

//6.3例指第四节--机关函数和析构函数中的例子(参看前文),经由过程两个例子的对照,你可以很好把握
//static办法与通俗办法之间的区分.

你可以写一个办法经由过程判别this是不是创立来显示是不是它被静态地或非静态地挪用. 固然,假如你用了static 关头字,不论它如何被挪用,这个办法老是静态的.

你的类也能够界说常量属性,不需求利用public static,只需求用const关头字便可. 常量属性老是静态的.它们是类的属性,而不是实例化该类的对象的属性.

Listing 6.7 Static members
PHP代码:
<?php
class Counter
{
private static $count = 0;
const VERSION = 2.0;

function __construct()
{
self::$count++;
}

function __destruct()
{
self::$count--;
}

static function getCount()
{
return self::$count;
}
};

//创立一个实例,则__construct()将履行
$c = new Counter();

//输入 1
print(Counter::getCount() . "<br>\n");

//输入类的版本属性
print("Version used: " . Counter::VERSION . "<br>\n");
?>
第八节--会见体例

PHP5的会见体例答应限制对类成员的会见. 这是在PHP5中新增的功效,但在很多面向对象言语中都早已存在. 有了会见体例,才干开辟一个牢靠的面向对象使用法式,而且构建可重用的面向对象类库.

像C++和Java一样,PHP有三种会见体例ublic,private和protected. 关于一个类成员的会见体例,可所以个中之一. 假如你没有指明会见体例,默许地会见体例为public. 你也能够为静态成员指明一种会见体例,将会见体例放在static关头字之前(如public static).

Public成员可以被毫无穷制地会见.类内部的任何代码都可以读写public属性. 你可以从剧本的任何中央挪用一个public办法. 在PHP的前几个版本中,一切办法和属性都是public, 这让人感觉对象就像是布局精致的数组.

Private(公有)成员只在类的外部可见. 你不克不及在一个private属性地点的类办法以外改动或读取它的值. 一样地,只要在统一个类中的办法可以挪用一个private办法. 承继的子类也不克不及会见父类中的private 成员.

要注重,类中的任何成员和类的实例都可以会见private成员. 看例子6.8,equals办法将两个widget停止对照.==运算符对照统一个类的两个对象,但这个例子中每一个对象实例都有独一的ID.equals办法只对照name和price. 注重equals办法若何会见另外一个Widget实例的private属性. Java和C都答应如许的操作.

Listing 6.8 Private members
PHP代码:
<?php
class Widget
{
private $name;
private $price;
private $id;

public function __construct($name, $price)
{
$this->name = $name;
$this->price = floatval($price);
$this->id = uniqid();
}
//checks if two widgets are the same 反省两个widget是不是不异
public function equals($widget)
{
return(($this->name == $widget->name)AND
($this->price == $widget->price));
}
}
$w1 = new Widget('Cog', 5.00);
$w2 = new Widget('Cog', 5.00);
$w3 = new Widget('Gear', 7.00);

//TRUE
if($w1->equals($w2))
{
print("w1 and w2 are the same<br>\n");
}

//FALSE
if($w1->equals($w3))
{
print("w1 and w3 are the same<br>\n");
}

//FALSE, == includes id in comparison
if($w1 == $w2) //不等,由于ID分歧
{
print("w1 and w2 are the same<br>\n");
}
?>
假如你对面向对象编程不熟习,你能够想晓得用private成员的目标是甚么. 你可以回想一下封装和耦合的设法,这在本章开首咱们有会商过. Private成员有助于封装数据. 他们可以埋没在一个类外部而不被类内部的代码接触到. 同时他们还有助于完成松懈的耦合. 假如数据布局外的代码不克不及直接会见外部属性,那末就不会发生一个隐性的联系关系性.

固然,大局部private属性依然可以被内部代码同享. 处理办法是用一对public办法,一个是get(获得属性的值),另外一个是set(设置属性的值). 机关函数也承受属性的初始值. 这使得成员间的交换经由过程一个狭小的,经由优秀限制的接口来停止. 这也供应改动传递给办法的值的时机. 注重在例子6.8中,机关函数若何强迫使price成为一个float数(floadval()).

Protected(受回护的) 成员能被同个类中的一切办法和承继出的类的中一切办法会见到. Public属性有背封装的精力,由于它们答应子类依附于一个特定的属性来书写.protected办法则不会带来这方面的担心.一个利用protected办法的子类需求很清晰它的父类的布局才行.

例子6.9由例子6.8改善而失掉,包括了一个Widget的子类Thing. 注重Widget如今有一个叫作getName的protected办法. 假如Widget的实例试图挪用protected办法将会失足: $w1->getName()发生了一个毛病. 但子类Thing中的getName办法可以挪用这个protected办法.固然关于证实Widget::getName办法是protected,这个例子显得过于复杂. 在实践情形下,利用protected办法要依附于对对象的外部布局的了解.

Listing 6.9 Protected members
PHP代码:
<?php
class Widget
{
private $name;
private $price;
private $id;

public function __construct($name, $price)
{
$this->name = $name;
$this->price = floatval($price);
$this->id = uniqid();
}

//checks if two widgets are the same
public function equals($widget)
{
return(($this->name == $widget->name)AND
($this->price == $widget->price));
}

protected function getName()
{
return($this->name);
}
}

class Thing extends Widget
{
private $color;

public function setColor($color)
{
$this->color = $color;
}

public function getColor()
{
return($this->color);
}

public function getName()
{
return(parent::getName());
}
}

$w1 = new Widget('Cog', 5.00);
$w2 = new Thing('Cog', 5.00);
$w2->setColor('Yellow');

//TRUE (still!) 了局依然为真
if($w1->equals($w2))
{
print("w1 and w2 are the same<br>\n");
}

//print Cog 输入 Cog
print($w2->getName());
?>
一个子类能够改动经由过程覆写父类办法来改动办法的会见体例,虽然如斯,依然有一些限制. 假如你覆写了一个public类成员,他子类中必需坚持public. 假如你覆写了一个protected成员,它可坚持protected或酿成public.Private成员依然只在以后类中可见. 声明一个与父类的private成员同名的成员将复杂地在以后类中创立一个与本来分歧的成员. 因而,在手艺上你不克不及覆写一个private成员.

Final关头字是限制会见成员办法的另外一个办法. 子类不克不及覆写父类中标识为final的办法. Final关头字不克不及用于属性.

//haohappy注:PHP5的面向对象模子依然不敷完美,如final不像Java中那样对Data,Method乃至Class都可以用.
第九节--绑定

除限制会见,会见体例也决意哪一个办法将被子类挪用或哪一个属性将被子类会见. 函数挪用与函数自己的联系关系,和成员会见与变量内存地址间的关系,称为绑定.

在盘算机言语中有两种次要的绑定体例―静态绑定和静态绑定. 静态绑定产生于数据布局和数据布局间,法式履行之前. 静态绑定产生于编译期, 因而不克不及使用任何运转期的信息. 它针对函数挪用与函数的主体,或变量与内存中的区块. 由于PHP是一种静态言语,它不利用静态绑定. 然而可以摹拟静态绑定.

静态绑定章针对运转期发生的会见恳求,只用到运转期的可用信息. 在面向对象的代码中,静态绑定意味着决意哪一个办法被挪用或哪一个属性被会见,将基于这个类自己而不基于会见局限.

Public和protected成员的举措相似于PHP的前几个版本中函数的举措,利用静态绑定. 这意味着假如一个办法会见一个在子类中被覆写的类成员,并是一个子类的实例,子类的成员将被会见(而不是会见父类中的成员).

看例子6.10. 这段代码输入” Hey! I am Son.” 由于当PHP挪用getSalutation, 是一个Son的实例,是将Father中的salutation覆写而来. 假如salutation是public的,PHP将发生不异的了局. 覆写办法的操作很相似.在Son中,关于identify的挪用绑定到谁人办法.

即便在子类中会见体例被从protected减弱成public, 静态绑定依然会产生. 依照会见体例利用的准绳,加强关于类成员的会见限制是不成能的. 所以把会见体例从public改动成protected不成能停止.

Listing 6.10 Dynamic binding 静态绑定
PHP代码:
<?php
class Father
{
protected $salutation = "Hello there!"; //问候

public function getSalutation()
{
print("$this->salutation\n");
$this->identify();
}

protected function identify()
{
print("I am Father.<br>\n");
}
};

class Son extends Father
{
protected $salutation = "Hey!"; //父类中的protected $salutation 被覆写

protected function identify() //父类中的protected identify() 被覆写
{
print("I am Son.<br>\n");
}
};

$obj = new Son();
$obj->getSalutation(); //输入Hey! I am Son.
?>
//注: 在子类中没有覆写getSalutation(),但实践上依然存在一个getSalutation().这个类中的$salutation和identify()
//与Son子类的实例中的getSalutation()办法静态绑定,所以挪用Son的实例的getSalutation()办法,
//将挪用Son类中的成员salutation及identify(),而不是父类中的成员salutation及identify().

Private成员只存在于它们地点的类外部. 不像public和protected成员那样,PHP摹拟静态绑定. 看例子6.11. 它输入”Hello there! I am Father.”,虽然子类覆写了salutation的值. 剧本将this->salutation和以后类Father绑定. 相似的准绳使用于private办法identify().

Listing 6.11 Binding and private members
PHP代码:
<?php
class Father
{
private $salutation = "Hello there!";

public function getSalutation()
{
print("$this->salutation\n");
$this->identify();
}

private function identify()
{
print("I am Father.<br>\n");
}
}

class Son extends Father
{
private $salutation = "Hey!";
private function identify()
{
print("I am Son.<br>\n");
}
}

$obj = new Son();
$obj->getSalutation(); //输入Hello there! I am Father.
?>
静态绑定的优点是答应承继类来改动父类的行动,同时可以坚持父类的接口和功效. 看例子6.12. 因为利用了静态绑定,在deleteUser中被挪用的isAuthorized的version 可以由对象的类型来肯定. 假如是一个通俗的user,PHP挪用User::isAuthorized会前往FALSE.假如是一个AuthorizedUser的实例,PHP挪用AuthorizedUser::isAuthorized,将答应deleteUser顺遂履行.

//haohappy注:用一句话说清晰,就是对象类型与办法,属性绑定. 挪用一个父类与子类中都存在的办法或会见一个属性时,会先判别实例属于哪一种对象类型,再挪用响应的类中的办法和属性.

Listing 6.12 静态绑定的优点
PHP代码:
<?php
class User //用户
{
protected function isAuthorized() //是不是是验证用户
{
return(FALSE);
}

public function getName() //取得名字
{
return($this->name);
}

public function deleteUser($username) //删除用户
{
if(!$this->isAuthorized())
{
print("You are not authorized.<br>\n");
return(FALSE);
}

//delete the user
print("User deleted.<br>\n");
}
}

class AuthorizedUser extends User //认证用户
{
protected function isAuthorized() //覆写isAuthorized()
{
return(TRUE);
}
}

$user = new User;
$admin = new AuthorizedUser;

//not authorized
$user->deleteUser("Zeev");

//authorized
$admin->deleteUser("Zeev");
?>
为何private的类成员摹拟静态绑定? 为了回覆这个成绩, 你需求回想一下为何需求有private成员.甚么时分用它们来取代protected成员是成心义的?

private成员只要当你不想让子类承继改动或特别化父类的行动时才用到. 这类情形比你想像的要少. 凡是来讲,一个好的对象分层布局应该答应绝大多半功效被子类特别化,改善,或改动―这是面向对象编程的基本之一. 必定的情形下需求private办法或变量,例如当你确信你不想答应子类改动父类中的某个特定的部分.


第十节--笼统办法和笼统类

面向对象法式经由过程类的分层布局构建起来. 在单重承继言语如PHP中, 类的承继是树状的. 一个根类有一个或更多的子类,再从每一个子类承继出一个或更多下一级子类. 固然,能够存在多个根类,用来完成分歧的功效. 在一个优秀设计的系统中,每一个根类都应当有一个有效的接口, 可以被使用代码所利用. 假如咱们的使用代码被设计成与根类一同任务,那末它也能够和任何一个从根类承继出来的子类协作.

笼统办法是就像子类中普通的办法的占位符(占个中央但不起感化),它与普通办法分歧―没有任何代码. 假如类中存在一个或更多笼统办法, 那末这个类就成了笼统类. 你不克不及实例化笼统类. 你必需承继它们,然后实例化子类. 你也能够把笼统类当作是子类的一个模板.

假如你覆写一切的笼统办法, 子类就酿成一个通俗的类. 假如没有覆写一切办法, 子类还是笼统的. 假如一个类中中包括有笼统办法(哪怕只要一个), 你必需声明这个类是笼统的, 在class关头字前加上abstract.

声明笼统办法的语法与声明普通办法分歧. 笼统办法的没有像普通办法那样包括在大括号{}中的主体部分,并用分号;来停止.

在例子6.13中, 咱们界说了一个含有getArea办法的类Shape. 但因为不晓得外形不成能肯定图形的面积,确良咱们声了然getArea办法为笼统办法. 你不克不及实例化一个Shape对象,但你可以承继它或在一个表达式中利用它, 就像例6.13中那样.

假如你创立了一个只要笼统办法的类,你就界说了一个接口(interface). 为了申明这类情形, PHP中有interface 和implements关头字. 你可以用interface来取代笼统类, 用implements来取代extends来讲明你的类界说或利用一个接口. 例如, 你可以写一个myClass implements myIterface. 这两种办法可以依团体偏心来选择.

/*注:
两种办法即指:
1. abstract class aaa{} (注重aaa中只要笼统办法,没有普通办法)
class bbb extends aaa{} (在bbb中覆写aaa中的笼统办法)
2. interface aaa{}
class bbb implements aaa{} (在bbb中覆写aaa中的笼统办法)
*/

Listing 6.13 Abstract classes
PHP代码:
<?php
//abstract root class 笼统根类
abstract class Shape
{
abstract function getArea(); //界说一个笼统办法
}

//abstract child class 笼统子类
abstract class Polygon extends Shape //多边形
{
abstract function getNumberOfSides();
}

//concrete class 实体类 三角形类
class Triangle extends Polygon
{
public $base;
public $height;

public function getArea() //覆写盘算面积办法
{
return(($this->base * $this->height)/2);
}

public function getNumberOfSides() //覆写边数统计办法
{
return(3);
}
}

//concrete class 实体类四边形
class Rectangle extends Polygon
{
public $width;
public $height;

public function getArea()
{
return($this->width * $this->height);
}

public function getNumberOfSides()
{
return(4);
}
}

//concrete class 实体类 圆形
class Circle extends Shape
{
public $radius;

public function getArea()
{
return(pi() * $this->radius * $this->radius);
}
}

//concrete root class 界说一个色彩类
class Color
{
public $name;
}

$myCollection = array(); //创立外形的纠合,放入数组

//make a rectangle
$r = new Rectangle;
$r->width = 5;
$r->height = 7;
$myCollection[] = $r;
unset($r);

//make a triangle
$t = new Triangle;
$t->base = 4;
$t->height = 5;
$myCollection[] = $t;
unset($t);

//make a circle
$c = new Circle;
$c->radius = 3;
$myCollection[] = $c;
unset($c);

//make a color
$c = new Color;
$c->name = "blue";
$myCollection[] = $c;
unset($c);

foreach($myCollection as $s)
{
if($s instanceof Shape) //假如$s是Shape类的实例
{
print("Area: " . $s->getArea() .
"<br>\n");
}

if($s instanceof Polygon)
{
print("Sides: " .
$s->getNumberOfSides() .
"<br>\n");
}

if($s instanceof Color)
{
print("Color: $s->name<br>\n");
}

print("<br>\n");
}

?>
第十一节--重载

PHP4中已有了重载的语法来创立关于内部对象模子的映照,就像Java和COM那样. PHP5带来了壮大的面向对象重载,答应法式员创立自界说的行动来会见属性和挪用办法.

重载可以经由过程__get, __set, and __call几个特别办法来停止. 当Zend引擎试图会见一个成员并没有找到时,PHP将会挪用这些办法.

在例6.14中,__get和__set取代一切对属性变量数组的会见. 假如需要,你可以完成任何类型你想要的过滤. 例如,剧本可以制止设置属性值, 在入手下手时用必定的前缀或包括必定类型的值.

__call办法申明了你若何挪用未经界说的办法. 你挪用不决义办法时,办法名和办法吸收的参数将会传给__call办法, PHP传递__call的值前往给不决义的办法.

Listing 6.14 User-level overloading
PHP代码:
<?php
class Overloader
{
private $properties = array();

function __get($property_name)
{
if(isset($this->properties[$property_name]))
{
return($this->properties[$property_name]);
}
else
{
return(NULL);
}
}

function __set($property_name, $value)
{
$this->properties[$property_name] = $value;
}

function __call($function_name, $args)
{
print("Invoking $function_name()<br>\n");
print("Arguments: ");
print_r($args);

return(TRUE);
}
}
$o = new Overloader();

//invoke __set() 给一个不存在的属性变量赋值,激活__set()
$o->dynaProp = "Dynamic Content";

//invoke __get() 激活__get()
print($o->dynaProp . "<br>\n");

//invoke __call() 激活__call()
$o->dynaMethod("Leon", "Zeev");
?>
第十二节--类的主动加载

当你测验考试利用一个不决义的类时,PHP会呈报一个致命毛病. 处理办法就是添加一个类,可以用include包括一个文件. 究竟你晓得要用到哪一个类. 然而,PHP供应了类的主动加载功效, 这可以节俭编程的工夫. 当你测验考试利用一个PHP没有组织到的类, 它会寻觅一个__autoload的全局函数. 假如存在这个函数,PHP会用一个参数来挪用它,参数即类的称号.

例子6.15申明了__autoload是若何利用的. 它假定以后目次下每一个文件对应一个类. 当剧本测验考试来发生一个类User的实例,PHP会履行__autoload. 剧本假定class_User.php中界说有User类.. 不论挪用时是大写仍是小写,PHP将前往称号的小写.

Listing 6.15 Class autoloading
PHP代码:
<?php
//define autoload function
function __autoload($class)
{
include("class_" . ucfirst($class) . ".php");
}

//use a class that must be autoloaded
$u = new User;
$u->name = "Leon";
$u->printName();
?>
第十三节--对象串行化

串行化可以把变量包含对象,转化成一连bytes数据. 你可以将串行化后的变量存在一个文件里或在收集上传输. 然后再反串行化复原为本来的数据. 你在反串行化类的对象之前界说的类,PHP可以胜利地存储其对象的属性和办法. 有时你能够需求一个对象在反串行化后当即履行. 为了如许的目标,PHP会主动寻觅__sleep和__wakeup办法.

当一个对象被串行化,PHP会挪用__sleep办法(假如存在的话). 在反串行化一个对象后,PHP 会挪用__wakeup办法. 这两个办法都不承受参数. __sleep办法必需前往一个数组,包括需求串行化的属性. PHP会丢弃其它属性的值. 假如没有__sleep办法,PHP将保留一切属性.

例子6.16显示了若何用__sleep和__wakeup办法来串行化一个对象. Id属性是一个不盘算保存在对象中的一时属性. __sleep办法包管在串行化的对象中不包括id属性. 当反串行化一个User对象,__wakeup办法创立id属性的新值. 这个例子被设计成自我坚持. 在实践开辟中,你能够发明包括资本(如图象或数据流)的对象需求这些办法.

Listing 6.16 Object serialization
PHP代码:
<?php

class User
{
public $name;
public $id;

function __construct()
{
//give user a unique ID 付与一个分歧的ID
$this->id = uniqid();
}

function __sleep()
{
//do not serialize this->id 不串行化id
return(array("name"));
}

function __wakeup()
{
//give user a unique ID
$this->id = uniqid();
}
}

//create object 创立一个对象
$u = new User;
$u->name = "Leon";

//serialize it 串行化 注重不串行化id属性,id的值被丢弃
$s = serialize($u);

//unserialize it 反串行化 id被从头赋值
$u2 = unserialize($s);

//$u and $u2 have different IDs $u和$u2有分歧的ID
print_r($u);
print_r($u2);
?>
第十四节--定名空间

定名变量,函数和类是挺坚苦的,除要思索到变量的称号要易于了解,还要忧虑是不是这个称号在其它某个中央已利用过. 在一小段剧本中,第二个成绩是根基成绩. 当你思索重用你的代码, 在这以后的项目代码必需防止利用你用过的定名. 凡是来讲,可重用的代码老是包括在函数或类中, 需求处置很多能够产生的定名抵触. 但函数和类之间也能够产生定名抵触. 你可以测验考试防止呈现这类情形,经由过程在一切类前添加前缀的办法,或你可使用namespace语句.

Namespace关头字给一块代码定名. 在这个代码块内部,剧本必需用操作符::加上定名空间的称号来援用这个代码块. 援用静态的类成员也是用不异的办法. 在定名空间内代码不需求声明定名空间, 它自己就是默许的. 这类办法比添加前缀的办法好. 你的代码可由此变得加倍紧凑和可读.

你能够想晓得是不是可以创立分层的(嵌套的)定名空间. 谜底是不成以. 但你可以在定名空间称号后加上冒号, 你可以再次挪用在称号中不包括冒号的变量,函数和类. 定名空间答应存在冒号,只需不是第一个字符和最初一个字符或接着另外一个冒号. 定名空间的称号中的冒号关于PHP来讲没有任何意义, 但假如你用他们来辨别逻辑上的区块, 他们可以很好地申明你的代码中的父子(parent-child)关系.


/* 注: 便可以利用如许:
namespace animal:dog {}
namespace animalig {}

用冒号来讲明parent-child关系.
*/


你能够在一个定名空间语句内没有包括函数,类或常量界说之外的任何器材. 这将禁止你利用他们来改善旧的利用全局变量的函数库. 定名空间最合适于面向对象. 定名空间内的常量与类中的常量利用不异的语法.

例子6.17显示了若何利用定名空间.

Listing 6.17 Using a namespace
PHP代码:
<?php
namespace core_php:utility
{
class textEngine
{
public function uppercase($text) //大写
{
return(strtoupper($text));
}
}

//make non-OO interface 创立一个非OO的接口
function uppercase($text)
{
$e = new textEngine;
return($e->uppercase($text));
}

}

//test class in namespace 测试定名空间中的类
$e = new core_php:utility::textEngine;
print($e->uppercase("from object") . "<br>");

//test function in namespace 测试定名空间中的函数
print(core_php:utility::uppercase("from function") . "<br>");

//bring class into global namespace 把类导入全局定名空间
import class textEngine from core_php:utility;
$e2 = new textEngine;
?>
Import语句把定名空间中的某个部分导入全局的定名空间.
要导入单一的定名空间的成员,可以指定类型为constant,function或class,接着写上成员的称号;
//如import class XXX
假如你想导入某一特定类型的一切成员,你可以用*来取代称号;
//如 import constant * 导入一切常量
假如你想导入一切类型的一切成员,用*便可.
//如 import *

在成员以后,用from关头字加上定名空间的称号.
//如 import class textEngine from core_php:utility;

总之你要写成像import * from myNamespace或 import class textEngine from core_php:utility如许的语句,就像例6.17中那样.

第十五节--Zend引擎的开展

本章的最初一节,Zeev会商了Zend引擎带来的对象模子,出格提到它与PHP的前几个版本中的模子有甚么分歧.
当1997年炎天,咱们开辟出PHP3, 咱们没有企图要使PHP具有面向对象的才能. 事先没有任何与类和对象有关的设法. PHP3是一个地道面向进程的言语. 然而,在1997.8.27的早晨PHP3 alpha版中增添了对类的撑持. 增添一个新特征给PHP,事先仅需求少少的会商,由于事先探究PHP的人太少. 因而从1997年八月起, PHP迈出了走向面向对象编程言语的第一步.

的确,这只是第一步. 由于在这个设计中只要少少的相干的设法,关于对象的撑持不敷壮大. 这个版本中利用对象仅是会见数组的一个很酷的办法罢了. 代替利用$foo[“bar”],你可使用看起来更大度的$foo->bar. 面向对象办法的次要的优势是经由过程成员函数或办法来贮存功效. 例子6.18中显示了一个典范的代码块. 然而它和例6.19中的做法其实并没有太大分歧.

Listing 6.18 PHP 3 object-oriented programming PHP3中的面向对象编程
PHP代码:
<?php
class Example
{
var $value = "some value";
function PrintValue()
{
print $this->value;
}
}
$obj = new Example();
$obj->PrintValue();
?>
Listing 6.19 PHP 3 structural programming PHP3 PHP3中的布局化编程
PHP代码:
<?php
function PrintValue($arr)
{
print $arr["value"];
}

function CreateExample()
{
$arr["value"] = "some value";
$arr["PrintValue"] = "PrintValue";

return $arr;
}

$arr = CreateExample();

//Use PHP's indirect reference
$arr["PrintValue"]($arr);
?>
以上咱们在类中写上两行代码,或显示地传递数组给函数. 但思索到PHP3中这两种选择并没有任何分歧,咱们依然可以仅把对象模子当做一种”语法上的掩饰”来会见数组.

想要用PHP来停止面向对象开辟的人们,出格是想利用设计形式的人,很快就发明他们受阻了. 侥幸地,事先(PHP3时期)没有太多人想用PHP来停止面向对象开辟.

PHP4改动了这类情形. 新的版本带来了援用(reference)的概念, 它答应PHP的分歧标识符指向内存中的统一个地址. 这意味着你可使用两个或更多的称号来给统一个变量定名,就像例6.20那样.

Listing 6.20 PHP 4 references PHP4中的援用
PHP代码:
<?php
$a = 5;

//$b points to the same place in memory as $a $b与$a指向内存中同个地址
$b = &$a;

//we're changing $b, since $a is pointing to 改动$b,指向的地址改动
//the same place - it changes too $a指向的地址也改动
$b = 7;

//prints 7 输入7
print $a;
?>
因为构建一个指向彼此的对象收集是一切面向对象设计形式的基本,这个改善具有十分严重的意义.当援用答应创立更多壮大的面向对象使用法式, PHP看待对象和其它类型数据不异的做法带给开辟者极大的疾苦.就像任何PHP4的法式员将会告知你的, 使用法式将会遭受WTMA(Way Too Many Ampersands过量&)综合症. 假如你想构建一个实践使用,你会感应极其疾苦,看看例6.21你就分明.

Listing 6.21 Problems with objects in PHP 4 PHP4中利用对象的成绩

1 class MyFoo {
2 function MyFoo()
3 {
4 $this->me = &$this;
5 $this->value = 5;
6 }
7
8 function setValue($val)
9 {
10 $this->value = $val;
11 }
12
13 function getValue()
14 {
15 return $this->value;
16 }
17
18 function getValueFromMe()
19 {
20 return $this->me->value;
21 }
22 }
23
24 function CreateObject($class_type)
25 {
26 switch ($class_type) {
27 case "foo":
28 $obj = new MyFoo();
29 break;
30 case "bar":
31 $obj = new MyBar();
32 break;
33 }
34 return $obj;
35 }
36
37 $global_obj = CreateObject ("foo");
38 $global_obj->setValue(7);
39
40 print "Value is " . $global_obj->getValue() . "\n";
41 print "Value is " . $global_obj->getValueFromMe() . "\n";





让咱们一步步来会商. 起首,有一个MyFoo类.在机关函数里,咱们给$this->me一个援用,并设定
咱们有其它三个成员函数: 一个设定this->value的值;一个前往this->value的值;另外一个前往this->value->me的值. 然而--$this不是不异的器材吗? MyFoo::getValue()和MyFoo::getValueFromMe()前往的值不是一样的吗?

起首,咱们挪用CreateObject("foo"),这会前往一个MyFoo类型的对象. 然后咱们挪用MyFoo::setValue(7). 最初,咱们挪用MyFoo::getValue() 和MyFoo::getValueFromMe(), 希冀失掉前往值7.
固然,假如咱们在任何情形下都失掉7, 以上这个例子将不是本书中最没成心义的例子. 所以我信任你已猜到―咱们得不到两个7如许的了局.

然而咱们将失掉甚么了局,而且更主要地,为何呢?

咱们将失掉的了局分离是7和5. 至于为何―--有三个很好的来由.

起首,看机关函数. 当在机关函数外部,咱们在this和this->me间创立援用. 换句话说,this和this->me是同个器材. 然而咱们是在机关函数内. 当机关函数停止,PHP要从头创立对象(new MyFoo的了局,第28行)分派给$obj. 由于对象没有特别化看待,就像其它任何数据类型一样,赋值X给Y意味着Y是X的一个正本. 也就是说,obj将是new MyFoo的一个正本,而new MyFoo是一个存在于机关函数的对象. Obj->me怎样呢? 由于它是一个援用,它原封不动依然指向本来的对象―this. Voila-obj和obj->me不再是同个器材了―改动个中一个另外一个不变.

以上是第一层次由. 还有其它相似于第一条的来由. 事业般地咱们盘算克制实例化对象这个成绩(第28行). 一旦咱们把CreateObject前往的值赋给global_object,咱们依然要撞上不异的成绩―global_object将酿成前往值的一个正本,而且再次地,global_object和global_object->me将不再不异. 这就是第二层次由.

然而,现实上咱们还走不了那末远― 一旦CreateObject前往$obj,咱们将损坏援用(第34行) . 这就是第三层次由.

那末,咱们若何更正这些? 有两个选择. 一是在一切中央增添&符号,就像例6.22那样(第24, 28, 31, 37行). 二.假如你侥幸地利用上了PHP5,你可以忘了以上这一切,PHP5会主动为你思索这些. 假如你想晓得PHP5是若何思索这些成绩的,持续浏览下去.

Listing 6.22 WTMA syndrome in PHP 4 PHP4中的WTMA综合症

1 class MyFoo {
2 function MyFoo()
3 {
4 $this->me = &$this;
5 $this->value = 2;
6 }
7
8 function setValue($val)
9 {
10 $this->value = $val;
11 }
12
13 function getValue()
14 {
15 return $this->value;
16 }
17
18 function getValueFromMe()
19 {
20 return $this->me->value;
21 }
22 };
23
24 function &CreateObject($class_type)
25 {
26 switch ($class_type) {
27 case "foo":
28 $obj =& new MyFoo();
29 break;
30 case "bar":
31 $obj =& new MyBar();
32 break;
33 }
34 return $obj;
35 }
36
37 $global_obj =& CreateObject ("foo");
38 $global_obj->setValue(7);
39
40 print "Value is " . $global_obj->getValue() . "\n";
41 print "Value is " . $global_obj->getValueFromMe() . "\n";




PHP5是第一个把对象当作与其它类型数据分歧的PHP版本. 从用户的角度看,这证实它十分分明的体例―在PHP5中,对象老是经由过程援用来传递,而其它类型数据(如integer,string,array)都是经由过程值来传递. 最明显地,没有需要再用&符号来暗示经由过程援用来传递对象了.

面向对象编程普遍使用了对象收集和对象间的庞杂关系,这些都需求用到援用. 在PHP的前些版本中,需求显示地指明援用. 因而, 如今默许用援用来挪动对象,而且只要在明白请求复制时才复制对象,如许比之前更好.

它是若何完成的呢?

在PHP5之前,一切值都存在一个名为zval(Zend Value)的特别布局里. 这些值可以存入复杂的值,如数字和字符串,或庞杂的值如数组和对象. 当值传给函数或从函数前往时,这些值会被复制,在内存的另外一个地址创立一个带有不异内容的布局.

在PHP5中,值仍存为zval布局中,但对象除外. 对象存在一个叫做Object Store的布局里,而且每一个对象有一个分歧的ID. Zval中,不贮存对象自己,而是存着对象的指针. 当复制一个持有对象的zval布局,例如咱们把一个对象当做参数传给某个函数,咱们不再复制任何数据. 咱们仅仅坚持不异的对象指针并由另外一个zval告诉如今这个特定的对象指向的Object Store. 由于对象自己位于Object Store,咱们对它所作的任何改动将影响到一切持有该对象指针的zval布局.这类附加的直接感化使PHP对象看起来就像老是经由过程援用来传递,用通明和无效率的体例.

利用PHP5,咱们如今可以回到示例6.21,除去一切的&符号, 一切代码都依然可以正常任务.当咱们在机关函数(第4行)中持有一个援用时一个&符号都不必.
  应该大致熟悉了一些学习过程,也许我的过程和你的有些出路,但是不管怎么样是殊途同归,我写这么多,也只是给大家一个借鉴的机会,至于好与不好,默默不敢打包票^0^
金色的骷髅 该用户已被删除
沙发
发表于 2015-2-4 13:15:17 | 只看该作者
如果你可以写完像留言板这样的程序,那么你可以去一些别人的代码了,
谁可相欹 该用户已被删除
板凳
发表于 2015-2-9 14:42:20 | 只看该作者
当留言板完成的时候,下步可以把做1个单人的blog程序,做为目标,
柔情似水 该用户已被删除
地板
 楼主| 发表于 2015-2-13 15:52:46 | 只看该作者
首先声明:我是一个菜鸟,是一个初学者。学习了一段php后总是感觉自己没有提高,无奈。经过反思我认为我学习过程中存在很多问题,我改变了学习方法后自我感觉有了明显的进步。
变相怪杰 该用户已被删除
5#
发表于 2015-2-27 09:05:26 | 只看该作者
php里的数组为空的时候是不能拿来遍历的;(这个有点低级啊,不过我刚被这个边界问题墨迹了好长一会)
不帅 该用户已被删除
6#
发表于 2015-3-4 19:14:36 | 只看该作者
你很难利用原理去编写自己的代码。对于php来说,系统的学习我认为还是很重要的,当你有一定理解后,你可你针对某种效果研究,我想那时你不会只是复制代码的水平了。
兰色精灵 该用户已被删除
7#
发表于 2015-3-11 20:44:55 | 只看该作者
你很难利用原理去编写自己的代码。对于php来说,系统的学习我认为还是很重要的,当你有一定理解后,你可你针对某种效果研究,我想那时你不会只是复制代码的水平了。
透明 该用户已被删除
8#
发表于 2015-3-17 12:34:33 | 只看该作者
,熟悉html,能用div+css,还有javascript,优先考虑linux。我在开始学习的时候,就想把这些知识一起学习,我天真的认为同时学习能够互相呼应,因为知识是相通的。
愤怒的大鸟 该用户已被删除
9#
发表于 2015-3-24 10:03:19 | 只看该作者
个人呢觉得,配wamp 最容易漏的一步就是忘了把$PHP$目录下的libmysql.dll拷贝到windows系统目录的system32目录下,还有重启apache。
因胸联盟 该用户已被删除
10#
发表于 2015-3-29 07:42:52 | 只看该作者
Apache不是非得用80或者8080端口的,我刚开始安得时候就是80端口老占用,就用了个 81端口,结果照常,就是输localhost的时候,应该输入为 localhost:81
飘灵儿 该用户已被删除
11#
发表于 2015-4-4 10:32:00 | 只看该作者
有时候汉字的空格也能导致页面出错,所以在写代码的时候,要输入空格最好用引文模式。
爱飞 该用户已被删除
12#
发表于 2015-4-6 23:08:43 | 只看该作者
多看优秀程序员编写的代码,仔细理解他们解决问题的方法,对自身有很大的帮助。
小妖女 该用户已被删除
13#
发表于 2015-4-11 12:08:42 | 只看该作者
装在C盘下面可以利用windows的ghost功能可以还原回来(顺便当做是重转啦),当然啦我的编译目录要放在别的盘下,不然自己的劳动成果就悲剧啦。
只想知道 该用户已被删除
14#
发表于 2015-4-19 12:27:28 | 只看该作者
最后介绍一个代码出错,但是老找不到错误方法,就是 go to wc (囧),出去换换气没准回来就找到错误啦。
灵魂腐蚀 该用户已被删除
15#
发表于 2015-4-26 02:08:23 | 只看该作者
Apache不是非得用80或者8080端口的,我刚开始安得时候就是80端口老占用,就用了个 81端口,结果照常,就是输localhost的时候,应该输入为 localhost:81
再见西城 该用户已被删除
16#
发表于 2015-6-14 21:23:23 | 只看该作者
我还是推荐用firefox ,配上firebug 插件调试js能省下不受时间。谷歌的浏览器最好也不少用,因为谷歌的大侠们实在是太天才啦,把一些原来的js代码加了一些特效。
小魔女 该用户已被删除
17#
发表于 2015-7-1 15:13:13 | 只看该作者
有时候汉字的空格也能导致页面出错,所以在写代码的时候,要输入空格最好用引文模式。
若相依 该用户已被删除
18#
发表于 2015-7-7 07:37:26 | 只看该作者
有时候汉字的空格也能导致页面出错,所以在写代码的时候,要输入空格最好用引文模式。
蒙在股里 该用户已被删除
19#
发表于 2015-7-8 22:24:00 | 只看该作者
遇到出错的时候,我经常把错误信息直接复制到 google的搜索栏,一般情况都是能搜到结果的,不过有时候会搜出来一大片英文的出来,这时候就得过滤一下,吧中文的弄出来,挨着式方法。
admin 该用户已被删除
20#
发表于 2015-7-9 04:02:40 | 只看该作者
,熟悉html,能用div+css,还有javascript,优先考虑linux。我在开始学习的时候,就想把这些知识一起学习,我天真的认为同时学习能够互相呼应,因为知识是相通的。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-12-23 06:40

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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