PHP想入门? 看这个就够了

PHP 进阶整理

本文将介绍PHP的一些较重要的内容。
包括:
面向对象编程、正则表达式、
程序错误处理、XML、
AJAX、图像处理、MySQL数据库、
开发模式。

一、面向对象的PHP编程


和其他面向对象语言差不多,有区别的地方会指出,其他简要介绍一下。

注:
构造函数:function __construct();
析构函数:function __destruct();
有默认的set和get方法
指向父类:parent::
指向子类:self::

//类
<?php
class Person
{
      private $name;
      //构造函数
      function __construct(){
              $name = "MrLiuQ";
      }
      //析构函数
      function __destruct(){
              echo "析构函数被调用";
      }
      public function set_name($name){
              $this->name = $name;
      }
      public function get_name(){
              echo "My name is ".$this->name."<br/>";
      }
}

//继承
class Worker extends Person
{
      private $salary;
      //构造函数
      function __construct(){
              $salary = 5000;
      }
      //析构函数
      function __destruct(){
              echo "析构函数被调用";
      }
      public function set_salary($salary){
              $this->salary = $salary;
      }
      public function get_salary(){
              return $this->salary;
      }
}

$boy = new Person;
$boy->set_name("Harry Pottor");
$boy->get_name();

$girl = new Person;
$girl->set_name("Emma");
$girl->get_name();

$a_work = new worker;
$a_work->set_name('Paul');
$a_work->set_salary(3500);

$name = $a_work->get_name();
$salary = $a_work->get_salary();
echo $name."的月薪为".$salary;
?>

<?php
class Counter
{
      private static $count = 0;    //静态成员变量
      
      function __construct(){    //构造函数
            echo "计数开始";      
      }
      function __destruct(){      //析构函数
            echo "计数结束";
      }
      
      static function get_count(){    //静态成员函数
            return self::$count;
      }
      
      static function counts(){
            self::$count++;      //注意这里静态成员变量的使用方法,加self::
      }
}

$c = new Counter();
$i = 0;

while($i<5){
Counter::counts();    //通过限定Count::直接调用静态函数counts(),并没有使用对象$c来调用。
      $i = Counter::get_count();
      echo Counter::get_count()."<br/><br/>";
}
?>

相关函数:

__construct():构造函数
__destruct():析构函数
__get():用到不存在属性时,系统默认调用
__set():当设置不存在属性时,系统默认调用
__call():访问一个不存在的方法时,默认调用
__toString():将一个对象转换成字符串
__clone():克隆一个对象时使用。
克隆:PHP默认通过引用传递对象。使用$obj2 = $obj1两对象是关联的,如果不希望产生关联,就使用clone,克隆一个新的对象。

二、正则表达式:Regular expression


定义:是负责对字符串做解析对比,从而分析出字符串的构成,以便进一步对字符串做相关的处理。

注:正则表达式允许用户通过使用某种特殊字符构建匹配模式,然后把匹配模式与文件中的数据、程序输入或者Web页面的表单输入等目标对象进行比较,根据这些输入中是否包含匹配模式,来执行相应的程序。

1.正则表达式的语法:

元字符:
^ :匹配指定字符串开头的字符串
$ :匹配指定字符串结尾的字符串
. :匹配除\n之外的任何单个字符,代替任何字符
[] :匹配指定范围内的单个字符,代替指定字符
| :在多项之间选择一个进行匹配
\ :转义字符
() :标记子表达式的开始和结束位置
* :匹配其左边的子表达式0次或多次
+ :匹配其左边的子表达式1次或多次
? :匹配其左边的子表达式0次或1次

限定符:
{n}:表示匹配该限定符左边字符n次
{n,}:表示匹配该限定符左边至少n次
{n,m}:表示匹配该限定符左边至少n次,最多m次

转义字符:
\n :一个换行符。等价于\x0a和\cJ
\r :一个回车符。等价于\x0d和\cM
\s :任何空白字符,包括空格、制表符、换页符等。等价于[\f\n\r\t\v]
\S :任何非空白字符。等价于[^\f\n\r\t\v]
\t :一个制表符。等价于\x09和\cI
\v :一个垂直制表符。等价于\x0b和\cK
\f :一个换页符。等价于\x0c和\cL
\cx :由x指明的控制字符。

字符类:
[[:alpha:]] :匹配任何字母
[[:digit:]] :匹配任何数字
[[:alnum:]] :匹配任何字母和数字
[[:space:]] :匹配任何空白字符
[[:upper:]] :匹配任何大写字母
[[:lower:]] :匹配任何小写字母
[[:punct:]] :匹配任何标点符号
[[:xdigit:]] :匹配任何16进制数字,相当于[0-9a-fA-F]
[[:blank:]] :匹配空格和Tab,等价于[\t]
[[:cntrl:]] :匹配所有ASCII 0到31之间的控制符
[[:graph:]] :匹配所有的可打印字符,等价于[^ \t\n\r\f\v]
[[:print:]] :匹配所有的可打印字符和空格,等价于[^\t\n\r\f\v]

反义:
\W :匹配任意不是字母,数字,下划线或汉子的字符
\S :匹配任意不是空白符的字符
\D :匹配任意非数字的字符
\B :匹配不是单词开头或结束的位置

//模式:举例

^once  //匹配给定模式开头的字符串

PHP$   //匹配给定模式结尾的字符串 

^Python$  //精确定位:指定字符串

b.s   //这个单词可以是bes、bis、bos....

b[eiou]s //这个单词只匹配 bes、bis、bos、bus

b(a|e|i|o|oo)s  //这个单词匹配bas、bes、bis、bos、boos

pe* //匹配perl、peel、pet、port...

co+  //匹配come、code、cool、co...

a{3}  //匹配aaa、cacaaad、aacoaaao...

a{3,}  //匹配aaa、aaab、caaaaa...

a{1,3}b  //匹配ab、aab、aaab...

ab*  //和ab{0,}同义,a、ab、abb...

ab+  //和ab{1,}同义,ab、abb...

ab?  //和ab{0,1}同义,a、ab

a?b+$  //匹配ab、abb...

a(bc)*  //匹配a、abc、abcbc...

[ab]  //与a|b同义,匹配a、b

[a-d]  //与a|b|c|d及[abcd]同义,匹配a、b、c、d。

^[a-zA-Z_]$  //匹配所有的只有字母和下划线的字符串。如果不加^和$,凡是含有字母和下划线的字符都会被匹配。

^[a-zA-Z0-9_]{1,}$  //匹配所有包含一个以上的字母、数字或下划线的字符串。

^[0-9]{1,}$  //匹配所有正数

^\-{0,1}[0-9]{1,}$  //匹配所有的整数

^\-{0,1}[0-9]{0,}\.{0,1}[0-9]{0,}$  //匹配所有小数

PHP有两大类函数支持正则表达式,
一类是POSIX扩展函数(PHP5.2之后弃用),
另一类是Perl兼容的正则表达式函数(PHP4.0后支持)。

2.POSIX扩展正则表达式函数(PHP5后弃用):

ereg() :字符串的正则匹配函数
ereg_replace() :区分大小写的正则表达式替换
eregi() :不区分大小写的正则表达式匹配
eregi_replace() :不区分大小写的正则表达式替换
split() :用正则表达式将字符串分割到数组中
spliti() :用正则表达式不区分字母大小写将字符串分割到数组中
sql_regcase() :产生用于不区分大小的正则表达式

//正则表达式匹配函数
int ereg(string $pattern, string $string [, array &regs]);  //区分大小写
int eregi(string $pattern, string $string [, array &regs]);  //不区分大小写

<?php
$arr_date = array(
'2008-06-01',
'1997-06-25',
'1996-11-29',
'2005-0x-10',
'12-12-12',
'2012-12-25 00:10:20'
);

for ($i=0; $i<5; ++$i){
      $date = $arr_date[$i];
      if(ereg("([0-9]){4})-([0-9]{1,2})-([0-9]{1,2})", $date , $regs)){
              echo "日期字符串$date 符合'YYYY-MM-DD'格式:";
              echo "$regs[1].$regs[2].$regs[3]<br/><br/>";
      }else{
              echo "<b>日期字符串$date 不符合'YYYY-MM-DD'格式</b><br/><br/>";
      }
}
?>

//替换匹配字符串的函数
string ereg_replace(string $pattern, string $replacement, string $string);  //区分大小写
string eregi_replace(string $pattern, string $replacement, string $string);  //不区分大小写

<?php
$str = "You have a car , I have a Car , We have cARs!"  //源字符串
echo "<b>替换前字符串为:</b><br/>";
echo $str;
echo "<br/>";
echo "<br/>";

$pattern = "car";    //匹配字符串
$replacement = "Apple";   //替换后字符串
$str_rpc = eregi_replace($pattern,$replacement,$str);
echo "<b>替换后字符串为:</b><br/>";
echo $str_rpc;
?>

//根据正则表达式分割字符串函数
array split(string $pattern, string $string [, int $limit]);

<?php
$str = "aaa~bbb~ccc~ddd";  //定义字符串变量
echo "字符串截取前:$str";
echo "<br/>";
echo "<br/>";

$sep_arr = split("~",$str);
echo "<b>字符串截取后:</b><br/>";  //分割字符串变量$str
echo "<pre>";

print_r($str_arr);
?>

//生成正则表达式的函数
string sql_regcase(string $string);   //不区分大小正则表达式

<?php
$str = "K#V3050"
echo "<b>原字符串:</b><br/>$str";    //定义字符串变量
echo "<br/>";
echo "<br/>";

$reg_str = sql_regcase($str);
echo "<b>生成的正则表达式为:</b><br/>";  //生成正则表达式
echo $reg_str;
?>

3.PERL兼容正则表达式函数(PHP4后支持,重点):

PERL兼容正则表达式使用修正符,
所谓修正符,是指正则表达式最后的补充说明。
另外,
PERL兼容正则表达式中所有的模式前后都需要加/

修正符
i :匹配时忽略大小写
m :除了匹配^$整个字符串开头和结尾,还匹配其中的换行符(\n)的之后和之前
s :使原点字符(.)匹配任意一个字符同时也匹配换行符
x :模式中的空白字符除了被转义的或在字符类中的以外完全被忽略
e :preg_replace()在替换字符串中对逆向引用作正常的替换,将其作为PHP代码求值,并用其结果来替换所搜索的字符串

A :模式被强制为“anchored”,即强制仅从目标字符串的开头开始匹配
D :模式中的行结束($)仅匹配目标字符串的结尾,否则包含换行符
S :为加速匹配而对其进行分析,分析一个模式仅对没有单一固定其实字符的nonanchored模式有用
U :使“?”的默认匹配成为贪婪状态
X :一个反斜线后面跟一个没有特殊意义的字母被当成该字母本身
u :模式字符串被当成UTF-8

preg_grep() :返回与模式匹配的数组单元的正则表达式函数
preg_match() :进行正则表达式匹配的函数
preg_match_all() :进行全局正则表达式匹配的函数
preg_replace() :执行正则表达式的搜索和替换的函数
preg_split() :用正则表达式分割字符串的函数

//返回与模式匹配的数组单元的正则表达式函数
array preg_grep(string $pattern, array $input [, int $flag]);

<?php
$test_preg = array(
"AK47",
"163.com",
"happy new year",
"EX0000",
"007 in USA",
"abc123",
"TEST-abc-315",
"123654789",
"Euapa00!"
);

echo "<b>原数组:</b>";
echo "<pre>";
print_r($test_preg);
echo "</pre>";

$preg_arr = preg_grep("/^[A-Z].*[0-9]$/",$test_preg);  //正则表达式
echo "<br>";
echo "<b>将原数组中以任意大写字母开头的、中间任意个字符、最后以数字结尾的字符串找出:</b>";
echo "<pre>";
print_r($preg_arr);  //输出匹配的元素
echo "</pre>";
?>


//进行正则表达式匹配的函数
int preg_match(string $pattern , string $subject [, arrayy $matches [, int $flag]]);

<?php
$str_arr = array(
"PHP 是优秀的Web脚本语言",
"Perl的文本处理功能很强大"
);

foreach($str_arr as $str){
      //使用了修正符
      if(preg_match("/php/i",$str)){
            echo "在字符串'$str'中找到对'php'的匹配";
            echo "<br/>";
            echo "<br/>";
      }else{
             echo "在字符串'$str'中<b>未</b>找到对'php'的匹配";
            echo "<br/>";
            echo "<br/>";           
      }
}
?>


//进行全局正则表达式匹配的函数
int preg_match_all (string $pattern, string $subject, array $matches [,int $flag]);

<?php
$html = "<b>粗体字符</b><a href=index.html>可点击的连接</a>";

preg_match_all("/(<([\w]+)[^>]*>)(.*)(<\/\\2>)/", $html , $matches);

for ($i=0;$i<count($matches[0]);$i++){
      echo "匹配:".$matches[0][$i]."\n";
      echo "第一部分:".$matches[1][$i]."\n";
      echo "第二部分:".$matches[2][$i]."\n";
      echo "第三部分:".$matches[3][$i]."\n\n";
}
?>

//执行正则表达式的搜索和替换的函数
mixed preg_replace(mixed $pattern,mixed $replacement,mixed $subject [, int $limit]);

<?php
$string = "The quick brown fox jumped over the lazy dog.";  
echo "原字符串:<br/>";
echo $string;
echo "<br/><br/>";

$patterns[0] = "/quick/";
$patterns[1] = "/brown/";
$patterns[2] = "/fox/";

$replacements[2] = "bear";
$replacements[1] = "black";
$replacements[0] = "slow";

$str1 = preg_replace($patterns,$replacements,$string);  //替换字符串
echo "使用函数ksort()之前字符串替换为:<br/>";
echo $str1;
echo "<br/><br/>";

ksort($patterns);        //排序
ksort($replacements);    //排序

$str2 = preg_replace($patterns,$replacements,$string);
echo "使用函数ksort()之后字符串替换为:<br/>";
echo $str2;
echo "<br/><br/>";
?>


//用正则表达式分割字符串的函数
array preg_split(string $pattern,string $subject [,int $limit [, int $flag]]);
//参数$limit=-1,$flag参数如下:
PREG_SPLIT_NO_EMPTY:只返回非空的部分
PREG_SPLIT_DELIM_CAPTURE:界定符模式中的括号表达式会被捕捉返回
PREG_SPLIT_OFFSET_CAPTURE:对每个出现的匹配结果同时返回其附属的字符串偏移量。注意,这改变了返回的数组的值,使其中的每个单元也是一个数组,其中第一项为匹配字符串,第二项为它在$subject中的偏移量

<?php
$str = 'PHP language programming in Web';  //定义字符串变量
echo "<b>原字符串:</b><br/>";
echo $str;
echo "<br/><br/>";

$chars = preg_split('/ /',$str,-1,PREG_SPLIT_OFFSET_CAPTURE);  //分割字符串
echo "<b>调用函数preg_split()后:</b>";
echo "<pre>";
print_r($chars);
?>

4.几例常见的正则表达式分析:

  • 实例1:检查IP地址的正则表达式:
    直接上代码:
<?php
$arr_ip = array(  //定义了一个数组
  "192.168.1.100",
  "-12.255.0.10",
  "256.1.2.255",
  "10.9c.132.69",
  "255.255.255.255",
  "123.0.0.0.1"
);

foreach ($arr_ip as $ip ) {  //验证数组里的IP
  if (validateIp($ip)) {  //验证ip
    echo "<b>$ip 是正确的IP地址</b>";
    echo "<br/><br/>";
  }else {
    echo "$ip 不是正确的IP地址";
    echo "<br/><br/>";
  }
}

function validateIp($ip){  //验证ip的函数
  $iparray = explode(".",$ip);
  for ($i=0; $i < count($iparray); $i++) {
    if ($iparray[$i]>255) {
      return (0);
    }
    return preg_match("/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/",$ip);
  }
}
?>
  • 实例2:检查中文字符的正则表达式:
    直接上代码
<?php
$str_arr = array( //测试数组
  "I am very happy",
  "快乐编程快乐生活",
  "PHP编程",
  "1997年香港回归",
  "英语学习ABC",
  "123456789"
);

$patt_ch = chr(0xa1)."-".chr(0xff); //匹配中文字符的ASCII范围

foreach ($str_arr as $str){
  echo "字符串'$str'是";
  if(preg_match("/[$patt_ch]+/",$str)){  //注意在正则表达式的前后使用界定符
    echo "<b>存在中文</b>";
    echo "<br>";
    echo "<br>";
  }else {
    echo "不存在中文";
    echo "<br>";
    echo "<br>";
  }
}
?>
  • 实例3:检查Email地址的正则表达式
<?php
$str_arr = array( //测试数组
  "mymail@somesite.com",
  "my_mail@somesite.com",
  "my-mail@somesite.com",
  "my.mail@somesite.com",
  "mymail@somesite.ccoomm",
  "mymail@site.cn",
  "mymail@@@site.com",
  "mymail@site",
  "MyMail@somesite.com",
  "My2007@somesite.com",
  "163mail_for-me777@somesite.com",
  "510137672@qq.com"
);

$patt_email = "/^[_a-zA-Z0-9-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,4}$/"; //验证邮箱

foreach ($str_arr as $str){
  echo "字符串'$str'是";
  if(preg_match($patt_email,$str)){  //注意在正则表达式的前后使用界定符
    echo "<b>合法的Email格式</b>";
    echo "<br>";
    echo "<br>";
  }else {
    echo "不合法的Email格式";
    echo "<br>";
    echo "<br>";
  }
}
?>
  • 实例4:检查URL地址的正则表达式
    直接上代码:
<?php
$str_arr = array( //测试数组
  "http://www.liubaiqi.cn",
  "www.liubaiqi.cn",
  "http://www.liubaiqi.cn/login.html",
  "//liubaiqi.com",
  ":www.liubaiqi.cn"
);

$patt_url = "/^(http:\/\/)?[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)*.+$/"; //验证URL的正则表达式

foreach ($str_arr as $str){ //遍历数组
  echo "字符串'$str'是";
  if(preg_match($patt_url,$str)){  //匹配URL
    echo "<b>合法的URL格式</b>";
    echo "<br>";
    echo "<br>";
  }else {
    echo "不合法的URL格式";
    echo "<br>";
    echo "<br>";
  }
}
?>

三、PHP程序中的错误处理


PHP程序异常通常有3种情况:
1.语法错误:代码书写、语法错误

2.运行时错误:代码本身没有错,在运行时操作时出错
3.逻辑错误:最难改,程序能正常运行,但最终结果不是所期望的值

1.内置异常处理类——Exception

PHP5增加了内置的异常处理类——Exception,内置函数
getMessage():返回对错误的描述信息
getCode():返回错误代码,以数字形式出现
getFile():返回发送错误的文件名
getLine():返回发送错误的代码行号
getTrace():返回backtrace()错误
getTraceAsString():返回已格式化成字符串的、由函数getTrace()所产生的信息
__toString():产生异常的字符串信息,可以重载

现在让我们来看一下PHP中内置异常处理类的完整代码:

<?php
class Exception{
  protected $message = 'Unknown exception'; //异常信息
  protected $code = 0;  //用户自定义异常代码
  protected $file;  //发生异常的文件名
  protected $line;  //发生异常的代码行号

  function __construct($message = null,$code = 0);

  final function getMessage();  //返回异常信息
  final function getCode(); //返回异常代码
  final function getFile(); //返回发生异常的文件名
  final function getLine(); //返回发送异常的代码行号
  final function getTrace(); //backtrace()数组
  final function getTraceAsString(); //已格式化成字符串的getTrace()信息

  function __toString();; //可输出的字符串,可重载
}
?>

2.捕获异常的方法:

和JAVA很像,
try...catch...:异常处理的格式
throw:抛出异常

例如:

<?php
try{
  $error = '抛出异常信息,并且跳出try块<br/>';
  if (is_dir('./test')) {
    echo '监测到../ch16是一个目录';
    echo '<br/>';
    echo '可能继续做其他一些操作';
    echo '<br/>';
    echo '....';
    echo '<br/>';
  }else {
    throw new Exception($error, 12345);  //抛出异常
  }
  echo '上面throw异常的话,这行代码不会执行,转而执行catch块<br/>';
}catch(exception $e){  //获取异常
  echo '捕获异常:'.$e->getMessage()."<br/>错误代码:".$e->getCode().'<br/>';
  echo '<br/>';
}
echo '继续执行';
?>

3.获取异常信息的函数使用:

直接上代码例子

<?php
$file = './var/www/html//index.html';  //指定文件地址

try{
  if (is_dir($file)) {  //判断是否是目录
    echo '检测到目录';
  }else {
    //创建异常对象,错误信息将由Exception类的成员函数getMessage()返回
    throw new Exception('未找到该目录或文件');
  }
}catch(Exception $e){
  echo '捕获异常:'.$e->getMessage();
  echo '<br/><br/>';
  echo '错误所在文件:'.$e->getFile();
  echo '<br/><br/>';
  echo '错误所在行号:'.$e->getLine();
  echo '<br/>=================================<br/>';
}

echo '程序执行完毕';
?>

4.自定义的错误处理:myHandler()

PHP中默认错误处理器被自定义的错误处理函数myHandler()替代

<?php
set_error_handler('myHander');  //自定义错误处理函数

function myHander($code,$msg,$file,$line){
  echo "<br/>";
  echo "程序<b>$file</b>执行过程中,在第<b>$line</b>行,产生一个错误。";
  echo "<br/>";
  echo "错误代码为:<b>$code</b>,错误的原因是:<b>$msg</b>";
}

echo $uvar; //输出未定义变量,错误处理
?>

四、PHP 与 XML


XML:扩展标记语言(eXtensible Markup Language),由W3C制定
它不仅仅是一种标记语言,还是一种存储数据的格式。
用XML可以描述标记建立数据,
现在由于JSON的优越性(解析完能转换成非常好的数据结构,使用起来会很方便),数据解析上更多的使用JSON,
但作为初学者,还是要学习一下XML的内容。
这里参考一篇技术博客,这里关于XML和JSON解析讲解的很好。

1.XML与HTML的不同:

注意:XML和HTML有些不同,
XML用来描述数据,并关注数据是什么;
而HTML用来显示数据,它关注的是如何使数据显示出来。
XML并不是作为HTML的替代品而出现,它们有各自的领域和价值。

2.XML实例:

下面描述一个图书馆信息的XML文档

<?xml version="1.0" encoding="UTF-8"?>
<books>
  <book>
    <title>Learning PHP7</title>
    <author>David</author>
    <publisher>White Water Press</publisher>
    <price>29.90</price>
  </book>
  <book>
    <title>Learning XML</title>
    <author>MrLiu</author>
    <publisher>White Water Press</publisher>
    <price>58.90</price>
  </book>
  <book>
    <title>Using PERL</title>
    <author>Lucy</author>
    <publisher>White Water Press</publisher>
    <price>17.90</price>
  </book>
  <book>
    <title>Windous Networks</title>
    <author>Paul</author>
    <publisher>White Water Press</publisher>
    <price>32.99</price>
  </book>
  <book>
    <title>Fly Leaf</title>
    <author>Jenny</author>
    <publisher>White Water Press</publisher>
    <price>19.50</price>
  </book>
</books>
  • 1.XML声明:

version属性:描述XML的版本号
standalone属性:描述该XML文件是否和一个独立的声明文件(DTD)配套使用,YES表示没有DTD,NO表示有DTD配套
encoding属性:XML分析器支持的编码标准,常用的是UTF-8和GB2312(简体中文码)

  • 2.XML元素:<标记>数据内容</标记>
<国籍>中国</国籍>
<title>Learning XML</title>
  • 3.标记和属性:<标记名 属性名="属性取值">
<person sex="female">
  • 4.处理指令:<?处理指示名 处理指示信息?>
<?cocoon-process type="sql"?>

cocoon是来自Apache软件基金会的XML处理框架,该实例告诉cocoon,XML文档包含一个SQL语句。

  • 5.实体:

实体是文档用来替换一些特殊标记符号的字符串。
XML和HTML中常见的实体如下:
&lt:代表小于符号<,less than
&gt:代表大于符号>,greater than
&quot:代表一个双引号
&apos:代表一个单引号,或撇号
&amp:代表一个“与”符号&
注:实体以“&”开头,以英文“;”结束。

  • 6.文件类型定义(DTD):

一个完全意义上的XML文件不仅应该是形式良好的,而且还该使用自定义标记的XML文件。定义来表示数据的标记,最常用的方法是实用文档定义类型(Document Type Definition)DTD。
简而言之,DTD规定了一个语法分析器为了解释一个“有效的”XML文件所需要知道的所有规则和细节。

实例:DTD用来指定XML文档的基本结构,在XML文件的序言部分加入一个DTD描述,加入位置在XML处理指示之后

<?xml version = "1.0" encoding="UTF-8"?>
<!DOCTYPE 根元素名[
           元素描述
]>
文件体

DTD中使用元素类型声明(Element Type Definition,ETD)来声明所有有效的文件元素。ETD结构如下:
<!ELEMENT 元素名 元素内容描述>
所以刚才的图书馆实例可以修改为:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 这些是图书馆中图书的有关信息-->
<!DOCTYPE books[
<!ELEMENT books (book)*>
<!ELEMENT book (title,author,publisher,price)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT publisher (#PCDATA)>
<!ELEMENT price (#PCDATA)>
]>
<books>
  <book>
    <title>Learning PHP7</title>
    <author>David</author>
    <publisher>White Water Press</publisher>
    <price>29.90</price>
  </book>
  <book>
    <title>Learning XML</title>
    <author>MrLiu</author>
    <publisher>White Water Press</publisher>
    <price>58.90</price>
  </book>
  <book>
    <title>Using PERL</title>
    <author>Lucy</author>
    <publisher>White Water Press</publisher>
    <price>17.90</price>
  </book>
  <book>
    <title>Windous Networks</title>
    <author>Paul</author>
    <publisher>White Water Press</publisher>
    <price>32.99</price>
  </book>
  <book>
    <title>Fly Leaf</title>
    <author>Jenny</author>
    <publisher>White Water Press</publisher>
    <price>19.50</price>
  </book>
</books>

使用DTD中也可以定义属性,格式如下:
<!ATTLIST 元素名 (属性名 属性类型 默认值) *>
实例:

<!ELEMENT city (#PCDATA)>
<!ATTLIST city province CDATA #REQUIRED>

这段示例XML定义了<city>元素,同时使用关键字ATTLIST声明元素的属性。属性列表中的名称city告诉解析器这些属性是为元素<city>定义的。名称province是属性的名称,关键字CDATA和#REQUIRED告诉XML解析器province属性包含文本并且是必须的。如果是可选的,使用CDATA #IMPLIED。

3.PHP对XML的支持:

PHP5后支持符合W3C标准的DOM和SimpleXML扩展,默认情况下同时支持SAX(原生支持)、DOM、SimpleXML。

XML解析器分为两种类型:
一种是基于树型的解析器:将XML文档转换成树型结构。提供一个API来访问所产生数的每个元素,其通用的标准为DOM,即文档对象模式。重点在结构,树型结构。
二种是基于事件的解析器:将XML文档视为一系列的事件。当一个而特殊事件发生时,默认调用开发者提供的函数处理。重点在数据,从头到尾。

  • PHP函数处理XML文档:
//XML解析器的建立
resource xml_parser_create([string $encoding]);
//XML解析器的释放
bool xml_parser_free(resource $parser);

//处理XML元素的函数
bool xml_set_element_handler(resource $parser,callback $start_elem_handler,callback $end_elem_handler);

//处理XML字符数据的函数
bool xml_set_character_data_handler(resource $parser,callback $handler);

//解析一个XML文档
int xml_parse (resource $parser,string $data [, bool $is_final]);

Expat函数XML文档实例:

//ExpatXML.php
<?php
$parser = xml_parser_create();    //初始化XML分析器

function start($parser , $elem_name,$elem_attrs){  //在一个元素开始时调用的函数
  switch ($elem_name) {
    case "BOOKS":
      echo "<b>-- 图书信息 --</b><br/><br/>";
      break;
    case "TITLE":
      echo "<b>书名:</b>";
      break;
    case "AUTHOR":
      echo "<b>作者:</b>";
      break;
    case "PUBLISHER":
      echo "<b>出版社:</b>";
      break;
    case "PRICE":
      echo "<b>价格:</b>";
      break;
  }
}

function stop($parser,$elem_name){  //在一个元素结束时调用的函数
  echo "<br/>";
}

function char($parser,$data){ //当找到一个字符数据时调用该函数
  echo $data;
}

xml_set_element_handler($parser,"start","stop");  //指定元素处理器
xml_set_character_data_handler($parser,"char");   //指定字符数据处理器

$fp=fopen("XMLTest.xml","r");   //打开XML文件
while($data=fread($fp,1024)){   //循环读入XML文件中的内容
  xml_parse($parser,$data,feof($fp)) or
  die(sprintf("XML错误:%s at line %d",
  xml_error_string(xml_get_error_code($parser)),
  xml_get_current_line_number($parser)));
}

xml_parser_free($parser); //释放XML分析器资源
?>
  • 使用SimpleXML处理XML

SimpleXML,名副其实,使用起来十分简单,最适合简单的、类似记录的数据。
SimpleXML函数:

//载入XML文件的函数
object simplexml_load_file(string $filename [, string $class_name [,int $options]]);

<?php
if(file_exists('XMLTest.xml')){   //判断文件是否存在
  $xml = simplexml_load_file('XMLTest.xml');  //加载文件
  var_dump($xml);
}else{
  exit('载入文件test.xml失败');
}
?>

//载入XML字符串的函数
object simplexml_load_strig(string $data [, string $class_name[, int $options]]);

<?php
$xml_str = "<?xml version='1.0' encoding='UTF-8'?>";
$xml_str .= "<EMAILDOCUMENT>";
$xml_str .= "<TITLE>最近在学什么</TITLE>";
$xml_str .= "<FROM>小强</FROM>";
$xml_str .= "<TO>大强</TO>";
$xml_str .= "<BODY>";
$xml_str .= "我最近在学PHP,你呢?";
$xml_str .= "</BODY>";
$xml_str .= "</EMAILDOCUMENT>";

$xml = simplexml_load_string($xml_str); //加载XML字符串
var_dump($xml);
?>

SimpleXML实例:

<?php
$xml = simplexml_load_file("XMLTest.xml");  //载入指定的XML文档

echo "==== " . $xml->getName() . "====<br/>"; //获取当前元素的名称

foreach ($xml->children() as $child) {
  echo "--- ".$child->getName()."---<br/>";
  foreach ($child->children() as $ch) {
    echo $ch->getName().":".$ch."<br/>";
  }
  echo "<br/>";
}
?>
  • 使用PHP的DOM库处理XML文档

DOM是Document Object Model的缩写。它是在浏览器中使用的、用JavaScript操作的W3C DOM规范。分析成DOM的树型结构。

下面介绍如何通过DOM在PHP中处理XML文档:
步骤如下:
1> 首先需要创建一个DOM的实例,即DOMDocument

$dom = new DOMDocument;

2>载入XML到该实例中,有两种方法:一是从一个字符串载入,使用函数loadXML(),二是从文件载入,使用load()。

//使用字符串载入
$dom->loadXML('<string>books</string>');

//从文件载入
$dom->load('XMLTest.xml');

3>使用DOM对象的documentElement属性可以访问XML文档的根元素

<?php
$dom = new DOMDocument;  //1.创建DOM实例

$dom->load('XMLTest.xml');  //2.载入XML到该实例中
$root = $dom->DOMDocumentElement;   //3.获取XML文档的根元素
?>

4>使用DOM对象的saveXML输出XML字符串,而使用方法save()可以将XML保存为一个XML文件

<?php
$xml_str = "<?xml version='1.0'?>";   //开始下定义XML字符串
$xml_str .="<books>";
$xml_str .="<book>";
$xml_str .="<title>Harry Potter</title>";
$xml_str .="<author>J.K.Rowling</author>";
$xml_str .="<publisher>Warner Bros.</publisher>";
$xml_str .="<price>39.0</price>";
$xml_str .="</book>";
$xml_str .="</books>";

$dom = new DOMDocument;
$dom->LoadXML($xml_str);  //载入定义的XML字符串

echo $dom->saveXML();     //将XML输出到一个字符串
$dom->save("test.xml");
?>

5>使用DOM的getElementsByTagName()方法可以返回一个元素的字符数据,该函数接受一个元素名称作为参数。

<?php
$doc = new DOMDocument();
$doc->load('XMLTest.xml');    //载入指定的XML文档

$books = $doc->getElementsByTagName("book");    //返回book元素的数据
foreach($books as $book){                       //遍历book元素
  $authors = $book->getElementsByTagName("author");
  $author = $authors->item(0)->nodeValue;

  $publishers = $book->getElementsByTagName("publisher");
  $publisher = $publishers->item(0)->nodeValue;

  $titles = $book->getElementsByTagName("title");
  $title = $titles->item(0)->nodeValue;

  $prices = $book->getElementsByTagName("price");
  $price = $prices->item(0)->nodeValue;

  echo "$title - $author - $publisher - $price";
  echo "<br/>";
  echo "<br/>";
}
?>

五、PHP 与 AJAX


AJAX是当今Web应用中的一种相当流行的技术,
它最大的优点是给用户最佳的浏览体验。
无论是使用Java、ruby还是PHP,都可以实现AJAX应用

注:AJAX并不完全依赖于某种服务器脚本程序,它是在浏览器端实现的技术

1.什么是AJAX?

AJAX,全称:“Asynchronous JavaScript and XML”
翻译一下,是异步JavaScript和XML
是一种创建交互式网页应用的网页开发技术。
其中包括:使用XHTML和CSS标准实现Web页面,使用DOM实现动态显示和交互,使用XML进行数据交换与处理,最后使用JavaScript绑定和处理所有数据。

AJAX将一些服务器负担的工作下放至客户端,利用客户端的某些能力来处理数据,从而减轻了服务器和带宽的负担。

AJAX最大的优点是页面无序刷新就可以更新页面内容和数据,减少用户实际等待的时间,给了用户最佳的体验效果。

2.AJAX的工作原理:

在AJAX之前,Web站点强制用户进入提交、等待、页面刷新显示数据的流程。其中有大量的网络请求,服务器和网络带宽有很大的负担。

然而,AJAX可以在用户单击按钮时,使用JavaScript和DHTML立即更新Web页面,并向服务器发出异步请求,以执行更新或查询数据库。当请求返回时,就可以使用JavaScript和CSS响应更新Web页面,而不是刷新整个页面。最重要的时,这种速度非常快,Web站点看起来是即使响应的。

原理:关于AJAX工作原理,可以用一句话概括:通过XMLHttpRequest对象来向服务器发一部请求,从服务器获得数据,然后用JavaScript来操作DOM从而完成页面更新。

AJAX工作原理

缺陷:然而AJAX并不是完美的,它也有缺陷。AJAX破坏了浏览器的“后退”机制。即后退无法返回原先的页面,这是一个相当大的缺陷,虽然后来有使用一个隐藏的IFRAME来重现页面上的变更,但是成本是非常大的。

3.PHP与AJAX:

  • 创建XMLHttpRequest对象(JavaScript对象):
<script language="javascript">
    var xmlHttp = new XMLHttpRequest();
</script>

不同的浏览器使用不同的方法创建XMLHttpRequest对象,
例如,IE使用ActiveXObject,所以最好使用如下代码,改进版:

var xmlHttp = null;
if(window.xmlHttpRequest){
        xmlHttp=new xmlHttpRequest();
}else if(window.ActiveXObject){
        xmlHttp=new ActiveXObject("Microsoft.xmlHTTP");
}

完整的XMLHttpRequest对象的JavaScript程序:

//AJAXTest.js
function GetXmlHttpRequest(){
  var xmlHttp=null;
  try{
    xmlHttp = new XMLHttpRequest();   //对于Firefox等浏览器
  }
  catch(e){
    try{
      xmlHttp = new ActiveXObject("Msxm12.XMLHTTP");  //对于IE浏览器
    }
    catch(e)
    {
      try{
        xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
      }
      catch(e){
        xmlHttp =false;
      }
    }
  }
  return xmlHttp;
}
  • 发送异步请求:
    先了解一下XMLHttpRequest对象的一些方法:

open(method,url[ ,async]):使用method参数所指定的方式(POST或GET)打开一个url指定的链接。async为true表示异步,false为同步。
setRequestHeader(label,value):在请求报头增加一个键值对
send(content):JavaScript将请求和数据向服务器发送出去
getAllResponseHeaders():获取服务器所有的HTTP响应报头,并作为一个字符串返回
getResponseHeader(label):获取一个有参数label指定的HTTP响应报头
abort():用来终止当前的请求
再了解一下XMLHttpRequest对象的属性和含义:
onreadystatechange:每次请求状态发生改变时,会调动由该属性保存的事件处理时间
readyState:对象状态值,有5种选择:0表示为初始化,1表示正在加载(loading),2表示加载完毕(loaded),3表示正在接受响应,4表示响应接受完毕(complete)
responseTest:从服务器返回的数据,以字符串形式给出
responseXML:从服务器返回DOM兼容的文档数据对象,即XML数据对象
status:从服务器返回数字代码,比如404(未找到)或200(一切正常)
statusText:与状态相关的文本信息
发送异步请求的JavaScript程序:

function sendRequest(){
  //获取页面表单的文本框name的值
  var user_name = document.getElementById("name").value;

  if ((user_name == null)||(user_name == "")) {
    return;
  }

  xmlHttp = GetXmlHttpRequest();
  if(xmlHttp == null){
    alert("浏览器不支持XmlHttpRequest!");
    return;
  }

  var url = "getUserName.php";  //构建请求的URL地址
  url = url + "?name=" + user_name;

  xmlHttp.open("GET",url,true); //使用GET方法打开一个到url的连接,为发出请求做准备
  //设置一个回调函数,当服务器完成请求后调用
  xmlHttp.onreadystatechange = updatePage;
  xmlHttp.send(null);   //发送请求
}

回调函数:

function updatePage(){
  if (xmlHttp.readyState == 4) {
    var response = xmlHttp.responseText;
    document.getElementById("userInfo").value = response
  }
}

完整实例:

//AJAXTest.html
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>ajax应用实例</title>
<script language="javascript">
var xmlHttp = null;

function GetXmlHttpRequest(){
  var xmlHttp = null;
  try{      //创建XMLHttpRequest对象
    xmlHttp = new XMLHttpRequest();
  }
  catch(e){
    try {
      xmlHttp = new ActiveXObject("Msxm12.XMLHTTP");
    }
    catch (e) {
      try{
        xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
      }
      catch (e) {
        xmlHttp = false;
      }
    }
  }
  return xmlHttp;         //返回XMLHttpRequest对象
}

function sendRequest(){       //发送异步请求
  var prov_name = document.getElementById("province").value;

  if ((prov_name == null)||(prov_name == "")) {
    return;
  }

  xmlHttp = GetXmlHttpRequest();
  if (xmlHttp == null) {
    alert("浏览器不支持XMLHttpRequest!");
    return;
  }

  var url = "AJAXTest.php";
  url = url + "?prov=" + prov_name;

  xmlHttp.open("GET",url,true);
  xmlHttp.onreadystatachange = updatePage;
  xmlHttp.send(null);
}

function updatePage(){  //处理服务器响应
  if(xmlHttp.readyState == 4 && xmlHttp.status == 200){
    var response = xmlHttp.responseText;
    document.getElementById("city").innerHTML = response;
  }
}

</script>
</head>

<body>
  <h3>请选择一个省(自治区):</h3>

  <form action="AJAXTest.php">
    <div>
      <select id="province" onchange="sendRequest()">
        <option value="">请选择一个省(自治区)</option>
        <option value="ah">安徽</option>
        <option value="fj">福建</option>
        <option value="gd">广东</option>
        <option value="js">江苏</option>
        <option value="sh">上海</option>
        <option value="ln">辽宁</option>
        <option value="bj">北京</option>
        <option value="hb">河北</option>
        <option value="hn">河南</option>
        <option value="hlj">黑龙江</option>
        <option value="xj">新疆</option>
        <option value="xz">西藏</option>
        <option value="nmg">内蒙古</option>
      </select>
    </div>
  </form>

  <div id="city">
  </div>

</body>
</html>

//AJAXTest.php
<?php
$city_arr = array(
  "ah"=>"合肥",
  "fj"=>"福州",
  "gd"=>"广州",
  "js"=>"南京",
  "sh"=>"上海",
  "ln"=>"沈阳",
  "bj"=>"北京",
  "hb"=>"石家庄",
  "hn"=>"郑州",
  "hlj"=>"哈尔滨",
  "xj"=>"乌鲁木齐",
  "xz"=>"拉萨",
  "nmg"=>"呼和浩特"
);

if (empty($_GET['prov'])) {
  echo '<font color="red">您没有选择省(自治区)</font>';
}else{
  $prov = $_GET['prov'];
  $city = $city_arr[$prov];
  echo '所选省(自治区)省会(首府)为:'.$city;
}
?>

注意:在这个实例中,我遇到一些问题,用ajax始终无法响应,我猜测可能是html和php文件关联上有问题,存在bug,我没调出来。回过头我再调。

  • 一个已经实现AJAX的PHP类——xajax

xajax是一个开源的PHP类库,它能综合HTML、CSS、JavaScript、PHP,轻而易举就开发出强大的、基于AJAX的Web应用。

下载xajax:官网:http://www.xajaxproject.org/

如何在PHP程序中使用xajax:
1>包含xajax库:require_once("xajax.inc.php");
2>创建xajax对象:$xajax = new xajax();
3>注册需要通过xajax调用的名称:$xajax->registerFunction("myFunction");注册函数名为:myFunction
4>编写注册的PHP函数,并且在函数中使用xajaxResponse对象创建向浏览器端返回的XML指令
5>在PHP程序输出任何信息之前,调用xajax用于接管请求:$xajax->processRequests();
6>在页面的<head></head>标签之间,使用xajax生成实现AJAX应用所必须的JavaScript代码:$xajax->printJavascript();
7>在程序中,从Javascript时间或者函数调用前面注册的函数,例如:<button onclick="xajax_myFunction(SomeArgument);">

实例:

<?php
require_once("xajax/xajax.inc.php");

$xajax = new xajax();     //实例化xajax对象

//$xajax->debugOn();      //打开ajax调试功能

//注册一个xajax调用的php函数名(与JavaScript中的函数名xajax_showOutput相对应)
$xajax->registerFunction("showOutput");

//编写上面已经注册的php函数,在此函数中用xajaxResponse对象来返回XML指令集
function showOutput(){
  $testResponse = new xajaxResponse();
  $testResponse->addAlert("Hello");

  $testResponse2 = new xajaxResponse();
  $testResponse2->loadXML($testResponse->getXML());
  $testResponse2->addReplace("this","is","a","replacement");
  $testResponseOutput = htmlspecialchars($testResponse2->getXML());

  $objResponse = new xajaxResponse();

  //使用xajaxResponse对象的addAssign方法添加XML指令
  //该指令将id为submittedDiv的元素的innerHTML属性更新为$testResponseOutput
  $objResponse->addAssign("submittedDiv","innerHTML",$testResponseOutput);
  return $objResponse;
}

$xajax->processRequest();   //在脚本传送出任何东西前,xajax都要处理所有请求
?>

<html>
<head>
  <meta http-equiv="content-type" content="text/html";charset="utf-8" />
  <title>xajaxTest</title>
  <?php
  //这代码使xajax对象可以生产所必须的JavaScript
  $xajax->printJavascript("xajax/");
  ?>
</head>

<body>
  <!--在这里调用 -->
  <p><div onclick="xajax_showOutput();">单击这里显示响应XML</div></p>
  <div id="submittedDiv">这里将被响应的XML指令所替换</div>
</body>
</html>

六、PHP 图像处理


PHP除了开发Web应用,还可以生成图片或对图片进行加工处理
目前主流图片处理库:Grafika
GitHub地址:https://github.com/kosinix/grafika/
是基于Imagick和GD,可以用于改变图片大小,剪裁,比较,添加水印等等功能。还有感知哈希,高级图像过滤,绘制贝塞尔曲线等功能,非常强大。
关于Grafika:可以参考这篇博客,写的非常完整详细。

本章主要讲述较底层的GD扩展库的方法和使用:

  • GD扩展库主要函数:

imagecreatefromgif():用来从指定的GIF文件取出图像
imagegif():创建一个GIF图像
imagecreatefrompng():从指定PNG文件取出图像
imagepng():创建一个PNG图像
imagecreate():新建一个基于调色板的图像
imagecreateturecolor():返回一个黑色图像的标识符
imagecolorallocate():创建一个由RGB颜色指定的图像
imagefill():用指定的颜色填充图像
imageline():用指定颜色画出一条线段
imagestring():在图像上显示一个字符串
imagettftext():用TrueType字体向图像写入文本
imageSX/imageSY():分别用来去的图像宽度和高度
imagettfbbox():用来去的使用TrueType字体的文本范围
imagealphablending():用来设定图像的混色模式
imagecopyresized():用来复制部分图像并调整大小
imagecopyresampled():重采赋值部分图像并调整大小
getimagesize():获取图像属性

  • 步骤:

1>建立画布
2>在画布上绘制形状或书写文本
3>输出最终的图片
4>清空绘图资源

  • 图像的建立:
//1.生成图像:
<?php
$width = 200;   //宽度
$height = 200;  //高度

$img = imagecreatetruecolor($width,$height)or die("不支持GD图像处理"); //创建图像  
imagepng($img);
imagedestory($img);
?>


//2.设定图像颜色:
<?php
$width = 200;   //宽度
$height = 200;  //高度

$img = imagecreatetruecolor($width,$height)or die("不支持GD图像处理"); //创建图像

$bg_color = imagecolorallocate($img,255,0,0); //设置图像标识符所描述图像的颜色
imagefill($img,0,0,$bg_color);        //改变图像的颜色

imagepng($img);
imagedestory($img);
?>


//3.在图像上绘制直线:
<?php
$width = 200;   //宽度
$height = 200;  //高度

$img = imagecreatetruecolor($width,$height)or die("不支持GD图像处理"); //创建图像

$line_color = imagecolorallocate($img,255,255,255); //设置图像标识符所描述图像的颜色
imageline($img,0,40,200,40,$line_color);            //绘制直线
imageline($img,0,260,200,260,$line_color);          //绘制直线

imagepng($img);
imagedestory($img);
?>


//4.在图像上输出文字:
<?php
$width = 200;   //宽度
$height = 200;  //高度

$img = imagecreatetruecolor($width,$height) or die("不支持GD图像处理"); //创建图像

$line_color = imagecolorallocate($img,255,255,255); //设置图像标识符所描述图像的颜色
imageline($img,0,40,200,40,$line_color);            //绘制直线
imageline($img,0,260,200,260,$line_color);          //绘制直线
imagestring($img,5,0,60,"It's time to learn PHP!",$line_color); //显示文字

imagepng($img);
imagedestory($img);
?>


//5.在图像中显示中文字符:
<?php
$width = 200;   //宽度
$height = 300;  //高度

$img = imagecreatetruecolor($width,$height) or die("不支持GD图像处理"); //创建图像
$line_color = imagecolorallocate($img,255,255,255);
$font_type = "C://WINDOUS//Fonts//SIMLI.TFF"; //获取TrueType字体,采用隶书字体

//"西游记"3个字的16进制字符
$cn_char1 = chr(0xE8).chr(0xA5).chr(0xBF);
$cn_char2 = chr(0xE6).chr(0xB8).chr(0xB8);
$cn_char3 = chr(0xE8).chr(0xAE).chr(0xB0);

//"吴承恩著"4个字的16进制字符
$cn_str = chr(0xE5).chr(0x90).chr(0xB4).chr(0xE6).chr(0x89).chr(0xBF).chr(0xE6).chr(0XE6).chr(0X81).chr(0XA9);
$cn_str .=" ".chr(0xE8).chr(0x91).chr(0x97);

imageline($img,0,40,200,40,$line_color);    //绘制直线
imageline($img,0,260,200,260,$line_color);    //绘制直线

//竖排显示"西游记"3字
imagettftext($img,30,0,10,80,$line_color,$font_type,$cn_char1);
imagettftext($img,30,0,10,120,$line_color,$font_type,$cn_char2);
imagettftext($img,30,0,10,160,$line_color,$font_type,$cn_char3);

//横排显示“吴承恩著”4字
imagettftext($img,15,0,90,254,$line_color,$font_type,$cn_str);

imagepng($img);
imagedestroy($img);
?>
  • 图片的处理:
//1.打开已存在的图片:
<?php
$img = imagecreatefromjpeg("tower.jpg");  //打开指定的图片文件

Imagejpeg($img);
Imagedestroy($img);
?>


//2.获取图片的相关属性:
<?php
$img = imagecreatefromjpeg("tower.jpg");  //打开指定的图片文件

$x = imageSX($img);
$y = imageSY($img);
echo "图片tower.jpg的宽为:<b>$x</b> pixels";
echo "<br/>";
echo "<br/>";
echo "图片tower.jpg的高为:<b>$y</b> pixels";
Imagejpeg($img);
Imagedestroy($img);
?>


//3.对图片加水印效果:
<?php
function makeImageWaterMark($image,$pos,$water_text,$font_size,$color){
  $font_type = "C://WINDOWS//Fonts//cour.ttf";

  if (!empty($image) && file_exists($image)) {
    $img_info = getimagesize($image);
    $g_w = $img_info[0];    //取得背景图片的宽
    $g_h = $img_info[1];    //取得背景图片的高

    switch($img_info[2]){   //取得背景图片的格式
        case 1:
            $img = imagecreatefromgif($image);
            break;
        case 2:
            $img = imagecreatefromjpeg($image);
            break;
        case 3:
            $img = imagecreatefrompng($image);
            break;
        default:
            die("图片格式错误");
    }
  }
  else{
    die("需要加水印的图片片不存在!");
  }

  //取得使用 TrueType字体的文本范围
  $temp = imagettfbbox(ceil($font_size*2.5),0,$font_type,$water_text);
  $w = $temp[2] - $temp[6];
  $h = $temp[3] - $temp[7];
  if (($g_w<$w)||($g_h<$h)) {
    echo "需要加水印的图片的大小比水印文字区域小,无法生成水印";
    return;
  }

  //设置4种水印效果位置:0和默认是随机位置,1为顶端居左,2为中部居中,3为底端居右
  switch($pos){
    case 0:
        $pos_x = rand(0,($g_w - $w));
        $pos_y = rand(0,($g_h - $h));
        break;
    case 1:
        $pos_x = 0;
        $pos_y = 0;
        break;
    case 2:
        $pos_x = ($g_w - $w)/2;
        $pos_y = ($g_h - $h)/2;
        break;
    case 3:
        $pos_x = $g_w - $w;
        $pos_y = $g_h - $h;
        break;
    default:
        $pos_x = rand(0,($g_w - $w));
        $pos_y = rand(0,($g_h - $h));
        break;
  }

  imagealphablending($img,true);  //设置图像混色模式

  if(!empty($color)&&(strlen($color)==7)){
    $R = hexdec(substr($color,1,2));
    $G = hexdec(substr($color,3,2));
    $B = hexdec(substr($color,5));
  }
  else{
    die("水印文字颜色格式不正确!");
  }
  $text_color = imagecolorallocate($img,$R,$G,$B);

  imagettftext($img,$font_size,0,$pox_x,$pos_y,$text_color,$font_type,$water_text);
  switch($img_info[2]){
    case 1:
        imagegif($img,$image);
        break;
    case 2:
        imagejpeg($img,$image);
        break;
    case 3:
        imagepng($img,$image);
        break;
    default:
        die("不被支持格式的图片!");
  }

  Imagedestroy($img);
}

if(isset($_FILES)&&!empty($_FILES['userfile'])&&$_FILES['userfile']['size']>0){
  $uploadfile = "./".time()."_".$_FILES['userfile']['name'];
  if (copy($_FILES['userfile']['tmp_name'],$uploadfile)) {
    makeImageWaterMark($uploadfile,2,"Photo by Macc",16,"$43042A");
    echo "<img src=\"".$uploadfile."\"border=\"0\">";
  }
  else{
    echo "文件上传错误!<br/>";
  }
}
?>

<html>
<head>
<title>GDTest.php</title>
</head>

<body>
  <form enctype="multipart/form-data" method="POST">
    选择上传图片:<input name="userfile" type="file">
    <input type="submit" value="上传">
  </form>
</body>
</html>


//4.生成已有图片的缩略图:
<?php
$img_name = "tower.jpg";
$src_img = imagecreatefromjpeg($img_name);

$ow = imagesx($src_img);    //取得原图的宽
$oh = imagesy($src_img);    //取得原图的高

$nw = round($ow*200.0/$ow); //计算新图的宽度
$nh = round($oh*200.0/$oh); //计算新图的高度

$desc_img = imagecreate($nw,$nh); //建立新图

imagecopyresized($desc_img,$src_img,0,0,0,0,$nw,$nh,$ow,$oh); //生成缩略图
imagejpeg($desc_img);

imagedestroy($desc_img);
imagedestroy($src_img);
?>


//5.使用imagecopyresampled函数做缩略图:
<?php
$img_name = "tower.jpg";
$percent = 0.2;

$src_img = imagecreatefromjpeg($img_name);

$ow = imagesx($src_img);    //取得原图的宽
$oh = imagesy($src_img);    //取得原图的高

$nw = $ow * $percent   //计算新图的宽度
$nh = $oh * $percent   //计算新图的高度

$desc_img = imagecreate($nw,$nh); //建立新图

imagecopyresampled($dec_img,$src_img,0,0,0,0,$nw,$nh,$ow,$oh); //生成缩略图

imagejpeg($desc_img);
imagedestroy($desc_img);
imagedestroy($src_img);
?>
  • 实例:生成带有底纹的数字验证码图片
<?php
$img_height = 60;
$img_width = 20;

for ($tmpa=0; $tmpa <4 ; ++$tmpa) {
  $nmsg[$tmpa]=dechex(rand(0,15));    //生成随机数,并转成十六进制,作为验证码
}

$aimg = imagecreate($img_height,$img_width);    //生成图片
imagecolorallocate($aimg,255,255,255);          //图片底色
$black = imagecolorallocate($aimg,0,0,0);       //定义需要的黑色

//用黑色的矩形把图片包围
imagerectangle($aimg,0,0,$img_height-1,$img_width-1,$black);

//下面的代码生成底纹,其实就是在图片上生成的一些符号
for ($i=0; $i < 100; ++$i) {
  //使用*行号作为底纹,为了使底纹看起来杂乱无章、五颜六色,需要一个个地生成,同时使位置、颜色、大小都用随机数
  imagestring($aimg,1,mt_rand(1,$img_height),mt_rand(1,$img_width),"*",
  imagecolorallocate($aimg,mt_rand(200,255),mt_rand(200,255),mt_rand(200,255)));
}

//生成验证码,同样的道理,验证码一个个地输出到图片上,同时其位置、颜色、大小都用随机数
for($i=0;$i<count($nmsg);++$i){
  imagestring($aimg,mt_rand(3,5),$i*$img_height/4+mt_rand(1,10),mt_rand(1,$img_width/4),
  $nmsg[$i],imagecolorallocate($aimg,mt_rand(0,100),mt_rand(0,150),mt_rand(0,200)));
}

header("Content-type:image/png");
imagepng($aimg);
imagedestroy($aimg);
?>

七、PHP 与 MySQL

Web程序中的各类数据需要靠数据库存储,只有在数据库配合的基础上,PHP才能发挥其最大功效。

MySQL本身并不是数据库,他只是用来创建、维护、管理数据库的计算机软件。

1.MySQL数据库的基本操作

//windous 登录MySQL命令
mysql -u user_name -p password -h host
//退出MySQL
quit
exit

//创建数据库
create database database_name;

//删除数据库
drop database database_name;

//表的建立
create table Users(
UserId int unsignd not null,
UserName varchar(50) not null,
Gender char(6) not null defaultale',
RegTime date not null;
);
// varchar是变长字符串,在1-255之间
// char指定长度,不足空格补

//建立索引:INDEX
create table books(
id int not null,
name varchar(40) not null,
price = decimal(3,2),
index idx(id)
);

//特殊索引,主键
create table users(
id int not null primary key,
name varchar(30),
create_time date
);

//查看某个数据库中所有表的命令
show tables

//查看某个表的结构
use database
describe table_name

//插入数据
insert into users(id,name,created_time) values (1,'MrLiuQ','2017-07-22 10:18:00');
insert into users values(1,'MrLiuQ','2017-07-22 10:18:00');//省略字段名
insert into users set id=2,name='David',create_name='2017-07-22 10:18:00';

//查询数据
SELECT name,created_time AS ct FROM users;

//条件查询
SELECT *FROM users WHERE name='MrLiuQ';
SELECT *FROM users WHERE created_time>'2017-07-22 10:18:00';
SELECT *FROM users WHERE name='MrLiuQ'->AND created_time>'2017-07-22 10:18:00';
SELECT *FROM users WHERE name='MrLiuQ'->OR created_time>'2017-07-22 10:18:00';

//更新数据
UPDATE users SET name'Lily Cameron' WHERE id=3;//成功后,表users中id为3的用户名被修改为Lily Cameron

//删除数据
DELETE FROM users WHERE name='Lily Cameron';

//对查询结果做排序
SELECT *FROM users WHERE created_time >'2017-07-22 10:18:00'->ORDER BY id DESC;//ASC表示升序,DESC表示降序。

//对查询结果做分组
SELECT city FROM users GROUP BY city;

//对查询结果做限定
SELECT name,city FROM users ORDER BY name LIMIT 4;//返回前4条信息

2.MySQL的数据类型

INT:整数值。UNSIGNED INT指定无符号整数值
DECIMAL:指定数字值的精度和范围
REAL:浮点数值
CHAR:定长字符类型
VARCHAR:变长字符串,在1~255之间
TEXT:文本类型
DATE:日期值
TIME:时间值
DATETIME:MySQL支持,存放日期和日期类型

3.MySQL函数

COUNT():统计表中记录个数或这列中值的个数
MAX():返回某列中的最大值
MIN():返回某列中的最小值
SUM():指定列的值求和
AVG():计算指定列的平均值
LENGTH():字符串的长度
SUBSTRING():截取子字符串
YEAR():返回指定日期的年份
UNIX_TIMESTAMP():返回一个UNIX时间戳
DATE_FORMAT():将一个日期格式化
NOW():返回MySQL服务器系统的当前日期和时间

//计算表中总共有多少条记录
SELECT COUNT(*) FROM users;
//计算特定值的个数
SELECT COUNT(*) FROM users WHERE name LIKE 'J%';

//计算列最大值
SELECT MAX(salary) AS max_salary FROM emp_salary;

//计算列最小值
SELECT MIN(salary) AS max_salary FROM emp_salary;

//求和
SELECT SUM(salary) AS total_salary FROM emp_salary;

//求平均
SELECT AVG(salary) AS avg_salary FROM emp_salary;

//字符串长度
SELECT LENGTH('string in MySQL');

//截取指定长度字符串
SUBSTRING(string,pos,len);

//获取一个UNIX时间戳
SELECT UNIX_TIMESTAMP() AS timestamp;

//格式化输出日期
SELECT DATE_FORMAT<created_time,'%Y年%m月%d日'> AS DATE-> FROM users WHERE id=3;

4.用PHP操作MySQL数据库

步骤:
=> 建立数据库的链接
=> 选择要使用的数据库
=> 创建SQL语句
=> 执行SQL语句
=> 获取SQL执行结果
=> 处理数据结果集
=> 关闭与数据库的链接

//连接数据库
mysql_connect(string $server,string $user_name,string $password,[bool $new_link,int $client_type]);
mysql_pconnect(...)  //长久链接
$conn = mysql_connect('locolhost','root','user_pass');

//关闭数据库
bool mysql_close([resource $link]);

//执行SQL语句
mysql_query(string $sql);

//处理查询结果集的函数
mysql_affected_rows();      //取前一次MySQL操作记录行数。
mysql_fetch_row($result);  //从查询结果集中返回一行数据。$result是执行mysql_query()之后返回的资源标识符
mysql_fetch_array($result,$type);  //从结果集中返回一行作为关联数组
mysql_fetch_assoc($result);        //该函数只将结果集作为关联数组返回

//获取字段信息
object mysql_fetch_field($result [, int field_offset]);

//选择一个数据库
mysql_select_db($database);
//取得结果集的行目数
mysql_num_rows($result);
//返回最近一次MySQL操作产生的错误文本信息
mysql_error();


//PHP程序
<?php
$host = 'localhost';    //定义服务器
$user_name = 'root';  //定义用户名
$password = 'admin';  //定义密码

$conn = mysql_connect($host,$user_name,$password);  //连接MySQL
if(!$conn){
      die('数据库连接失败:'.mysql_error());
}
mysql_select_db('test');  //连接数据库

$sql = 'select id,name,city from users';  
$result = mysql_query($sql) OR die("<br/>ERROR:<b>".mysql_error()."</b><br/><br/><br/>产生问题的SQL<br/>".$sql);  //获取查询结果


if($result){
    echo 'SQL语句:'.$sql.'<br/>已经成功执行!';
    $num = mysql_num_rows($result);  //调用mysql_num_row()获取SELECT语句查询
    echo '<br/>该SQL语句查询到<b>'.$num.'</b>行数据';
}

if($num = mysql_num_rows($result))  //判断SELECT语句查找到的行数
{
    $row = mysql_fetch_array($result);  //mysql_fetch_array()将结果集中的一行作为数组返回
    echo '<pre>';   //格式化输出
    while($row = mysql_fetch_array($result,MYSQL_ASSOC))
    {
      print_r($row);    //输出每行数据
    }
}

mysql_close($conn);
?>

八、PHP 与 MVC开发设计模式


1.什么是MVC模型?

MVC是Model_View_Control的缩写,简单的讲Model是程序的数据模型,View是程序的视图界面,Control是程序的流程控制处理部分。

大部分的操作由Control完成,主要有两个动作:
1.根据用户界面(view)的操作完成对程序数据(model)的更新
2.将程序数据(model)的改变及时反映到用户界面(view)上

优点:程序结构更加清晰,代码稳定性更强,有利于提高开发效率,有利于控制开发速度。

2.MVC模型的核心组成:

1.模型(Model——M):既然是数据模型,那么它就携带着数据,通常还会将业务规则的实现放进模型,这意味着模型不仅仅是数据的容器,还是数据的监控者
2.视图(View——V):Web而言,视图就是用户看到的HTML页面,从程序角度来说,视图负责生成用户界面,通常根据数据模型中的数据转化成HTML输出给用户
3.控制器(Controller——C):负责协调整个应用程序的运转,对于WEB而言,就是接受浏览器的请求,并决定调用哪个模型构件去处理浏览器端发出的请求,然后确定用哪个视图来显示模型处理返回的数据。

3.PHP开发中的模板技术:

在PHP开发中,模板不可或缺。本节将首先介绍模板的基本概念和其在PHP程序中的用法,然后一个优秀的模板引擎——Smarty。

  • 什么是模板?
    模板是一组插入了HTML的PHP脚本,或者说是插入了PHP脚本的HTML文件
  • 在PHP程序中使用模板:Demo
//temp.html
<html>
  <head>
    <title>{pagetitle}</title>
  </head>
  <body>
    {greetings}
  </body>
</html>


//temp.php
<?php
$template_file = "temp.html";     //模板文件

$fs = fopen($template_file,"r");  //打开文件
$content = fread($fs,filesize($template_file));   //读取文件内容
fclose($fs);

$content = print_page($content,"pagetitle","模板应用");
$page = print_page($content,"greetings","您好,这个页面由模板生成");
echo $page;

function print_page($temp_c,$temp_v,$str_c){
  return preg_replace("/\{".$temp_v."\}/",$str_c,$temp_c);
}
?>
  • Smarty模板引擎:
    PHP中有很多模板引擎可供选择,Smarty是一款易于使用且功能强大的PHP模板引擎
    Demo:
//Smarty.tpl
{* 这里是Smarty模板的注释*}
<html>
<head>
  <title>{$page_title}</title>
</head>

<body>
大家好,我是{$name}模板引擎,欢迎大家在PHP程序中使用{$name}。
</body>
</html>
{*模板文件结束*}


//Smarty.php
<?php
include("./Smarty/libs/Smarty.class.php");  //包含Smarty类文件

$smarty = new Smarty();   //建立Smarty类的实例$smarty
$smarty->template_dir = "./templates";  //设置模板目录
$smarty->compile_dir = "./templates_c"; //设置编译目录

$smarty->left_delimiter = "{";    //设定左右边界符为{},Smarty推荐使用<{}>
$smarty->right_delimiter = "}";

$smarty->assign("name","Smarty");            //进行模板变量替换
$smarty->assign("page_title","Smarty的使用"); //进行模板变量替换

$smarty->display("Smarty.tpl");     //编译并显示位于./templates下的Smarty.tpl模板
?>

4.其他常见的基于MVC的PHP框架简介:

  • Laravel:在国外非常流行,国内用的少,适用于大项目。官网:http://laravel.com
  • thinkphp:适用于小项目,国产,在中国用的比较多。官网:http://thinkphp.cn
  • CodeIgniter:适用于中小型项目。一个小巧、但功能强大的、由PHP编写的、基于MVC的Web应用开发框架。同时也是经过Apache/BSD-style开源许可授权的免费框架。官网:http://codeigniter.org.cn
  • CakePHP:命令行代码生成工具让开发者可以快速生成应用程序框架。官网:http://www.cakephp.org
  • Zend Framework: PHP官方的框架,由Zend公司负责开发和维护。官网:http://framework.zend.com
  • FleaPHP:一款国产Web开发框架,官网:http://www.fleaphp.org

尾篇:总结了15天,终于写完了,存在很多不足,需要去完善
各位大神如果发现那里写的不对,可以私信我。
我会细心修改,
谢谢!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,598评论 18 139
  • PHP 学习目录 ├─PHP视频教程 1 LAMP网站构建 │ ├─PHP教程 1.1.1 新版视频形式介绍│ ...
    曹渊说创业阅读 16,147评论 29 417
  • PHP常用函数大全 usleep() 函数延迟代码执行若干微秒。 unpack() 函数从二进制字符串对数据进行解...
    上街买菜丶迷倒老太阅读 1,352评论 0 20
  • 本文原发于微信公众号“小夭书咖”,关注我们,更多精彩。如若转发,请联系作者,就是我啦,嘻嘻( •̀∀•́ ) 在无...
    慕谖阅读 316评论 0 0
  • tomcat的会话保持方式有三种:1、session sticky:会话粘滞,通过同一个客户端的相关请求分发到同一...
    姜饼人_9e7b阅读 1,908评论 0 2