PHP是一门弱类型的语言,和之前学习的C/C++相比还是有很大的出入,不过就像老师常说的编程思想都是相通的。
这里主要想总结下过去两周学习PHP遇到的各种陷阱,欢迎拍砖~
一、基础概念
a.在PHP中函数名、类名、系统关键字都对大小写不敏感,而自定义变量名是对大小写敏感的。
b.弱类型语言的一个表现就是在定义变量的时候不需要指定变量类型,变量会在首次赋值的时候创建,PHP根据变量的值确定变量的类型
c.作用域问题:
1、PHP全局变量默认在局部函数不可见,这和C/C++是完全两码事。局部函数使用全局变量必须global声明。或者通过放置全局变量的超全局数组访问变量:
- <?php
- $val = "global";
- function func1()
- {
- $val = "I am func1";
- }
- function func2()
- {
- global $val;
- $val = "I am func2";
- }
- function func3()
- {
- $GLOBALS['val']="I am func3";
- }
- func1();
- //输出global
- echo $val."\n";
- func2();
- //输出"I am func2"
- echo $val."\n";
- func3();
- //输出"I am func3"
- echo $val."\n";
d.文件包含
PHP提供了四个文件包含相关的操作:require/require_once/include/include_once。区别如下
1.require/require_once在文件不存在的时候脚本错误停止运行,include/include_once在被包含脚本不存在的时候提示一个错误并继续运行
2.require_once/include_once只有在文件没有被包含的情况下才包含它,这样做可以防止类和方法的重定义。
3.开发过程中require_once运用的相对比较多一些
e.文件查找
PHP可以使用require/inclue包含相对路径下的文件,解析器在指定路径下没有找到文件的情况下会去include_path路径下去找,可以通过php.ini文件来配置。或者调用set_include_path(get_include_path(), ":/home/xxx"),添加一个路径。当然这只对当前执行有效。
二、数据获取
HTTP协议 HTTP协议规定的 HTTP 请求方法有 OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT 这几种。其中 POST 一般用来向服务端提交数据,其中 POST 一般用来向服务端提交数据, PHP内置全局数组$_POST是通过 HTTP POST传递到当前脚本的变量数组。$_GET 是通过 URL 参数传递到当前脚本的变量数组。
通过GET方法发送的消息全部人都可见,信息量也有限制,2000个字符。POST传递信息其他人不可见,POST还可以支持高阶功能如:multi part二进制传输等。总的来说还是POST用的比较多。
三、参数检测
参数检测当然是进入函数模块执行的第一步,PHP提供了丰富的参数检测函数,陷阱也是很多。
1.基本类型检测
获取/设置类型:gettype/settype, 传入变量的同时需要传入类型对应的字符串标示,不过官方不推荐这组函数。
is_xxx:判断变量是否为某类型
defined() - 检查某个名称的常量是否存在
2.数组相关类型检测
PHP数组键限定为integer/string类型,其实PHP并不区分索引数组和关联数组,可以认为索引数组的键就是索引。
检测键是否存在:array_key_exists();(还可用于检测对象属性是否存在)
检测值是否存在:in_array();
在使用数组的过程中需要注意的是:如果对给出的值没有指定键名,则取当前最大的整数索引值,而新的键名将是该值加一。如果指定的键名已经有了值,则该值会被覆盖。对于可以转换为整数的字符串会被转换为整数键。要修改某个值,通过其键名给该单元赋一个新值。要删除某键值对,对其调用 unset() 函数。
在对数组排序过程中,对于非数字索引的数组才ksort/asort/uksort/uasort才会有效;
each — 返回数组中当前的键/值对并将数组指针向前移动一步 。
next/...等函数返回的是数组值。
我们常定义一个空数组在需要的时候对其添加参数:
- $arr = array()
- if(xxx)
- {
- $arr[] = $elem;
- }
- else
- {
- .....
- }
3.类相关的检测
判断属性是否存在:property_exists(),
判断方法是否存在:method_exists(),
判断对象是否是某一类的实例:( $obj) instanceof (class name)
获取对象类名:get_class($obj)
判断类是否存在:class_exists()
获取对象的方法:get_class_methods(class_name, $obj)。(只有public会显示出来)。
检测方法是否存在:
a.in_array($method, get_class_methods(xx))
b.is_callable()(判断是否可以调用)
c.method_exists()(对于private/public/protected的方法都返回true)
值得一提的是,PHP提供了一套拦截器,在访问对象不存在的属性或方法的时候拦截器自动被促发。__get/__set/__call/__isset/__unset
几个函数的实现大致如下:
- class test
- {
- function __get($property)
- {
- $method = "get$property";
- if(method_exists($this, $method))
- {
- return $this->$method();
- }
- }
- function __set($property, $value)
- {
- $method= "set$property";
- if(method_exists($this, $method))
- {
- return $this->$method($value);
- }
- }
4.isset和empty的区别联系:
a.ISSET为false的情况有:1.定义一个变量没有给他赋值、2.把变量设置为null、3对变量执行了unset操作.
b.empty为true的清空有:1.变量值为0、2.空字符串、3.“0”/0、4.null
四、其他
1、PHP 5 引入了析构函数的概念,这类似于其它面向对象的语言,如 C++。析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。unset操作一个对象时相当于解除一个引用(引用计数器减一)
2、父类的构造/析构函数不会被引擎暗中调用。要执行父类的构造/析构函数,必须在子类的析构函数体中显式调用 parent::__destruct()。此外也和构造函数一样,子类如果自己没有定义析构函数则会继承父类。派生类没有构造函数,实例化对象的时候会默认调用父类的构造函数。
3、常量属性只包含基本数据类型-不需要美元符号,只能通过类访问,而不是对象。(这点和C++一样)
4、static延迟静态绑定:static指的是被调用的类而不是被包含的类。(适合在工厂方法构建不同派生对象的时候使用)。
5、PHP只支持单一继承(extends),但是同时可以继承多个接口(implements),同时出现的时候extends必须在前。
6、self关键字只查找本类,parent关键字只查找父类,static关键字先查找本类再查找父类(延迟静态绑定)。