原文:http://www.imooc.com/learn/26 判断函数是否存在 当我们创建了自定义函数,并且了解了可变函数的用法,为了确保程序调用的函数是存在的,经常会先使用function_exists判断一下函数是否存在。同样的method_exists可以用来检测类的方法是否存在。 类是
原文:http://www.imooc.com/learn/26
判断函数是否存在
当我们创建了自定义函数,并且了解了可变函数的用法,为了确保程序调用的函数是存在的,经常会先使用function_exists判断一下函数是否存在。同样的method_exists可以用来检测类的方法是否存在。
类是否定义可以使用class_exists。
PHP中有很多这类的检查方法,例如文件是否存在file_exists等。
类的属性及方法
在类中定义的变量称之为属性,类中定义的函数为方法
访问控制的关键字代表的意义为:
public:公开的
protected:受保护的
private:私有的
构造函数和析构函数
PHP5可以在类中使用__construct()定义一个构造函数,具有构造函数的类,会在每次对象创建的时候调用该函数,因此常用来在对象创建的时候进行一些初始化工作。
在子类中如果定义了__construct则不会调用父类的__construct,如果需要同时调用父类的构造函数,需要使用parent::__construct()显式的调用。
同样,PHP5支持析构函数,使用__destruct()进行定义,析构函数指的是当某个对象的所有引用被删除,或者对象被显式的销毁时会执行的函数。
当PHP代码执行完毕以后,会自动回收与销毁对象,因此一般情况下不需要显式的去销毁对象。
访问控制
前面的小节,我们已经接触过访问控制了,访问控制通过关键字public,protected和private来实现。被定义为公有的类成员可以在任何地方被访问。被定义为受保护的类成员则可以被其自身以及其子类和父类访问。被定义为私有的类成员则只能被其定义所在的 类访问。
类属性必须定义为公有、受保护、私有之一。为兼容PHP5以前的版本,如果采用 var 定义,则被视为公有。
类中的方法可以被定义为公有、私有或受保护。如果没有设置这些关键字,则该方法默认为公有。
如果构造函数定义成了私有方法,则不允许直接实例化对象了,这时候一般通过静态方法进行实例化,在设计模式中会经常使用这样的方法来控制对象的创建,比如单例模式只允许有一个全局唯一的对象。
Static静态关键字
静态属性与方法可以在不实例化类的情况下调用,直接使用类名::方法名的方式进行调用。静态属性不允许对象使用->操作符调用。
静态方法也可以通过变量来进行动态调用
静态方法中,$this伪变量不允许使用。可以使用self,parent,static在内部调用静态方法与属性。
对象继承
继承是面向对象程序设计中常用的一个特性,汽车是一个比较大的类,我们也可以称之为基类,除此之外,汽车还分为卡车、轿车、东风、宝马等,因为这些子类具有很多相同的属性和方法,可以采用继承汽车类来共享这些属性与方法,实现代码的复用。
当扩展一个类的时候,子类会继承父类所有的protected与public的属性与方法,子类也可以覆盖父类相应的方法。
重载
PHP中的重载指的是动态的创建属性与方法,是通过魔术方法来实现的。属性的重载通过__set,__get,__isset,__unset来分别实现对不存在属性的赋值、读取、判断属性是否设置、销毁属性。
方法的重载通过__call来实现,当调用不存在的方法的时候,将会转为参数调用__call方法,当调用不存在的静态方法时会使用__callStatic重载。
对象的高级特性
对象比较,当同一个类的两个实例的所有属性都相等时,可以使用比较运算符==进行判断,当需要判断两个变量是否为同一个对象的引用时,可以使用全等运算符===进行判断。
对象复制,在一些特殊情况下,可以通过关键字clone来复制一个对象,这时__clone方法会被调用,通过这个魔术方法来设置属性的值。
对象序列化,可以通过serialize方法将对象序列化为字符串,用于存储或者传递数据,然后在需要的时候通过unserialize将字符串反序列化成对象进行使用。
字符串介绍
获取字符串的长度
字符串的截取
英文字符截取:
substr(字符串变量,开始截取的位置,截取个数)
中文字符串截取:
mb_substr(字符串变量,开始截取的位置,截取个数,网页编码)
正则表达式
正则表达式的基本语法
PCRE库函数中,正则匹配模式使用分隔符与元字符组成,分隔符可以是非数字、非反斜线、非空格的任意字符。经常使用的分隔符是正斜线(/)、hash符号(#)以及取反符号(~),例如:
/foobar/
#^[^0-9]$#
~php~
如果模式中包含分隔符,则分隔符需要使用反斜杠(\)进行转义。
/http:\/\//
如果模式中包含较多的分割字符,建议更换其他的字符作为分隔符,也可以采用preg_quote进行转义。
分隔符后面可以使用模式修饰符,模式修饰符包括:i,m, s, x等,例如使用i修饰符可以忽略大小写匹配:
元字符与转义
正则表达式中具有特殊含义的字符称之为元字符,常用的元字符有:
\ 一般用于转义字符
^断言目标的开始位置(或在多行模式下是行首)
$断言目标的结束位置(或在多行模式下是行尾)
. 匹配除换行符外的任何字符(默认)
[ 开始字符类定义
] 结束字符类定义
| 开始一个可选分支
( 子组的开始标记
) 子组的结束标记
? 作为量词,表示 0 次或 1次匹配。位于量词后面用于改变量词的贪婪特性。 (查阅量词)
* 量词,0 次或多次匹配
+ 量词,1 次或多次匹配
{ 自定义量词开始标记
} 自定义量词结束标记
元字符具有两种使用场景,一种是可以在任何地方都能使用,另一种是只能在方括号内使用,在方括号内使用的有:
\ 转义字符
^仅在作为第一个字符(方括号内)时,表明字符类取反
- 标记字符范围
其中^在反括号外面,表示断言目标的开始位置,但在方括号内部则代表字符类取反,方括号内的减号-可以标记字符范围,例如0-9表示0到9之间的所有数字。
贪婪模式与懒惰模式
正则表达式中每个元字符匹配一个字符,当使用+之后将会变的贪婪,它将匹配尽可能多的字符,但使用问号?字符时,它将尽可能少的匹配字符,既是懒惰模式。
贪婪模式:在可匹配与可不匹配的时候,优先匹配
懒惰模式:在可匹配与可不匹配的时候,优先不匹配
当我们确切的知道所匹配的字符长度的时候,可以使用{}指定匹配字符数
使用正则表达式进行匹配
使用正则表达式的目的是为了实现比字符串处理函数更加灵活的处理方式,因此跟字符串处理函数一样,其主要用来判断子字符串是否存在、字符串替换、分割字符串、获取模式子串等。
PHP使用PCRE库函数来进行正则处理,通过设定好模式,然后调用相关的处理函数来取得匹配结果。
preg_match用来执行一个匹配,可以简单的用来判断模式是否匹配成功,或者取得一个匹配结果,他的返回值是匹配成功的次数0或者1,在匹配到1次以后就会停止搜索
上面的代码简单的执行了一个匹配,简单的判断def是否能匹配成功,但是正则表达式的强大的地方是进行模式匹配,因此更多的时候,会使用模式:
查找所有匹配结果
preg_match只能匹配一次结果,但很多时候我们需要匹配所有的结果,preg_match_all可以循环获取一个列表的匹配结果数组。
可以使用preg_match_all匹配一个表格中的数据:
正则表达式的搜索和替换
正则表达式的搜索与替换在某些方面具有重要用途,比如调整目标字符串的格式,改变目标字符串中匹配字符串的顺序等。
例如我们可以简单的调整字符串的日期格式:
其中${1}与$1的写法是等效的,表示第一个匹配的字串,$2代表第二个匹配的。
通过复杂的模式,我们可以更加精确的替换目标字符串的内容。
用正则替换来去掉多余的空格与字符:
正则匹配常用案例
cookie简介
Cookie是存储在客户端浏览器中的数据,我们通过Cookie来跟踪与存储用户数据。一般情况下,Cookie通过HTTP headers从服务端返回到客户端。多数web程序都支持Cookie的操作,因为Cookie是存在于HTTP的标头之中,所以必须在其他信息输出以前进行设置,类似于header函数的使用限制。
PHP通过setcookie函数进行Cookie的设置,任何从浏览器发回的Cookie,PHP都会自动的将他存储在$_COOKIE的全局变量之中,因此我们可以通过$_COOKIE['key']的形式来读取某个Cookie值。
PHP中的Cookie具有非常广泛的使用,经常用来存储用户的登录信息,购物车等,且在使用会话Session时通常使用Cookie来存储会话id来识别用户,Cookie具备有效期,当有效期结束之后,Cookie会自动的从客户端删除。同时为了进行安全控制,Cookie还可以设置域跟路径
PHP设置Cookie最常用的方法就是使用setcookie函数,setcookie具有7个可选参数,我们常用到的为前5个:
name( Cookie名)可以通过$_COOKIE['name']进行访问
value(Cookie的值)
expire(过期时间)Unix时间戳格式,默认为0,表示浏览器关闭即失效
path(有效路径)如果路径设置为'/',则整个网站都有效
domain(有效域)默认整个域名都有效,如果设置了'www.imooc.com',则只在www子域中有效
PHP中还有一个设置Cookie的函数setrawcookie,setrawcookie跟setcookie基本一样,唯一的不同就是value值不会自动的进行urlencode,因此在需要的时候要手动的进行urlencode。
setrawcookie('cookie_name',rawurlencode($value), time()+60*60*24*365);
因为Cookie是通过HTTP标头进行设置的,所以也可以直接使用header方法进行设置。
header("Set-Cookie:cookie_name=value");
cookie的删除与过期时间
通过前面的章节,我们了解了设置cookie的函数,但是我们却发现php中没有删除Cookie的函数,在PHP中删除cookie也是采用setcookie函数来实现。
setcookie('test', '',time()-1);
可以看到将cookie的过期时间设置到当前时间之前,则该cookie会自动失效,也就达到了删除cookie的目的。之所以这么设计是因为cookie是通过HTTP的标头来传递的,客户端根据服务端返回的Set-Cookie段来进行cookie的设置,如果删除cookie需要使用新的Del-Cookie来实现,则HTTP头就会变得复杂,实际上仅通过Set-Cookie就可以简单明了的实现Cookie的设置、更新与删除。
了解原理以后,我们也可以直接通过header来删除cookie。
header("Set-Cookie:test=1393832059;expires=".gmdate('D, d M Y H:i:s \G\M\T', time()-1));
这里用到了gmdate,用来生成格林威治标准时间,以便排除时差的影响。
cookie的有效路径
cookie中的路径用来控制设置的cookie在哪个路径下有效,默认为'/',在所有路径下都有,当设定了其他路径之后,则只在设定的路径以及子路径下有效,例如:
setcookie('test',time(), 0, '/path');
上面的设置会使test在/path以及子路径/path/abc下都有效,但是在根目录下就读取不到test的cookie值。
一般情况下,大多是使用所有路径的,只有在极少数有特殊需求的时候,会设置路径,这种情况下只在指定的路径中才会传递cookie值,可以节省数据的传输,增强安全性以及提高性能。
当我们设置了有效路径的时候,不在当前路径的时候则看不到当前cookie。
setcookie('test','1',0, '/path');
var_dump($_COOKIE['test']);
session与cookie的异同
cookie将数据存储在客户端,建立起用户与服务器之间的联系,通常可以解决很多问题,但是cookie仍然具有一些局限:
cookie相对不是太安全,容易被盗用导致cookie欺骗
单个cookie的值最大只能存储4k
每次请求都要进行网络传输,占用带宽
session是将用户的会话数据存储在服务端,没有大小限制,通过一个session_id进行用户识别,PHP默认情况下sessionid是通过cookie来保存的,因此从某种程度上来说,seesion依赖于cookie。但这不是绝对的,sessionid也可以通过参数来实现,只要能将session id传递到服务端进行识别的机制都可以使用session。
使用session
在PHP中使用session非常简单,先执行session_start方法开启session,然后通过全局变量$_SESSION进行session的读写。
session会自动的对要设置的值进行encode与decode,因此session可以支持任意数据类型,包括数据与对象等。
默认情况下,session是以文件形式存储在服务器上的,因此当一个页面开启了session之后,会独占这个session文件,这样会导致当前用户的其他并发访问无法执行而等待。可以采用缓存或者数据库的形式存储来解决这个问题,这个我们会在一些高级的课程中讲到。
删除与销毁session
删除某个session值可以使用PHP的unset函数,删除后就会从全局变量$_SESSION中去除,无法访问。
如果要删除所有的session,可以使用session_destroy函数销毁当前session,session_destroy会删除所有数据,但是session_id仍然存在。
值得注意的是,session_destroy并不会立即的销毁全局变量$_SESSION中的值,只有当下次再访问的时候,$_SESSION才为空,因此如果需要立即销毁$_SESSION,可以使用unset函数。
如果需要同时销毁cookie中的session_id,通常在用户退出的时候可能会用到,则还需要显式的调用setcookie方法删除session_id的cookie值。
使用session来存储用户的登录信息
session可以用来存储多种类型的数据,因此具有很多的用途,常用来存储用户的登录信息,购物车数据,或者一些临时使用的暂存数据等。
用户在登录成功以后,通常可以将用户的信息存储在session中,一般的会单独的将一些重要的字段单独存储,然后所有的用户信息独立存储。
一般来说,登录信息既可以存储在sessioin中,也可以存储在cookie中,他们之间的差别在于session可以方便的存取多种数据类型,而cookie只支持字符串类型,同时对于一些安全性比较高的数据,cookie需要进行格式化与加密存储,而session存储在服务端则安全性较高。
读取文件内容
判断文件是否存在
一般情况下在对文件进行操作的时候需要先判断文件是否存在,PHP中常用来判断文件存在的函数有两个is_file与file_exists.
如果只是判断文件存在,使用file_exists就行,file_exists不仅可以判断文件是否存在,同时也可以判断目录是否存在,从函数名可以看出,is_file是确切的判断给定的路径是否是一个文件。
更加精确的可以使用is_readable与is_writeable在文件是否存在的基础上,判断文件是否可读与可写。
删除文件
跟Unix系统命令类似,PHP使用unlink函数进行文件删除。
删除文件夹使用rmdir函数,文件夹必须为空,如果不为空或者没有权限则会提示失败。
取得文件的大小
通过filesize函数可以取得文件的大小,文件大小是以字节数表示的。
如果要转换文件大小的单位,可以自己定义函数来实现。
值得注意的是,没法通过简单的函数来取得目录的大小,目录的大小是该目录下所有子目录以及文件大小的总和,因此需要通过递归的方法来循环计算目录的大小。
取得文件的修改时间
写入内容到文件
上例中,$data参数可以是一个一维数组,当$data是数组的时候,会自动的将数组连接起来,相当于$data=implode('',$data);
取得当前的Unix时间戳timestamp
取得当前的日期
取得日期的Unix时间戳
PHP提供了内置函数strtotime实现功能:获取某个日期的时间戳,或获取某个时间的时间戳。
将格式化的日期字符串转换为Unix时间戳
strtotime函数预期接受一个包含美国英语日期格式的字符串并尝试将其解析为Unix 时间戳。
格式化格林威治(GMT)标准时间
gmdate 函数能格式化一个GMT的日期和时间,返回的是格林威治标准时(GMT)。
GD库简介
GD指的是GraphicDevice,PHP的GD库是用来处理图形的扩展库,通过GD库提供的一系列API,可以对图像进行处理或者直接生成新的图片。
PHP除了能进行文本处理以外,通过GD库,可以对JPG、PNG、GIF、SWF等图片进行处理。GD库常用在图片加水印,验证码生成等方面。
绘制线条
在图像中绘制文字
使用imagestring函数来进行文字的绘制,这个函数的参数很多:imagestring( resource $image , int $font , int $x , int $y , string $s , int $col),可以通过$font来设置字体的大小,x,y设置文字显示的位置,$s是要绘制的文字,$col是文字的颜色。
输出图像文件
使用imagepng可以将图像保存成png格式,如果要保存成其他格式需要使用不同的函数,使用imagejpeg将图片保存成jpeg格式,imagegif将图片保存成gif格式,需要说明的是,imagejpeg会对图片进行压缩,因此还可以设置一个质量参数。
生成图像验证码
给图片添加水印
抛出一个异常
从PHP5开始,PHP支持异常处理,异常处理是面向对象一个重要特性,PHP代码中的异常通过throw抛出,异常抛出之后,后面的代码将不会再被执行。
异常处理类
PHP具有很多异常处理类,其中Exception是所有异常处理的基类。
Exception具有几个基本属性与方法,其中包括了:
message 异常消息内容
code 异常代码
file 抛出异常的文件名
line 抛出异常在该文件的行数
其中常用的方法有:
getTrace 获取异常追踪信息
getTraceAsString获取异常追踪信息的字符串
getMessage 获取出错信息
如果必要的话,可以通过继承Exception类来建立自定义的异常处理类。
捕获异常信息
这里我们只是通过案例来了解trycatch的机制以及异常捕获的方法,在实际应用中,不会轻易的抛出异常,只有在极端情况或者非常重要的情况下,才会抛出异常,抛出异常,可以保障程序的正确性与安全,避免导致不可预知的bug。
获取错误发生的所在行
在异常被捕获之后,我们可以通过异常处理对象获取其中的异常信息,前面我们已经了解捕获方式,以及获取基本的错误信息。
在实际应用中,我们通常会获取足够多的异常信息,然后写入到错误日志中。
通过我们需要将报错的文件名、行号、错误信息、异常追踪信息等记录到日志中,以便调试与修复问题。
PHP支持哪些数据库
PHP通过安装相应的扩展来实现数据库操作,现代应用程序的设计离不开数据库的应用,当前主流的数据库有MsSQL,MySQL,Sybase,Db2,Oracle,PostgreSQL,Access等,这些数据库PHP都能够安装扩展来支持,一般情况下常说的LAMP架构指的是:Linux、Apache、Mysql、PHP,因此Mysql数据库在PHP中的应用非常广泛,我们会在本章中简单的了解Mysql的操作方法。
数据库扩展
PHP中一个数据库可能有一个或者多个扩展,其中既有官方的,也有第三方提供的。像Mysql常用的扩展有原生的mysql库,也可以使用增强版的mysqli扩展,还可以使用PDO进行连接与操作。
不同的扩展提供基本相近的操作方法,不同的是可能具备一些新特性,以及操作性能可能会有所不同。
插入新数据到MySQL中
在mysql中,执行插入语句以后,可以得到自增的主键id,通过PHP的mysql_insert_id函数可以获取该id。
取得数据查询结果
查询分页数据
通过mysql的limit可以很容易的实现分页,limitm,n表示从m行后取n行数据,在PHP中我们需要构造m与n来实现获取某一页的所有数据。
在上面的例子中,我们使用了$m与$n变量来表示偏移量与每页数据条数,但我们推荐使用更有意义的变量名来表示,比如$pagesize,$start, $offset等,这样更容易理解,有助于团队协作开发。
更新与删除数据
数据的更新与删除相对比较简单,只需要构建好相应的sql语句,然后调用mysql_query执行就能完成相应的更新与删除操作。
对于删除与更新操作,可以通过mysql_affected_rows函数来获取更新过的数据行数,如果数据没有变化,则结果为0。
关闭MySQL连接
当数据库操作完成以后,可以使用mysql_close关闭数据库连接,默认的,当PHP执行完毕以后,会自动的关闭数据库连接。
mysql_close();
虽然PHP会自动关闭数据库连接,一般情况下已经满足需求,但是在对性能要求比较高的情况下,可以在进行完数据库操作之后尽快关闭数据库连接,以节省资源,提高性能。
在存在多个数据库连接的情况下,可以设定连接资源参数来关闭指定的数据库连接。
$link =mysql_connect($host, $user, $pass);
mysql_close($link);