人小时候总是鄙夷“酒肉朋友”这四个字,长大后才发现,在你最难过的时候,只有喝杯酒和大块吃肉能让你稍微舒服些。某种意义上说酒肉才是你永恒的好朋友,因为它们从不弃你而去,所以世界上伤心的胖子越来越多。

文件包含

文件包含有点类似Python中的包,你可以自己写包然后在另一个脚本中调用你自己写的包,PHP的文件包含有两个函数include与require,看看他们的区别:

  • require 生成一个致命错误(E_COMPILE_ERROR),在错误发生后脚本会停止执行。
  • include 生成一个警告(E_WARNING),在错误发生后脚本会继续执行。

区别就是require出错了就停止了并且报错,include出错了还可以继续执行。

案例一:

在当前目录下有一个index.php,里面的内容是:

<?php
header("Content-type: text/html; charset=utf-8");
echo 'www.sxadmin.github.io';
echo "<br>";
echo '不将就';
?>

同目录下新建一个PHP文件:

<?php
header("Content-type: text/html; charset=utf-8");
include 'index.php';
?>

运行结果:

www.sxadmin.github.io
不将就

如果使用require的话就直接把include改掉就ok。

案例二

上面只是一个简单的包含调用,如果你包含调用的文件中有变量需要你使用的话,看看下面的例子。

首先写一个菜单超链接文件,并且包含两个变量$name与$age,内容如下:

<?php
header("Content-type: text/html; charset=utf-8");
echo '<a href="/">首页</a>
<a href="/phpinfo.php">info信息</a>
<a href="/l.php">探针</a>';
$name='langzi';
$age='22';
?>

运行结果:

点击探针的话或跳转过去的哟~

这个时候我可以调用后直接使用被调用的文件内的变量哦~

<html>
<body>
<div class="leftmenu">
<?php
header("Content-type: text/html; charset=utf-8");
include 'index.php';
echo '<hr>';
echo $name.'<br>';
echo $age;
?>
</body>
</html>

运行结果:

文件处理

就像Python中打开处理文本一样,除了格式上略有不同。

<?php
header("Content-type: text/html; charset=utf-8");
// 设置编码
$file = fopen("index.txt", "r") or exit("无法打开文件!");
// 打开文件,如果不存在输输出无法打开文件
while(!feof($file))
{
    echo fgets($file). "<br>";
}
// 读取文件每一行,直到文件结尾
fclose($file);
// 关闭文件
?>

相关函数:

  • feof() 函数检测是否已到达文件末尾(EOF)。

    if (feof($file)) echo “文件结尾”;

  • fgets() 函数用于从文件中逐行读取文件。在调用该函数之后,文件指针会移动到下一行。

  • fgetc() 函数用于从文件中逐字符地读取文件。在调用该函数之后,文件指针会移动到下一个字符。

关于PHP中文件操作还有很多知识点,这里不一一列举,详细请参考PHP文件操作

Cookie

使用setcookie()创建cookies,注意setcookie() 函数必须位于 标签之前。下面的例子是先创建一个cookie值,有效时间为一个小时

<?php
setcookie("langzi", "zhaohan", time()+3600);
?>
<html>
<?php
// 输出 cookie 值
echo $_COOKIE["langzi"];
echo '<hr>';
// 查看所有 cookie
print_r($_COOKIE);
?>
</html>

运行结果:

zhaohan
--------------------------------------------------
Array ( [langzi] => zhaohan [Pycharm-31941b8e] => 016cf837-253e-4bd4-bebc-bb57ec4bdc6e [Phpstorm-d94e29df] => 9ab3f44d-78b3-48ff-9a0d-621a484e0cdf )

删除COOKIE

<?php
// 设置 cookie 过期时间为过去 1 小时
setcookie("langzi", "", time()-3600);
?>

错误/异常/捕获异常处理

PHP中对错误异常的处理比Python中要多一些,错误处理PHP中可以使用die()函数来处理,但是重点还是放在异常处理与异常捕获上面。

  • Try - 和Python中一样。
  • Throw - 里规定如何触发异常。有点像Python异常处理里面的raise抛出异常,但是在PHP当中你先定义出现异常的条件,每一个 “throw” 必须对应至少一个 “catch”。如果抛出了异常,就必须捕获它。
  • Catch - 和Python中的Exception一样,”catch” 代码块会捕获异常,并创建一个包含异常信息的对象。

案例:

<?php
header("Content-type: text/html; charset=utf-8");
// 创建一个有异常处理的函数
function checkNum($number)
{
    if($number>1)
    {
        throw new Exception("变量值必须小于等于 1");
        // 出现异常的条件,新建一个异常对象
    }
    return true;
}

// 在 try 块 触发异常
try
{
    checkNum(2);
    // 如果抛出异常,以下文本不会输出
    echo 'okok';
    //如果是正常的话就执行上面的输出okok,但是传入参数2大于1,会出现异常
}
// 捕获异常
catch(Exception $e)
    // 这里就像Python的 except Exception as e
{
    echo 'Message: ' .$e->getMessage();
}
?>

运行结果:

Message: 变量值必须小于等于 1

创建一个异常的类

就像Python的类class一样,PHP中创建自定义的异常处理程序非常简单。我们简单地创建了一个专门的类,当 PHP 中发生异常时,可调用其函数。该类必须是 exception 类的一个扩展。
这个自定义的 customException 类继承了 PHP 的 exception 类的所有属性,可向其添加自定义的函数。:

<?php
header("Content-type: text/html; charset=utf-8");
class customException extends Exception
// 从Exception继承过来,类似Py的class(exception)它从旧类继承了属性和方法,我们可以使用 exception 类的方法,比如 getLine()、getFile() 和 getMessage()。
{
    public function errorMessage()
        // 公共属性,这个类的每个函数都能使用这个公共的函数
    {
        // 错误信息
        $errorMsg = '错误行号 '.$this->getLine().' in '.$this->getFile().': <b>'.$this->getMessage().'</b> 不是一个合法的 E-Mail 地址';
        //
        return $errorMsg;
    }
}

$email = "someone@example...com";

try
{
    // 检测邮箱
    if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE)
    {
        // 如果是个不合法的邮箱地址,抛出异常
        throw new customException($email);
    }
}

catch (customException $e)
{
//display custom message
    echo $e->errorMessage();
}
?>

运行结果:

错误行号 22 in E:\PHPSTUDY\PHPTutorial\WWW\PHP study5-10\PHP-base\php-exeption.php: someone@example...com 不是一个合法的 E-Mail 地址

在类中public是用来声明公共作用域中的属性。公共属性,就是可以有相应的对象直接操作和访问的。

操作MYSQL数据库

就像在Python中操作数据库一样,在PHP中使用mysql_xx()函数可以直接对MYSQL数据库进行连接关闭与增删改查。

连接数据库与关闭

<?php
mysql_connect("localhost:3306",'root','root');
mysql_close();
?>

和Python中的oymysql一样,首先定义一个数据库连接,最后关闭连接。定义一个变量$coon当作这个数据库的连接变量。如果连接失败就报个异常。

<?php
$coon = mysql_connect('localhost:3306','roottt','root');
if (!$coon)  {
    echo 'Could not connect: ' . mysql_error();
}
?>

运行结果:

Warning: mysql_connect(): Access denied for user 'roottt'@'localhost' (using password: YES) in E:\PHPSTUDY\PHPTutorial\WWW\PHP study5-10\PHP-base\php_mysql.php on line 2
Could not connect: Access denied for user 'roottt'@'localhost' (using password: YES)

创建数据库与表

<?php
/**
 * Created by PhpStorm.
 * User: Sxadmin
 * Blog: sxadmin.github.io
 * Date: 2018/5/18 0018
 * Time: 15:08
 */

header("Content-type: text/html; charset=utf-8");
$coon = mysql_connect('127.0.0.1','root','root');
if (!$coon){
    echo '连接数据库失败'.mysql_error();
}
//创建一个数据库 lang
if (mysql_query('create database lang',$coon)){
    echo '数据库创建成功';
}else{
    echo '数据库创建失败'.mysql_error();
}
// 在lang数据库创建一个表 msg
// 首先选择数据库,使用mysql_select_db
mysql_select_db('lang');
// 然后开始创建表了
// 就像在Python中一样,你可以把SQL语句放在一个变量里面,注意这里的语法不一样,括号内容不要加引号
$sql = 'create table msg(
    name varchar(10),
    age varchar(10)
)';
// 执行这条SQL语句
if (mysql_query($sql,$coon)){
    echo 'msg表创建成功';
}else{
    echo 'msg表创建失败'.mysql_error();
}
mysql_close();
?>

运行结果:

数据库创建成功msg表创建成功

数据库中也多了lang这个数据库,其中有msg这个表,可以增加一个自增长的ID作为主键,此时SQL语句可以这么写。

$sql = "CREATE TABLE Persons 
(
personID int NOT NULL AUTO_INCREMENT, 
PRIMARY KEY(personID),
FirstName varchar(15),
LastName varchar(15),
Age int
)";

增加数据

和Python中一样,知道MYSQL的基础语法就好了,增删改查与pymysql一样,只是记住PHP的语法比如括号引号要注意即可。

<?php
/**
 * Created by PhpStorm.
 * User: Sxadmin
 * Blog: sxadmin.github.io
 * Date: 2018/5/18 0018
 * Time: 15:32
 */

header("Content-type: text/html; charset=utf-8");
$coon = mysql_connect('localhost:3306','root','root');
if (!$coon){
    echo '数据库连接失败'.mysql_error().'<br>';
}else{
    echo '数据库连接成功'.'<br>';
}
mysql_select_db('lang');
$sql="insert into msg(name,age) values ('langzi','18')";
if (!mysql_query($sql,$coon)){
    echo '数据插入失败<br>';
}else{
    echo '数据插入成功<br>';
}
mysql_close($coon);
?>

运行结果:

数据库连接成功
数据插入成功

查看数据库,可以看到数据插进去了…

name|langzi            
age    |18            

获取表单提交的内容

$sql="INSERT INTO Persons (Name, Age)  VALUES  ('$_POST[name]','$_POST[age]')";

查询数据

<?php
/**
 * Created by PhpStorm.
 * User: Sxadmin
 * Blog: sxadmin.github.io
 * Date: 2018/5/18 0018
 * Time: 15:32
 */

header("Content-type: text/html; charset=utf-8");
$coon = mysql_connect('localhost:3306','root','root');
if (!$coon){
    echo '数据库连接失败'.mysql_error().'<br>';
}else{
    echo '数据库连接成功'.'<br>';
}
mysql_select_db('lang');
$sql="select * from msg";
$result = mysql_query($sql,$coon);
if (!$result){
    echo '数据查询失败<br>'.mysql_error();
}else{
    echo '数据查询成功<br>';
    // 这里和pymysql一样,用一个变量存储获取到的数据
    while($row = mysql_fetch_array($result))
        // 打印这个变量
    {
        echo $row['name'] . " " . $row['age'];
        echo "<br />";
    }
}
mysql_close($coon);
?>

运行结果:

数据库连接成功
数据查询成功
langzi 18

要注意的是,这个迭代遍历的结果的值必须与数据库的字段名一致,比如$row[‘name’]就不能用$row[‘naaame’]。

后面的改与删除都和pymysql差不多,只要记住php的语法结构上的差别即可。

文件上传

这个是一个很大的类目,在后面的安全审计中占用很重要的地位,看看php怎么实现文件上传先参考PHP基础

测试上传文件有一个文件夹和两个文件

|-----upload             # 文件上传的目录
|-----form.html          # 表单文件
|-----upload_file.php    # php 上传代码

让我们来逐一分析这些代码:

<html>
<head>
<meta charset="utf-8">
<title>langzi-test-upload</title>
</head>
<body>

<form action="upload_file.php" method="post" enctype="multipart/form-data">
    <!--提交到当目录下的upload_file.php文件-->
<!--application/x-www-form-urlencoded是只能上传文本格式的文件,multipart/form-data是将文件以二进制的形式上传,这样可以实现多种类型的文件上传 -->
    <label for="file">文件名:</label>
    <!--label 元素不会向用户呈现任何特殊的样式。不过,它为鼠标用户改善了可用性,因为如果用户点击 label 元素内的文本,则会切换到控件本身。-->
    <input type="file" name="file" id="file"><br>
    <!--选择文件框框-->
    <input type="submit" name="submit" value="提交">
    <!--上传文件按钮-->
</form>
</body>
</html>

运行结果:

继续分析上传的PHP代码:

<?php
header("Content-type: text/html; charset=utf-8");
$allowedExts = array("gif", "jpeg", "jpg", "png");
// 数组内保存是允许上传的文件后缀
$temp = explode(".", $_FILES["file"]["name"]);
//explode把字符串变成数组,这个就像Python的字典变成JSON一样,不过只是像并非性质一样。参考https://sxadmin.github.io/PHP之String函数笔记.html
//通过使用 PHP 的全局数组 $_FILES,你可以从客户计算机向远程服务器上传文件。
echo $_FILES["file"]["size"];
// 输出文件名和大小
$extension = end($temp);
// 获取文件后缀名
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/jpg")
|| ($_FILES["file"]["type"] == "image/pjpeg")
|| ($_FILES["file"]["type"] == "image/x-png")
|| ($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 204800)
// 小于 200 kb
&& in_array($extension, $allowedExts))
    // in_array() 函数搜索数组中是否存在指定的值。
// php中的关系运算符:&&(and)、||(or)、xor(亦或)、!(非)
{
    if ($_FILES["file"]["error"] > 0)
    // 上传文件的返回信息中如果出现error这个单词就说明上传失败,有点类似Py中的find('error')>0
    {
        echo "错误:: " . $_FILES["file"]["error"] . "<br>";
    }
    else
    {
        echo "上传文件名: " . $_FILES["file"]["name"] . "<br>";
        echo "文件类型: " . $_FILES["file"]["type"] . "<br>";
        echo "文件大小: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
        echo "文件临时存储的位置: " . $_FILES["file"]["tmp_name"] . "<br>";

        // 判断当期目录下的 upload 目录是否存在该文件
        // 如果没有 upload 目录,你需要创建它,upload 目录权限为 777
        if (file_exists("upload/" . $_FILES["file"]["name"]))
        {
            echo $_FILES["file"]["name"] . " 文件已经存在。 ";
        }
        else
        {
            // 如果 upload 目录不存在该文件则将文件上传到 upload 目录下
            move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $_FILES["file"]["name"]);
            echo "文件存储在: " . "upload/" . $_FILES["file"]["name"];
        }
    }
}
else
{
    echo "非法的文件格式";
}
?>

选择文件再上传