├── README.md ├── SUMMARY.md └── syntax ├── codes ├── comments01.php ├── data01.php ├── data02.php ├── data03.php ├── tags01.php └── tags01_view.php ├── comments.md ├── data.md ├── operators.md └── tags.md /README.md: -------------------------------------------------------------------------------- 1 | # 从入门到专业的 PHP 程序员 2 | 3 | ##目录 4 | * 开篇 5 | * 前言 6 | * 什么叫专业 7 | * 如何成为专业的 PHP 程序员 8 | * 认真的态度 9 | * 不断地学习 10 | * 专业技能 11 | * 专业素养 12 | * PHP 的发展历程和现状 13 | * PHP 的应用领域 14 | * 不得不提的语法 15 | * 前言 16 | * [标记](syntax/tags.md) 17 | * [注释](syntax/comments.md) 18 | * [数据](syntax/data.md) 19 | * 类型 20 | * 变量 21 | * 常量 22 | * 表达式 23 | * [运算符](syntax/operators.md) 24 | * 流程控制 25 | * 函数 26 | * 类和对象 27 | * 命名空间 28 | * 异常及错误处理 29 | * 引用 30 | * 结束语 31 | * 不得不说的主题 32 | * 前言 33 | * 数组 34 | * 字符串 35 | * 异常处理 36 | * 代码风格 37 | * 结束语 38 | * 不要急着下手 39 | * 下手之前先构思 40 | * 一些设计和构思的简便方法 41 | * 设计和架构的原则 42 | * 可复用 43 | * 可维护 44 | * 可测试 45 | * 可读性 46 | * 面向对象 47 | * 前言(面向对象不仅仅是语法) 48 | * 以面向对象的思维和方式进行开发 49 | * 设计模式 50 | * 结束语 51 | * 用 PHP 写脚本 52 | * 前言(PHP 是优秀的脚本工具) 53 | * 脚本的应用 54 | * 单元测试 55 | * 前言(测试的重要性) 56 | * PHPUnit 介绍 57 | * 试着进行一些测试 58 | * 结束语 59 | * 学会重构 60 | * 理论结合实践 61 | * 前言 62 | * 试着开发一套简单的框架 63 | * 进一步学习 64 | * 前言 65 | * 我认为最好的学习方法 66 | * 不得不提的开源项目 67 | * 不得不提的一些工具 68 | * 结束语 69 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | * [index](README.md) 4 | * [不得不提的语法](syntax/basic.md) 5 | 6 | -------------------------------------------------------------------------------- /syntax/codes/comments01.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | /** 9 | * 获得当天的日期,返回格式为 “年(4位)-月(2位)-日(2位)” 10 | * 11 | * @return string 12 | */ 13 | function today() 14 | { 15 | $today = new DateTime(); 16 | 17 | return $today->format('Y-m-d'); 18 | } 19 | 20 | /** 21 | * 日程列表的数据 22 | * 23 | * @var array $todoList 24 | */ 25 | $todoList = [ 26 | '09:00' => '调试代码', 27 | '14:00' => '完成 UML 制图', 28 | '17:00' => '下班去买菜', 29 | ]; 30 | 31 | //包含视图文件,并执行 32 | require_once 'tags01_view.php'; 33 | -------------------------------------------------------------------------------- /syntax/codes/data01.php: -------------------------------------------------------------------------------- 1 | 网址 = 'http://www.php-go.com'; 8 | 9 | //无需使用引用符号 10 | $我的网站 = $phpGO网站; 11 | 12 | //我们无论操作哪个变量名,操作的其实都是同一个数据。 13 | $我的网站->网址 = 'http://www.dongww.com'; 14 | 15 | //输出的是改变后的网址。 16 | echo $phpGO网站->网址 . PHP_EOL; 17 | 18 | /** 19 | * 进行网址更改的函数。 20 | * 21 | * @param stdClass $网站 网站对象 22 | * @param string $新网址 新的网址 23 | */ 24 | function 更改网址($网站, $新网址) 25 | { 26 | $网站->网址 = $新网址; 27 | } 28 | 29 | 更改网址($phpGO网站, 'http://example.com'); 30 | 31 | //输出的是改变后的网址。 32 | echo $phpGO网站->网址; 33 | -------------------------------------------------------------------------------- /syntax/codes/tags01.php: -------------------------------------------------------------------------------- 1 | format('Y-m-d'); 9 | } 10 | 11 | $todoList = [ 12 | '09:00' => '调试代码', 13 | '14:00' => '完成 UML 制图', 14 | '17:00' => '下班去买菜', 15 | ]; 16 | 17 | require_once 'tags01_view.php'; 18 | -------------------------------------------------------------------------------- /syntax/codes/tags01_view.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 今天的 TODO 列表 6 | 7 | 8 | 9 | 10 |

今天是:,今天该做的事情:

11 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /syntax/comments.md: -------------------------------------------------------------------------------- 1 | #PHP 注释 2 | 3 | 只要是一门正儿八经的编程语言,都会提供给开发者注释的语法。或许你尚未意识到注释的重要性,甚至从来不写注释, 4 | 但至少也应该从前面这个事实意识到,注释这个功能在编程领域是不可或缺的。而且,越是身经百战的程序员,对这点的认识越是深刻。 5 | 我个人无法想象如果 PHP 没有添加注释的能,我是否能把一个项目持续地做下去,以及能做到什么程度。 6 | 7 | 注释最基本的用途是可以让你为某个局部的代码或者某个文件甚至整个项目注上说明。良好的注释可以使你回头再来阅读这段代码的时候,立马就能唤起已经中断的思绪。 8 | 如果是团队协作开发一个项目,注释就显得更加重要。良好的注释不至于让你的队友花上半天时间通读代码以后才明白你的意图。 9 | 10 | ##什么是良好的注释 11 | 12 | **一目了然** 13 | 14 | 好的注释能让人望文生义,使读者迅速明白作者的意图,并对主要功能和关键信息有一个大概的了解。 15 | 16 | **恰如其分** 17 | 18 | 归纳起来有以下几点: 19 | 20 | * 在合适的地方添加注释 21 | * 恰当的详细程度 22 | 23 | 要做到这几点,对专业技能的要求其实并不高,无非就是掌握一些语法和规范。但对作者的专业素养以及经验的要求就很高了。 24 | 注释的质量的确需要长期的经验积累才能逐渐提高,我的建议是,经常阅读高质量的代码,学习高手是如何添加注释的,从照瓢画葫芦开始。 25 | 26 | **良好并一致的风格** 27 | 28 | 这完全是态度问题了。 29 | 30 | 随着 PHP 越来越标准化,代码的风格的选择余地其实很小。我们所要在的,就是认认真真地在项目中遵行一致的风格,无论是个人项目还是团队开发,无论项目的大小。 31 | 虽然现在的 IDE 越来越智能,可以辅助你很好地实现这一点,但我们在态度上绝对不能产生依赖性。 32 | 33 | ##演示代码 34 | 35 | 我们试着将之前的 `tags01.php` 的代码加上注释: 36 | 37 | ~~~ .php 38 | 39 | 44 | */ 45 | 46 | /** 47 | * 获得当天的日期,返回格式为 “年(4位)-月(2位)-日(2位)” 48 | * 49 | * @return string 50 | */ 51 | function today() 52 | { 53 | $today = new DateTime(); 54 | 55 | return $today->format('Y-m-d'); 56 | } 57 | 58 | /** 59 | * 日程列表的数据 60 | * 61 | * @var array $todoList 62 | */ 63 | $todoList = [ 64 | '09:00' => '调试代码', 65 | '14:00' => '完成 UML 制图', 66 | '17:00' => '下班去买菜', 67 | ]; 68 | 69 | //包含视图文件,并执行 70 | require_once 'tags01_view.php'; 71 | 72 | ~~~ 73 | 74 | ##注释的进化 75 | 76 | 我们在演示代码中看到了几个注释片段,顶部的注释一般用来描述该文件的总体信息和版权信息。其他局部的注释一般加在要说明的代码上方。 77 | `today()` 函数的注释说明了该函数的用途,以及数据的返回类型。`$todoList` 变量的注释说明了该变量的用途,以及该变量的类型。 78 | 79 | 但随着技术的发展和经验的累积,一些天才异想天开,觉得是不是能利用注释来做更多的事呢?于是他们真的发明了一些很神奇的用法,大幅提升了开发人员的效率。 80 | 可见异想天开并不是什么坏事,人类的进步往往源自于异想天开。 81 | 82 | 目前,代码的注释被用来自动生成文档和自动生成代码已经极为普遍,作为一项专业技能,我们非常有必要来了解一下。 83 | 84 | ###自动生成文档 85 | 86 | 演示代码中的注释我们使用了 `/** */` 这样的格式,PHP 本身并没有要求我们必须使用这样的格式,但这种写法已经成为了事实上的标准。 87 | 以这样的格式来书写注释,有助于一些文档生成工具进行识别,进而根据注释内容自动生成完整的 API 文档。 88 | 换句话说,我们在为代码添加注释的同时,其实已经在编写文档了。多么神奇啊! 89 | 90 | 当然,如果希望自己的代码能生成高质量的文档,还需要了解一些额外的知识。例如,如何标记函数的返回值、参数、类型等等。 91 | 在我们的注释中,已经加入了一些这样的标记,例如: `@return string` 指明 `today` 将返回一个字符串; 92 | `@var array $todoList` 指明 `$todoList` 变量是数组类型。 93 | 94 | 学习这些额外知识的负担并不大,但是回报巨大,所以建议大家能多多了解。本文的目的是抛砖引玉,并不打算对所有的知识加以详细说明。 95 | 你可以参考 [phpDocumentor](http://www.phpdoc.org/),来进一步深入学习。上面也有生成后的 API 文档演示。 96 | 97 | ###自动生成代码、执行代码 98 | 99 | 除了用于生成文档,注释还有一些更高级的功能。例如 [Doctrine ORM](http://www.doctrine-project.org/)中, 100 | 就大量地使用了该项技术。这是一个操作数据库的封装类库,可以将“类”映射到数据库表,以便开发者用面向对象的方式来思考和操作数据库。 101 | 关于面向对象的知识我们会在后续章节详细探讨。目前只需要大概了解一下,主要目的还是为了说明注释的用途。 102 | 103 | 我们来看一段基于 Doctrine ORM 的代码: 104 | 105 | ~~~ .php 106 | 107 | getName(); 132 | 133 | ~~~ 134 | 135 | 当然,重点不在于此,而在于,到底这个 `$product` 对象是如何同数据库关联起来并且获取数据库中数据的呢? 136 | 这里面最大的功臣当属于类定义文件中的特定注释,注释中指明了该类对应的数据库表,以及某个属性对应的数据库字段和字段类型。 137 | Doctrine ORM 会解析注释,用于自动生成数据库表,以及同数据库进行映射和关联,就像变魔术一样! -------------------------------------------------------------------------------- /syntax/data.md: -------------------------------------------------------------------------------- 1 | #数据 2 | 3 | 编程,说白了就是进行数据的计算,数据的处理,数据的传输,数据的呈现等工作。所以把数据说成是编程的核心我认为一点也不为过。 4 | 5 | 有些数据可能会发生变化,例如“年龄”,一年大一岁,今年19,明年20。可改变的数据称之为 **变量**。更改变量数据的过程,我们称为 **赋值**。 6 | 不过有一个例外:`$this`,它虽然也称之为变量,但是它不能直接被赋值。 7 | 8 | > 当一个类实现了 `ArrayAccess` 接口之后,`$this` 可以数组的形式进行赋值:$this['age'] = 12; 9 | 10 | 还有一些数据绝不可能发生变化,例如“性别”,你是男的这辈子都是男的,虽然可以变性成女的,但你体内无数个 YY 却掩饰不了你是个男人的本质。 11 | 不允许变化的数据称之为 **常量**。 12 | 13 | 我们需要频繁地使用数据,所有还得给它起个名字,否则我们很难召唤到它。 14 | 给变量起的名字叫做 **变量名**,给常量起的名字叫做 **常量名**。 15 | 16 | ##变量 17 | 18 | 我们已经在 `tags01.php` 中看到过一些变量。在 PHP 中,变量名的第一个字符必须是 `$`。其实我个人很反感这个符号, 19 | 敲起来不太顺手,而敲它的次数又是如此之多,严重影响效率加速疲劳。不过它也有它的好处,正是由于这个字符的存在, 20 | 使得我们可以简单地将变量插入到字符串中,例如: 21 | 22 | ~~~ .php 23 | 24 | $name = 'dongww'; 25 | 26 | echo "my name is $name" ; //输出为: my name is dongww 27 | 28 | ~~~ 29 | 30 | 在我自己的开发工具里,`$` 符号已经被替换成 `d + 回车`,我感觉这样更顺手。 31 | 如果你的工具也支持替换功能,强烈建议你替换掉它。虽然敲几个 `$` 费不了多少劲,但是大量地累积以后,你会疲劳得更快。 32 | 我们不仅要努力写出高质量的代码,也要想办法提高效率,减少疲劳度无疑是提高效率的一种办法。 33 | 减少疲劳度的方法还有很多,例如换个好键盘,尽可能使用快捷键等等。 34 | 35 | ###引用 36 | 37 | 任何数据都会有与之对应的变量名,并且,同一个数据,可以有多个变量名,就好像一个人可能会有多种称呼。有人叫我哥哥,有人叫我弟弟,有人直呼我的姓名, 38 | 但在特定的场合,别人无论叫的啥,我都知道是在叫我。 39 | 40 | 数据也同样可以有多个别名,可以让你通过任意一个别名操作同一个数据。在 PHP 中,别名的专业术语叫做 **引用**。 41 | 42 | 下面的代码是使用引用的演示: 43 | 44 | ~~~ .php 45 | 46 | 网址 = 'http://www.php-go.com'; 117 | 118 | //无需使用引用符号 119 | $我的网站 = $phpGO网站; 120 | 121 | //我们无论操作哪个变量名,操作的其实都是同一个数据。 122 | $我的网站->网址 = 'http://www.dongww.com'; 123 | 124 | //输出的是改变后的网址。 125 | echo $phpGO网站->网址 . PHP_EOL; 126 | 127 | /** 128 | * 进行网址更改的函数。 129 | * 130 | * @param stdClass $网站 网站对象 131 | * @param string $新网址 新的网址 132 | */ 133 | function 更改网址($网站, $新网址) 134 | { 135 | $网站->网址 = $新网址; 136 | } 137 | 138 | 更改网址($phpGO网站, 'http://example.com'); 139 | 140 | //输出的是改变后的网址。 141 | echo $phpGO网站->网址; 142 | 143 | ~~~ 144 | 145 | 更多关于引用的帮助,请参考官方文档。 146 | 147 | ##数据类型 148 | 149 | 这个世界是如此的复杂,以至于为这个现实世界服务的程序语言再怎么精炼,也不得不提供多种数据类型来满足开发人员的需求。 150 | 仅仅这样还不够,这些类型总有无能为力的时候,所以程序语言又不得不提供给开发人员自定义数据类型的能力。 151 | -------------------------------------------------------------------------------- /syntax/operators.md: -------------------------------------------------------------------------------- 1 | #运算符 2 | 3 | 运算符是 PHP 中最重要的概念之一。我们要操作数据(计算、比较、赋值等等),就必须用到运算符。关于运算符详细的文档可以查看 PHP 官网。 4 | 这里提到的仅是最重要,或是容易忽视的内容。 5 | 6 | ##关于优先级 7 | 8 | 很多编程书对优先级的叙述会长篇大论,仿佛不搞清楚优先级关系就无法编程似的。这在我看来总觉得有点骇人听闻,也有误导之嫌, 9 | 不明就里的读者往往会在这上面花上大量的时间。更有甚者还会写出一些稀奇古怪的表达式,来显示自己的水平有多高。大可不必。 10 | 11 | 当然一些最基本的优先级我们还是必须得搞清楚的,比如乘除的运算优先于加减的运算。除此之外,我们可别忘了,PHP 中有种东西叫做 **括号**。 12 | 它可以帮助我们清晰地来表达优先级关系。 13 | 14 | 我们要清楚地认识一点,代码是写给人看的,不是用来搞脑子的。清晰的代码可以提高效率,也可以避免一些潜在的或无意中犯下的错误。这才是最重要的。 15 | 特别是团队开发的时候,成员的水平参差不齐,水平差一些的成员有时候不一定能很好理解复杂的表达式,这就会导致效率的低下、错误的产生以及疲劳的加剧。 16 | 所以我给出以下几点建议: 17 | 18 | * 尽量写简单的表达式,宁可拆成多个表达式,多写几行。 19 | * 除了最基本、一目了然的优先级,一概用上括号来明示。 20 | * 容易造成误解的地方,加上注释。 21 | 22 | ##比较运算符 23 | 24 | 比较运算符是一个容易产生潜在错误的地方。例如我们可能无意中把 `$age == 18` 写成了 `$age = 18`。不仅是新手,就连老手也可能会犯这种低级错误。 25 | 而且这种错误一旦出现,很可能一时半会还发现不了。例如下面的代码: 26 | 27 | ~~~ .php 28 | `,其中代码将被解析。 4 | 若解析器未寻获结束标记,则会一直解析,直至文件结束。 5 | 6 | PHP 代码通常以两种形式出现。其一为纯 PHP 文件,其二可嵌入到其他格式中,例如 html 格式。 7 | 8 | > 在设计合理的项目中,复杂的逻辑处理往往置于纯 PHP 文件中,以使其与视图文件分离。 9 | > 当 PHP 嵌于视图部分时,尽量不要涉及太多数据处理。而应只承担调取处理后的数据并输出它的责任。 10 | 11 | 请看下面的代码: 12 | 13 | ~~~ .php 14 | 15 | format('Y-m-d'); 23 | } 24 | 25 | $todoList = [ 26 | '09:00' => '调试项目1的代码', 27 | '14:00' => '完成项目2的 UML 制图', 28 | '17:00' => '下班去买菜', 29 | ]; 30 | 31 | require_once 'tags01_view.php'; 32 | 33 | ~~~ 34 | 35 | ~~~ .php 36 | 37 | 38 | 39 | 40 | 41 | 今天的 TODO 列表 42 | 43 | 44 | 45 | 46 |

今天是:,今天该做的事情:

47 | 52 | 53 | 54 | 55 | 56 | ~~~ 57 | 58 | 上述为两个代码文件,相互关联,可尝试运行 `tags01.php` 以观其结果。 59 | 60 | `tags01.php` 是一个纯 PHP 代码文件。请注意,这里我们仅使用了开始标记。 61 | 62 | > 如果文件内容是纯 PHP 代码,最好在文件末尾删除 PHP 结束标记。 63 | > 这可以避免在 PHP 结束标记之后万一意外加入了空格或者换行符,会导致 PHP 开始输出这些空白, 64 | > 而脚本中此时并无输出的意图。出处: 65 | [http://php.net/manual/zh/language.basic-syntax.phptags.php](http://php.net/manual/zh/language.basic-syntax.phptags.php)。 66 | 67 | 在 `tags01_view.php` 中,我们看到了几对特殊的标记 ``,此为简便写法,谓之短标记, 68 | 其用于输出表达式的结果,等同于 `` 。在视图文件中,每一个相对独立的数据输出都应放置在独立的这对短标记中,以使代码清晰。 69 | 另还有一对短标记: ``,用于替代 ``,但随着 PHP 语法的标准化,已等同于废除,在 PHP 配置中,也被默认禁用。 70 | 71 | > `` 这对标记可谓一波三折。曾由于短标记被默认禁用,其也受到牵联。 72 | > 当 PHP 文件用作视图使用的时候,这种短标记其实是行之有效且清晰易读的, 73 | > 于是在 PHP 5.4 中,又被默认启用,且无法禁用。 74 | 75 | `tags01_view.php` 里面 `foreach` 的写法有点特殊,没有使用通常的大括号。 76 | 当 PHP 代码用于嵌入时,应当选择这种写法,它会使代码看上去更加简洁易读。 77 | 78 | 之前说过,当 PHP 嵌于视图文件中的时候,不应进行太多的数据处理。但类似于调用函数这种一目了然的代码,完全没有理由拒绝。 79 | 另外,类似于判断和循环这种基本的逻辑处理,在视图中实无法避免,只要保证代码简短清晰即可。 80 | 总之记住一点:**数据处理尽量与视图分离,代码可读性要强,最好一目了然**。 --------------------------------------------------------------------------------