最早接触PHP就是看高洛峰的视频,坦白的说他第一套视频录得并不算好,有些冗长,晚上看会有催眠的效果,但那是在当时能找到关于PHP最好的视频。很遗憾虽然通过这套视频了解了PHP基础知识,但受限于当时对于编程的理解,始终没能做到有所突破,离专业程序员还有相当大的差距。这次决定通过书本来重新梳理一遍,期待能有所突破,因《细说PHP》第三版要到暑假后才会出,所以买了精要版来进行学习。
第一个示例文件:
<html> <head> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <title>第一个PHP程序(获取服务器信息)</title> </head> <body> <?php $sysos = $_SERVER["SERVER_SOFTWARE"]; $phpversion = PHP_VERSION; //连接数据库并获取MySQL版本 mysql_connect("localhost","root",""); $mysqlinfo = mysql_get_server_info(); //获取GD库的信息 if(function_exists("gd_info")){ $gd = gd_info(); $gdinfo = $gd["GD Version"]; }else{ $gdinfo = "未知"; } //查看GD库是否支持FreeType字体 $freetype = $gd["FreeType Support"] ? "支持" : "不支持" ; $allowurl = ini_get("allow_url_fopen") ? "支持" : "不支持" ; $max_upload = ini_get("file_uploads") ? ini_get("upload_max_filesize") : "Disabled"; $max_ex_time = ini_get("max_execution_time")."秒"; date_default_timezone_set("Etc/GMT-8"); $systemtime = date("Y-m-d H:i:s", time()); echo "<table align=center cellspacing=0 cellpadding=0>"; echo "<caption><h2>系统信息</h2></caption>"; echo "<tr><td>Web服务器:</td><td>$sysos</td></tr>"; echo "<tr><td>PHP版本:</td><td>$phpversion</td></tr>"; echo "<tr><td>MySQL版本:</td><td>$mysqlinfo</td></tr>"; echo "<tr><td>GD库版本:</td><td>$gdinfo</td></tr>"; echo "<tr><td>FileType:</td><td>$freetype</td></tr>"; echo "<tr><td>远程文件获取:</td><td>$allowurl</td></tr>"; echo "<tr><td>最大上传限制:</td><td>$max_upload</td></tr>"; echo "<tr><td>最大执行时间:</td><td>$max_ex_time</td></tr>"; echo "<tr><td>服务器时间:</td><td>$systemtime</td></tr>"; echo "</table>"; ?> </body> </html>
第二天
如同任何一门编程语言一样,首先复习的自然还是基础语法结构,对于PHP而言代码以<?开启,以?>关闭(非强制性要求),变量以$开头。然后自然少不了数据类型,有布尔型、整型、浮点型和字符串四种标量类型,数组和对象两种复合类型以及资源和NULL两种特殊类型。PHP是弱类型语言,因而无需像JAVA等语言那样要求先声明数据类型。
对应于变量的还有常量,通常采用大写字母来进行命名,常量多用于配置文件,如数据库用户名、密码等则可以通过常量写入配置文件,方便程序中各处调用,这样修改后其它代码均无需修改,且由于其是常量,不会担心别人在代码中对其重新赋值。
运行在计算机上的程序自然少不了计算的功能,对于不同运算则需采用不同运算符,像最基础的算术运算符+,-,*,/,%,++,–,字符串运算符点.,对应的赋值运算符有+=,-=,*=,/=,%=,.=,此外还有比较运算符、逻辑运算符、位运算符等。
第三天
程序中另一个基础的内容就是流程控制,if…elseif…elseif条件分支语句,另一种分支语句switch
switch(expr){ case 1: expr 1; break; case 2: expr 2; break; ... default: expr; }
另一种则是循环语句,有while(){}循环,与之对应至少执行一次的do{}while();循环,还有应用更为广泛的for(;;){}循环。
此外还有一些流程控制语句如break退出循环,值得一提的是break 1退出一层循环,break 2退出两重循环,所以在break后添加数字可以退出一重或多重循环。cotninue语句则用于跳过某一次循环,接着执行下面的循环,exit()和die()可以退出当前脚本。
第四天
函数是一个被命名的、独立的代码段,它执行特定的任务,并可能给调用 它的程序返回一个值。
function 函数名([参数1, 参数2, ... 参数n]) { 函数休; return 返回值; }
定义函数时函数名后面括号内的表达式称为形式参数(”形参“),而调用函数时后面括号中的表达式称为实际参数(“实参”)。使用global关键字或超全局变量$GLOBALS[]来调用函数外声明的变量或进行重新赋值。在定义函数时对形参赋初值则形成了带有默认参数的函数,在调用时可不传参数值或仅传入部分值,在实参少于形参时,靠右边的形参不会被传值。
而要定义可变个数参数的函数则需要借助于函数func_get_args(),示例如下
function more_args(){ $args = func_get_args(); for($i=0; $i<func_num_args(); $i++){ //或count($args) echo "第{$i}个参数是:".$args[$i]."<br />"; } }
require()和include()语句性能相似,都是包含并运行指定文件。不同之处在于,对include()语句来说,在执行文件时每次都要进行读取和评估,而对require()语句文件只处理了一次。所以需多次执行代码,require()效率比较高,而每次执行代码时如读取不同的文件,则使用Include()语句。
第五天
数组根据索引下标为数字和字符串划分为索引数组和关联数组。调试数组时可通过print_r()和var_dump()打印出下标和值,声明数组可以通过$arr[“key”] = “value”的方式,也可以通过
$arr = array( key1 => value1, key2 => value2 …);
的方式。
遍历数组:for()循环的方式进行遍历,但这仅限于索引数组且下标为连续数字的数组;另一种更为常用的方式是用foreach()来对数组进行遍历,不仅适用于索引数据还适用于关联数组。
foreach($array as $value){ 循环体; } foreach($array as $key => $value){ 循环体; }
PHP中有一套预定义数组,叫做全局变量或超全局变量,如$_SERVER, $_ENV, $_GET, $_POST, $_REQUEST, $_FILES, $_COOKIE, $_SESSION, $GLOBALS
第六天
面向对象(Object Oriented Programming , OOP)。对象需要对类进行实例化,声明一个类需通过关键字class来进行(成员属性,成员方法),示例如下
class SimpleClass { // property declaration public $var = 'a default value'; // method declaration public function displayVar() { echo $this->var; } }
通关键字new来实例化一个类,如$obj = new class(),访问类中的成中属性或成员方法则通过->符号,如$obj->name,引用对象内的成员属性或方法使用$this,如$this->name。
构造方法:对象创建后第一个自动调用的方法__construct(),析构方法:对象销毁前最后调用的方法__destruct(),
封装性
在类中成员属性或方法前添加private关键字可限制外部的访问,默认为public(成员属性前未
添加public, private时应使用var)。
魔术方法:除__construct(),__desctruct()外,还有__set(), __get(), __isset(), __unset()
继承性
PHP中通过关键字extends一个类可以继承另一个类,不同于C++,PHP仅支持单继承。
访问控制修饰符public公有的,private私有的,protected受保护的
PHP中不能定义第一名的函数,所以不能进行重载,但子类中的方法可以和父类同名,也便实现了重载。使用”parent::方法名“可在子类中重载的同时使用父类中其要覆盖的方法。
常见关键字和魔术方法:final标识的类不能被继承,final标识的成员方法不能被覆盖;static可将类中的成员属性和成员方法标识为静态的,可通过类名::静态成员属性名,类名::静态成员方法名()来进行调用,在类中可使用self::::静态成员属性名,self::静态成员方法名()进行调用,此外静态方法中只能访问静态成员;类中的常量不能使用define()函数定义,而要使用关键字const,访问方法和静态成员属性相同;clone用来克隆对象,如$obj2 = clone $obj1,克隆时需对成员属性重新赋值时可在类中声明一个魔术方法__clone();通过在类中声明魔术方法__toString(),则可直接通过echo加对象名输出类中所返回的字符串;在类中声明魔术方法__call()来自定义调用不存在方法时的提示信息,同时不会退出程序而将继续向下执行;__autoload()魔术方法用于自动包含满足指定条件的文件。
第七天
使用大括号的方法可以像访问数组那样访问字符串中指定位置的字符,如访问字符串最后一个字符$str{strlen(str)-1}
字符串输出函数echo(), print(), die(), printf(), sprintf()
第八天
正则表达式通过特定规则配合函数实现对字符串的匹配、查找、替换和分割等操作。
在正则表达式模式或部分模式两边添加括号()可将匹配内容存储到临时缓冲区区,依次通过\\1, \\2…来进行调用,若不想保存相关匹配,可在括号内添加非捕获元字符?:, ?=, ?!忽略保存相关匹配。
正则表达式相关函数:
int preg_match ( string pattern , string subject [, array matches])
int preg_match_all ( string pattern , string subject , array matches [, int flags])
array preg_grep ( string $pattern , array $input)
strstr(), strpos(), strrpos(), substr(), str_replace(),preg_split(),explode(),implode()
mixed preg_replace ( mixed pattern , mixed replacement , mixed subject [, int limit])
第九天
使用clearstatcache()函数可清除被PHP缓存的文件信息。UNIX系统使用正斜线/作为路径分隔符,Windows中默认使用反斜线\作为分隔符,在程序中需要使用\用进行转义,Windows也支持使用正斜线/作为路径分隔符。PHP中内置了常量DIRECTORY_SEPARATOR来表示不同操作系统中的默认文件路径分隔符。与路径相关的函数有basename(),dirname(),pathinfo()。目录相关的函数有opendir(),readdir(),closedir(),rewinddir()。复制、删除非空目录需要自定义函数来进行操作,以下为复制目录的示例代码:
function copyDir($dirSrc, $dirTo){ if(is_file($dirTo)){ echo "目标不是目录不能创建!!"; return; } if(!file_exists($dirTo)){ mkdir($dirTo); } if($dir_handle = @opendir($dirSrc)){ while($filename = readdir($dir_handle)){ if($filename != "." && $filename != ".."){ $subSrcFile = $dirSrc."/".$filename; $subToFile = $dirTo."/".$filename; if(is_dir($subSrcFile)) copyDir($subSrcFile, $subToFile); if(is_file($subSrcFile)) copy($subSrcFile, $subToFile); } } closedir($dir_handle); } } copyDir("phpMyAdmin", "D:/admin");
操作文件的相关函数
fopen(), fclose(), fwrite()/fputs(),file_put_contents(), feof(), ftell(), fseek(), rewind(), flock(), copy(), unlink(), ftruncate(), rename()
读取文件内容的相关函数
文件上传在form表单中通过method=”post”指明发送数据的方法,enctype=”multipart/form-data”来指定表单编码数据方式 ,另外在form表单中可以添加一个类型为hidden的input,name设置为MAX_FILE_UPLOAD,用value来限制所上传文件的大小,当然这个值不能大于php.ini中的upload_max_filesize。PHP为上传文件专门提供了另外两个函数is_uploaded_file()和move_uploaded_file(),处理单个文件上传的示例脚本代码如下:
<?php header("content-type:text/html; charset:utf-8"); error_reporting(E_ALL & ~(E_STRICT | E_NOTICE)); $allowtype = array("gif", "png", "jpg"); $size = 1000000; $path = "./uploads"; if($_FILES['myfile']['error']>0){ echo "上传错误"; switch($_FILES['myfile']['error']){ case 1: die('上传文件大小超出了PHP配置文件中的约定值:upload_max_filesize'); case 2: die('上传文件大小超出了表单中的约定值:MAX_FILE_SIZE'); case 3: die('文件只被部分上传'); case 4: die('没有上传任何文件'); default: die('未知错误'); } } $hz = array_pop(explode(".",$_FILES['myfile']['name'])); if(!in_array($hz,$allowtype)){ die("这个后缀名{$hz}不是允许上传的文件类型!"); } if($_FILES['myfile']['size']>$size){ die("超过允许的<b>{$size}</b>字节大小!"); } $filename = date("YmdHis").rand(100,999).".".$hz; if(is_uploaded_file($_FILES['myfile']['tmp_name'])){ if(!move_uploaded_file($_FILES['myfile']['tmp_name'], $path.'/'.$filename)){ die("问题:不能将文件移动到指定目录。"); } }else{ die("问题:上传文件{$_FILES['myfile']['name']}不是一个合法文件!"); } echo "文件{$_FILES['myfile']['name']}上传成功,保存在目录{$path}中,大小为{$_FILES['myfile']['size']}字节";
如果上传多个文件,可在表单中设置name=”myfile[]”,$_FILES[‘myfile’][‘name’]二维数组将会变为三维数组$_FILES[‘myfile’][‘name’][n]
第十天 – PHP动态图像处理
PHP中通过使用GD扩展库实现对图像的处理,创建图像主要有4个步骤:创建画布、绘制图像、输出图像和释放资源。
创建画布:imagecreate(), imagecreatetruecolor()前者支持256色,后者支持真彩色,但不能用于GIF文件格式,可通过imagesx()和imagesy()函数来获取图像的大小,如果画布引用句柄不再使用,则需通过imagedestroy()来进行销毁。
设置颜色:通过imagecolorallocate()函数即可设置图像中的颜色,其后三个参数分别代表RGB,可以是0到255的整数,也可以是十六进制的0x00到0xFF,如果使用Imagecreate()创建画布,第一次调用此函数将会作为背景色进行填充。
生成图像:通过imagegif(), imagejpeg(), imagepng(), imagewbmp()函数可分别生成对应格式的图像,在输出前还要通过header()头信息来通知浏览器使用用正确的MIME类型来接收,如header(“Content-Type: image/gif”)。
绘制图像:绘制图像的函数有图形区域填充函数imagefill(), 绘制点和线的函数imagesetpixel()和imageline(), 绘制矩形函数imagerectangle()和imagefilledrectangle(), 绘制多边形函数imagepolygon()和imagefilledpolygon(), 绘制椭圆函数imageellipse(()和imagefilledellipse(), 绘制弧线函数imagearc()和imagefilledarc()。
绘制文字:通过函数imagestring(), imagestringup(), imagechar(), imagecharup(), imagettftext()来实现图像中文字的绘制,后者按坐标从左下角开始绘制,而其它的则是从左上角开始绘制 ,关于中文字符可通过iconv()或mb_convert_encoding()进行转码,但在新版本中似乎无需进行转码即可直接输出。
从现有图片创建画布资源:imagecreatefromjpeg(), imagecreatefrompng(), imagecreatefrompng(), 获取图像宽高和类型使用函数 getimagesize()
图片缩放和图片裁剪函数:imagecopyresized(), imagecopyresampled(), 后者处理后质量会更好些。为图片添加水印的函数imagecopy(), 图片旋转函数imagerotate(), 水平翻转代码示例如下,进行垂直翻转时只需对代码进行微调
function turn_y($filename){ $back = imagecreatefromjpeg($filename); $width = imagesx($back); $height = imagesy($back); $new = imagecreatetruecolor($width, $height); for($x=0; $x<$width; $x++){ imagecopy($new, $back, $width-$x-1, 0, $x, 0, 1, $height); } imagejpeg($new, $filename); imagedestroy($back); imagedestroy($new); }
第十一天 – MySQL数据库
SQL语言包含四个部分:数据定义语言(DDL)如CREATE, DROP, ALTER, 数据操作语言(DML)如INSERT, UPDATE, DELETE, 数据查询语言(DQL)如SELECT, 数据控制语言(DCL)如GRANT, REVOKE, COMMIT, ROLLBACK。
添加列:ALTER TABLE 表名 ADD 字段名 <建表语句> [FIRST|AFTER 列名]
修改列:ALTER TABLE 表名 CHANGE(MODIFY) 列名 <建表语句>
数据表重命名:ALTER TABLE 旧表名 RENAME AS 新表名
字符集相关:配置文件中character_set_server, collation_server等,客户端查看SHOW VARIABLES LIKE ‘character%’; 创建数据表时可在最后添加类似DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci的语句来进行设置。
索引相关:主键索引(PRIMARY KEY), 唯一索引(UNIQUE), 常规索引(INDEX|KEY)和全文索引(FULLTEXT)
PDO(PHP Data Object) Window下通过php.ini中extension=php_pdo_mysql.dll进行支持。连接数据库创建PDO对象:
try{ $dbh = new PDO('mysql:dbname=testdb;host=localhost','user','pwd'); }catch(PDOException $e){ echo '数据库连接失败:'.$e->getMessage(); exit; }
常用的一些方法:PDO::exec(), PDo::query(),预处理PDO::prepare(),绑定参数bindParam(),绑定后执行execute(),获取数据fetch()和fetchAll()。
第十二天 – 会话控制
bool setcookie ( string $name [, string $value [, int $expire = 0 [, string $path [, string $domain [, bool $secure = false [, bool $httponly = false ]]]]]] )
会话的声明通过session_start()开启会话和$_SESSION全局数组赋值,这样就会将对应的值保存到php,ini中通过session.save_path指定的路径下,通过session_destroy()可以销毁当前会话,要删除SESSION,可通过$_SESSION=array()将其赋值为空数组,或unset()来删除特定变量,此外要彻底注销一个session,还应将cookie中对应的session id删除,所以删除一个session应有以下几步
session_start(); //$_SESSION['username']="Alan"; $_SESSION = array(); if(isset($_COOKIE[session_name()])){ setcookie(session_name(),'',time()-3600,'/'); } session_destroy();
第十三天 – PHP模板引擎Smarty
在http://www.smarty.net/download选择Smarty的对应版本(这里选用3.*.*)然后到Github去进行下载,解压出libs文件夹即可,使用时通过require()语句加载该文件夹中的Smarty.class.php类文件即可以进行使用了。通过$smarty = new Smarty()即可对该类进行实例化。
根据书的建议在libs所在的同一级目录中新建一个Init.inc.php文件来设置上述的成员属性以供其它php脚本文件包含
define("ROOT",str_replace("\\","/",dirname(__FILE__)).'/'); //指定项目的根目录 require ROOT.'libs/Smarty.class.php'; //加载Smarty类文件 $smarty = new Smarty(); //实例化Smarty类 $smarty->setTemplateDir(ROOT.'templates/') //设置模板文件存放路径 //->addTemplateDir(ROOT.'templatess/') //添加多个模板目录 ->setCompileDir(ROOT.'templates_c') //设置编译后文件存放路径 ->setPluginsDir(ROOT.'plugins/') //设置插件存放路径 ->setCacheDir(ROOT.'cache/') //设置缓存存放路径 ->setConfigDir(ROOT.'configs/'); //设置模板配置文件存放路径 $smarty->caching = false; //Smarty缓存开关 $smarty->cache_lifetime = 60*60*24; //缓存有效期 $smarty->left_delimiter = '<{'; //模板语言左起始符 $smarty->right_delimiter = '}>'; //模板语言右结束符
通过assign()方法赋值,display()方法输出,Smarty中可通过{*comment*}的方式来添加评论并且不会在前端页面输出