PHP核心技术与最佳实践(第2版)(txt+pdf+epub+mobi电子书下载)


发布时间:2020-05-29 13:51:45

点击下载

作者:列旭松,陈文

出版社:机械工业出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

PHP核心技术与最佳实践(第2版)

PHP核心技术与最佳实践(第2版)试读:

前言

本书的第1版写作于2011年,并在2012年末出版,至今已经过去六七年了。本书第1版受到了许多读者的热爱,并得到了很多有建设性的意见。

PHP到底要怎么学?学什么?一个中高级PHP程序员应该是什么样的?我想这也是很多PHP新手和工作了一两年的PHP开发者的疑惑。本书所要解决的就是这一系列问题。很欣慰收到了许多读者的来信,反馈本书第1版帮助他们在PHP的道路上越走越远,读者的来信让我感受到了鼓励,也感受到了压力。

随着PHP社区的发展,以及整个互联网开发领域层出不穷的新技术和新理论,第1版的一些内容已经跟不上技术的发展,我们深感有必要在第1版的基础上做出大的更新,以满足读者的需求。

我们先来看一看第1版写作至今,PHP社区以及互联网开发领域技术的一些发展。

1)PHP版本从主流的PHP5.3发展到PHP7,性能有了一倍以上的提升,无论是语法还是PHP内核,都有了许多新变化。

2)面向对象开发理念已深入人心,PHP框架存在的必要性也已达成共识。模板引擎和PEAR基本退出PHP框架开发领域,PHP框架开始使用Composer管理依赖和构建,Composer已经发展成为一种必备技能。

3)数据库领域,事务的重要性更多被提及和承认。随着业务规模的增长,单机已经不能满足业务需求,分布式事务、数据库中间件以及全文搜索已经成了数据库里常用的三个工具。同时,NoSQL也从一个小众技术发展为主流技术。

4)分布式的概念已经尽人皆知,服务治理和微服务的概念横空出世并在PHP领域越来越受到重视,Docker等容器概念也已成为寻常技术。

基于上述变化,本书的第2版应运而生,引入了更多内容,并去除了已经过时和淘汰的篇章。

在我看来,一本技术书籍的价值在于其对知识的提炼和其与众不同的地方。举例来说,到一个书店去看书,你最想用笔抄下来或用手机拍下来的那几页,就是对你帮助最大的部分,也是你认为这本书的价值所在。正是基于这个想法,我们思考了第2版该写什么,怎么写,哪些地方会对读者有帮助。我们试图从不同的角度带领读者来看PHP,给这本书注入一些不一样的东西。我希望这是一件有意义的事。

新技术和新理念爆炸式增长,一本书不能说尽天下事,但是我还是希望本书能够帮到你。本书适合的对象

·PHP爱好者;

·掌握了PHP语法基础,想要进阶的初级程序员;

·对PHP框架和扩展开发感兴趣的读者;

·对NoSQL应用和实现原理感兴趣,对高并发感兴趣的读者;

·对PHP网络应用感兴趣,想知道HTTP协议、Socket等更多细节的读者;

·想要在大型互联网公司的PHP面试中获得成功的读者;

·开设相关课程的大专院校的学生;

·公司内部培训的学员。如何阅读本书

本书一共有13章。每个章节都可以单独阅读,但部分知识点存在一定的衔接,建议按先后顺序阅读。

第1章主要讲解了面向对象开发的思想,重点讲述面向对象模型的建立,以及面向对象的一些基础概念。本章通过大量的对比和举例,尤其是与Java的对比,力图从不同的角度来讲解PHP的面向对象特性,让读者加深理解,也让PHP程序员看到不同的面向对象。求同存异是本章的核心思想。

第2章用简练的语言讲解面向对象设计的五大原则,这五大原则也是理解设计模式的基础所在,目的在于帮助读者站在一个更高的角度来思考面向对象的问题。

第3章着重介绍HTTP协议、Socket开发和TCP/IP抓包工具的使用,WebService、Cookie和Session的使用等。结合实战,向读者阐述网络开发的核心和重点,特别是对HTTP协议的理解。HTTP协议是Web开发的基石,也是各种面试和开发中必然会遇到的知识点。而Socket则是应用交互的桥梁,保证了应用的可扩展性。

第4章着重介绍RPC的概念,包括其定义和组成元素,然后以ZooKeeper和etcd为例,介绍服务注册和发现的概念。读者在学习了本章内容后,就能对微服务中最关键的服务治理有更清晰的了解,进而理解微服务中服务治理组件的原理。

第5章没有介绍CRUD,而是主要介绍PDO、MySQL优化、事务、存储过程和事件调度机制以及MySQL安全防范。随着PHP社区的发展以及PHP7带来的性能提升,PHP在互联网大型应用中起到了举足轻重的作用。在这些大型应用中,事务是个很关键的东西,用好事务,才能保证数据的一致性和准确性。同时,针对大型应用中涉及的性能优化这一块,本章讲解了分表分库、MySQL中间件以及全文搜索的知识。读者在学习了本章后,对MySQL的性能优化和扩展会有一个更清晰的把握和理解。

第6章以MVC为理论依据,从零开始写一个简单的PHP框架,讲解控制器层、数据模型层、视图层的原理和实现,并且引入了自动加载、异常管理、拦截器的概念。随着PSR规范的完善以及Composer构建工具的流行,使用Composer来管理依赖已经成为一种很流行和通用的做法,因此我们在本章中介绍了Composer的概念,并用其改造了我们的框架,最后介绍了控制反转与依赖注入的概念。

第7章是本书的核心所在,介绍PHP扩展开发的几个重要知识点,如扩展框架搭建、PHP生命周期和PHP变量在内核中的实现方式、Zend引擎、内存管理等。最后讲解唯一ID生成扩展实例,帮助读者巩固前面学到的知识。通过学习本章,读者可以深入到PHP底层,做到知其然也知其所以然。

第8章主要介绍缓存的基本原理和三个衡量指标,通过几个实例讲解,加深读者对缓存的理解。学习本章后,读者应该能设计出一个比较合理的缓存方案。除了缓存的基本概念外,本章还讲述了Opcache服务端缓存和客户端缓存的应用。

第9章不是对Memcached的泛泛而谈,而是深入Memcached的实现和内部结构,让读者掌握Memcached的高级应用,对架构复杂环境的缓存层有清晰的认识。

第10章重点介绍Redis的深入应用,如事务处理、主从同步等,和第9章类似,同样深入探讨了Redis的实现内幕。最后,本章着重讲解了Redis集群的原理和落地实现,合理利用Redis可以为我们解决大流量高并发的应用。

第11章探讨了高性能架构的基本出发点,重点以HandlerSocket的使用、MySQL主从复制、反向代理缓存软件Varnish和任务分发框架Gearman为例,讲述了几种高性能架构中会使用的技术。

第12章科学的调试方法有助于快速找出潜在的BUG和理解复杂应用的流程,提高开发效率。单元测试是代码质量的保障。最后,介绍了使用JMeter进行压力测试的方法。

第13章通过介绍Hash算法的基本原理,然后用此算法实现一个简单的基于Hash的数据库,让读者意识到算法的重要性和可操作性。

本书第1、2、3、5、6、8、12章由陈文撰写,第7、9、10、11、13章由列旭松撰写,第4章由两人共同参与完成。勘误和支持

由于水平和开发经验有限,且计算机技术更新较快,在撰写的过程中难免有不足,有些章节的内容可能在未来的某个时候不再适用,还望读者理解和体谅,并恳请读者批评指正。如果你有好的建议,或者对书中部分内容有疑惑,可与我们联系,我们将尽量为读者提供满意的解答。

联系方式:

陈文:waitfox@qq.com

列旭松:liexusong@qq.com

期待能够得到你们的真挚反馈。感谢

首先要感谢PHP之父——Rasmus Lerdorf,是他创建了这个简单、轻松、有趣、快速而高效的语言。

其次要感谢PHP社区每一位充满活力的朋友,正是在和你们的交流中,使我学到了更多的东西,本书有不少内容来自于社区的智慧。

这是我和列旭松合著的第一本书,在这里尤其要感谢机械工业出版社的大力支持,特别是杨福川老师和张锡鹏老师,在一年多的时间里,是你们耐心地指导和认真编审才有了这本书的诞生。

还要感谢我的合作人列旭松的大力支持,正是他完成了本书最核心的章节,在后期与出版社和编辑沟通,并在稿件修改上付出了很多心血才保证书稿得以按时完成。

最后,还要感谢我的家人和朋友的支持。陈文第1章面向对象思想的核心概念

面向对象是什么?以下是维基百科对面向对象的解释:

面向对象程序设计(Object-Oriented Programming,OOP)是一种程序设计范型,同时也是一种程序开发方法。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和可扩展性。

面向过程、面向对象以及函数式编程被人们称为编程语言中的三大范式(实际上,面向过程与面向对象都同属于命令式编程),是三种不同编码和设计风格。其中面向对象的核心思想是对象、封装、可重用性和可扩展性。

面向对象是一种更高级、更抽象的思维方式,面向过程虽然也是一种抽象,但面向过程是一种基础的抽象,面向对象又是建立在面向过程之上的更高层次的抽象,因此对面向对象的理解也就不是那么容易了。

面向对象和具体的语言无关。在面向对象的世界里,常常提到的两种典型语言——C++和Java。它们都是很好的面向对象的开发语言。实际上,像C语言这种大家普遍认为的面向过程开发的主打语言,也能进行面向对象的开发,就连JavaScript这门很久之前一直被视作面向过程编程的语言,人们对它的认识也发生了改变,逐渐承认其是面向对象的语言,并且也接受了JavaScript独特的面向对象的语法。所以我们说面向对象只是种程序设计的理念,和具体的语言无关。不同的程序员既可以用C语言写出面向对象的风格来,也可以用Java写成面向对象的风格。这里并不是说面向对象的风格要优于面向过程,而是二者各有自己所擅长的领域。OOPL(Object-Oriented Programming Language)可以提高程序的封装性、复用性、可维护性,但仅仅是“可以”,能不能真正实现这些优点,还取决于编程和设计人员。就PHP而言,其不是一门纯的面向对象的语言,但是仍然可以使用PHP写出好的面向对象风格的代码。

实际开发中,面向对象为什么让我们觉得那么难?面向对象究竟难在什么地方?为什么面向对象开发在PHP里一直不是很受重视,并且没有得到普及和推广?PHP对面向对象的支持到底如何?怎么学习面向对象的思维?

在这里,我们将就面向对象一些概念展开讨论,其中重点讨论PHP特色的面向对象的风格和语法,并通过相互借鉴和对比,使读者认识PHP自身的特点,尤其是和其他语言中不同的地方。1.1 面向对象的“形”与“本”

类是对象的抽象组织,对象是类的具体存在。

2200年前的战国时期,赵国平原君的食客公孙龙在骑着白马进城时,被守城官以马不能入城拦下,公孙龙即兴演讲,口述“白马非马”一论,守城官无法反驳,于是公孙龙就骑着他的白马(不是马的)进城去了。这就是历史上最经典的一次对面向对象思维的阐述。

公孙龙的“白马非马”论如下:“白马非马”,可乎?曰:“可。”曰“何哉?”曰:“马者,所以命形也;白者,所以命色也。命色者非命形也。故曰:‘白马非马’。”曰:“有白马不可谓无马也。不可谓无马者,非马也?有白马为有马,白之,非马何也?”曰:“求马,黄、黑马皆可致;求白马,黄、黑马不可致。使白马乃马也,是所求一也。所求一者,白者不异马也。所求不异,如黄、黑马有可有不可,何也?可与不可,其相非明。故黄、黑马一也,而可以应有马,而不可以应有白马,是白马之非马,审矣!”

公孙龙乃战国时期的“名家”,名家的中心论题是所谓“名”(概念)和“实”(存在)的逻辑关系问题。名者,抽象也,类也。实者,具体也,对象也。从这个角度讲,公孙龙是我国早期的最著名的面向对象思维的思想家。“白马非马”这一论断的关键就在于“非”字,公孙龙一再强调白马与马的特征,通过把白马和马视为两个不同的类,用“非”这一关系,成功地把“白马”与“马”的关系由从属关系转移到“白马”这个对象与“马”这个对象的相等关系上,显然,二者不等,故“白马非马”。而我们正常的思维是,马是一个类,白马是马这个类的一个对象,二者属于从属关系。说“白马非马”,就是割裂马与白马之间的从属关系,偷换概念,故为诡辩也。

白马非马这个典故,我们可以称之为诡辩。但我们把这个问题抽象出来,实际上讨论的就是类与类之间的界定、类的定义等一系列问题,类应该抽象到什么程度,其中即涉及了类与对象的本质问题,也涉及了类的设计过程中的一些原则。1.1.1 对象的“形”

要回答类与对象本质这个问题,我想可以先从“形”的角度来回答。本节以PHP为例,来探讨对象的“形”与“本”的问题。

类是我们对一组对象的描述。

在PHP里,每个类的定义都以关键字class开头,后面跟着类名,紧接着一对花括号,里面包含有类成员和方法的定义。如下面代码所示:

在这里,我们定义了一个person类。代表了抽象出来的人这个概念,它含有姓名和性别这两个属性,还具有一个开口说话的方法,这个方法会告诉外界这个人的性别和姓名。我们接下来就可以产生这个类的实例:

这段代码则实例化了person类,产生了一个student对象和teacher对象的实例。实际上也就是从抽象到具体的过程。现实世界中,仅仅说“人”是没有意义的,中国人把它叫“人”,美国人把它叫person或者human,如果高兴,把它叫“God”或者“板凳”都无所谓。但是只要你把“人”这个概念加上各种属性和方法,比如说有两条腿、直立行走、会说话,则无论是中国人,还是美国人,甚至外星人都是能理解你所描述的事物。所以,一个类的设计需要能充分展示其最重要的属性和方法,并且能与其他事物相区分。只有类本身有意义,从抽象到具体的实例化才会有意义。

根据上面的实例代码,可以有下面的一些理解:

·类定义了一系列的属性和方法,并提供了实际的操作细节,这些方法可以用来对属性进行加工。

·对象含有类属性的具体值,这就是类的实例化。正是由于属性的不同,才能区分不同的对象。在上面例子里,由于student和teacher的性别和姓名不一样,才得以区分开二人。

·类与对象的关系类似一种服务与被服务、加工与被加工的关系,具体而言,就如同原材料与流水线的关系。只需要在对象上调用类中所存在的方法,就可以对类的属性进行加工,并且展示其功能。

类是属性和方法的集合,那么在PHP里,对象是什么呢?比较普遍的说法就是“对象由属性和方法组成”。对象是由属性组成,这很好理解,一个对象的属性是它区别于另一个对象的关键所在。由于PHP的对象是用数组来模拟的,因此我们把对象转为数组,就能看到这个对象所拥有的属性了。

继续使用上面代码,可以打印student对象:

到这里,可以很直观地认识到,对象就是一堆数据。既然如此,可以把一个对象存储起来,以便需要时用。这就是对象的序列化。

所谓序列化,就是把保存在内存中的各种对象状态(属性)保存起来,并且在需要时可以还原出来。下面的代码实现了把内存中的对象当前状态保存到一个文件中:

输出序列化后的结果:

在需要时,反序列化取出这个对象:注意

在序列化和反序列化时都需要包含类的对象的定义,不然有可能出现在反序列化对象时,找不到该对象的类的定义,而返回不正确的结果。

可以看到,对象序列化后,存储的只是对象的属性。类是由属性和方法组成的,而对象则是属性的集合,由同一个类生成的不同对象,拥有各自不同的属性,但共享了类的代码空间中方法区域的代码。1.1.2 对象的“本”

我们需要更深入地了解这种机制,看对象的“本”。对象是什么?对象在PHP中也是变量的一种,所以先看PHP源码中对变量的定义:图1-1 对象的组成

zvalue_value,就是PHP底层的变量类型,zend_object_value obj就是变量中的一个结构。接着看对象的底层实现。

在PHP5中,对象在底层的实现是采取“属性数组+方法数组”来实现的。可以简单地理解为PHP对象在底层的存储如图1-1所示。

对象在PHP中是使用一种zend_object_value结构体来存储的。对象在ZEND(PHP底层引擎,类似Java的JVM)中的定义如下:

ce是存储该对象的类结构,在对象初始化时保存了类的入口,相当于类指针的作用。properties是一个HashTable,用来存放对象属性。guards用来阻止递归调用。

类的标准方法在zend/zend_object_handlers.h文件中定义,具体实现则是在zend/zend_object_handlers.c文件中。关于PHP变量的存储结构的底层实现,将在第7章中进行更深入的介绍。

通过对上述源代码的简单阅读,可以更清晰地认识到对象也是一种很普通的变量,不同的是其携带了对象的属性和类的入口。1.1.3 对象与数组

对象是什么,我们不好理解,也不容易回答,但是我们知道数组是什么。数组的概念比较简单。可以拿数组和对象对比来帮助我们理解对象。对象转化为数组,数组也能转换成对象。数组是由键值对数据组成的,数组的键值对和对象的属性/属性值对十分相似。对象序列化后和数组序列化后的结果是惊人的相似。如下面的代码所示:

输出为:

可以很清楚地看出,对象和数组在内容上一模一样!

而对象和数组的区别在于:对象还有个指针,指向了它所属的类。在对student对象序列化时,我们看到了“person”这几个字符,这个标识符就标志了这个对象归属于person类,故在取出这个对象后,可以立即对其执行所包含的方法。如果对象中还包含对象呢?我们来看下一节的内容。1.1.4 对象与类

在前面代码中定义了一个类,并创建了这个类的对象,把前面产生的对象作为这个新对象的一个属性,完整代码如代码清单1-1所示。

代码清单1-1 object.php

输出结果如下:

注意:新的PSR规范要求每个类都必须有一个nameSpace,但为了行文方便和突出重点,下面的一些代码在不影响语义的情况下可能会省略nameSpace。

可以看出,序列化后的对象会附带所属的类名,这个类名保证此对象能够在执行类的方法(也是自己所能执行的方法)时,可以正确地找到方法所在的代码空间(即对象所拥有的方法存储在类里)。另外,当一个对象的实例变量引用其他对象时,序列化该对象时也会对引用对象进行序列化。

基于如上的分析,可以总结出对象和类的概念以及二者之间的关系:

·类是定义一系列属性和操作的模板,而对象则把属性进行具体化,然后交给类处理。

·对象就是数据,对象本身不包含方法。但是对象有一个“指针”指向一个类,这个类里可以有方法。

·方法描述不同属性所导致的不同表现。

·类和对象是不可分割的,有对象就必定有一个类和其对应,否则这个对象也就成了没有亲人的孩子(但有一个特殊情况存在,就是由标量进行强制类型转换的object,没有一个类和它对应。此时,PHP中一个称为“孤儿”的stdClass类就会收留这个对象)。

理解了以上四个概念,结合现实世界从实现和存储理解对象和类,这样就不会把二者看成一个抽象、神秘的东西,也就能写出符合现实世界的类了。

如果需要一个类,要从客观世界抽象出一套规律,就得总结这类事物的共性,并且让它可以与其他类进行区分。而这个区分的依据就是属性和方法。区分的办法就是实例化出一个对象,是骡子是马,拉出来遛遛。

现在,你是否对“白马非马”这个典故有了新的认识?1.2 魔术方法的应用

魔术方法是以两个下划线“__”开头、具有特殊作用的一些方法,可以看作PHP的“语法糖”。

语法糖指那些没有给计算机语言添加新功能,而只是对人类来说更“甜蜜”的语法。语法糖往往给程序员提供了更实用的编码方式或者一些技巧性的用法,有益于更好的编码风格,使代码更易读。不过其并没有给语言添加什么新东西。PHP里的引用、SPL等都属于语法糖。

实际上,在1.1节代码中就涉及魔术方法的使用。family类中的__construct方法就是一个标准魔术方法。这个魔术方法又称构造方法。具有构造方法的类会在每次创建对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。因此,这个方法往往用于类进行初始化时执行一些初始化操作,如给属性赋值、连接数据库等。

以代码清单1-1所示代码为例,family中的__construct方法主要做的事情就是在创建对象的同时对属性赋值。也可以这么使用:

这样做就不需要在创建对象后再去赋值了。有构造方法就有对应的析构方法,即__destruct方法,析构方法会在某个对象的所有引用都被删除,或者当对象被显式销毁时执行。这两个方法是常见也是最有用的魔术方法。1.2.1 __set和__get方法

__set和__get是两个比较重要的魔术方法,如代码清单1-2所示。

代码清单1-2 magic.php

运行这段代码会怎样呢?结果报错如下:

所报错误大致是说,不能访问Account对象的私有属性user。在代码清单1-2的类定义里增加以下代码,其中使用了__set魔术方法。

再次运行,看到正常输出,没有报错。在类里以两个下划线开头的方法都属于魔术方法(除非是你自定义的),它们是PHP中的内置方法,有特殊含义。手册里把这两个方法归到重载。

PHP的重载和Java等语言的重载不同。Java里,重载指一个类中可以定义参数列表不同但名字相同的多个方法。比如,Java也有构造函数,Java允许有多个构造函数,只要保证方法签名不一样就行;而PHP则在一个类中只允许有一个构造函数。

PHP提供的“重载”指动态地“创建”类属性和方法。因此,__set和__get方法被归到重载里。

这里可以直观看到,若类中定义了__set和__get这一对魔术方法,那么当给对象属性赋值或者取值时,即使这个属性不存在,也不会报错,一定程度上增强了程序的健壮性。

我们注意到,在account类里,user属性的访问权限是私有的,私有属性意味着这个属性是类的“私有财产”,只能在类内部对其进行操作。如果没有__set这个魔术方法,直接在类的外部对属性进行赋值操作是会报错的,只能通过在类中定义一个public的方法,然后在类外调用这个公开的方法进行属性读写操作。

现在有了这两个魔术方法,是不是对私有属性的操作变得更方便了呢?实际上,并没有什么奇怪的,因为这两个方法本身就是public的。它们和在对外的public方法中操作private属性的原理一样。只不过这对魔术方法使其操作更简单,不需要显式地调用一个public的方法,因为这对魔术方法在操作类变量时是自动调用的。当然,也可以把类属性定义成public的,这样就可以随意在类的外部进行读写。不过,如果只是为了方便,类属性在任意时候都定义成public权限显然是不合适的,也不符合面向对象的设计思想。

当然,__set和__get方法的使用场景不仅有上面提到的那些。现在我们假设这样一个场景,有一个电话销售列表管理页,在第1个版本中,营销状态只有一个字段,包含是与否两种状态。到了第2版,需要细化成4个筛选条件:是否接通、是否销售、是否跟进和是否推送。这4个筛选条件能产生16种组合,同时每个电销产品都需要入库保存这4个状态。如果我们把这4个状态都记入数据库,那么原先的一个字段就需要增加到4个字段。

有没有不改动原表结构(数据模型)并且尽量不大幅改动原有代码的做法呢?有的,那就是使用二进制的方法。比如,把以上4个细分状态的确认值分别对应1、2、4、8,如果一条电销产品的记录即是已接通且已跟进的状态,那么就在数据库中保存1+4=5这个值,对应之前的那个字段。

思路有了就好办了。原有的表结构不需要做任何变动,原有的数据模型只要新增4个属性即可,让这4个属性自动对应上原先的那个单一营销状态,这样所有使用到这个模型的已有代码都不需要做任何变动。

这样,页面只需要传入新增的4个属性,而后端已有的涉及这个类的代码不需要做任何修改,它会自动把新增的4个属性对应到原有的属性上去。这段代码同时体现了__get/__set这对魔术方法以及类属性访问修饰符的使用方法。不过并不建议过度滥用__get/__set方法,以免造成代码使用者的困惑。

当然,读者也可以思考是否还有其他更简单的方法来解决这个问题。1.2.2 __call和__callStatic方法

如何防止调用不存在的方法而出错?一样的道理,使用__call魔术重载方法。

__call方法原型如下:

当调用一个不可访问的方法(如未定义,或者不可见)时,__call()会被调用。其中$name参数是要调用的方法名称。$arguments参数是一个数组,包含着要传递给方法的参数,如下所示:

以上代码模拟了类似其他语言中的根据参数类型进行重载。跟__call方法配套的魔术方法是__callStatic。当然,使用魔术方法“防止调用不存在的方法而报错”,并不是魔术方法的本意。实际上,魔术方法使方法的动态创建变为可能,这在MVC等框架设计中是很有用的语法。假设一个控制器调用了不存在的方法,那么只要定义了__call魔术方法,就能友好地处理这种情况。

试着理解代码清单1-3所示代码。这段代码通过使用__callStatic这一魔术方法进行方法的动态创建和延迟绑定,实现一个简单的ORM模型。

代码清单1-3 simpleOrm.php

再举个类似的例子。PHP里有很多字符串函数,假如要先过滤字符串首尾的空格,再求出字符串的长度,一般会这么写:

如果要实现JS里的链式操作,比如像下面这样,应该怎么实现?

很简单,先实现一个String类,对这个类的对象调用方法进行处理时,触发__call魔术方法,接着执行call_user_func即可。

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载