当前位置:首页 > PHP > 网站开发pdf电子书下载
《PHP和MySQL Web开发(第4版)》电子书封面

PHP和MySQL Web开发(第4版)

  • 发布时间:2020年11月24日 16:32:41
  • 作者:威利,汤姆森
  • 大小:51.6 MB
  • 类别:网站开发电子书
  • 格式:PDF
  • 版本:中文版
  • 评分:7.6

    PHP和MySQL Web开发(第4版) PDF 中文版

      给大家带来的一篇关于网站开发相关的电子书资源,介绍了关于PHP、MySQL、Web开发方面的内容,本书是由机械工业出版社出版,格式为PDF,资源大小51.6 MB,威利,汤姆森编写,目前豆瓣、亚马逊、当当、京东等电子书综合评分为:9.5分

      Tags:Web开发 php MySQL 

      内容介绍

      里面的内容规规矩矩,有板有眼,没有那种大气,也没有很深入的讲解,好像一本规矩的教科书,所以一开始我非常不了解他为什么被称作“圣经”。
      这本书我读了至少3遍,从大二初,一直到大三上学期,期间我在做开发的时候都还想着拿它做参考,对于初学者,这本书确实是一本非常好的书,但对于已经入门的读者,这本书就没什么价值了,现在我已经不再阅读他了。

      很详细的教程,彽中高级別,应该是忯至中高,不适合一周以内快速入门,适合两周以上。如果是高应用,则不合适。我十多年开发经验,但无搞php,遇到项目需要,买来快速入门,高强度看了几天,算入门了,可编小型电商项目。但这书没有高阶的应用或说明不多。不过已达我要求。

      我觉得国内的那些写程序教科书的人真该好好研究研究人家的写作结构。大部分学计算机的人恐怕都有类似的感觉,大学的时候学了n多的语言,可是每个语言刚刚学完了,都不知道能做什么,只有在浪费了很长时间之后才发现“原来是用来××的啊!”这还算好的,更有甚者学了n年之后才发现“原来这东西没用啊!”。

      目前翻阅不到一半,说说大致的感受:
      1.没有html+css基础的建议先学好网页布局后再来看这个比较合适,本书并没有介绍这些基础知识,所以不适合零基础web的同学们;
      2.即使提供了不少例子但还是偏概念了点(可能是翻译的锅);
      3.什么是类,什么是对象?一句话就能说明的问题($obj = new classxxx{};其中$obj就是对象,而classxxx{}就是类)偏偏拿自行车汽车和交通工具比喻了半天……蛋疼的是翻译水平还有点捉急;
      4.inc后缀格式的问题,书中推荐单独设立一个web服务器外的目录,但这样可移植性太差,个人推荐的命名格式应该是xxx.inc.php,这样能正常的被php解析且不会泄露代码,也能第一眼看出这是个inc文件,方便后续维护(类似的还有xxx.class.php,专门存放类的文件);
      5.发现一例错误,《第二篇:使用Mysql》关于存储过程的,句柄声明应该在游标声明之后,否则会出现Error1338 (42000)报错,建议作者修正;

      之前一直犹豫要买这本还是《php与mysql程序设计》,当时还是因为销量的原因买了这本。
      因为写php大概写了半年左右,不过学的都不太系统,之前就一直在找类似这样的书,想要再认认真真的系统的学一遍。没系统学过,基础打的不扎实,写起来发现好累。
      结果拿回来这本书之后,看完前面两章。发现真的没买错,内容很充实,个人感觉排版比《php与mysql程序设计》好多了,看起来舒服好多。
      可以好好的补下脑了,打好基础才是王道。

      虽然我们都知道每本书都有自己的特色,即使是同一个人写的两部著作,因为它们绝不可能是同一时间完成的。
      面对着越来越多的同类书籍,如何选择成了难题了。我也遇到了这样的难题。因为准备对PHP及MySQL做一些了解,所以准备买一本书。
      通常作为比较的这两本
      《PHP和MySQL Web开发》SAMS
      《PHP与MySQL 5程序设计》Apress
      今天花了一小段时间在书店把两本书反复翻了一下,当然,是译本,最终自己做了如下的总结,很短:
      《PHP和MySQL Web开发》(SAMS)风格类似散文,精髓就是形散神不散,牢牢抓住“web开发”的主旨,粗看前两篇(记得是1~14章)会让人感觉“东一榔头西一棒”,提了下显示动态内容,即刻就带到使用函数。这粗看让人觉得有些乱,但实际上这种写作风格却更好的体现了本书作者的思想,他把实践看的很重,所以几乎每篇每节都是围绕一个实例在做诠释,而因此本书的精髓则在后三篇。但正如上面一位老师说的,它没有详细的函数说明。
      《PHP与MySQL 5程序设计》(Apress)则是“说明文”,详细严谨的逐步解释每个概念,本书的读者能够了解并熟悉php和mysql技术中的各个细节,这非常适合刚入门的初学者,甚至你无需了解更多的相关内容(如asp,c语言)就能够看懂本书。而讲到的各个细节,则是说本书对函数做了大篇幅的说明,这是本书的一个特色。
      本人最终选择了前者,我喜欢的风格。

      本书给出了php的快速入门教程,并且全面地介绍了使用mysql来开发应用程序。它还给出了一些完整的且相当实用的示例程序,对于那些希望投身于实战项目的人来说,是一本相当不错的参考用书。

      本书有比较丰富的实例,而且是互联网上常见的场景,对开发人员学习非常有帮助,我以为一本PHP手册可以供查询使用,真正的学习是需要一个真实项目的环境,投入到项目中才能快速掌握,本书提供的正式这样一个环境。同时必须指出的是,这是一本入门书籍,如果想深入学习PHP还应该学习设计模式,需要多看一些框架,和多参加一些商业应用的项目!

      PHP的书我只看过这一本,当时是冲着“圣经”的名头买下的。然后花了三四个星期断断续续看了一部分比较基础的和一些应用的部分,发现对我做一个比较简单的网站已经足够了。
      这本书稳扎稳打,一步步把你引入PHP和MySql开发的殿堂,程序例子都很好很实际,后面也有几个比较实用的网站应用实例,而且讨论了很多关于安全问题,再仔细看看的话会有更大的收获。
      值得好好看几次,一个比较大的缺憾是:这本书没有索引啊!想找个函数,得翻很久。其实这应该是很多书籍的问题吧,或者是我比较习惯有索引的书。

      专业评价

      “我从来没有购买过如此棒的编程书籍……本书信息量大、容易掌握,文字浅显易懂,而且与我曾经购买过的其他计算机图书相比,它给出了示例和实践建议。”—Nick Landman

      “Welling和Thomson撰写的这本书是我发现的唯*不可或缺的图书。文字清晰直观,从来不会浪费我的时间。本书结构合理,章节篇幅适当而且主题清晰。”—Wright Sullivan,A&E工程公司董事长,南卡罗来纳-格里尔

      “我只想告诉你,这本书真的太棒了!它逻辑清晰,难度适中,有趣易懂,当然,全是有用的信息!”—CodE-E,奥地利

      “关于PHP,有几本非常不错的入门级图书,但是Welling和Thomson所撰写的这本书对那些希望创建复杂而又可靠系统的人来说,是非常优秀的手册。很明显,作者在开发专业应用程序方面经验丰富,他们不仅教授了语言本身,还介绍了如何通过良好的软件工程实践来使用它。”—Javier Garcia,Telefonica研发实验室高级电信工程师,马德里

      “两天前我开始阅读本书,现在读了一半。我对它爱不释手。本书布局和结构严谨,读者可以很快掌握所有概念,示例也具有很强的实用性,是一本不容错过的好书。”—Jason B. Lancaster

      “本书内容很值得信赖,它给出了PHP的快速入门教程,并且全面地介绍了如何使用MySQL来开发Web应用程序。书中还给出了一些完整的示例程序,对于使用PHP创建模块化、可伸缩的应用程序来说,这些示例是非常不错的选择。无论你是PHP新手,还是正在寻找参考书的经验丰富的开发人员,这本书都是你的明智选择。”—Web Dynamic

      “Welling和Thomson撰写的这本书的确是学习PHP和MySQL开发的经典著作。它使我意识到编程和数据库对任何人来说都是可以掌握的;而我只了解本书所介绍内容的极少部分,我完全被它迷住了。”—Tim Luoma TnTLuoma.com

      “Welling和Thomson撰写的这本书对于那些希望投入实战项目的人来说,是一本不错的参考用书。它包括了基于Web的电子邮件客户端、购物车、社交媒体集成等,从PHP的基础知识开始介绍,然后介绍MySQL的相关知识。”—twilight30 on Slashdot

      “这本书太精彩了……Welling和Thomson撰写的这本书中有我见到过的对正则表达式、类和对象以及会话等*好的介绍。我感觉本书让我理解了一些我原来不太理解的内容……本书深入地介绍了PHP函数和特性,此外还从项目经理的角度介绍了现实项目、MySQL集成以及安全性问题。我发现本书各个方面组织得非常合理,容易理解。”—codewalkers.com站点的评论

      “PHP和MySQL开发人员*棒的参考书,强烈推荐。”—《The Internet Writing Journal》

      “这本书太精彩了!我是一个经验丰富的编程人员,因此我并不需要太多的PHP语法介绍;毕竟它非常类似于C/C++。我不了解关于数据库的内容,但是当我准备(在其他项目中)开发一个图书评论引擎时,我希望找到一本关于使用PHP和MySQL的参考书。我有O扲eilly出版的《mSQL and MySQL》一书,该书可能是关于纯SQL的不错参考,但是本书在我的参考书中绝对占有一席之地……强烈推荐。”—Paul Robichaux

      “我读过的*棒的编程指南图书之一。”—jackofsometrades,芬兰拉赫蒂

      “这是一本非常不错的书,对于学习如何使用这两个*流行的开源Web开发技术创建Internet应用来说是非常优秀的……书中介绍的项目是本书的闪光点。不但是因为项目介绍和组织的逻辑结构合理,而且项目的选择也涵盖了许多Web站点常用的组件。”—Craig Cecil

      “本书采用了一种简单的、按部就班的方式向程序员介绍PHP语言。因此,我经常发现自己在进行Web设计时需要参考本书。我还在学习关于PHP的新知识,但是这本书给我提供了一个学习的基础,一直以来给了我很多帮助。”—Stephen Ward

      “本书是少数使我感动并“爱”上的图书之一。我不能将它放到我的书架中;我必须将它放在一个我伸手可及的地方,这样我就可以经常翻翻它。本书的结构合理,措辞简单而且直观。在阅读本书以前,我对PHP和MySQL一无所知。但是在阅读本书后,我就对开发复杂的Web应用充满了信心,而且掌握了足够的技术。”—Power Wong

      “这本书太棒了……我向任何数据库驱动的Web应用程序员强烈推荐此书。我希望更多的计算机图书能够按这样的方式进行编写。”—Sean C Schertell

      内容简介

      本书将PHP开发与MySQL应用相结合,分别对PHP和MySQL做了深入浅出的分析,不仅介绍PHP和MySQL的一般概念,而且对PHP和MySQL的Web应用做了较全面的阐述,并包括几个经典且实用的例子。

      本书是第4版,经过了全面的更新、重写和扩展,包括PHP 5.3*改进的特性(例如,更好的错误和异常处理),MySQL的存储过程和存储引擎,Ajax技术与Web 2.0以及Web应用需要注意的安全问题。

      PHP平IEIMySQL是非常流行的开源技术,它们非常适合快速开发数据库驱动的Web应用。PHP是一种功能强大的脚本语言,专门用于快速创建高性能的Web应用,而MySQL则是一个快速而又可靠的数据库,它能很好地与PHP集成,适用于基于互联网的动态应用。

      本书介绍了如何使用这些工具创建高效和交互式的Web应用。它清晰地介绍了PHP语言的基础,解释了如何设置和使用MySQL数据,以及如何使用PHP与数据库和服务器进行交互。

      本书非常实用,包括大量实际应用中的例子。例如,用户验证、创建购物车、动态生成PDF文档和图像、发送和管理电子邮件、管理用户讨论、使用XML连接Web服务,以及使用基于Ajax的交互性开发Web 2.0应用。

      与上一版相比,本书经过了更新、重写以及扩展,并涵盖了PHP 5到5.3的所有特性,例如命名空间和闭包以及MySQL 5.1引入的特性。

      作者介绍

      Laura Thomson,Mozilla公司的高级软件工程师。之前,她是OmniTI公司和Tangled Web Design公司的合伙人。此外,Laura曾经在RMIT大学和波士顿顾问集团工作过。她获得了应用科学(计算机科学)的学士学位和工程学(计算机系统工程)学士学位。在她的空闲时间,她非常喜欢骑马,讨论免费软件和开源软件以及睡觉。

      Luke Welling,OmniTI公司的一位Web架构师,他经常在一些国际会议(例如,OSCON,ZendCon,MySQLUC,HPCon,OSDC以及LinuxTag)中就开源和Web开发的话题发表演讲。在加入OmniTI公司之前,他曾作为数据库提供商的Web分析师为Hitwise.com公司工作。此外,他还是Tangled Web Design公司的独立顾问。他还在澳大利亚墨尔本的RMIT大学教授计算机科学课程。他获得了应用科学(计算机科学)的学士学位。在他的空闲时间,他希望治好他的失眠症。

      其他参与者:

      Julie C. Meloni,i2i Interactive公司的技术总监,这是一家位于加利弗里亚Los Altos的多媒体公司。她从Web一问世以及出现首个GUI Web浏览器时就致力于基于Web的应用开发。她编著过大量书籍,撰写过大量关于Web开发语言和数据的问题,其中包括销售情况良好的《Sams Teach Yourself PHP, MySQL, and Apache All in One》。

      Adam DeFields,Web应用开发方面,项目管理以及UI设计方面的顾问。他居住在密歇根的Grand Rapids。在这个城市,有他自己的公司Emanation Systems,LLC,这是一家在2002年成立的公司。他参加过使用不同技术实现的Web开发项目,但是,他还是最喜欢开发基于PHP/MySQL的项目。

      Marc Wandschneider,一个软件开发方面的自由职业者,此外他还是作家和演讲者,经常在全球范围参与有意思的项目开发。最近,他的注意力集中在编写健壮和可扩展的Web应用。在2005年,他编写了一本名为《Core Web Application Programming with PHP and MySQL》的图书。此前,他是SWiK开源社区的主要开发人员。目前,Marc居住在北京,他将他的时间花在中文学习和编程。

      目录

      • 读者反馈
      • 译者序
      • 前言
      • 作者简介
      • 第一篇 使用PHP
      • 第1章 PHP快速入门教程
      • 1.1 开始之前:了解PHP
      • 1.2 创建一个示例应用:Bob汽车零部件商店
      • 1.2.1 创建订单表单
      • 1.2.2 表单处理
      • 1.3 在HTML中嵌入PHP
      • 1.3.1 使用PHP标记
      • 1.3.2 PHP语句
      • 1.3.3 空格
      • 1.3.4 注释
      • 1.4 添加动态内容
      • 1.4.1 调用函数
      • 1.4.2 使用date()函数
      • 1.5 访问表单变量
      • 1.5.1 简短、中等以及长风格的表单变量
      • 1.5.2 字符串的连接
      • 1.5.3 变量和文本
      • 1.6 理解标识符
      • 1.7 检查变量类型
      • 1.7.1 PHP的数据类型
      • 1.7.2 类型强度
      • 1.7.3 类型转换
      • 1.7.4 可变变量
      • 1.8 声明和使用常量
      • 1.9 理解变量的作用域
      • 1.10 使用操作符
      • 1.10.1 算术操作符
      • 1.10.2 字符串操作符
      • 1.10.3 赋值操作符
      • 1.10.4 比较操作符
      • 1.10.5 逻辑操作符
      • 1.10.6 位操作符
      • 1.10.7 其他操作符
      • 1.11 计算表单总金额
      • 1.12 理解操作符的优先级和结合性:
      • 1.13 使用可变函数
      • 1.13.1 测试和设置变量类型
      • 1.13.2 测试变量状态
      • 1.13.3 变量的重解释
      • 1.14 根据条件进行决策
      • 1.14.1 if语句
      • 1.14.2 代码块
      • 1.14.3 else语句
      • 1.14.4 elseif语句
      • 1.14.5 switch语句
      • 1.14.6 比较不同的条件
      • 1.15 通过迭代实现重复动作
      • 1.15.1 while循环
      • 1.15.2 for和foreach循环
      • 1.15.3 do...while循环
      • 1.16 从控制结构或脚本中跳出
      • 1.17 使用可替换的控制结构语法
      • 1.18 使用declare
      • 1.19 下一章
      • 第2章 数据的存储与检索
      • 2.1 保存数据以便后期使用
      • 2.2 存储和检索Bob的订单
      • 2.3 文件处理
      • 2.4 打开文件
      • 2.4.1 选择文件模式
      • 2.4.2 使用fopen()打开文件
      • 2.4.3 通过FTP或HTTP打开文件
      • 2.4.4 解决打开文件时可能遇到的问题
      • 2.5 写文件
      • 2.5.1 fwrite()的参数
      • 2.5.2 文件格式
      • 2.6 关闭文件
      • 2.7 读文件
      • 2.7.1 以只读模式打开文件:fopen()
      • 2.7.2 知道何时读完文件:feof()
      • 2.7.3 每次读取一行数据:fgets()、fgetss()和fgetcsv()
      • 2.7.4 读取整个文件:readfile()、fpassthru()和file()
      • 2.7.5 读取一个字符:fgetc()
      • 2.7.6 读取任意长度:fread()
      • 2.8 使用其他有用的文件函数
      • 2.8.1 查看文件是否存在:file_exists()
      • 2.8.2 确定文件大小:filesize()
      • 2.8.3 删除一个文件:unlink()
      • 2.8.4 在文件中定位:rewind()、fseek()和ftell()
      • 2.9 文件锁定
      • 2.10 更好的方式:数据库管理系统
      • 2.10.1 使用普通文件的几个问题
      • 2.10.2 RDBMS是如何解决这些问题的
      • 2.11 进一步学习
      • 2.12 下一章
      • 第3章 使用数组
      • 3.1 什么是数组
      • 3.2 数字索引数组
      • 3.2.1 数字索引数组的初始化
      • 3.2.2 访问数组的内容
      • 3.2.3 使用循环访问数组
      • 3.3 使用不同索引的数组
      • 3.3.1 初始化相关数组
      • 3.3.2 访问数组元素
      • 3.3.3 使用循环语句
      • 3.4 数组操作符
      • 3.5 多维数组
      • 3.6 数组排序
      • 3.6.1 使用sort()函数
      • 3.6.2 使用asort()函数和ksort()函数对相关数组排序
      • 3.6.3 反向排序
      • 3.7 多维数组的排序
      • 3.7.1 用户定义排序
      • 3.7.2 反向用户排序
      • 3.8 对数组进行重新排序
      • 3.8.1 使用shuffle()函数
      • 3.8.2 使用array_reverse()函数
      • 3.9 从文件载入数组
      • 3.10 执行其他的数组操作
      • 3.10.1 在数组中浏览:each()、current()、reset()、end()、next()、pos()和prev()
      • 3.10.2 对数组的每一个元素应用任何函数:array_walk()
      • 3.10.3 统计数组元素个数:count()、sizeof()和array_count_values()
      • 3.10.4 将数组转换成标量变量:extract()
      • 3.11 进一步学习
      • 3.12 下一章
      • 第4章 字符串操作与正则表达式
      • 4.1 创建一个示例应用程序:智能表单邮件
      • 4.2 字符串的格式化
      • 4.2.1 字符串的整理:chop()、ltrim()和trim()
      • 4.2.2 格式化字符串以便显示
      • 4.2.3 格式化字符串以便存储:addslashes()和stripslashes()
      • 4.3 用字符串函数连接和分割字符串
      • 4.3.1 使用函数explode()、implode()和join()
      • 4.3.2 使用strtok()函数
      • 4.3.3 使用substr()函数
      • 4.4 字符串的比较
      • 4.4.1 字符串的排序:strcmp()、strcasecmp()和strnatcmp()
      • 4.4.2 使用strlen()函数测试字符串的长度
      • 4.5 使用字符串函数匹配和替换子字符串
      • 4.5.1 在字符串中查找字符串:strstr()、strchr()、strrchr()和stristr()
      • 4.5.2 查找子字符串的位置:strpos()、strrpos()
      • 4.5.3 替换子字符串:str_replace()、substr_replace()
      • 4.6 正则表达式的介绍
      • 4.6.1 基础知识
      • 4.6.2 字符集和类
      • 4.6.3 重复
      • 4.6.4 子表达式
      • 4.6.5 子表达式计数
      • 4.6.6 定位到字符串的开始或末尾
      • 4.6.7 分支
      • 4.6.8 匹配特殊字符
      • 4.6.9 特殊字符一览
      • 4.6.10 在智能表单中应用
      • 4.7 用正则表达式查找子字符串
      • 4.8 使用正则表达式分割字符串
      • 4.9 比较字符串函数和正则表达式函数
      • 4.10 进一步学习
      • 4.11 下一章
      • 第5章 代码重用与函数编写
      • 5.1 代码重用的好处
      • 5.1.1 成本
      • 5.1.2 可靠性
      • 5.1.3 一致性
      • 5.2 使用require()和include()函数
      • 5.2.1 文件扩展名和require()语句
      • 5.2.2 使用require()制作Web站点的模版
      • 5.2.3 使用auto_prepend_file和auto_append_file
      • 5.3 在PHP中使用函数
      • 5.3.1 调用函数
      • 5.3.2 调用未定义的函数
      • 5.3.3 理解字母大小写和函数名称
      • 5.4 理解为什么要定义自己的函数
      • 5.5 了解基本的函数结构
      • 5.5.1 函数命名
      • 5.6 使用参数
      • 5.7 理解作用域
      • 5.8 参数的引用传递和值传递
      • 5.9 使用Return关键字
      • 5.9.1 从函数返回一个值
      • 5.10 实现递归
      • 5.10.1 名称空间
      • 5.11 进一步学习
      • 5.12 下一章
      • 第6章 面向对象的PHP
      • 6.1 理解面向对象的概念
      • 6.1.1 类和对象
      • 6.1.2 多态性
      • 6.1.3 继承
      • 6.2 在PHP中创建类、属性和操作
      • 6.2.1 类的结构
      • 6.2.2 构造函数
      • 6.2.3 析构函数
      • 6.3 类的实例化
      • 6.4 使用类的属性
      • 6.5 使用private和public关键字控制访问
      • 6.6 类操作的调用
      • 6.7 在PHP中实现继承
      • 6.7.1 通过继承使用private和protected访问修饰符控制可见性
      • 6.7.2 重载
      • 6.7.3 使用final关键字禁止继承和重载
      • 6.7.4 理解多重继承
      • 6.7.5 实现接口
      • 6.8 类的设计
      • 6.9 编写类代码
      • 6.10 理解PHP面向对象新的高级功能
      • 6.10.1 使用Per-Class常量
      • 6.10.2 实现静态方法
      • 6.10.3 检查类的类型和类型提示
      • 6.10.4 克隆对象
      • 6.10.5 使用抽象类
      • 6.10.6 使用__call()重载方法
      • 6.10.7 使用__autoload()方法
      • 6.10.8 实现迭代器和迭代
      • 6.10.9 将类转换成字符串
      • 6.10.10 使用Reflection(反射)API
      • 6.11 下一章
      • 第7章 错误和 异常处理
      • 7.1 异常处理的概念
      • 7.2 Exception类
      • 7.3 用户自定义异常
      • 7.4 Bob的汽车零部件商店应用程序的异常
      • 7.5 异常和PHP的其他错误处理机制
      • 7.6 进一步学习
      • 7.7 下一章
      • 第二篇 使用MySQL
      • 第8章 设计Web数据库
      • 8.1 关系数据库的概念
      • 8.1.1 表格
      • 8.1.2 列
      • 8.1.3 行
      • 8.1.4 值
      • 8.1.5 键
      • 8.1.6 模式
      • 8.1.7 关系
      • 8.2 如何设计Web数据库
      • 8.2.1 考虑要建模的实际对象
      • 8.2.2 避免保存冗余数据
      • 8.2.3 使用原子列值
      • 8.2.4 选择有意义的键
      • 8.2.5 考虑需要询问数据库的问题
      • 8.2.6 避免多个空属性的设计
      • 8.2.7 表格类型的总结
      • 8.3 Web数据库架构
      • 8.4 进一步学习
      • 8.5 下一章
      • 第9章 创建Web数据库
      • 9.1 使用MySQL监视程序
      • 9.2 登录到MySQL
      • 9.3 创建数据库和用户
      • 9.4 设置用户与权限
      • 9.5 MySQL权限系统的介绍
      • 9.5.1 最少权限原则
      • 9.5.2 创建用户:GRANT命令
      • 9.5.3 权限的类型和级别
      • 9.5.4 REVOKE命令
      • 9.5.5 使用GRANT和REVOKE的例子
      • 9.6 创建一个Web用户
      • 9.7 使用正确的数据库
      • 9.8 创建数据库表
      • 9.8.1 理解其他关键字的意思
      • 9.8.2 理解列的类型
      • 9.8.3 用SHOW和DESCRIBE来查看数据库
      • 9.8.4 创建索引
      • 9.9 理解MySQL的标识符
      • 9.10 选择列数据类型
      • 9.10.1 数字类型
      • 9.10.2 日期和时间类型
      • 9.10.3 字符串类型
      • 9.11 进一步学习
      • 9.12 下一章
      • 第10章 使用MySQL数据库
      • 10.1 SQL是什么
      • 10.2 在数据库中插入数据
      • 10.3 从数据库中获取数据
      • 10.3.1 获取满足特定条件的数据
      • 10.3.2 从多个表中获取数据
      • 10.3.3 以特定的顺序获取数据
      • 10.3.4 分组与合计数据
      • 10.3.5 选择要返回的行
      • 10.3.6 使用子查询
      • 10.4 更新数据库记录
      • 10.5 创建后修改表
      • 10.6 删除数据库中的记录
      • 10.7 表的删除
      • 10.8 删除整个数据库
      • 10.9 进一步学习
      • 10.10 下一章
      • 第11章 使用PHP从Web访问MySQL数据库
      • 11.1 Web数据库架构的工作原理
      • 11.2 从Web查询数据库的基本步骤
      • 11.2.1 检查与过滤用户输入数据
      • 11.2.2 建立一个连接
      • 11.2.3 选择使用的数据库
      • 11.2.4 查询数据库
      • 11.2.5 检索查询结果
      • 11.2.6 从数据库断开连接
      • 11.3 将新信息放入数据库
      • 11.4 使用Prepared语句
      • 11.5 使用PHP与数据库交互的其他接口
      • 11.5.1 使用常规的数据库接口:PEAR MDB2
      • 11.6 进一步学习
      • 11.7 下一章
      • 第12章 MySQL高级管理
      • 12.1 深入理解权限系统
      • 12.1.1 user表
      • 12.1.2 db表和host表
      • 12.1.3 tables_priv表,columns_priv表和procs_priv表
      • 12.1.4 访问控制:MySQL如何使用Grant表
      • 12.1.5 更新权限:修改什么时候生效
      • 12.2 提高MySQL数据库的安全性
      • 12.2.1 从操作系统角度来保护MySQL
      • 12.2.2 密码
      • 12.2.3 用户权限
      • 12.2.4 Web问题
      • 12.3 获取更多关于数据库的信息
      • 12.3.1 使用SHOW获取信息
      • 12.3.2 使用DESCRIBE获取关于列的信息
      • 12.3.3 用EXPLAIN理解查询操作的工作过程
      • 12.4 数据库的优化
      • 12.4.1 设计优化
      • 12.4.2 权限
      • 12.4.3 表的优化
      • 12.4.4 使用索引
      • 12.4.5 使用默认值
      • 12.4.6 其他技巧
      • 12.5 备份MySQL数据库
      • 12.6 恢复MySQL数据库
      • 12.7 实现复制
      • 12.7.1 设置主服务器
      • 12.7.2 执行初始的数据传输
      • 12.7.3 设置一个/多个从服务器
      • 12.8 进一步学习
      • 12.9 下一章
      • 第13章 MySQL高级编程
      • 13.1 LOAD DATA INFILE语句
      • 13.2 存储引擎
      • 13.3 事务
      • 13.3.1 理解事务的定义
      • 13.3.2 通过InnoDB使用事务
      • 13.4 外键
      • 13.5 存储过程
      • 13.5.1 基本示例
      • 13.5.2 局部变量
      • 13.5.3 游标和控制结构
      • 13.6 进一步学习
      • 13.7 下一章
      • 第三篇 电子商务与安全性
      • 第14章 运营一个电子商务网站
      • 14.1 我们要实现什么目标
      • 14.2 考虑电子商务网站的类型
      • 14.2.1 使用在线说明书公布信息
      • 14.2.2 接收产品或服务的订单
      • 14.2.3 提供服务和数字产品
      • 14.2.4 为产品或服务增值
      • 14.2.5 减少成本
      • 14.3 理解风险和威胁
      • 14.3.1 网络黑客
      • 14.3.2 不能招揽足够的生意
      • 14.3.3 计算机硬件故障
      • 14.3.4 电力、通信、网络或运输故障
      • 14.3.5 广泛的竞争
      • 14.3.6 软件错误
      • 14.3.7 不断变化的政府政策和税收
      • 14.3.8 系统容量限制
      • 14.4 选择一个策略
      • 14.5 下一章
      • 第15章 电子商务的安全问题
      • 15.1 信息的重要程度
      • 15.2 安全威胁
      • 15.2.1 机密数据的泄露
      • 15.2.2 数据丢失和数据破坏
      • 15.2.3 数据修改
      • 15.2.4 拒绝服务
      • 15.2.5 软件错误
      • 15.2.6 否认
      • 15.3 易用性,性能、成本和安全性
      • 15.4 建立一个安全政策
      • 15.5 身份验证原则
      • 15.6 加密技术基础
      • 15.6.1 私有密钥加密
      • 15.6.2 公有密钥加密
      • 15.6.3 数字签名
      • 15.7 数字证书
      • 15.8 安全的Web服务器
      • 15.9 审计与日志记录
      • 15.10 防火墙
      • 15.11 备份数据
      • 15.11.1 备份常规文件
      • 15.11.2 备份与恢复MySQL数据库
      • 15.12 自然环境安全
      • 15.13 下一章
      • 第16章 Web应用的安全
      • 16.1处理安全性问题的策略
      • 16.1.1 以正确心态为开始
      • 16.1.2 安全性和可用性之间的平衡
      • 16.1.3 安全监视
      • 16.1.4 基本方法
      • 16.2 识别所面临的威胁
      • 16.2.1 访问或修改敏感数据
      • 16.2.2 数据丢失或破坏
      • 16.2.3 拒绝服务
      • 16.2.4 恶意代码注入
      • 16.2.5 服务器被攻破
      • 16.3了解与我们“打交道”的用户
      • 16.3.1 破解人员
      • 16.3.2 受影响机器的未知情用户
      • 16.3.3 对公司不满的员工
      • 16.3.4 硬件被盗
      • 16.3.5 我们自身
      • 16.4 代码的安全性
      • 16.4.1 过滤用户输入
      • 16.4.2 转义输出
      • 16.4.3 代码组织
      • 16.4.4 代码自身的问题
      • 16.4.5 文件系统因素
      • 16.4.6 代码稳定性和缺陷
      • 16.4.7 执行引号和exec
      • 16.5 Web服务器和PHP的安全性
      • 16.5.1 保持软件的更新
      • 16.5.2 查看php.ini文件
      • 16.5.3 Web服务器配置
      • 16.5.4 Web应用的商业主机服务
      • 16.6 数据库服务器的安全性
      • 16.6.1 用户和权限系统
      • 16.6.2发送数据至服务器
      • 16.6.3 连接服务器
      • 16.6.4 运行服务器
      • 16.7 保护网络
      • 16.7.1 安装防火墙
      • 16.7.2使用隔离区域(DMZ)
      • 16.7.3应对DoS和DDoS攻击
      • 16.8 计算机和操作系统的安全性
      • 16.8.1 保持操作系统的更新
      • 16.8.2只运行必须的软件
      • 16.8.3 服务器的物理安全性
      • 16.9 灾难计划
      • 16.10 下一章
      • 第17章 使用PHP和MySQL实现身份验证
      • 17.1 识别访问者
      • 17.2 实现访问控制
      • 17.2.1 保存密码
      • 17.2.2 密码的加密
      • 17.2.3 保护多个网页
      • 17.3 使用基本身份验证
      • 17.4 在PHP中使用基本身份验证
      • 17.5 在Apache的.htaccess文件中使用基本身份验证
      • 17.6 使用mod_auth_mysql身份验证
      • 17.6.1 安装mod_auth_mysql
      • 17.6.2 使用mod_auth_mysql
      • 17.7 创建自定义身份验证
      • 17.8 进一步学习
      • 17.9 下一章
      • 第18章 使用PHP和MySQL实现安全事务
      • 18.1 提供安全的事务处理
      • 18.1.1 用户机器
      • 18.1.2 Internet
      • 18.1.3 我们的系统
      • 18.2 使用加密套接字层(SSL)
      • 18.3 屏蔽用户的输入
      • 18.4 提供安全存储
      • 18.5 存储信用卡号码
      • 18.6 在PHP中使用加密技术
      • 18.6.1 安装GPG
      • 18.6.2 测试GPG
      • 18.7 进一步学习
      • 18.8 下一章
      • 第四篇 PHP的高级技术
      • 第19章 与文件系统和服务器的交互
      • 19.1 文件上载
      • 19.1.1 文件上载的HTML代码
      • 19.1.2 编写处理文件的PHP
      • 19.1.3 避免常见上载问题
      • 19.2 使用目录函数
      • 19.2.1 从目录读取
      • 19.2.2 获得当前目录的信息
      • 19.2.3 创建和删除目录
      • 19.3 与文件系统的交互
      • 19.3.1 获取文件信息
      • 19.3.2 更改文件属性
      • 19.3.3 创建、删除和移动文件
      • 19.4 使用程序执行函数
      • 19.5 与环境变量交互:getenv()和putenv()
      • 19.6 进一步学习
      • 19.7 下一章
      • 第20章 使用网络函数和协议函数
      • 20.1 了解可供使用的协议
      • 20.2 发送和读取电子邮件
      • 20.3 使用其他Web站点的数据
      • 20.4 使用网络查找函数
      • 20.5 备份或镜像一个文件
      • 20.5.1 使用FTP备份或镜像一个文件
      • 20.5.2 上传文件
      • 20.5.3 避免超时
      • 20.5.4 使用其他的FTP函数
      • 20.6 进一步学习
      • 20.7 下一章
      • 第21章 日期和时间的管理
      • 21.1 在PHP中获取日期和时间
      • 21.1.1 使用date()函数
      • 21.1.2 使用UNIX时间戳
      • 21.1.3 使用getdate()函数
      • 21.1.4 使用checkdate()函数检验日期有效性
      • 21.1.5 格式化时间戳
      • 21.2 在PHP日期格式和MySQL日期格式之间进行转换
      • 21.3 在PHP中计算日期
      • 21.4 在MySQL中计算日期
      • 21.5 使用微秒
      • 21.6 使用日历函数
      • 21.7 进一步学习
      • 21.8 下一章
      • 第22章 创建图像
      • 22.1 在PHP中设置图像支持
      • 22.2 理解图像格式
      • 22.2.1 JPEG
      • 22.2.2 PNG
      • 22.2.3 WBMP
      • 22.2.4 GIF
      • 22.3 创建图像
      • 22.3.1 创建一个背景图像
      • 22.3.2 在图像上绘图或打印文本
      • 22.3.3 输出最终图形
      • 22.3.4 清理
      • 22.4 在其他页面中使用自动生成的图像
      • 22.5 使用文本和字体创建图像
      • 22.5.1 创建基本画布
      • 22.5.2 将文本调整到适合按钮
      • 22.5.3 放置文本
      • 22.5.4 将文本写到按钮上
      • 22.5.5 完成
      • 22.6 绘制图像与用图表描绘数据
      • 22.7 使用其他的图像函数
      • 22.8 进一步学习
      • 22.9 下一章
      • 第23章 在PHP中使用会话控制
      • 23.1 什么是会话控制
      • 23.2 理解基本的会话功能
      • 23.2.1 什么是cookie
      • 23.2.2 通过PHP设置cookie
      • 23.2.3 在会话中使用cookie
      • 23.2.4 存储会话 ID
      • 23.3 实现简单的会话
      • 23.3.1 开始一个会话
      • 23.3.2 注册一个会话变量
      • 23.3.3 使用会话变量
      • 23.3.4 注销变量与销毁会话
      • 23.4 创建一个简单的会话例子
      • 23.5 配置会话控制
      • 23.6 通过会话控制实现身份验证
      • 23.7 进一步学习
      • 23.8 下一章
      • 第24章 其他有用的特性
      • 24.1 使用eval()函数对字符串求值
      • 24.2 终止执行:die和exit
      • 24.3 序列化变量和对象
      • 24.4 获取PHP环境信息
      • 24.4.1 找到所加载的PHP扩展部件
      • 24.4.2 识别脚本所有者
      • 24.4.3 确定脚本最近修改时间
      • 24.5 暂时改变运行时环境
      • 24.6 源代码加亮
      • 24.7 在命令行中使用PHP
      • 24.8 下一章
      • 第五篇 创建实用的PHP和MySQL项目
      • 第25章 在大型项目中使用PHP和MySQL
      • 25.1 在Web开发中应用软件工程
      • 25.2 规划和运行Web应用程序项目
      • 25.3 重用代码
      • 25.4 编写可维护代码
      • 25.4.1 编码标准
      • 25.4.2 分解代码
      • 25.4.3 使用标准的目录结构
      • 25.4.4 文档化和共享内部函数
      • 25.5 实现版本控制
      • 25.6 选择一个开发环境
      • 25.7 项目的文档化
      • 25.8 建立原型
      • 25.9 将逻辑和内容分离
      • 25.10 优化代码
      • 25.10.1 使用简单优化
      • 25.10.2 使用Zend产品
      • 25.11 测试
      • 25.12 进一步学习
      • 25.13 下一章
      • 第26章 调试
      • 26.1 编程错误
      • 26.1.1 语法错误
      • 26.1.2 运行时错误
      • 26.1.3 逻辑错误
      • 26.2 使用变量帮助调试
      • 26.3 错误报告级别
      • 26.4 改变错误报告设置
      • 26.5 触发自定义错误
      • 26.6 巧妙地处理错误
      • 26.7 下一章
      • 第27章 建立用户身份验证机制和个性化设置
      • 27.1 解决方案的组成
      • 27.1.1 用户识别和个性化设置
      • 27.1.2 保存书签
      • 27.1.3 推荐书签
      • 27.2 解决方案概述
      • 27.3 实现数据库
      • 27.4 实现基本的网站
      • 27.5 实现用户身份验证
      • 27.5.1 注册
      • 27.5.2 登录
      • 27.5.3 登出
      • 27.5.4 修改密码
      • 27.5.5 重设遗忘的密码
      • 27.6 实现书签的存储和检索
      • 27.6.1 添加书签
      • 27.6.2 显示书签
      • 27.6.3 删除书签
      • 27.7 实现书签推荐
      • 27.8 考虑可能的扩展
      • 27.9 下一章
      • 第28章 创建一个购物车
      • 28.1 解决方案的组成
      • 28.1.1 创建一个在线目录
      • 28.1.2 在用户购买商品的时候记录购买行为
      • 28.1.3 实现一个付款系统
      • 28.1.4 创建一个管理界面
      • 28.2 解决方案概述
      • 28.3 实现数据库
      • 28.4 实现在线目录
      • 28.4.1 列出目录
      • 28.4.2 列出一个目录中的所有图书
      • 28.4.3 显示图书详细信息
      • 28.5 实现购物车
      • 28.5.1 使用show_cart.php脚本
      • 28.5.2 浏览购物车
      • 28.5.3 将物品添加到购物库
      • 28.5.4 保存更新后的购物车
      • 28.5.5 打印标题栏摘要
      • 28.5.6 结账
      • 28.6 实现付款
      • 28.7 实现一个管理界面
      • 28.8 扩展该项目
      • 28.9 使用一个已有系统
      • 28.10 下一章
      • 第29章 创建一个基于Web的电子邮件服务系统
      • 29.1 解决方案的组成
      • 29.1.1 电子邮件协议:POP3和IMAP
      • 29.1.2 PHP对POP3和IMAP的支持
      • 29.2 解决方案概述
      • 29.3 建立数据库
      • 29.4 了解脚本架构
      • 29.5 登录与登出
      • 29.6 建立账户
      • 29.6.1 创建一个新账户
      • 29.6.2 修改已有账户
      • 29.6.3 删除账户
      • 29.7 阅读邮件
      • 29.7.1 选择账户
      • 29.7.2 查看邮箱内容
      • 29.7.3 阅读邮件消息
      • 29.7.4 查看消息标题
      • 29.7.5 删除邮件
      • 29.8 发送邮件
      • 29.8.1 发送一则新消息
      • 29.8.2 回复或转发邮件
      • 29.9 扩展这个项目
      • 29.10 下一章
      • 第30章 创建一个邮件列表管理器
      • 30.1 解决方案的组成
      • 30.1.1 建立列表和订阅者数据库
      • 30.1.2 上载新闻信件
      • 30.1.3 发送带附件的邮件
      • 30.2 解决方案概述
      • 30.3 建立数据库
      • 30.4 定义脚本架构
      • 30.5 实现登录
      • 30.5.1 新账户的创建
      • 30.5.2 登录
      • 30.6 用户函数的实现
      • 30.6.1 查看列表
      • 30.6.2 查看邮件列表信息
      • 30.6.3 查看邮件列表存档
      • 30.6.4 订阅与取消订阅
      • 30.6.5 更改账户设置
      • 30.6.6 更改密码
      • 30.6.7 登出
      • 30.7 管理功能的实现
      • 30.7.1 创建新的邮件列表
      • 30.7.2 上载新的新闻信件
      • 30.7.3 多文件上载的处理
      • 30.7.4 预览新闻信件
      • 30.7.5 发送邮件
      • 30.8 扩展这个项目
      • 30.9 下一章
      • 第31章 创建一个Web论坛
      • 31.1 理解流程
      • 31.2 解决方案的组成
      • 31.3 解决方案概述
      • 31.4 数据库的设计
      • 31.5 查看文章的树型结构
      • 31.5.1 展开和折叠
      • 31.5.2 显示文章
      • 31.5.3 使用treenode类
      • 31.6 查看单个的文章
      • 31.7 添加新文章
      • 31.8 添加扩充
      • 31.9 使用一个已有的系统
      • 31.10 下一章
      • 第32章 生成PDF格式的个性化文档
      • 32.1 项目概述
      • 32.1.1 评估文档格式
      • 32.2 解决方案的组成
      • 32.2.1 问题与回答系统
      • 32.2.2 文档生成软件
      • 32.3 解决方案概述
      • 32.3.1 提问
      • 32.3.2 给答题评分
      • 32.3.3 生成RTF证书
      • 32.3.4 从模板生成PDF证书
      • 32.3.5 使用PDFlib生成PDF文档
      • 32.3.6 使用PDFlib的一个“Hello World”程序
      • 32.3.7 用PDFlib生成证书
      • 32.4 处理标题的问题
      • 32.5 扩展该项目
      • 32.6 下一章
      • 第33章 使用XML和SOAP来连接Web服务
      • 33.1 项目概述:使用XML和Web服务
      • 33.1.1 理解XML
      • 33.1.2 理解Web服务
      • 33.2 解决方案的组成
      • 33.2.1 使用Amazon的Web服务接口
      • 33.2.2 XML的解析:REST响应
      • 33.2.3 在PHP中使用SOAP
      • 33.2.4 缓存
      • 33.3 解决方案概述
      • 33.3.1 核心应用程序
      • 33.3.2 显示特定种类的图书
      • 33.3.3 获得一个AmazonResultSet类
      • 33.3.4 使用REST发送和接收请求
      • 33.3.5 使用SOAP发送和接收请求
      • 33.3.6 缓存请求返回的数据
      • 33.3.7 创建购物车
      • 33.3.8 到Amazon付账
      • 33.4 安装项目代码
      • 33.5 扩展这个项目
      • 33.6 进一步学习
      • 第34 章使用Ajax构建Web 2.0应用
      • 34.1 Ajax 是什么?
      • 34.1.1 HTTP请求和响应
      • 34.1. 2 DHTML和XHTML
      • 34.1.3 级联样式单(CSS)
      • 34.1.4 客户端编程
      • 34.1.5 服务器端编程
      • 34.1.6 XML和XSLT
      • 34.2 Ajax基础
      • 34.2.1 XMLHTTPRequest对象
      • 34.2.2 与服务器通信
      • 34.2.3 处理服务器响应
      • 34.2.4 整合应用
      • 34.3 在以前的项目添加Ajax元素
      • 34.3.1在PHPBookmark应用中添加Ajax元素
      • 34.4 进一步学习
      • 34.4.1 进一步了解文档对象模型(DOM)
      • 34.4.2 Ajax应用可用的JavaScript函数库
      • 34.4.3 Ajax开发人员网站
      • 第六篇 附录
      • 附录A 安装PHP及MySQL
      • 附录B Web资源
      • 第1章 PHP快速入门教程
      • 第2章 数据的存储与检索
      • 第3章 使用数组
      • 第4章 字符串操作与正则表达式
      • 第5章 代码重用与函数编写
      • 第6章 面向对象的PHP
      • 第7章 错误和异常处理

       

      读书笔记

      《PHP和MySQL Web开发》知识点总结(一)

      前言

      简要记录了PHP的标识符,变量,常量,作用域,操作符及变量的几个常用函数。

      标识符

      PHP中变量的标识符由$开头,后接字母,数字,下划线。

      变量的标识符区分大小写。如 $var 与 $VAR 是不同的。

      函数的标识符不区分大小写! 对 FOO() 与 foo() 进行的是等价的调用。

      一个变量的名称可以和函数的名称相同,但是不建议这么做。

      变量

      PHP变量有以下几种数据类型:

      • Integer (整数)
      • Float (浮点数,也叫Double)
      • String (字符串)
      • Boolean (布尔值)
      • Array (数组)
      • Object (对象) 用来保存类的实例
      • NULL (空)
      • resource (资源) 代表外部资源,如数据库链接

      对变量类型的判断可以利用下文将要提到的函数。

      类型转换类似于C语言,如:

      $float_var = (float)$int_var

      可变变量:这算是PHP中的特色了。一个例子就很容易明白是什么意思。

      $var = 1;
      $var_name = 'var';
      echo $$var_name; //output: 1

      单引号与双引号中字符串的不同:双引号支持插值操作,即用字符串内容来代替变量。

      $var = 'happy';
      echo "I have a $var day !"; //output: I have a happy day !
      echo 'I have a $var day !'; //output: I have a $var day !

      常量

      在PHP中使用define函数来定义常量。

      define('YEAR',2018);

      使用常量时,不需要加$。

      习惯使用全大写字母来定义常量,但这不是必须的。

      一个例子:

      define('YEAR',2019);
      echo "Next year is YEAR"; //output : Next year is YEAR
      echo 'Next year is YEAR'; //output : Next year is YEAR
      echo "Next year is ".YEAR; //output : Next year is 2019

      常量不支持双引号的插值操作!

      作用域

      作用域基本规则:

      • 内置的超级全局变量可以在脚本的任何地方使用和可见。
      • 一个脚本中声明的全局变量在整个脚本可见,但在函数内部不可见。
      • 常量一旦被声明,将可以在全局可见。这里的全局并非全局变量的全局范围,常量也可以在函数内直接使用。
      • 函数内部创建的(非静态)变量当函数终止时就不存在了。
      • 函数内部创建的静态变量无法在函数外部可见,但是在函数多次执行过程始终保持该值。

      假设想在函数内部使用全局变量:

      • 在函数内部使用global关键字声明,如使用全局变量a:global a;。
      • 通过全局变量数组进行访问,如使用全局变量a: $GLOBALS[‘a’]。

      操作符

      PHP中的大多数运算符和C语言中一致,下面主要记录一些特殊的操作符。

      & 引用操作符:通常将一个变量的值赋给另一个变量时,先创建原变量的一个副本,然后将被赋值变量指向该副本。使用引用操作符可以避免该副本的产生,使得被赋值变量和原变量指向同一块内存。

      $a = 0;
      $b = &$a;
      $b = 1; //$a 和 $b 都变为 1

      可通过unset解除引用。

      ===与!==操作符:当操作符两侧为整数,浮点数,字符串或波尔值时,当两边操作数相等且具有同种数据类型时恒等操作符成立,反之不成立。当操作符两侧为数组时,当两边数组具有相同的键值对且顺序相同时恒等操作符成立,反之不成立。

      0 == '0'; //true
      0 === '0' //false

      类型操作符: instanceof检查一个对象是否为特定类的实例。

      变量几个常用函数

      settype与gettype: gettype接受一个变量并返回一个包含变量类型的字符串。settype接受一个变量和一个数据类型用于将变量设置为指定的数据类型。

      $a = 1;
      gettype($a);
      settype($a,'double');

      isset,unset与empty:

      isset函数接受一个变量并返回一个波尔值用于判断该变量是否存在。

      unset用来销毁一个存在的变量。

      empty检查一个变量是否存在以及它的值是否为非空和非零。

      变量重解释

      即调用函数将某变量转换为指定的数据类型。

      int intval($var [, int $base]);

      float floatval($var);

      string strval($var);

      如:

      intval('42'); //42

       

      PHP调整数组顺序使奇数位于偶数前(代码/闭包扩展)

      php如何实现原址排序数组使奇数位于偶数前面(代码)

      输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

      1、遍历数组,判断元素奇数偶数,push进新数组,空间换时间

      2、插入排序的思想 空间上是原址排序

      2.1从前往后遍历,判断当前的是奇数

      2.2从当前的开始,从后往前遍历,如果是偶数就往后一位移动

      2.3当前奇数插入位置

      for i=1;i<arr.length;i++
          target=arr[i]
          if arr[i]%2==1
              j=i-1
              while j>=0&&arr[j]%2==0
                  arr[j+1]=arr[j]
                  j--
              arr[j+1]=target
      <?php
      $arr=array(1,2,3,4,5,6,7,8,9,10);
      function reOrderArray($arr){
              $length=count($arr);
              //从前往后遍历
              for($i=1;$i<$length;$i++){
                      //判断当前元素是奇数
                      $target=$arr[$i];
                      if($target%2==1){
                              //从后往前遍历,如果有偶数就往后移动一位
                              $j=$i-1;
                              while($j>=0 && $arr[$j]%2==0){
                                      $arr[$j+1]=$arr[$j];
                                      $j--;
                              }   
                              //把奇数插入位置
                              $arr[$j+1]=$target;
                      }   
              }   
              return $arr;
      }
       
      $arr2=reOrderArray($arr);
      var_dump($arr2);
      array(10) {
        [0]=>
        int(1)
        [1]=>
        int(3)
        [2]=>
        int(5)
        [3]=>
        int(7)
        [4]=>
        int(9)
        [5]=>
        int(2)
        [6]=>
        int(4)
        [7]=>
        int(6)
        [8]=>
        int(8)
        [9]=>
        int(10)
      }

      调整数组顺序使奇数位于偶数前(闭包扩展)

      这道题意思就是,给所有奇数放到偶数前面,我们可以设置两个指针,一个从前往后,直到他扫到偶数,一个从后往前,直到他扫到奇数,然后交换两个数的位置,然后往下扫,当begin>end的时候停止。代码实现很简单,如下:

      <?php
      //调整数组,使奇数位于偶数前面
      
      function reorder($arr){
              $length = count($arr);
              $begin = 0;
              $end = $length - 1;
              while($begin < $end){
                      //向后移动begin,直到它指到偶数
                      while(($begin < $end) && (($arr[$end] & 0x1) != 0)){
                              $begin++;
                      }
      
                      //向前移动end,指到它指到奇数
                      while(($begin < $end) && (($arr[$end] & 0x1) == 0)){
                              $end--;
                      }
      
                      if($begin < $end){
                              $temp = $arr[$begin];
                              $arr[$begin] = $arr[$end];
                              $arr[$end] = $temp;
                      }
              }
              return $arr;
      }
      
      $arr = [1,2,3,4,5,6,7,8];
      var_dump(reorder($arr));

      上面需要注意的时,判断一个数是奇数还是偶数的时候,我用的$num & 0x1 如果等于1,则为奇数,等于0,则为偶数,效率比%要高一些。

      到这里,如果单纯对于这道题,已经算是完事了。

      但是如果题目一改,将所有偶数放于奇数前,你可能又要重写一个函数了。

      这时,需求又改了,将所有能被3整除的放到前面………

      所有负数放到前面…….

      写完以上那么多函数,发现这些函数都类似啊,只有判断条件不一样。

      我们可不可以将整个函数,解耦成两部分,一个是判断数字应该在函数的前半部分还是后半部分,一个是交换数组位置。

      这时候我们就用到了闭包,代码如下

      <?php
      //调整数组,使奇数位于偶数前面
      
      function reorder($arr, $func){
              $length = count($arr);
              $begin = 0;
              $end = $length - 1;
              while($begin < $end){
                      //向后移动begin,直到它指到偶数
                      while(($begin < $end) && (!$func($arr[$begin]))){
                              $begin++;
                      }
      
                      //向前移动end,指到它指到奇数
                      while(($begin < $end) && ($func($arr[$end]))){
                              $end--;
                      }
      
                      if($begin < $end){
                              $temp = $arr[$begin];
                              $arr[$begin] = $arr[$end];
                              $arr[$end] = $temp;
                      }
              }
              return $arr;
      }
      
      $func = function($condition){
              $flag = ($condition & 0x1) == 0;
              return $flag;
      };
      
      $arr = [1,2,3,4,5,6,7,8];
      var_dump(reorder($arr, $func));

       

      《PHP、MySQL与JavaScript学习手册》学习笔记与总结

      php常用系统函数大全

      字符串函数

      strlen:获取字符串长度,字节长度

      substr_count 某字符串出现的次数

      substr:字符串截取,获取字符串(按照字节进行截取)

      mb_strlen
      mb_substr

      strchr:与substr相似,从指定位置截取一直到最后

      strrchr(获取文件后缀名):与strchr一样,只是从右边开始查找字符

      strtolower:所有的字符都小写(针对英文字母)

      strtoupper:所有的字符都大写

      strrev:字符串反转(只能反转英文:英文存储只有一个字节),按照字节进行反转

      strpos:从字符串中找对应字符出现的位置(数字下标),从最左边开始找

      strrpos:与strpos一样,只是从字符串的右边开始找

      trim:去掉函数两边的字符,默认是空格

      str_split 函数把字符串分割到数组中。

      chunk_split() 函数把字符串分割为一连串更小的部分

      str_repeat("Shanghai",5);把字符串 "Shanghai " 重复 5 次

      str_replace('\\', '/', dirname(DIR))); 替换

      ucfirst 首字母大写

      时间日期函数

      time:得到当前时间的时间戳(整型:从格林威治时间1970年1月1日0时0分0秒开始)秒数

      date:时间序列化函数,将指定的时间戳转换成规定时间日期的显示格式(随意的字符串:有专业的格式符规定),如果没有指定时间戳,系统默认使用当前时间的时间戳

      strtotime:时间日期格式的字符串转换成对应的时间戳(只要是正确的英语时间表达方式,都可以进行转换)

      microtime:微秒时间戳,根据不同的要求返回不同的结果 混合 microtime (布尔类型 ),可以返回一个浮点数的时间,也可以返回一个数组(时间戳和微秒数)

      数学相关函数

      abs:绝对值

      floor:向下取整 floor(3.2) 结果等于3

      ceil:向上取整

      round:四舍五入

      rand:取得一个指定范围内的随机整数

      mt_rand:取得一个指定范围内的随机整数(效率更高)

      min:PHP 会将非数值的 string 当成 0,但如果这个正是最小的数值则仍然会返回一个字符串。如果多个参数都求值为 0 且是最小值,min() 会返回按字母表顺序最小的字符串,如果其中没有字符串的话,则返回数值的 0;

      max:PHP 会将非数值的字符串当成 0,但如果这个正是最大的数值则仍然会返回一个字符串。如果多个参数都求值为 0 且是最大值,max() 会返回其中数值的 0,如果参数中没有数值的 0,则返回按字母表顺序最大的字符串。对于多个数组,max从左到右比较;如果同时出现数组和非数组参数总把数组作为最大值返回;

      数组相关函数

      count() // 非数组返回1

      key:获取当前数组当前指针所指向的元素的下标

      current:获取的当前指针指向元素的数值

      next:获取下一个元素的值,并且将指针下移

      prev:获取上一个元素的值,并且将指针上移

      end :将指针移到数组的最后一个元素,并返回最终指针位置的值

      reset:将指针移到数组的第一个元素,返回最终指针位置的值

      array_keys:获取一个数组的所有键名,返回一个索引数组

      array_values:获取一个数组的所有值,返回一个索引数组

      explode:爆炸,将一个字符串按照某个指定的规则(通常是特殊字符),将数组分成多个段,每一段都当做一个数组的元素,返回一个索引数组

      split 类似 explode explode('.', 'abc.txt')等于split('\.','abc.txt')

      implode:粘合,将一个数组内部的所有元素按照某个指定的规则(特殊字符),将所有的元素拼接成一个字符串

      join() 把数组元素组合为一个字符串

      array_merge:合并,指的是将两个数组中的元素进行累计。如果后面的数组与前面的数组有下标(键名:关联)相同的,那么后面的元素的值会覆盖前面的;如果是索引的相同下标,会自动的修改下标叠加到前面的数组里。

      array_reverse — 返回反转后的数组

      array_flip — 交换数组中的键和值

      数据结构模拟函数

      array_shift:从数组的前面弹出元素,得到元素的值

      array_pop:从数组的后面弹出元素,获得元素的值

      array_unshift:从数组的前面压入元素,得到当前数组元素的个数

      array_push:从数组的后面压入元素,得到当前数组元素的个数

      判断变量

      is_bool:判断是否是布尔类型

      is_float:判断浮点型

      is_integer:判断整型

      is_object:判断对象

      is_array:判断数组

      is_string:判断字符串

      is_resource:判断资源

      is_scalar:scalar是标量的,判断是基本数据类型:整型,浮点型,布尔型和字符串型

      is_null 检测变量是否为NULL 是返回TRUE 否则返回false。1.被赋值为NULL;2.变量没被赋值;3.被unset()

      is_numeric:判断数字或者纯数字组成的字符串

      gettype:获得数据类型

      settype:改变数据类型

      isset

      unset() 如果在函数中 unset() 一个全局变量,则只是局部变量被销毁,而在调用环境中的变量将保持调用 unset() 之前一样的值,如果在函数中 unset() 一个通过引用传递的变量,则只是局部变量被销毁,而在调用环境中的变量将保持调用 unset() 之前一样的值。

      empty//array(),"",0,"0",NULL,FALSE 都返回true

      文件操作函数

      opendir(路径):打开一个路径资源(将路径内部的所有数据读入到内存)

      readdir(路径资源):从文件夹资源中读取当前资源指针所指向的文件的名字,指针会向下移动一位

      closedir(资源):释放对应的文件资源

      scandir(路径):读取一个路径内部的所有文件名,返回一个数组,数组的每一个元素都是文件名。

      file_exists:判断一个文件是否存在(文件是广义:路径和文件)

      is_dir:判断一个指定路径是否存在(文件夹)

      is_file:判断一个指定路径是否是文件(文件)

      mkdir:创建一个路径,如果路径存在就会报错

      rmdir:移除文件夹

      file_get_contents:从一个指定的文件内读取数据内容。

      file_put_contents:将指定的字符串写入到对应的文件

      fopen:打开一个文件资源

      fgetc:c代表character,一次读取一个字符

      fgets:s代表string,代表可以读取多个字符,取决于指定的读取长度或者是否碰到换行(最多只能读取一行数据)

      两个函数都是对当前资源指针进行操作,读取之后都会将指针下移

      fread:获取指定长度的数据直到文件结束

      fwrite:向文件资源指针所在的位置写入数据,写东西不会将当前位置已有的东西往后移,而是会覆盖

      fseek:将指针指定到对应的位置

      fclose:使用对应的文件资源

      copy:复制

      unlink:删除文件

      rename:重命名文件

      filemtime:m代表modify,文件最后被修改的时间

      filesize:文件大小(字节)

      fileperms:文件权限(Linux下的八进制)

      排序

      rsort() 函数用于对数组单元从高到低进行排序。
      asort() 函数用于对数组单元从低到高进行排序并保持索引关系。
      arsort() 函数用于对数组单元从高到低进行排序并保持索引关系。
      ksort() 函数用于对数组单元按照键名从低到高进行排序。
      krsort() 函数用于对数组单元按照键名从高到低进行排序。

      报错

      error_reporting(E_ALL)

      ini_set('display_errors', 1)

      常量

      define() 定义常量
      defined() 检测常量是否定义

      序列化

      serialize

      unserialize

      json_encode 对变量进行 JSON 编码

      json_decode 对JSON 格式的字符串进行编码

      编码

      base64_encode 本函数将字符串以 MIME BASE64 编码。在 BASE64 编码后的字符串只包含英文字母大小写、阿拉伯数字、加号与反斜线,共 64 个基本字符,不包含其它特殊的字符,因而才取名 BASE64。

      base64_decode 解码

      MySQL常用命令

      # @Date    : 2017-11-15 13:18:34
      # @Author  : 师兵范 (shibingfan@163.com)
       
      #常用MySQL数据库命令
      +------------+----------------+
      | COMD       |   DESCRIPTION  | 
      +------------+----------------+
      |ALTER       |修改            |
      |BACKUP      |备份            | 
      |\C          |取消输入        | 
      |CREATE      |创建            | 
      |DELETE      |删除行          | 
      |DESCRIBE    |表结构          | 
      |DROP        |删除            | 
      |EXIT(CTRL-C)|退出            | 
      |GRANT       |修改权限        | 
      |HELP(\h,\?) |帮助            | 
      |INSERT      |插入            | 
      |LOCK        |锁住            | 
      |QUIT(\q)    |退出            | 
      |RENAME      |重命名          | 
      |SHOW        |项目说明        | 
      |SOURCE      |从文件名执行命令| 
      |STATUS(\s)  |显示当前状态    | 
      |TRUNCATE    |清空表          | 
      |UNLOCK      |解锁表          | 
      |UPDATE      |更新数据        | 
      |USE         |打开数据库      | 
      +------------+----------------+
      #显示已有数据库
      mysql> SHOW databaseS; 
      +--------------------+
      | Database           |
      +--------------------+
      | information_schema |
      | drupal7            |
      | mysql              |
      | northwind          |
      | performance_schema |
      | shibingfan         |
      | sys                |
      | testdb             |
      +--------------------+
      8 rows in set (0.06 sec)
      #创建数据库
      mysql> CREATE DATABASE publications;
      Query OK, 1 row affected (0.03 sec)
      #使用数据库
      mysql> USE publications;
      Database changed
      #数据库授权
      mysql> GRANT ALL ON publications.* TO 'shibingfan'@'localhost' IDENTIFIED BY 'shibingfan';
      Query OK, 0 rows affected, 1 warning (0.00 sec)
      #创建数据库表
      mysql> CREATE TABLE classics(
          -> author VARCHAR(128),
          -> title VARCHAR(128),
          -> type VARCHAR(16),
          -> YEAR char(4))ENGINE  MyISAM;
      Query OK, 0 rows affected (0.08 sec)
      #查询表结构
      mysql> DESCRIBE classics;
      +--------+--------------+------+-----+---------+-------+
      | Field  | Type         | Null | Key | Default | Extra |
      +--------+--------------+------+-----+---------+-------+
      | author | varchar(128) | YES  |     | NULL    |       |
      | title  | varchar(128) | YES  |     | NULL    |       |
      | type   | varchar(16)  | YES  |     | NULL    |       |
      | YEAR   | char(4)      | YES  |     | NULL    |       |
      +--------+--------------+------+-----+---------+-------+
      4 rows in set (0.02 sec)
      #数据类型
      CHAR(n)   VARCHAR(n)
      BINARY(n) VARBINARY(n)
      TEXT(n)   TINYTEXT(n)   MEDIUMTEXT(n)  LONGTEXT(n)
      TINYBLOB(n)  BLOB(n)
      TINYINT   SMALLINT      MEDIUMINT      INT/INTEGER    BIGINT
      FLOAT     DOUBLE/REAL
      DATETIME  DATE          TIMESTAMP      TIME           YEAR
      INT UNSIGNED,  NOT NULL,  AUTO_INCREMENT,  KEY
      #添加表列id
      mysql> ALTER TABLE classics ADD id INT UNSIGNED NOT NULL AUTO_INCREMENT KEY;
      Query OK, 0 rows affected (0.06 sec)
      Records: 0  Duplicates: 0  Warnings: 0
      #删除表列
      mysql> ALTER TABLE classics DROP id;
      Query OK, 0 rows affected (0.08 sec)
      Records: 0  Duplicates: 0  Warnings: 0
      #向表中添加数据
      mysql> INSERT INTO classics(author,title,type,year)VALUES('Shibingfan', 'LEARN MYSQL', 'EDUCATION', '1887');
      Query OK, 1 row affected (0.00 sec)
      #重命名表
      mysql> ALTER TABLE classics RENAME mytable ;
      Query OK, 0 rows affected (0.02 sec)
      #改变列数据类型
      mysql> ALTER TABLE mytable MODIFY year SMALLINT;
      Query OK, 5 rows affected (0.08 sec)
      #添加新列
      mysql> ALTER TABLE mytable ADD pages SMALLINT UNSIGNED;
      Query OK, 5 rows affected (0.08 sec)
      #重命名列
      mysql> ALTER TABLE mytable CHANGE type category VARCHAR(16);
      Query OK, 0 rows affected (0.31 sec)
      #删除列
      mysql> ALTER TABLE mytable DROP pages;//DROP命令不可逆
      Query OK, 5 rows affected (0.33 sec)
      #删除表
      mysql> DROP TABLE mytable;
      Query OK, 0 rows affected (0.02 sec)
      #创建索引
      mysql> ALTER TABLE mytable ADD INDEX(author(20));
      mysql> CREATE INDEX author ON mytable(author(20));//也可在创建表时添加索引
      Query OK, 5 rows affected (0.08 sec)
      #创建全文索引
      mysql> ALTER TABLE mytable ENGINE = MyISAM;		//将表转换为MyISAM
      mysql> ALTER TABLE mytable ADD FULLTEXT(author,title);
      #数据库查询
      SELECT * FROM mytable;
      SELECT author,title FROM mytable;
      SELECT COUNT(*) FROM mytable;			//计数
      SELECT DISTINCT author FROM mytable; 	//去重
      DELETE FROM mytable WHERE title = 'LEARN MYSQL';
      SELECT * FROM mytable WHERE author='Shibingfan';
      SELECT * FROM mytable WHERE author LIKE "Shi%";		//like关键字,模糊匹配
      SELECT author FROM mytable LIMIT 3;					//LIMIT关键字,限定返回的行数
      SELECT author FROM mytable LIMIT 3,1;				//LIMIT关键字,限定从表的什么位置开始返回多少行
      SELECT * FROM mytable WHERE MATCH(author,title) AGAINST('Shi'); //自然语言在FULLTEXT索引列上搜索
      SELECT * FROM mytable WHERE MATCH(author,title) AGAINST('+Shi -bing' IN BOLLEAN MODE);//布尔模式下搜索
      UPDATE mytable SET author='Shibf' WHERE author='shibingfan'; 	//更新数据
      SELECT author,title FROM mytable ORDER BY author;				//排序
      SELECT category,COUNT(author) FROM mytable GROUP BY category;	//分组
      #连接表,新建customers表
      SELECT * FROM mytable,customers WHERE mytable.isbn=customers.isbn;
      SELECT * FROM customers NATURAL JOIN mytable;		//自然连接,将相同列名的表自动合并
      SELECT * FROM customers JOIN mytable ON mytable.isbn=customers.isbn;
      SELECT author,title FROM mytable AS au,ti;			//AS重命名
      SELECT * FROM mytable,customers WHERE mytable.isbn=customers.isbn AND author='shibingfan';
       
       
      #事物
      #事物存储引擎InnoDB
      mysql> CREATE TABLE accounts(number INT, balance FLOAT, PRIMARY KEY(number))ENGINE InnoDB;
      mysql> INSERT INTO accounts(number,balance) VALUES(12345,1025.50);
      mysql> INSERT INTO accounts(number,balance) VALUES(67890,140.00);
      mysql> SELECT * FROM accounts ;
      +--------+---------+
      | number | balance |
      +--------+---------+
      |  12345 |  1025.5 |
      |  67890 |     140 |
      +--------+---------+
      #事物处理BEGIN, COMMIT, ROOLBACK
      mysql> BEGIN;
      mysql> UPDATE accounts SET balance=balance+25.11 WHERE number=12345;
      mysql> COMMIT; 		//确认提交,数据库发生更改
      mysql> ROLLBACK;	//回滚操作,数据库恢复到BEGIN之前的状态
      #使用EXPLAIN,得到查询快照,进而对查询进行优化
      mysql> EXPLAIN SELECT * FROM accounts WHERE number='12345';
      +----+-------------+----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
      | id | select_type | table    | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra |
      +----+-------------+----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
      |  1 | SIMPLE      | accounts | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | NULL  |
      +----+-------------+----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
      #备份和恢复
      mysql> LOCK TABLES mytable READ,accounts READ;		//锁定表UNLOCK TABLES;
      mysql> mysqldump -u user -ppassword publications;
      mysql> mysqldump -u user -ppassword publications mytable > mytable.sql;
      mysql> mysqldump -u user -ppassword publications --all-database > all_db.sql;
      mysql> mysqldump -u user -ppassword < all_db.sql;
      mysql> mysqldump -u user -ppassword -D publications < mytable.sql;

       

      PHP7协程概念以及实现方法

      php7协程知识点

      多任务 (并行和并发)

      在讲协程之前,先谈谈多进程、多线程、并行和并发。

      对于单核处理器,多进程实现多任务的原理是让操作系统给一个任务每次分配一定的 CPU 时间片,然后中断、让下一个任务执行一定的时间片接着再中断并继续执行下一个,如此反复。

      由于切换执行任务的速度非常快,给外部用户的感受就是多个任务的执行是同时进行的。

      多进程的调度是由操作系统来实现的,进程自身不能控制自己何时被调度,也就是说: 进程的调度是由外层调度器抢占式实现的

      而协程要求当前正在运行的任务自动把控制权回传给调度器,这样就可以继续运行其他任务。这与抢占式的多任务正好相反, 抢占多任务的调度器可以强制中断正在运行的任务, 不管它自己有没有意愿。如果仅依靠程序自动交出控制的话,那么一些恶意程序将会很容易占用全部 CPU 时间而不与其他任务共享。

      协程的调度是由协程自身主动让出控制权到外层调度器实现的

      回到刚才生成器实现 xrange 函数的例子,整个执行过程的交替可以用下图来表示:

      协程可以理解为纯用户态的线程,通过协作而不是抢占来进行任务切换。

      相对于进程或者线程,协程所有的操作都可以在用户态而非操作系统内核态完成,创建和切换的消耗非常低。

      简单的说协程 就是提供一种方法来中断当前任务的执行,保存当前的局部变量,下次再过来又可以恢复当前局部变量继续执行。

      我们可以把大任务拆分成多个小任务轮流执行,如果有某个小任务在等待系统 IO,就跳过它,执行下一个小任务,这样往复调度,实现了 IO 操作和 CPU 计算的并行执行,总体上就提升了任务的执行效率,这也便是协程的意义

      多线程

      在单核下,多线程必定是并发的;

      不过现在的统一进程的多线程是可以运行在多核CPU下,所以可以是并行的

      并发(Concurrency)

      是指能处理多个同时性活动的能力,并发事件之间不一定要同一时刻发生。

      并行(Parallesim)

      是指同时发生的两个并发事件,具有并发的含义,而并发则不一定并行。
      多个操作可以在重叠的时间段内进行。

      并行和并发区别

      并发指的是程序的结构,并行指的是程序运行时的状态

      并行一定是并发的,并行是并发设计的一种

      单线程永远无法达到并行状态

      协程

      协程的支持是在生成器的基础上, 增加了可以回送数据给生成器的功能(调用者发送数据给被调用的生成器函数).

      这就把生成器到调用者的单向通信转变为两者之间的双向通信.

      我们在上篇文章已经讲过了send方法, 下面让我们理解下协程

      同步代码

      在没有涉及到异步执行代码之前,我们的代码都是这样的

      function printNum($max, $caller)
      {
        for ($i=0; $i<$max; $i++ ) {
          echo "调度者:" . $caller . " 打印:" . $i . PHP_EOL;
        }
      }
       
      printNum(3, "caller1");
      printNum(3, "caller2");
       
      # output
      调度者:caller1 打印:0
      调度者:caller1 打印:1
      调度者:caller1 打印:2
      调度者:caller2 打印:0
      调度者:caller2 打印:1
      调度者:caller2 打印:2

      使用协程后改进的代码

      初稿,手动调整生成器执行

      # 本代码手动调整了进程执行代码的顺序,当然本代码实现不用协程也可以,只是利用本流程说明协程作用
      # 生成器给了我们函数中断,协程[生成器send]给了我们重新唤起生成器函数的能力
      function printNumWithGen($max)
      {
        for ($i=0; $i<$max; $i++ ) {
          $res = yield $i;
          echo $res;
        }
      }
       
      $gen1 = printNumWithGen(3);
      $gen2 = printNumWithGen(3);
       
      // 手动执行caller1 再 caller2
      $gen1->send("调度者: caller1 打印:" . $gen1->current() . PHP_EOL);
      $gen2->send("调度者: caller2 打印:" . $gen2->current() . PHP_EOL);
       
      // 手动执行caller1 再 caller2
      $gen1->send("调度者: caller1 打印:" . $gen1->current() . PHP_EOL);
      $gen2->send("调度者: caller2 打印:" . $gen2->current() . PHP_EOL);
       
      // 手动执行caller2 再 caller1
      $gen2->send("调度者: caller2 打印:" . $gen2->current() . PHP_EOL);
      $gen1->send("调度者: caller1 打印:" . $gen1->current() . PHP_EOL);
       
      # output
      调度者: caller1 打印:0
      调度者: caller2 打印:0
      调度者: caller1 打印:1
      调度者: caller2 打印:1
      调度者: caller2 打印:2
      调度者: caller1 打印:2

      总结

      上面案例应该让大家理解了协程设计的意义和如何使用协程

      那么接下去我们为我们的协程自动一个自动调度器(Co自动执行器),无需再手动来中断和恢复了

      PHP7下协程的实现方法

      前言

      相信大家都听说过『协程』这个概念吧。

      但是有些同学对这个概念似懂非懂,不知道怎么实现,怎么用,用在哪,甚至有些人认为yield就是协程!

      我始终相信,如果你无法准确地表达出一个知识点的话,我可以认为你就是不懂。

      我写这篇文章的目的,是想对鸟哥文章做更加充足的补充,毕竟有部分同学的基础还是不够好,看得也是云头雾里的。

      什么是协程

      先搞清楚,什么是协程。

      你可能已经听过『进程』和『线程』这两个概念。

      进程就是二进制可执行文件在计算机内存里的一个运行实例,就好比你的.exe文件是个类,进程就是new出来的那个实例。

      进程是计算机系统进行资源分配和调度的基本单位(调度单位这里别纠结线程进程的),每个CPU下同一时刻只能处理一个进程。

      所谓的并行,只不过是看起来并行,CPU事实上在用很快的速度切换不同的进程。

      进程的切换需要进行系统调用,CPU要保存当前进程的各个信息,同时还会使CPUCache被废掉。

      所以进程切换不到费不得已就不做。

      那么怎么实现『进程切换不到费不得已就不做』呢?

      首先进程被切换的条件是:进程执行完毕、分配给进程的CPU时间片结束,系统发生中断需要处理,或者进程等待必要的资源(进程阻塞)等。你想下,前面几种情况自然没有什么话可说,但是如果是在阻塞等待,是不是就浪费了。

      其实阻塞的话我们的程序还有其他可执行的地方可以执行,不一定要傻傻的等!

      所以就有了线程。

      线程简单理解就是一个『微进程』,专门跑一个函数(逻辑流)。

      所以我们就可以在编写程序的过程中将可以同时运行的函数用线程来体现了。

      线程有两种类型,一种是由内核来管理和调度。

      我们说,只要涉及需要内核参与管理调度的,代价都是很大的。这种线程其实也就解决了当一个进程中,某个正在执行的线程遇到阻塞,我们可以调度另外一个可运行的线程来跑,但是还是在同一个进程里,所以没有了进程切换。

      还有另外一种线程,他的调度是由程序员自己写程序来管理的,对内核来说不可见。这种线程叫做『用户空间线程』。

      协程可以理解就是一种用户空间线程。

      协程,有几个特点:

      • 协同,因为是由程序员自己写的调度策略,其通过协作而不是抢占来进行切换
      • 在用户态完成创建,切换和销毁
      • ⚠️ 从编程角度上看,协程的思想本质上就是控制流的主动让出(yield)和恢复(resume)机制
      • 迭代器经常用来实现协程

      说到这里,你应该明白协程的基本概念了吧?

      PHP实现协程

      一步一步来,从解释概念说起!

      可迭代对象

      PHP5提供了一种定义对象的方法使其可以通过单元列表来遍历,例如用foreach语句。

      你如果要实现一个可迭代对象,你就要实现Iterator接口:

      <?php
      class MyIterator implements Iterator
      {
       private $var = array();
       public function __construct($array)
       {
        if (is_array($array)) {
         $this->var = $array;
        }
       }
       public function rewind() {
        echo "rewinding\n";
        reset($this->var);
       }
       public function current() {
        $var = current($this->var);
        echo "current: $var\n";
        return $var;
       }
       public function key() {
        $var = key($this->var);
        echo "key: $var\n";
        return $var;
       }
       public function next() {
        $var = next($this->var);
        echo "next: $var\n";
        return $var;
       }
       public function valid() {
        $var = $this->current() !== false;
        echo "valid: {$var}\n";
        return $var;
       }
      }
      $values = array(1,2,3);
      $it = new MyIterator($values);
      foreach ($it as $a => $b) {
       print "$a: $b\n";
      }

      生成器

      可以说之前为了拥有一个能够被foreach遍历的对象,你不得不去实现一堆的方法,yield关键字就是为了简化这个过程。

      生成器提供了一种更容易的方法来实现简单的对象迭代,相比较定义类实现Iterator接口的方式,性能开销和复杂性大大降低。

      <?php
      function xrange($start, $end, $step = 1) {
       for ($i = $start; $i <= $end; $i += $step) {
        yield $i;
       }
      }
      foreach (xrange(1, 1000000) as $num) {
       echo $num, "\n";
      }

      记住,一个函数中如果用了yield,他就是一个生成器,直接调用他是没有用的,不能等同于一个函数那样去执行!

      所以,yield就是yield,下次谁再说yield是协程,我肯定把你xxxx。

      PHP协程

      前面介绍协程的时候说了,协程需要程序员自己去编写调度机制,下面我们来看这个机制怎么写。

      0)生成器正确使用

      既然生成器不能像函数一样直接调用,那么怎么才能调用呢?

      方法如下:

      • foreach他
      • send($value)
      • current / next...

      1)Task实现

      Task就是一个任务的抽象,刚刚我们说了协程就是用户空间协程,线程可以理解就是跑一个函数。

      所以Task的构造函数中就是接收一个闭包函数,我们命名为coroutine。

      /**
       * Task任务类
       */
      class Task
      {
       protected $taskId;
       protected $coroutine;
       protected $beforeFirstYield = true;
       protected $sendValue;
      
       /**
        * Task constructor.
        * @param $taskId
        * @param Generator $coroutine
        */
       public function __construct($taskId, Generator $coroutine)
       {
        $this->taskId = $taskId;
        $this->coroutine = $coroutine;
       }
       /**
        * 获取当前的Task的ID
        * 
        * @return mixed
        */
       public function getTaskId()
       {
        return $this->taskId;
       }
       /**
        * 判断Task执行完毕了没有
        * 
        * @return bool
        */
       public function isFinished()
       {
        return !$this->coroutine->valid();
       }
       /**
        * 设置下次要传给协程的值,比如 $id = (yield $xxxx),这个值就给了$id了
        * 
        * @param $value
        */
       public function setSendValue($value)
       {
        $this->sendValue = $value;
       }
       /**
        * 运行任务
        * 
        * @return mixed
        */
       public function run()
       {
        // 这里要注意,生成器的开始会reset,所以第一个值要用current获取
        if ($this->beforeFirstYield) {
         $this->beforeFirstYield = false;
         return $this->coroutine->current();
        } else {
         // 我们说过了,用send去调用一个生成器
         $retval = $this->coroutine->send($this->sendValue);
         $this->sendValue = null;
         return $retval;
        }
       }
      }

      2)Scheduler实现

      接下来就是Scheduler这个重点核心部分,他扮演着调度员的角色。

      /**
       * Class Scheduler
       */
      Class Scheduler
      {
       /**
        * @var SplQueue
        */
       protected $taskQueue;
       /**
        * @var int
        */
       protected $tid = 0;
      
       /**
        * Scheduler constructor.
        */
       public function __construct()
       {
        /* 原理就是维护了一个队列,
         * 前面说过,从编程角度上看,协程的思想本质上就是控制流的主动让出(yield)和恢复(resume)机制
         * */
        $this->taskQueue = new SplQueue();
       }
       /**
        * 增加一个任务
        *
        * @param Generator $task
        * @return int
        */
       public function addTask(Generator $task)
       {
        $tid = $this->tid;
        $task = new Task($tid, $task);
        $this->taskQueue->enqueue($task);
        $this->tid++;
        return $tid;
       }
       /**
        * 把任务进入队列
        *
        * @param Task $task
        */
       public function schedule(Task $task)
       {
        $this->taskQueue->enqueue($task);
       }
       /**
        * 运行调度器
        */
       public function run()
       {
        while (!$this->taskQueue->isEmpty()) {
         // 任务出队
         $task = $this->taskQueue->dequeue();
         $res = $task->run(); // 运行任务直到 yield
      
         if (!$task->isFinished()) {
          $this->schedule($task); // 任务如果还没完全执行完毕,入队等下次执行
         }
        }
       }
      }

      这样我们基本就实现了一个协程调度器。

      你可以使用下面的代码来测试:

      <?php
      function task1() {
       for ($i = 1; $i <= 10; ++$i) {
        echo "This is task 1 iteration $i.\n";
        yield; // 主动让出CPU的执行权
       }
      }
      function task2() {
       for ($i = 1; $i <= 5; ++$i) {
        echo "This is task 2 iteration $i.\n";
        yield; // 主动让出CPU的执行权
       }
      }
      $scheduler = new Scheduler; // 实例化一个调度器
      $scheduler->newTask(task1()); // 添加不同的闭包函数作为任务
      $scheduler->newTask(task2());
      $scheduler->run();

      关键说下在哪里能用得到PHP协程。

      function task1() {
        /* 这里有一个远程任务,需要耗时10s,可能是一个远程机器抓取分析远程网址的任务,我们只要提交最后去远程机器拿结果就行了 */
        remote_task_commit();
        // 这时候请求发出后,我们不要在这里等,主动让出CPU的执行权给task2运行,他不依赖这个结果
        yield;
        yield (remote_task_receive());
        ...
      } 
      function task2() {
       for ($i = 1; $i <= 5; ++$i) {
        echo "This is task 2 iteration $i.\n";
        yield; // 主动让出CPU的执行权
       }
      }

      这样就提高了程序的执行效率。

      关于『系统调用』的实现,鸟哥已经讲得很明白,我这里不再说明。

      3)协程堆栈

      鸟哥文中还有一个协程堆栈的例子。

      我们上面说过了,如果在函数中使用了yield,就不能当做函数使用。

      所以你在一个协程函数中嵌套另外一个协程函数:

      <?php
      function echoTimes($msg, $max) {
       for ($i = 1; $i <= $max; ++$i) {
        echo "$msg iteration $i\n";
        yield;
       }
      }
      function task() {
       echoTimes('foo', 10); // print foo ten times
       echo "---\n";
       echoTimes('bar', 5); // print bar five times
       yield; // force it to be a coroutine
      }
      $scheduler = new Scheduler;
      $scheduler->newTask(task());
      $scheduler->run();

      这里的echoTimes是执行不了的!所以就需要协程堆栈。

      不过没关系,我们改一改我们刚刚的代码。

      把Task中的初始化方法改下,因为我们在运行一个Task的时候,我们要分析出他包含了哪些子协程,然后将子协程用一个堆栈保存。(C语言学的好的同学自然能理解这里,不理解的同学我建议去了解下进程的内存模型是怎么处理函数调用)

       /**
        * Task constructor.
        * @param $taskId
        * @param Generator $coroutine
        */
       public function __construct($taskId, Generator $coroutine)
       {
        $this->taskId = $taskId;
        // $this->coroutine = $coroutine;
        // 换成这个,实际Task->run的就是stackedCoroutine这个函数,不是$coroutine保存的闭包函数了
        $this->coroutine = stackedCoroutine($coroutine); 
       }

      当Task->run()的时候,一个循环来分析:

      /**
       * @param Generator $gen
       */
      function stackedCoroutine(Generator $gen)
      {
       $stack = new SplStack;
       // 不断遍历这个传进来的生成器
       for (; ;) {
        // $gen可以理解为指向当前运行的协程闭包函数(生成器)
        $value = $gen->current(); // 获取中断点,也就是yield出来的值
        if ($value instanceof Generator) {
         // 如果是也是一个生成器,这就是子协程了,把当前运行的协程入栈保存
         $stack->push($gen);
         $gen = $value; // 把子协程函数给gen,继续执行,注意接下来就是执行子协程的流程了
         continue;
        }
        // 我们对子协程返回的结果做了封装,下面讲
        $isReturnValue = $value instanceof CoroutineReturnValue; // 子协程返回`$value`需要主协程帮忙处理 
        if (!$gen->valid() || $isReturnValue) {
         if ($stack->isEmpty()) {
          return;
         }
         // 如果是gen已经执行完毕,或者遇到子协程需要返回值给主协程去处理
         $gen = $stack->pop(); //出栈,得到之前入栈保存的主协程
         $gen->send($isReturnValue ? $value->getValue() : NULL); // 调用主协程处理子协程的输出值
         continue;
        }
        $gen->send(yield $gen->key() => $value); // 继续执行子协程
       }
      }

      然后我们增加echoTime的结束标示:

      class CoroutineReturnValue {
       protected $value;
       
       public function __construct($value) {
        $this->value = $value;
       }
       // 获取能把子协程的输出值给主协程,作为主协程的send参数
       public function getValue() {
        return $this->value;
       }
      }
      function retval($value) {
       return new CoroutineReturnValue($value);
      }

      然后修改echoTimes:

      function echoTimes($msg, $max) {
       for ($i = 1; $i <= $max; ++$i) {
        echo "$msg iteration $i\n";
        yield;
       }
       yield retval(""); // 增加这个作为结束标示
      }

      Task变为:

      function task1()
      {
       yield echoTimes('bar', 5);
      }

      这样就实现了一个协程堆栈,现在你可以举一反三了。

      4)PHP7中yield from关键字

      PHP7中增加了yield from,所以我们不需要自己实现携程堆栈,真实太好了。

      把Task的构造函数改回去:

       public function __construct($taskId, Generator $coroutine)
       {
        $this->taskId = $taskId;
        $this->coroutine = $coroutine;
        // $this->coroutine = stackedCoroutine($coroutine); //不需要自己实现了,改回之前的
       }

      echoTimes函数:

      function echoTimes($msg, $max) {
       for ($i = 1; $i <= $max; ++$i) {
        echo "$msg iteration $i\n";
        yield;
       }
      }

      task1生成器:

      function task1()
      {
       yield from echoTimes('bar', 5);
      }

      这样,轻松调用子协程。

      总结

      这下应该明白怎么实现PHP协程了吧?

      实例分析PHP7的异常

      PHP 7 异常用于向下兼容及增强旧的assert()函数。它能在生产环境中实现零成本的断言,并且提供抛出自定义异常及错误的能力。

      老版本的API出于兼容目的将继续被维护,assert()现在是一个语言结构,它允许第一个参数是一个表达式,而不仅仅是一个待计算的 string或一个待测试的boolean。

      assert() 配置

      配置项默认值可选值
      zend.assertions1 1 - 生成和执行代码 (开发模式) 0 - 生成代码,但在执行时跳过它 -1 - 不生成代码 (生产环境)
      assert.exception0 1 - 断言失败时抛出,可以抛出异常对象,如果没有提供异常,则抛出 AssertionError 对象实例。 0 - 使用或生成 Throwable, 仅仅是基于对象生成的警告而不是抛出对象(与 PHP 5 兼容)

      参数

      assertion

      断言。在 PHP 5 中,是一个用于执行的字符串或者用于测试的布尔值。在 PHP 7 中,可以是一个返回任何值的表达式, 它将被执行结果用于指明断言是否成功。

      description

      如果 assertion 失败了,选项 description 将会包括在失败信息里。

      exception

      在 PHP 7 中,第二个参数可以是一个 Throwable 对象,而不是一个字符串,如果断言失败且启用了 assert.exception 该对象将被抛出。

      实例

      将 zend.assertions 设置为 0:

      <?php 
      ini_set('zend.assertions', 0); 
      
      assert(true == false); 
      echo 'Hi!'; 
      ?>

      以上程序执行输出结果为:

      Hi!

      将 zend.assertions 设置为 1,assert.exception 设置为 1:

      <?php 
      ini_set('zend.assertions', 1); 
      ini_set('assert.exception', 1); 
      
      assert(true == false); 
      echo 'Hi!'; 
      ?>

      以上程序执行输出结果为:

      Fatal error: Uncaught AssertionError: assert(true == false) in -:2
      Stack trace:
      #0 -(2): assert(false, 'assert(true == ...')
      #1 {main}
        thrown in - on line 2

       

      以上就是本次介绍的网站开发电子书的全部相关内容,希望我们整理的资源能够帮助到大家,感谢大家对码农之家的支持。

      上一篇:PHP从入门到精通(第4版)

      下一篇:PHP、MySQL与JavaScript学习手册(第4版)

      查看更多
      读者心得
      38小时10分钟前回答

      php+MySql实现登录系统与输出浏览者信息功能

      本系统,与之前在《ASP 连接Access数据库的登陆系统》(点击打开链接)一文中的asp登录系统的思想完全一样,只是编程语言从asp变成了php,数据库从Access变成了mysql。 一、基本目标 首先在mysql存在着如下的用户信息表: 在页面中有一个登录表单,上面需要用户填写用户名与密码等信息 如果用户输入的用户名在用户信息表里面根本就没有,那么则弹出“查无此人”的对话框,并返回本页 如果用户输入的密码错误,那么则弹出“密码错误”的对话框,并返回本页 如果用户输入的登录信息正确,那么则跳到“登录成功”的页面,并输出用户当前的IP、使用的系统的语言环境、与浏览器信息 “登录成功”的……

      13小时3分钟前回答

      PHP结合Redis+MySQL实现冷热数据交换应用案例详解

      本文实例讲述了PHP结合Redis+MySQL实现冷热数据交换应用案例。分享给大家供大家参考,具体如下: 场景: 某网站需要对其项目做一个投票系统,投票项目上线后一小时之内预计有100万用户进行投票,希望用户投票完就能看到实时的投票情况 这个场景可以使用redis+mysql冷热数据交换来解决。 何为冷热数据交换? 冷数据:之前使用的数据,热数据:当前使用的数据。 交换:将Redis中的数据周期的存储到MySQL中 业务流程 用户进行投票后,首先将投票数据保存到Redis中,这些数据就是热数据,然后定期(如5s)将热数据保存到MySQL中,这些数据就变为冷数据,然后将冷数据从Redis中删除,周而复始,知道一个小……

      码农之家

      燕宛曼 提供上传

      资源
      10
      粉丝
      41
      喜欢
      187
      评论
      11

      Copyright 2018-2021 www.xz577.com 码农之家

      版权投诉 / 书籍推广:520161757@qq.com