最近看了PHP编程动物书,在此记录下1-6章内容要点。
1.PHP介绍
* PHP可以做服务端编程、命令行编程(写脚本)、客户端图形界面
* PHP使用GD扩展处理图像
* PHP配置文件php.ini文档:https://php.net/manual/zh/configuration.file.php
* PHP关键字(关键字不区分大小写):
1. __CLASS__、__DIR__、__FILE__、__FUNCTION__、__LINE__、__METHOD__、__TRAIT__、__holt_compiler()__
2. and、array、as、echo、enddeclare、endfor、endforeach、endif、endswitch、endwhile、eval、exit、interface、insteadof、list、or、print、callable、instanceof、trait、var、xor
* PHP内置函数
2.PHP数据类型
* 数据类型
1. PHP数据类型共八种:四种标量型(整型、浮点型、字符串、布尔型),两种复合型(数组、对象),两种特殊类型(资源、NULL)
2. 整型范围通常是:-2^31 ~ 2^31-1 (4字节)
3. 浮点型和C语音双精度浮点型范围一样,通常是:1.7E-308 ~ 1.7E+308之间(8字节),精确到15位数字
4. 如果需要更高精度或更宽范围,可以使用BC或GM扩展
5. 浮点值只是数的近似表示,例如在许多系统中,3.5实际上表示未3.49999...。这意味着写代码的时候要尽量避免假定浮点数是准确的,例如直接使用==比较两个浮点数,一般的方法是比较前几位:
if (intval($a*10000) == intval($b)*10000) { ... }
6. 变量在双引号中会被解析,在单引号中不解析
7. 转义符号在双引号中可以解析,单引号中只有和‘会解析
8. PHP中以下值的计算结果为false:
false、0、0.0、空字符串和字符串‘0‘、空数组、空对象、null值。
一个值不是真的就是假的,包括所有资源类型的值(所以可以用if直接判断)
9. 数组分为普通数组和关联数组,遍历数组方法很多,最常用的是foreach
10. 资源:数据库连接、文件连接都是资源,is_resource()判断一个变量是否是资源
11. 回调(callable):一些函数被另一些函数调用,如call_user_func()。回调函数可以通过函数声明和闭包方式创建。
12. NULL,不区分大小写,表示变量没有值,可以通过is_null()判断是否为null。
* 变量
1. 变量以$开头,$$表示变量的变量:
$foo = "bar"; $$foo = "aaa"; echo $bar; //打印"aaa"
2. 变量的引用:引用是变量的别名,和原变量指向相同的变量地址,销毁(unset)其中一个不影响另一个的值。函数可以通过&引用返回值(可以避免大字符串和数组的拷贝)
function &retRef() { $var = "php";return $var; } $v = &retRef(); // 函数声明和调用的时候都需要带上引用符号&
3. PHP变量有四种作用域:全局、局部、静态、和函数参数
与其它语言不同,PHP只能在函数中提供局部作用域(只有在函数中声明的变量才是局部变量),不能在循环、嵌套、条件分支或其它块类型中创建局部变量。函数参数局部有效。
在函数中可以使用全局变量相同名称的局部变量,可以按如下方式使用全局变量:
$aaa = "bbb"; function print_aaa() { global $aaa; // 用global声明变量为全局变量 print($aaa); print($GLOBALS[‘aaa‘]); // 或者访问$GLOBALS数组 }
* 垃圾收集
PHP使用引用计数和写时复制来管理内存。PHP中,符号表将变量名映射到内存中变量地址,当一个变量赋值到另一个变量时,PHP不会复制值使用更多的内存,只是更改符号表说明另一个变量指向同样的变量地址,并且使变量的引用计数加1。此时,修改其中一个变量的值,PHP会分配一块内存来保存值,并且把原变量地址引用计数减1。引用计数就是指向一个变量地址的变量数目,当引用计数值为0时,变量内存地址被释放。
* 表达式和操作符
1. clone/new(创建新对象)
2. ~(按位取反)、<<(左移)、>>(右移)
3. !=/<>(不等于)、===(类型和值都相等)、!==(类型或值不等)、&(按位与)、^(按位异或)、|(按位或)
4. +=、*=、/=、%=、&=、|=、~=、^=、<<=、>>=、.=
5. and(&&)、or(||)、xor(异或)、!(非),PS:优先级与比或高
* 隐式转换
需要的数据类型与实际数据类型不符时,会对实际类型进行隐式类型转换
1. 字符串与数字算术操作时会转为数字。字符串转数字必须在字符串开头有数字,如果数字中有.或e/E会转为浮点数,否则转为0。
2. 字符串连接操作,会把数字转为字符串。
3. 比较操作符会根据操作类型按照数字大小或字典序进行比较。需要注意的是,如果两个字符串都是数字,会当作数字进行比较。*PS:字典序指的是ASCLL序,数字<大写字母<小写字母。*
4. 位操作符使用时,会用操作数的二进制形式进行操作,返回值与操作数类型一致。对字符串二进制进行操作,结果返回字符串,如~返回对字符串每一位取反后对应的字符串,&返回字符串长度与较短的字符串相同,|返回的字符串与较长的字符串相同。
5. <<、>>操作数不是整数会先转为整数,左移N位相当于乘以2^N ,移位时最右边用0补充,右移操作类似,最左边用0补充。
* 显示类型转换(强制类型转换)
1. (object)转为对象、(array)转为数组、(unset)转为NULL。
2. 类型转换只会影响其他操作符解析变量的方式,不会改变变量本身的值。不是所有转换都可以正常进行,把数组转为整数类型会变成1,转成字符串类型会变为"Array"。
3. 对象转为数组,会建立一个对象公开属性的关联数组。数组转为对象则相反(不合法的属性名,不能访问到)
* 其它操作符
1.@ //屏蔽操作
2.`...` //执行shell命令,并返回输出结果,如:```echo `ls /tmp`;```
3.instanceof //对象类型测试
4.insteadof //用于指定trait
5.break
break可以指定跳出的层数,所以可以从内层退出外层循环
while (true) { while (true) { break 2; //跳出2层循环 } }
break跳出本层循环,continue跳过本次循环,跳到下一次循环条件判断
6.可以使用do...while保证循环至少执行一次
7.require加载一个文件不存在时会产生致命错误,脚本停止执行,include产生一个警告,脚本不停止执行。所以用include包含一些html页头页脚,require包含一些库文件。
8.exit退出程序,脚本停止执行,die是exit的别名
3.函数
* 函数参数传递方式
1.按值传递和按引用传递,大多数情况按值传递,对大字符串、数组、对象,按值传递是一个昂贵的操作。
2.参数按引用传递时,传递的是实际值而不是值的拷贝,函数内部可以直接修改变量值。
3.数组做函数参数默认按值传递,对象做参数默认按引用传递?
* 函数参数
1.函数可以有多个带默认值的参数,但必须放在不带默认值参数后面。
2.PHP函数可以使用可变参数,声明方式是不带任何参数。
function varParamFunc() { //可变参数函数 }
3.可以使用func_get_args()、func_num_args()、func_get_arg()获取函数参数信息(可变参数只能通过这种方式获取参数值)。
4.调用参数时,遗漏参数会报一个warning,遗漏的参数会设置为NULL在函数中运行,多余参数则会忽略没有提示。
* 类型提示
定义函数时,可以限制参数类型为NULL、类或类的子类、数组或回调,调用时必须按指定类型传参,不然会报可捕获的致命错误。
* 返回引用
1.函数声明时必须要显示声明返回引用,调用时也必须在函数前加&。
2.这个技术有时被用于高效从函数中返回大字符串和数组,然而PHP的写时复制通常意味着很多时候返回引用是不必要的,返回引用比返回值慢。
* 可变函数
$func_name(); //调用名为$func_name()值的函数
* 匿名函数(也称为闭包)
//usort参数可以是callable类型(闭包)usort($array, function($a, $b) use ($sortOption) { ... } );
4.字符串
* 定义
1.双引号和heredoc定义的字符串可以解析变量,为了将变量与字符串分隔开,可以使用大括号{}。
2.单引号定义的变量,可以生效的转义字符只有和‘。
3.printf() //字符串格式化输出 sprintf() //字符串格式化返回
4.调试时使用echo、print、print_r、var_dump(echo是语言结构,其他是函数)
5.访问字符串单个字符:$string{$i} //$i是字符串偏移量
*编码和转义
- HTML:htmlentities()、htmlspecialchars() //html特殊字符转为html实体。strip_tags() //删除html标签 ,get_meta_tags() //提取元标签
- URL:有两种方式对url进行编码,区别在于如何处理空格。rawurlencode() rawurldecode() //空格->%20,urlencode() urldecode() //空格->+ PS:使用这些函数应该只编码域名后边的部分,不然域名中的:与/也会被编码。
- SQL:查询条件中需要对字符进行转义,转义方法很简单,就是在单引号、双引号、空字符和反斜杠前面加一个反斜杠。addslashes() //添加反斜杠 stripslashes() //删除反斜线
*字符串比较
1.==、===、>、<、>=、<=
2.按字典序排序:strcmp、strcasecmp;按自然序(字母和数字分开排序)排序:strnatcmp、strnatcasecmp 。
自然排序:pic1.jpg pic5.jpg pic10.jpg pic50.jpg
字典排序(按ASCLL码排序):pic1.jpg pic10.jpg pic5.jpg pic50.jpg
* 字符串截取与分割
substr //取字串 substr_replace //替换字串 sscanf($string, $template) //按模板分解字符串
parse_url() //解析url
正则表达式:使用正则表达式是处理字符串匹配和分割的一种思路,比如解析某种格式的日志,但比较复杂,用到的时候再研究下。
$string="FredtFlineStone(35)"; $a = sscanf($string, "%st%s(%d)"); print_r($a); //=>Array(0=>Fred,1=>FlintStone,2=>35)
5.数组
* PHP内部将所有数组都存储为关联数组
* count()、sizeof()、range(2,5)、range(5,2)、range(‘a‘,‘z‘)
* array本身实现了list与hashmap的功能,此外使用array可以实现集合交集并集差集,队列,堆栈等功能
6.对象
*用变量值作为标识符(变量名、类名、函数名等)
$object = new Person; // 等同于 $class = "Person"; $object = new $class; $account = new Account(); $object = "account"; ${$object}->init(5000, 100);
*对象引用
对象一旦被创建,就会通过引用传递,不会复制整个对象(既耗时又耗内存)
* 浅拷贝对象,可以使用clone
$p = new Person(); $p2 = clone $p;
当使用clone时,如果对象的类定义中有一个名为__clone()的方法,这个类方法可以在对象被复制后立即被调用(clone的钩子函数)。当一个对象带有外部资源(如文件句柄、数据库连接)时,可以使用这个功能来建立新的连接,而不是复制已有的连接(可以使用此功能实现深拷贝)。
*类
1.PHP类名区分大小写
类和方法可访问性默认都是public,声明属性时必须加上public等访问标识符。
2.访问父类中被重写的方法
parent::method_name();
3.判断一个对象是否属于某个类
if ($obj instanceof Class) {...}
* 特征trait
在不需要创建父类的情况下,复用类外部的代码。
trait Logger { public log($logString) { $class_name = __CLASS__; echo date(‘Y-m-d H:i:s‘.":[$class_name] [$log_string]" ); } } class User { use Logger; public $name; function __construct($name=‘‘) { $this->name = $name; $this->log("create user $name"); } } trait First { function doFirst() { ... } } trait Second { function doSecnod() { ... } } trait All { use First, Second; function doAll() { $this->doFirst(); $this->doSecond(); } } class Combined { use All; } $obj = new Combined(); $obj->doAll();
use多个trait方法名冲突时,可以指定使用哪个trait的方法,或给方法起别名。
class Person { use Command,Marathon { Command::run as runCommand; Marathon::run insteadof Command; } } $p = new Person(); $p->run(); //Marathon run $p->runCommand(); //Command run
* 自省introspection(相当于Java中的反射)
class_exists() //判断类是否存在 get_declared_classes() //获取已声明的类列表 get_class_methods() //获取类方法名列表 get_class_vars() //获取类属性数组
* 对象检验
is_object() //判断是否为对象 get_class() //得到类名 method_exists() //判断是否存在某方法 get_object_vars() //获取对象属性关联数组 get_parent_class() //获取父类名
* 对象序列化
将对象转换为字节流以方便存储和传输。
$bytes = serialize($obj); //序列化 $obj = unserialize($bytes); //反序列化
序列化可用在session存储上。在序列化和反序列化过程中,PHP有两个用于对象的钩子函数(hook)__sleep()和__wakeup()。序列化之前被调用的__sleep,它能执行一些清理工作,如关闭数据库连接,输出未保存的持久化数据,该方法返回写入字节流的数据成员的名称数组,如果返回空数组,说明没有任何数据写入字节流。反序列化之后被调用的是__wakeup(),它可以执行一些初始化操作,如重建数据库连接或打开文件等。
这个代码块删不掉。。。