[苏勇和他的 IterCast](https://www.zhihu.com/question/23871761/answer/25926171)。 学习环境:[runphponline](http://www.runphponline.com/?filename=php_default) 或 [anycodes](http://www.anycodes.cn/zh)。 - PHP学院 - phpxy.com 此站教程、手册齐全。 - 7天学会PHP - phpbook.phpxy.com 简明扼要。**看云上可以下载三种格式的电子书。** > **对应短小精悍的视频教程**:http://www.mobiletrain.org/video/php_download.html - 李炎恢 HTML CSS JavaScript PHP Bootstrap kancloud.cn/wizardforcel/liyanhui-tutorials/154156 ========== - 市场分析 目前PHP在全球网页市场、手机网页市场还有为手机提供API(程序接口)排名第一。 在中国微信开发大量使用PHP来进行开发。 - 我们把我们写代码的软件和运行代码的软件统一的称为开发环境。 时间宝贵,环境只要能满足学习要求即可。 - 所谓服务器:不要把它想的太过于高深,不过就是提供一项特殊功能(服务)的「电脑」而已。 显示网页的叫网页(web)服务器(server)。 帮我们代为收发电子邮件(email)的服务器叫邮件服务器。 帮我们把各个游戏玩家连接在一起的叫游戏服务器。 帮我们存储数据的叫数据库服务器。 > 所谓的 “\*\*服务器” 就是一台长期开机、可以访问的装有对应功能软件的电脑。 - 网页服务器、数据库服务器和PHP最核心的语法解释器。 强烈建议初学者使用集成环境包(XAMPP)。 _我还是使用 vagrant 吧。_ - htdocs。 - http://127.0.0.1 - 选择编辑器的标准:不带提示,要有高亮。(Notepad++) - 一看就懂,一写就错。 > **永远不要骗自己,写不出来代码就是不会。** ================================================== - 第一段PHP代码。 ~~~ <?php //从此处【尖括号、问号、PHP】这5个字符开始,往下的部份是PHP代码 phpinfo(); // 一行代码写完,就必须要加分号 ?> // 遇到上面的【问号、尖括号】说明PHP代码写完了。再之后的部份,跟我PHP没有关系啦 ~~~ - 源码文件命名不要用中文,不要用特殊符号,不要中间加空格,严格区分大小。 (a-zA-Z0-9_-) - 变量。 以$开始,首非数字,大小敏感,禁止中文。 下划线不算特殊符号。 > 符号读法:3\#井,4$刀,7&与,8\*星。 > 所谓“三井,四刀,七与,八星”。 - echo 是在PHP里面最常用的一个输出、显示功能的命令。 - 注释 ~~~ // 表示单行注释 /* * 多行注释 这里是注释区域代码 */ ~~~ - 没赋值的变量。变量值为空NULL。 - 字符串声明 用单引号 用双引号 用字界符(需要输入非常大段的字符串时使用) ~~~ <?php $dingjie = <<<ABC 如果 非要在这个滚犊子 前 面<br /> 加上一段 <i>距离的话</i> 我想说:<h1>思想有多远,你就跟我滚多远</h1> ABC; ?> ~~~ - **双引号解析变量,但是单引号不解析变量。** 在双引号里面插入变量,变量后面如果有英文或中文字符,它会把这个字符和变量拼接起来,【视为一整个变量】。 一定要在变量后面接上特殊字符,例如空格、!等分开。 如果在双引号里面插变量的时候,后面不想有空格,可以拿【大括号】将变量包起来。 双引号解析转义字符,单引号不解析转义字符。但,单引号能解析\' 和\ 单引号效率高于双引号,**【尽可能使用单引号】** 双引号需要解析变量,因此双引号的效率没有单引号高。我们如果为了更高的效率,我们通常使用单引号。 双号和单引号可以互插!!!双引号当中插入单引号,单引号当中插入变量,这个变量会被解析。 神奇的字符串拼接胶水——**(.)点,用来拼接字符串。** echo $shixi . $buran . $mimang . $xuexi; 因此,大括号的用法还是尽量少用,尽量使用字符串连接的方式比较好。 我们将定界符声明字符串视为双引号一样的功能来看待。 - 不可见字符:主要是计算机规定的一些特殊符号。例如:回车(\n)、缩进(\t)等。 双引号执行变量,所以…… - 浮点数。 php使用变量不用声明,直接 $变量名 = 值。 - var_dump() 是一个函数。向括号()中间插入变量。这个函数,会打印出来数据类型,还会对应显示变量的长度和值。 - if () {} else {} 一句话的时候可以不写大括号,但是规范。 - 空在英文里面表示是null,它是代表没有。空(null)不是false,不是0,也不是空格。 【重点】知道null产生的三种情况,学习empty 和 isset两个函数的区别。 主要有以下三空情况会产生空(null)类型: 通过变量赋值明确指定为变量的值为NULL 一个变量没有给任何值 使用函数unset()将变量销毁掉 - empty()可以向括号中间传入一个【变量】,字面量不行。 这个变量的值如果为false或者为null的话,返回true。 否则返回false。 $four = 1; var_dump(empty($four)); [注] 判断【变量】是否为空。 - isset()可以向括号中间传入一个或者多个【变量】,变量与变量间用逗号分开。 只要有一个变量为null,则返回false。 $four = null; var_dump(isset($four)); 否则,则返回true。 [注] 判断【变量】是否被赋值 - unset()这个函数的功能是毁掉变量。 - 对象是一个复合类型。var_dump一个变量的时候看到的类型为object的,这个变量就是对象类型。 - 数组是一个复合类型。var_dump一个变量的时候看到的类型为array的,这个变量就是数组类型。 数组声明。 $a = array(1,2,3); var_dump($a); - 资源。抽象。 电脑里面的资源是指: word,excel等文件 有人收藏的美女图片和我们的自拍照片等图片 音乐 某些人爱看的AVI小电影 打开的网页 数据库 ... ... 我们打开一个图片,用PHP来操作它,我们就是操作的一个资源。 我们打开的数据库**连接(就是你拽着的一条绳子,我们把这个也抽象成了资源,称作“连接”)**,我们需要连接数据库,数据库就是我们操作的资源。 包括网络连接,连接后发送邮件,我们也可以认为是一个资源。 本章重点:理解资源就提操作我们可见和不可见的文件、网络和数据。 我们在以后的章节中,操作图片和网络的时候大家会有更为深刻的印象。 - 回调。 callback,英文中的call是叫,back是返回,回来的意思。 callback 汉译过来的意思即为:回调。(执行完成,再调一次某个功能执行一次) 我们在讲解函数类型和对象的时候,我们会演示讲解回调函数。 Ajax 的异步。Ajax 是一种理念而非技术,这种理念是通过浏览器的内置对象支持实现的。 - gettype(传入一个变量) 能够获得变量的类型。 var_dump(传入一个变量) 输出变类型和值。 判断数据类型使用 is_* 系列函数。 is_int 是否为整型 is_bool 是否为布尔 is_float 是否是浮点 is_string 是否是字符串 is_array 是否是数组 is_object 是否是对象 is_null 是否为空 is_resource 是否为资源 is_scalar 是否为标量 is_numeric 是否为数值类型 is_callable 是否为【函数】 - 标量:整型(int) 浮点(float)、【布尔(bool)】、字符串(string) 混合类型: 数组(array)、对象(object) 特殊类型:空(null)、 资源(resouce)、回调(callback) //换成echo,is_int试试,为什么echo执行假区间呢? if(is_callable('var_dump')){ echo '执行真区间'; }else{ echo '执行假区间'; } 为什么最后的实验中 echo 执行假区间呢? 答:因为「echo」不是函数,「是基本语法」。大家眼前可以不用理解函数和基本语法的区别。了解和不了解在实际开发中没有影响。知道有这个知识点就行。 - PHP 7 的性能与 PHP5.6 相比,提升了性能接近 200%。 7中有些地方,我们可以强制指定类型,也可以不用强制指定类型来声明变量。 5.x 阶段都是完全的弱类型的编程语言。 - 自动类型转换,就是数据类型在某些情况下,自动会变为其他的类型参与运算。 自动类型转换的发生时机是:运算和判断的时候某些值会自动进行转换。 - 布尔值判断时的自动类型转换: 1. 整型的0为假,其他整型值全为真 2. 浮点的0.0,布尔值的假。小数点后只要有一个非零的数值即为真 3. 空字符串为假,只要里面有一个空格都算真 4. 字符串的0,也将其看作是假。其他的都为真 5. 空数组也将其视为假,只要里面有一个值,就为真 6. 空也为假 7. **未声明成功的资源也为假** - 强制类型转换有三种方式: 1. 用后面的三个函数可以完成类型转换,intval()、floatval()、strval() 2. 变量前加上()里面写上类型,将它转换后赋值给其他变量 3. settype(变量,类型) 直接改变量本身 - 常——汉语字面为:长久,经久不变。 常量那就好翻译了:长久不变的值。 - define(常量名,常量值) 1. 常量值只能为上一章中我们讲到的标量**(不能用数组去赋值)** 2. 常量名可以小写,但是通常大写 3. 常量名可以不加引号,但是通常加上引号 4. 在字符串中调用常量的时候,必须在引号外面 5. 常量名建议只用字母和下划线 - 系统内置常量 LINE 当前所在的行 FILE 当前文件在服务器的路径 FUNCTIOIN 当前函数名 CLASS 当前类名 METHOD 当前成员方法名 PHP_OS PHP运行的操作系统 PHP_VERSION 当前PHP的版本 TRAIT Trait 的名字,php5.4新加 DIR 文件所在的目录 NAMESPACE 当前命名空间的名称(区分大小写) - 为了防止其他人绕过安全检查文件。 ~~~ <?php //尝试将include 'version.php'这一行代码注释后再执行看看,对比结果 include 'version.php'; if(!defined('AUTH')){ echo '非法!非法!你尝试跳过授权文件'; exit; } //模拟后面用户注册和用户登陆的代码xxx行 echo '用户注册'; ?> ~~~ - 可变变量其实就是——已声明的变量前,再上变量符。 ~~~ <?php $a = 'b'; $b = 'c'; echo $$a; // c ?> ~~~ - PHP 的外部变量是 PHP 在使用过程中规定好的一些变量。 这个变量的规定是这样规定的,就这样使用。 **其实就是一些PHP内置的小工具,被语言发明人在解释器里写好提供的。** ~~~html <form action="reg.php" method="get"> <input type="text" name="username" /> <input type="password" name="pwd" /> <input type="submit" value="提交" /> </form> ~~~ 把用户和密码,采用get方法,将数据发送给reg.php。 reg.php想办法接收用户传过来的username和pwd这两个值。 我们得出我们的第一个外部变量:**$_GET**。 $_GET 的主要作用是**拿到表单中get传值的数据。** >$_GET后面加上中括号,将username作为字符串放在中括号里面,就得到了表单里面的`<input type="text" name="username" />` 的值。 ~~~ <?php $u = $_GET['username']; echo $u.'<br />'; $passwd = $_GET['pwd']; echo $passwd.'<br />'; ?> ~~~ - 需要使用到post传值,post传值是在地址栏中不可见的。 PHP的代码里面的$_GET全改为了 **$_POST**。 通过我们看不见的浏览器的请求头文件传递的数据。所以在URL(网址)栏不可见。 - **$_REQUEST** 即可以接收get传值也可以接收post传值。 - 常用外部变量。(超全局变量) $_COOKIE 得到会话控制中cookie传值 $_SESSION 得到会话控制中session的值 $_FILES 得到文件上传的结果 $_GET 得到get传值的结果 $_POST 得到post传值的结果 $_REQUEST 即能得到get的传值结果,也能得到post传值的结果 - firebug 可以在 post 的同时查看请求头的内容。查看header头传递数据(网络,点击POST reg.php 选择Post)。 若真是使用get传密码,密码在地址栏里面显示过后。浏览器的历史记录会自动记录访问过的地址。恶意用户会通过查看 你的浏览器的历史记录,得到你曾经输入的密码。因此,不能使用get方式来作密码的传输方式。 - chrome 的话,可以筛 method:POST,找到链接对应的 headers - form data。 - 环境变量。phpinfo(); 和TCL察看当前文件的路径什么的,一个道理。 $_SERVER["**REQUEST_METHOD**"] 请求当前PHP页面的方法 $_SERVER["**REQUEST_URI**"] 请求的URI $_SERVER["**SERVER_SOFTWARE**"] 用的是哪一种服务器 $_SERVER["**REMOTE_ADDR**"] 客户的IP地址 $_SERVER["**SERVER_ADDR**"] 当前服务器的IP地址 $_SERVER["**SCRIPT_FILENAME**"] 主前请求文件的路径 $_SERVER["**HTTP_USER_AGENT**"] 当前访问这个网址的电脑和浏览器的情况 $_SERVER["**HTTP_REFERER**"] 上级来源(用户从哪个地址进入当前网页的) $_SERVER["**REQUEST_TIME**"] 当前的时间 - URL带有了主机地址部份,而URI不带协议和主机地址部份。 - url:http://www.phpxy.com/abc.php?username=liwenkai - uri:abc.php?username=liwenkai - 变量引用。vs 指针。 $bar = &$fo; 一个变量名,对应了一个数据值(空间)。 两个变量名,就对应两个数据值(空间)。 …… 而加上&(and 符后),把变量指向同一个存值空间了。 **存的是地址?不是。直接变引用。和java一样,底层是指针,但是明面上你是读不到这个地址值的。** 也就是说 $bar 和 $fo 现在是指向同一个值空间。一间房子,原来只有一条路,现在又多了一条路,房子变了,从哪条路走都是走到这个房子来。 - %,取余,取模。 支持 += 和 .= 等快捷运算符。 支持自加自减。(关于先加后赋值$a=++$x 和 先赋值后加$a=$x++) - 等于 ==(赋值是=号,所以==规定为等于)。 全等(也叫判断类型等于) === 全不等(也叫判断类型不等于) !== $x = 5; $y = '5'; == true, === false。$x为整型,$y为字符串类型。 - 短路的用法。 ~~~ <?php //如果为defined('AUTH')存在AUTH常量则为true,不访问后面的exit了。如果为false则执行exit。 defined('AUTH') or exit('存在安全因素不准访问'); php> ~~~ - 位运算。左移乘2,右移除以2。对应十进制,左移乘10,右移除以10。 - 不用记优先级,确定不了的时候号上括号把优先级标出来即可。 - 其他运算符: - $x? 真代码段(只能写一句代码):假代码段(只能写一句代码)。判断是否为真假 ? 真情况 : 假情况; - \`\`(反引号) 反引号中间插代命令,执行系统命令,等价于shell_exec函数。echo \`ipconfig\`;(不过有些虚拟服务器是禁止执行这些的命令脚本的) - @ 单行抑制错误,把这一行的错误不让它显示出来了,效率低不建议使用 - **=> 数组下标访问符** - **-> 对象访问符** - **instanceof 判断某个对象是否来自某个类,如果是的返回true,如果不是返回false** - switch。 ~~~ <?php switch(变量){ //字符串,整型 case 具体值: 执行代码; break; case 具体值2: 执行代码2; break; case 具体值3: 执行代码3; break; default: } ?> ~~~ 可以不写 break 玩穿透。 - do...while... 有可能用在资源处理如:文件打开等地方。 - exit exit 之前我们讲过了,从当前处停止后续执行 break 之前遇到过,跳出循环或者跳出结构体执行后续代码 continue 跳出此次循环,下次循环继续 - PHP 5.3 起,可以使用 goto。通过标签实现。 - declare 在基础阶段,大家应该跳过此处学习。 - 函数的英文叫作:function,而 function 的解释项中有另外一个含义:功能。 函数 就是 功能。调用一个函数就是在调用一个功能。 函数是条狗,哪里需要哪里吼。 1. 需要用一个函数的时候,就吼一声它的名字。 2. 函数可以反复去吼,吼了它的名字它就过来了。也就是函数可以反复调用。 我们明白后,那我们接下来来讲解函数的分类,我们将函数分为两大类别: 1. 自定义函数 2. 系统函数 - 自定义函数。 ~~~ function 函数名([参数名1[=值1], 参数名2[=值2], 参数名n[=值n]]) { 函数中的功能体 [return 返回值] } ~~~ 函数名与变量命名规则基本一样,但是不同的是:**函数名不区分大小写**。 **PHP 函数不能被重载**。[伪重载方案](http://www.jb51.net/article/65711.htm)。 - 函数体的参数若是定义了,未传参数,代码会报错。 但函数后的参数如果有默认值,参数可以不填,代码也不会报错。 函数后如果有默认值和无默认值的参数,通常把无默认值的参数写在最前面。 - **函数**的执行没有顺序关系,**可以在定义处之前的位置调用**。 这一点与 TCL 着实不同。 - 回调函数:在一个函数的参数里面,再传入一个函数名,将函数名加上()括号,识为变量函数,配合执行。 ~~~ function woziji($one,$two,$func){ if(!is_callable($func)){ return false; } //$func是一个变量函数 echo $one + $two + $func($one,$two); } function plusx2( $foo , $bar){ $result = ($foo+$bar)*2; return $result; } echo woziji(20,10,'plusx2'); ~~~ - 变量部份,我们学习了可变变量($$a)。 可变函数仅仅是可变变量的一个变种、变形表达。 可变函数,我们也会称呼为变量函数。 > 核心思想就是一句话:函数也是一种变量类型。可变函数也是一种可变变量。 ~~~ function demo(){ echo '天王盖地虎'; } function test(){ echo '小鸡炖蘑菇'; } $fu = 'demo'; //把$fu变为了demo,把demo后加上了一个括号,就执行函数了 $fu(); ~~~ - 所谓匿名,就是没有名字。 匿名函数,也就是没有函数名的函数。 匿名函数的第一种用法,直接把赋数赋值给变量,调用变量即为调用函数。 1. 变量函数式的匿名函数 函数体没有函数名,通过$greent加上括号来调用的,这就是匿名函数。 ~~~ $greet = function($name) { echo $name.',你好'; }; $greet('明天'); $greet('PHP学院'); ~~~ 2. 回调函数式的匿名函数 实际使用场景中,我们想通过一个函数实现一个功能。 但是,我又不想专门定义一个函数。 ~~~ function woziji($one,$two,$func){ if(!is_callable($func)){ return false; } echo $one + $two + $func($one,$two); } woziji(20, 30, function($foo, $bar) { $result = ($foo+$bar)*2; return $result; } ); ~~~ 因此,函名函数在调用的时候没有函数名。 - 内部函数,是指在函数内部又声明了一个函数。 ~~~ <?php function foo() { echo '我是函数foo哟,调一下我才会执行定义函数bar的过程<br />'; function bar() { echo '在foo函数内部有个函数叫bar函数<br />'; } } //现在还不能调用bar()函数,因为它还不存在 bar(); foo(); //现在可以调用bar()函数了,因为foo()函数的执行使得bar()函数变为已定义的函数 bar(); //再调一次foo()看看是不是会报错? foo(); ?> ~~~ 1. 内部函数名,不能是已存在的函数名。 2. foo()调用两次会报错。 3. 如果不调foo()函数无法执行bar函数,因为bar是在foo的内部。**(调了一下母函数,内部函数才算初次声明了)** - 好像。 \`\`\` = <? php = php 内容就是内容。 \`\`\` = ?> - 变量作用域。 例外:超全局变量是外部变量,但在函数内部也是可以用。 $_COOKIE 得到会话控制中cookie传值 $_SESSION 得到会话控制中session的值 $_FILES 得到文件上传的结果 $_GET 得到get传值的结果 $_POST 得到post传值的结果 $_REQUEST 即能得到get的传值结果,也能得到Post传值的结果 - 通过 $GLOBLAS 在函数内创建、读取和修改外部变量(定义在函数外部的变量)。 - 在函数内使用global关键词后面跟一个或多个变量,就把变量变为了全局变量。我们越来越少的使用这种方式来声明全局变量了。**在TCL里还存在。** - 函数的参数引用,也是这个意思,将形参和实参指向到同一个位置。如果形参在函数体内发生变化,那么实参的值也发生变化。(函数传参的“传引用”用法,vs “传参”) - 递归函数。函数体内调用函数自己。主要是用在:文件和文件夹操作。 也可以用现成的文件和文件夹处理函数或文件处理类就可以。 >写出迭代公式,确定终止条件。 - 静态变量:函数被调用了多少次。 声明一个静态变量,第二次调用函数的时候,静态变量不再初始化变量,会在原值的基础上读取执行。 声明在函数内部,static $a = 0; - 使用系统内置函数:依靠**手册**。 http://down.phpxy.com/book%2Fphp_enhanced_zh.chm 1. 了解函数的功能,特别是常用函数的功能 2. 了解函数的参数 3. 了解函数的返回值 - 返回 bool 值的,通常为操作是否成功、验证是否通过、检查是否正确等。 - int array_unshift ( array &$array , mixed $value1 [, mixed $... ] ) &符,引用传参。 Mixed 表示任何类型的数据,指可传入任意类型。 所有遇到中括号的。都是指后面的参数可传,也可以不传。 ...(省略号)。代表可以传入任意多个参数。 ~~~ <?php $queue = array("凤姐", "芙蓉"); array_unshift($queue, "杨幂", "姚晨"); print_r($queue); ?> ~~~ - bool array_walk ( array &$array , callable $callback [, mixed $userdata = NULL ] ) ~~~ $shuaige = array("a" => "wuyanzhu", "b" => "huangxiaoming", "c" => "ninzetao"); function test_print($item2, $key) { echo $key ." ---". strtoupper($item2) . "<br />\n"; } echo '<pre>'; var_dump($shuaige); echo '</pre>'; array_walk($shuaige, 'test_print'); echo '用自定义函数test_print执行后的效果:'; echo '<pre>'; var_dump($shuaige); echo '</pre>'; ~~~ - 系统函数支持的版本号很重要。 - 文件包含函数。**模块化编程。** `如果被包含的 php 文件不存在:` inlcude(返回一条警告) 文件继续向下执行。通常用于动态包含 require(一个致命的错) 代码就不会继续向下执行。通常包含极为重要的文件,整个代码甭想执行 include_once(返回一条警告) 除了原有include的功能以外,它还会做once检测,如果文件曾经已经被被包含过,不再包含 require_once(一个致命的错) 除了原的功能一外,会做一次once检测,防止文件反复被包含 - 所以,少用带once的,因为它会消耗更多的资源去做检测的工作。 - include 每次都会执行,同一个文件不能被包含两次,因为函数不能定义两次,否则会报错。 - require_once:包含的文件必须存在,否则停止执行。会做重复包含检查哟。 - 数学函数。看一遍知道PHP的数学函数里面为大家准备了这么多就可。 以后需要的时候,直接来用现查。 mt_rand():更好的随机数。 - 日期常用函数。要记录数据的地方就有时间。、 >[info] 我们为什么不直接用数据库里面的时间,因为在实际开发过程中,我们需要把时间取出来再排序和显示,所以单纯的用数据库里面的时间达不到我们的业务需求。 - 时区:1884年在华盛顿召开国际经度会议时,为了克服时间上的混乱,规定将全球划分为24个时区。在中国采用首都北京所在地东八区的时间为全国统一使用时间。 - 世界时:格林尼治时间(英文简写:GMT)。各地都有各地的地方时间。如果对国际上某一重大事情,用地方时间来记录,就会感到复杂不便。而且将来日子一长容易搞错。因此,天文学家就提出一个大家都能接受且又方便的记录方法,那就是以格林尼治(英国某地区)的地方时间为标准。 - Unix 时间戳:电脑本身不认识时间,我们在电脑里面设置一个时间方便运算。于是我们规定了一种计算方式,unix时间戳。从Unix纪元(1970 年 1月1日零时)开始到一个时间经过的秒数。 - echo date_default_timezone_get(); echo date_default_timezone_set(TIMEZONE); http://php.net/manual/zh/timezones.php - time()获取当前的unix时间戳。 - date函数用于将一个时间进行格式化输出,以方便时间的显示或存储。 >[success] date 函数的格式参数表。详见原书。 - getdate获取当前系统时间。 返回值是一个根据timestamp得到的**包含时间键值信息的数组**。如果没有参数,则会返回当前的时间。 - print_r可以输出一个数组中所有的键名与值。 - 日期验证函数。checkdate可以判断一个输出的日期是否有效。在实际的工作中,我们需要经常用于检测常用于用户提交表单的数据验证。 - mktime()。生成时间戳 - 程序执行时间检测,测试某个函数效率的快慢时会用到:microtime(true)。记录开始时刻和结束时刻。 #### 数组、字符串和数据库是我们函数里面最、最、最常用的三类函数。 - 全文搜索:**“那你开始背函数吧”**。 - mb\* 和iconv\* 他们可以处理多字节字符,例如:中文。 中文主要用的是GBK和utf-8两种编码格式。 GBK和utf-8是两个不同的编码委员会对于汉字进行的编码的标准。 - 他们规定**GBK是双字节**,也就是一个汉字占用2Bytes。 - **utf-8是三字节**,一个汉字占用三个字节长度的存储空间。 - >[warning] dump = 倾倒。 - 数组。 ~~~ <?php $shu = array(1 , 1.5 , true ,'天王盖地虎,小鸡炖蘑菇'); echo '<pre>'; var_dump($shu); echo '</pre>'; ?> ~~~ - array(size = 4) 说明里面有4个元素。 0 => int 1 最前的 0 代表的是值的读取标识号,我们称之为下标或者键(英文:key)。 => 叫作:键值对应符。因此,以后再看到 0=> int 1 可以这样来说。 **下标访问符0 对应 整型的1。** >[info] 我们还称数组里面的键值对为元素,**元素是键值对的组合(而不只是值)。** - 索引数组的声明。通过 array() 函数返回数组对象。 所谓索引数组:就是下标全为整型的数组。 键值的增长规则与之前的规则一样。都是最大值加1的原则。 向索引数组中增加元素用: 数组变量名[]、数组变量名[键值]这两种方式来增加元素。 - 使用unset删除变量的方式来删除数组里面的值。 删除了中间的值,并不会让后面的下标向前自动移动。而是原来的值为多少就为多少 删除掉其中的某个值,新加入的值不会替换掉原来的位置,依然遵循最大值加1的原则。 - 索引数组的其他声明方式。 和 TCL 有异曲同工之妙。 ~~~ //直接写一个变量后面加上中括号,声明变量 $qi[] = '可口可乐'; $qi[10] ='百事'; ~~~或不使用 array() 而直接采用大括号。 - >[success] 还是统一使用 array() 的方式方法。 - 关联数组就是下标可以是字符串的数组。声明和使用方法同上。 - 数组元素的值还是数组,这是多维数组的实现方式。C语言本质也是如此。 - 读取时使用多个\[ \]。 - 数组元素间的分割符为逗号,在数组中插入数组的时候,不要在结尾处写成了分号(;)。 - 遍历二字,从字面解释就是一个接一个全读访问一次,显示出来。 ~~~ foreach( 要循环的数组变量 as [键变量 =>] 值变量){ //循环的结构体 } ~~~ - list() 函数:将索引数组下标为0的对应我变量1,下标1的对应变量2,依此类推。 **严格记住**:索引数组的一一对应原则。list第一个变量对应的是下标为0的数组元素,下标为1的对应的是list里面的第二个数组元素。 - each() 函数:读一次向后移动一次【可以想象有一个记录的箭头在移动】,将其中的每个元素拆解成一个新数组。 >[success] 拆解规则详见原书插图。 - 混合使用。遍历的代码量减少,但增加了理解成本。 - 数组操作函数。 array_shift 弹出数组中的第一个元素【shift在键盘上的图标就是一个向上的箭头】 array_unshift 在数组的开始处压入元素 array_push 向数组的末尾处压入元素 array_pop 弹出数组末尾的最后一个元素【就当成是屁从后面出来吧】 current 读出指针当前位置的值 key 读出指针当前位置的键 next 指针向下移 prev 向上移 reset 指针到开始处 end 指针到结束处 - 数组的常用函数 array_combine() 生成一个数组,用一个数组的值作为键名,另一个数组值作为值 range() 创建并返回一个包含指定范围的元素的数组。 compact() 创建一个由参数所带变量组成的数组 array_fill() 用给定的值生成数组 array_chunk() 把一个数组分割为新的数组块 array_merge() 把两个或多个数组合并为一个数组 array_slice() 在数组中根据条件取出一段值,并返回 array_diff() 返回两个数组的差集数组 array_search() 在数组中搜索给定的值,如果成功则返回相应的键名 array_splice() 把数组中的一部分去掉并用其它值取代 array_sum() 计算数组中所有值的和 in_array() 检查数组中是否存在某个值 array_key_exists() 检查给定的键名或索引是否存在于数组中 shuffle() 将数组打乱,保留键值 count() 计算数组中的单元数目或对象中的属性个数 array_flip() 返回一个键值反转后的数组 array_keys() 返回数组所有的键,组成一个数组 array_values() 返回数组中所有值,组成一个数组 array_reverse() 返回一个元素顺序相反的数组 array_count_values() 统计数组中所有的值出现的次数 array_rand() 从数组中随机抽取一个或多个元素,注意是键名 array_unique() 删除重复值,返回剩余数组 sort() 按升序对给定数组的值排序,不保留键名 rsort() 对数组逆向排序,不保留键名 asort() 对数组排序,保持索引关系 arsort() 对数组逆向排序,保持索引关系 ksort() 按键名对数组排序 krsort() 将数组按照键逆向排序 natsort() 用自然顺序算法对数组中的元素排序 natcasesort() 自然排序,不区分大小写 array_filter() 去掉数组中的空元素或者预定元素 extract 将键变为变量名,将值变为变量值 - 世界上最难懂的是道士的鬼符、医生的处方和程序员的正则表达式。 - 定界符//,就是定一个边界,边界以内的就是正则表达式。 - preg_match()。 - \d匹配一个0-9。 \D匹配一个非0-9的值。 \w匹配一个a-zA-Z0-9_。 \W匹配一个非a-zA-Z0-9_。 …… [] 指定范围 - 元字符。 \* 是代表匹配前面的一个原子,匹配0次或者任意多次前面的字符。 \+ 匹配一次或多前前面的一个字符。 ? 前面的字符可有可无【可选】 有或没有。 . 更标准一些应该把点算作原子。匹配除了\n以外的所有字符。 |(竖线)或者。注:它的优先级最低了。 ^ 必须要以抑扬符之后的字符串开始。 $ 必须要以$之前的字符结尾。 \b 词边界。 \B 非边界。 {m} 有且只能出现m次。 {n,m} 可以出现n到m次。 {m,} 至少m次,最大次数不限制。 () 改变优先级或者将某个字符串视为一个整体,匹配到的数据取出来也可以使用它。 - /正则表达式/模式匹配符 - 把正则的贪婪特性取消掉,让它找到了最近的匹配。 - 正则,**写一点、测一点。**先列出可能情况,TDD。 - 常用正则函数。`P`hp `REG`ular。 preg_filter 执行一个正则表达式搜索和替换 preg_grep 返回匹配模式的数组条目 preg_match 执行一个正则表达式匹配 preg_match_all 执行一个全局正则表达式匹配 preg_replace_callback_array 传入数组,执行一个正则表达式搜索和替换使用回调 preg_replace_callback 执行一个正则表达式搜索并且使用一个回调进行替换 preg_replace 执行一个正则表达式的搜索和替换 preg_split 通过一个正则表达式分隔字符串 - 学习文件处理本质上面就是学习文件处理的函数。 - readfile 读取文件。 file_get_contents 打开文件后,能够赋值给一个变量。 fopen、fread、fclose 操作读取文件。 file_put_contents 写入文件。 fwrite 配合 fopen 进行写入操作。fwrite的别名函数是fputs。 - tmpfile ( ) 功能:创建一个临时文件,返回资源类型。关闭文件即被删除。 ~~~ <?php //创建了一个临时文件 $handle = tmpfile(); //向里面写入了数据 $numbytes = fwrite($handle, '写入临时文件'); //关闭临时文件,文件即被删除 fclose($handle); echo '向临时文件中写入了'.$numbytes . '个字节'; ?> ~~~ - 重命名文件。bool rename($旧名,$新名); 复制文件。bool copy(源文件,目标文件); 删除文件。bool unlink(指定路径的文件); - 文件属性检测函数。 bool file_exists ( $指定文件名或者文件路径) 功能:文件是否**存在** bool is_readable ( $指定文件名或者文件路径) 功能:文件是否**可读**javascript:; bool is_writeable ( $指定文件名或者文件路径) 功能:文件是否**可写** bool is_executable ( $指定文件名或者文件路径) 功能:文件是否**可执行** bool is_file ( $指定文件名或者文件路径) 功能:是否**是文件** bool is_dir ( $指定文件名或者文件路径) 功能:是否**是目录** void clearstatcache ( void ) 功能:清楚文件的**状态缓存** - 文件操作的常量。 平台,分割符。 windows,\。 linux,/。 - 常量:DIRECTORY_SEPARATOR,\_\_FILE\_\_ - 文件指针操作函数。 rewind ( resource handle) 功能:指针回到开始处 fseek ( resource handle, int offset [, int from_where]) 功能:文件指针向后移动指定字符 - filesize 检测文件的大小。 file 把整个文件读入一个数组中。 fgets 从文件指针中读取一行,读到最后返回false。 fgetc 从文件指针中读取一个字符,读到最后返回false。 ftruncate 将文件截断到给定的长度。 - filectime 文件创建时间。 filemtime 文件修改时间。 fileatime 文件上次访问时间。 - 文件锁的用途: 若一个人在写入一个文件,另外一个人同时也打个了这个文件进行写入文件。 这情况下,如果遇到一定的碰撞概率的话,不知道到底谁的操作为准。 因此,这个时候我们引入锁机制。 若用户A在写入或者读取这个文件的时候,将文件加上共享锁。我可以读,其他人也可以读。 但是,我如果这与的时候。我使用独占锁。这个文件归我了,你们都别动,除非我将文件锁进行释放。 注意:加上了文件锁后要注意释放。 - bool flock ( resource $handle , int $operation) LOCK_SH 取得共享锁定(读取的程序) LOCK_EX 取得独占锁定(写入的程序) LOCK_UN 释放锁定(无论共享或独占) - 处理文件夹的基本思想如下: 1. 读取某个路径的时候判断是否是文件夹 2. 是文件夹的话,打开指定文件夹,返回文件目录的资源变量 3. 使用readdir读取一次目录中的文件,目录指针向后偏移一次 4. 使用readdir读取到最后,没有可读的文件返回false 5. 关闭文件目录 - opendir 打开文件夹,返回操作资源 readdir 读取文件夹资源 is_dir 判断是否是文件夹 closedir 关闭文件夹操作资源 filetype 显示是文件夹还是文件,文件显示file,文件夹显示dir - 文件权限设置 chmod 修改读取模式 chgrp 修改用户组 chown 修改权限 - 文件路径函数 pathinfo 返回文件的各个组成部分 basename 返回文件名 dirname 文件目录部分 parse_url 网址拆解成各部分 http_build_query 生成url 中的query字符串 http_build_url 生成一个url - ![](https://box.kancloud.cn/document_2015-09-09_55efe05a2efff.png =300x300) 程的项目也许用文件比较好,估计不会有那么大的订户。重复的话,可以进行文本去重。 >[warning] **文件上传的处理步骤:** > 1. 判断是否有错误码 > 2. 自定义判断是否超出文件大小范围 > 3. 判断后缀名和mime类型是否符合 > 4. 生成文件名 > 5. 判断是否是上传文件 > 6. 移动临时文件到指定位置 - php.ini 的配置项: file_uploads on为 开启文件上传功能,off为关闭。 post_max_size 系统允许的POST传参的最大值。 upload_max_filesize 系统允许的上传文件的最大值。 memory_limit 内存使用限制。 max_execution_time,上传超时参数的单位为秒。 - 系统返回的错误码详解: 0 无误,可以继续进行文件上传的后续操作。 1 超出上传文件的最大限制,upload_max_filesize = 2M php.ini中设置,一般默认为2M。可根据项目中的实际需要来修改 2 超出了指定的文件大小,根据项目的业务需求指定上传文件的大小限制 3 只有部分文件被上传 4 文件没有被上传 5 (php没有设) 6 找不到临时文件夹,可能目录不存在或没权限 7 文件写入失败,可能磁盘满了或没有权限 - MIME(Multipurpose Internet Mail Extensions)是多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。 - 文件上传用的表单。 ``` <html> <head> <meta charset="utf-8" /> <title>单文件上传</title> </head> <body> <form action="file.php" method="post" enctype="multipart/form-data"> <input type="file" name="file"> <input type="submit" value="上传"> </form> </body> </html> ``` - PHP为文件类数据准备了一个专用的系统函数$\_FILES,上传文件的所有相关数据,都保存在这个系统函数中。可以var_dump这个$\_FILES ,来观察这个数组的结构。 >'tmp_name' => string 'E:\wamp\tmp\phpC32A.tmp' (length=23) - 根据这个数组提供的相关信息对文件进行上传后的处理。 - 多个input,每个都是单文件上传 = 多文件上传。 - 从5.4开始,引入session.upload_progress的新特性,我们只需要在php.ini中开启配置,即可通过session监控文件上传进度。 --- - 学习图像处理(GD系统的函数)。需要连带GD库一起来编译 PHP。GD 库和PHP可能需要其他的库,这取决于你要处理的图像格式。 - 用 phpinfo() 查看我们当前的机器是否安装了GD扩展。存在了gd这个选项,就支持。 1.打开php.ini(在文件上传这一章已有说明) 2.在 Windows 中,需要将GD2的DLL文件php_gd2.dll作为一个扩展包含在 php.ini 中。修改;extension = php_gd2.dll,将前面的分号去掉 3.重新启动apache服务器 4.再次执行phpinfo尝试查看是否存在gd扩展 - 用图片处理函数画一张图: 1. 按照机器思维分析步骤。 - [《学完这招,你就可以开始用PPT画画了》](http://www.jianshu.com/p/99f75968e4fa) 2. 分析需要使用到的函数。 - 先把画布准备好: imagecreate() - 再准备颜料:imagecolorallocate() 3. 按步骤调用函数画图。 - allocate [ˈæləkeɪt]:把…拨给。 - 生成验证码。根据验证码的效果来推理实现的过程。 - 图像缩放和裁剪技术。(略) 图片水印处理。(略) - 在开发中,显示错误对我们的开发非常有利。因为,显示错误后能帮我们快速定位错误、解决问题。而在**生产环境(即公网)**给其他人访问的的网站、微网站、手机网站、手机接口等,如果错误显示出来了,就容易暴露: 1. 服务器的文件路径和文件存储规范 2. 有些人喜欢用个人名命名,通过社会工程学可以反向推理出密码 3. 有时还会暴露mysql数据库服务器的地址 ...... 上面这些信息特别容易被网上别有用心的一些人给利用。 - 在 php.ini 中可以控制 php 的错误显示状态:display_errors。 - ini_get() 和 ini_set() 函数。 修改完php.ini文件,需要重启服务器。 - 错误级别。 1. error 最严重,必须要解决。不然程序无法继续向下执行。 2. warning 也很重要。通常也必须要解决。如果明确的,故意的可以不用处理。 3. notice 你可以不用管。但是在有些公司,项目标准特别高。在高标准要求的项目中也必须要解决。因为,notice 会影响到 PHP 的执行效率。通常发生在函数未定义等。 4. parse 错误,是指语法写错了,必须要解决。 5. 代表全部类型的所有错误。 - 错误记录日志。 专门的日志收集系统 vs 通过文件来当服务器的运行日志。 其中:PHP 的错误、警告这些是必须要收集的。 为了不让用户看到,设置好了错误报告级别号,又如何将错误收集到日志系统中呢? - error_log() 函数可以把错误信息发送到web服务器的错误日志,或者到一个文件里。 >php.ini log_errors on/off 是否开启日志记录 log_errors_max_len 整型,默认1024 单行错误最大记录长度 error_log syslog或者指定路径 错误日志记录在什么地方 - syslog是指系统来记录。windows系统在电脑的日志收集器里面。linux默认在:/etc/syslog.conf。若Linux系统启动或修改了日志收集。可能存储在第三方专用的日志收集服务器中。 - 自定义错误处理函数。有计划开始要自己写框架时、或者您做完了本书的第一个项目,再回头来看。 - set_error_handler ( callable $回调的错误处理函数) 设置一个用户定义的错误处理函数 trigger_error ( string $error_msg) 产生一个用户级别的 error/warning/notice 信息 --- ## MySQL对于PHP程序员来说就是将业务转化成表结构。做好业务中的增、删、改、查。 - 大多数人都认为在不需要事务化处理的情况下,MySQL是管理内容最好的选择。 - 在最开始学习MySQL的时候,并不需要学习MySQL数据库,学到DBA(数据库管理员)的级别。 - [《3天入门MySQL》](http://mysql.phpxy.com/146038)。 - [sqlfiddle.com](http://www.sqlfiddle.com) 在线练习。 - 数据库的五个基本单位 1. 数据库服务器:用来运行数据库服务的一台电脑。 2. 数据库 3. 数据表 4. 数据字段,也叫数据列。 5. 数据行 - 社会工程学中,人们喜欢用相同的密码。因此,用户的密码必须要进行再次加密,不可逆向解密。因为害怕看到了某个用户的密码后,用这个密码去尝试用户的其他银行卡。 - 密码必须使用md5等加密方式帮用户进行加密。用户输入原密码如:123456。我们使用md5将用户输入的123456加密后与数据库的密码进行对比。 一致则密码通过。不一致则用户将密码输入错误了。 - 搜索 mysql **server** 下载。 1. develop 是指服务器为开发机【推荐】 2. server only只安装服务器 3. client only 只安装客户操作端 4. full 全部安装 5. custom 自定义 - Config Type(配置文件类型) 1. Development Machine 是指开发服务器 2. Server Machine 服务器 3. Dedicated Machine 专用服务器仅作为数据库服务器使用 TCP/IP 是指开放的端口:mysql 默认的端口是 3306。 - 设置 **数据库管理系统中 root 用户** 的密码,并非 linux 系统中的 root 用户密码。 - 结构化查询语言(Structured Query Language)简称SQL,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;**同时也是数据库脚本文件的扩展名**。 - SQL语句按照其功能范围不同可分为3个类别: **`结构`**:操作对象是数据库、数据表、数据字段 - 数据**定义**语言(DDL ,Data Defintion Language)语句:数据定义语句,用于定义不同的数据段、数据库、表、列、索引等。常用的语句关键字包括create、drop、alter等。 **`内容`**:操作对象是记录 - 数据**操作**语言(DML , Data Manipulation Language)语句:数据操纵语句,用于添加、删除、更新和查询数据库记录,并检查数据的完整性。常用的语句关键字主要包括insert、delete、update和select等。 **`权限`**:操作对象是用户 - 数据**控制**语言(DCL, Data Control Language)语句:数据控制语句,用于控制不同数据段直接的许可和访问级别的语句。这些语句定义了数据库、表、字段、用户的访问权限和安全级别。主要的语句关键字包括grant、revoke等。 > 这里作者没写事务操作。 - 如果加入到了windows的环境变量中,可以在命令行下直接操作。 在命令行下,通过以下命可以连接到数据库服务器: > mysql -h localhost -u root -p 上面的命令中: mysql 表示 mysql数据库启动工具。 -h 表示数据库连接地址,连接本机可不填 -u 表示要登录的用户 -p 表示使用密码登录 注:通常我们不直接输入密码。而是在回车之后,输入密码。 - 每一个命令结束可以输入\g 或者 ; - 需要帮助的话,通过 `help;` 或者 `\h` 命令来显示帮助内容。 通过 `\c` 命令来清除命令行历史。 - 操作数据库: ``` create database 数据库名; show databases; use 库名; show tables; drop database 库名; ``` - 操作数据表: ``` create table 表名(字段名1 字段类型, ...., 字段名n 字段类型n); // int 代表整型。float 代表浮点。char 和 varchar 代表字符串。 // 可以在类型后接上长度。 desc 表名; show create table 表名 \G; // 还可以看到表的 engine(存储引擎) 和 charset(字符集)等信息。 // “\G”选项的含义是使得记录能够按照字段竖着排列, // 对于内容比较长的记录更易于显示。 drop table 表名; ``` - 在创建表最后,我们常用 MyISAM 或者 InnoDB 引擎。 在指定引擎时,我们可以使用: > ENGINE=InnoDB 指定表默认字符集: > DEFAULT CHARSET=utf8 效果如下: > CREATE TABLE emp ( useraname varchar(10) DEFAULT NULL, password date DEFAULT NULL, ) **ENGINE=InnoDB** **DEFAULT CHARSET=utf8**; - 操作数据表: ``` alter table 表名 modify 字段名 varchar(20); // 修改表字段类型 modify。 alter table 表名 add column 字段名 类型; ALTER TABLE 表名 ADD 字段名 字段类型 AFTER 字段名; ALTER TABLE 表名 ADD 字段名 字段类型 FIRST; alter table 表名 drop column 字段名; alter table 表名 change 字段原名 字段新名 字段类型; ``` 字段 增加 和 修改 语句(add/change/modify)中,最后都可以加一个可选项 **first** | **after**。 ``` alter table 旧表名 rename 新的表名; ``` - 数据类型。 1. 数值类型(整型、浮点) 2. 字符串类型 3. 日期时间类型 4. 复合类型 5. 空间类型(非科学性工作基本不用,不做讲解) - 整型。 tinyint 1字节 -128~127 smallint 2字节 -32768~32767 mediumint 3字节 -8388608~8388607 **int 4字节 范围-2147483648~2147483647 // 正负21亿** bigint 8字节 +-9.22*10的18次方 - 浮点类型。 **float(m, d) 4字节 单精度浮点型,m总个数,d小数位** double(m, d) 8字节 双精度浮点型,m总个数,d小数位 decimal(m, d) decimal是存储为字符串的浮点数 - 字符类型。 **CHAR 0-255字节 定长字符串** **VARCHAR 0-255字节 变长字符串** TINYBLOB 0-255字节 不超过255个字符的二进制字符串 TINYTEXT 0-255字节 短文本字符串 >[info] BLOB 0-65535字节 **二进制形式**的长文本数据 TEXT 0-65535字节 长文本数据 MEDIUMBLOB 0-16 777 215字节 二进制形式的中等长度文本数据 MEDIUMTEXT 0-16 777 215字节 中等长度文本数据 LOGNGBLOB 0-4 294 967 295字节 二进制形式的极大文本数据 LONGTEXT 0-4 294 967 295字节 极大文本数据 VARBINARY(M) 允许长度0-M个字节的定长字节符串 值的长度+1个字节 BINARY(M) M 允许长度0-M个字节的定长字节符串 - CHAR 类型用于定长字符串,并且必须在圆括号内用一个**大小修饰符**来定义。这个大小修饰符的范围从 0-255。比指定长度大的值将被截短,而比指定长度小的值将会用空格作填补。VARCHAR 类型把该长度视为最大值并且只使用存储字符串实际需要的长度,类型不会被空格填补,但长于该指示器的值仍然会被截短。 因 VARCHAR 类型可以根据实际内容动态改变存储值的长度,所以在不能确定字段需要多少字符时使用 VARCHAR 类型可以大大地节约磁盘空间。 - text类型与blob类型。 对于字段长度要求超过 255 个的情况下,MySQL 提供了 TEXT 和 BLOB 两种类型。根据存储数据的大小,它们都有不同的子类型。 这些大型的数据用于存储文本块或图像、声音文件等二进制数据类型。 BLOB 类型区分大小写(**因为是二进制**),而 TEXT 不区分大小写。 - **大小修饰符**不用于各种 BLOB 和 TEXT 子类型。 - blob = binary large object = 二进制大对象。 - 时间类型。 date 3字节 日期,格式:2014-09-18 time 3字节 时间,格式:08:42:30 datetime 8字节 日期时间,格式:2014-09-18 08:42:30 timestamp 4字节 自动存储记录修改的时间 year 1字节 年份 >[success] 时间类型在web系统中用的比较少,很多时候很多人喜欢**使用int来存储时间。插入时插入的是unix时间戳**,因为这种方式更方便计算。在前端业务中用date类型的函数,再将unix时间戳转成人们可识别的时间。有些人**为了在数据库管理中方便查看,也有人使用datetime类型**来存储时间。 - 复合类型。