PHP基础学习
在php中 , . 表示字符串连接符
echo "1111111111" . "2222222222" . "333333333<br/>";
print "1111111111" . "2222222222" . "333333333<br/>";
echo "你好,你的余额为:" . 20000 . "元<br/>";
引号的问题:
-
双引号:里面可以包裹字符串和变量。
-
单引号:单引号只能表示字符串,不能引用变量。
-
反引号: 用于执行操作系统命令并返回结果
$addr = "四川成都";
echo "你当前所在城市为:$addr <br/>";
echo '你当前所在城市为:$addr <br/>';
echo `date /T`;
代码理解部分
$i = date("s");
while ($i <= 30) {
ob_flush(); // 清空缓冲区,直接输出
flush();
echo date("Y-m-d H:i:s") . "<br/>";
$i = date("s");
sleep(1);
}
数组部分
php中数组的定义方式
$students = array("李源远","王佳乐","李园翔","刘俊","冉攀","邹松鹤","陈凯","王一清","胡涛","李云颢","张先发","王淼", "徐志豪","张霖","崇青平","范金辉","李浩民","王昀东","张亚飞","何思成","王亮","张良","翁通达","廖志凌");
取数组的长度
$len = count($students);
echo $len . "<br/>";
删除最后一个值
array_pop($students);
print_r($students);
echo '<p/>';
数组的遍历
用循环生成下标的方式
for ($i=0; $i<count($students); $i++) {
echo $students[$i] . "<br/>";
}
foreach遍历
foreach ($students as $stu) {
echo $stu . "<br/>";
}
注意:这两种遍历方式,输出的结果一致!
数组去重
$grade = array(87, 95, 38, 59, 67, 49, 99, 82, 59, 99, 67, 73);
$new = array_unique($grade);
print_r($new);
echo '<p/>';
数组排序
$grade = array(87, 95, 38, 59, 67, 49, 99, 82, 59, 98, 67, 73);
rsort($grade);
foreach ($grade as $g) {
echo $g . "<br/>";
}
关联数组:以key=>value组成的键值对,取值的时候用key来取值,而不是下标 索引数组的key就是0、1、2、3这种数字
$student01 = array('name'=>'张三', 'age'=>30, 'addr'=>'成都高新区', 'phone'=>'18812345678');
$student02 = array('name'=>'李中', 'age'=>30, 'addr'=>'成都高新区', 'phone'=>'18912345676');
$student03 = array('name'=>'王九', 'age'=>25, 'addr'=>'成都高新区', 'phone'=>'19812345678');
$student04 = array('name'=>'赵六', 'age'=>30, 'addr'=>'成都高新区', 'phone'=>'18112345679');
$student05 = array('name'=>'周七', 'age'=>27, 'addr'=>'成都高新区', 'phone'=>'18812345978');
print_r($student01);
echo "<br/>";
echo $student01['name']. "<br/>";
$student01['addr'] = '成都天府新区';
补充4个重要的数组相关函数
直接取最后一个值,无所谓是哪种数组
echo end($student05) . "<br/>";
if (in_array('周八', $student05)) {
echo "在<br/>";
}
把字符串打散为数组。
$source = "Typora.exe#9284#Console#1#92680K";
$myarray = explode("#", $source);
print_r($myarray);
echo '<br/>';
把数组合并成字符串
$grade = array(87, 95, 38, 59, 67, 49, 99, 82, 59, 98, 67, 73);
$result = implode(",", $grade);
echo $result . "<br/>";
$student01 = array('name'=>'张三', 'age'=>30, 'addr'=>'成都高新区', 'phone'=>'18812345678');
$student02 = array('name'=>'李四', 'age'=>30, 'addr'=>'成都高新区', 'phone'=>'18912345676');
$student03 = array('name'=>'王九', 'age'=>25, 'addr'=>'成都高新区', 'phone'=>'19812345678');
$student04 = array('name'=>'赵六', 'age'=>30, 'addr'=>'成都高新区', 'phone'=>'18112345679');
$student05 = array('name'=>'周七', 'age'=>27, 'addr'=>'成都高新区', 'phone'=>'18812345978');
二维数组
$class01 = array($student01, $student02, $student03, $student04, $student05);
echo $class01[1]['name']; // 李四
设置使用中国北京时间作为系统时区
date_default_timezone_set("PRC");
后端与数据库端连接
定义一个方法,用于建立与数据库的连接
private function create_connection() {
$conn = mysqli_connect($this->host, $this->username, $this->password, $this->database)
or die("数据库连接不成功.");
mysqli_query($conn, "set names utf8");
return $conn;
}
设置编码格式的两种方式
mysqli_query($conn, "set names utf8");
mysqli_set_charset($conn, 'utf8')
拼接SQL语句并执行它
$sql = "select * from user where username='$username' and password='$password'";
$result = mysqli_query($conn, $sql); // $result获取到的查询结果,称结果集
函数
function calc($a, $b) {
$result = $a + $b;
echo "运算结果为:$result <br/>";
return $result;
}
function checkPhone_01($phone) {
$len = strlen($phone);
if ($len != 11) {
echo "长度必须为11位.<br/>";
return false; // 代码运行到此,就会返回到调用的地方,不再往下运行
}
if ($phone[0] != 1) {
echo "第1位必须为1.<br/>";
return false;
}
if ($phone[1] < "3" || $phone[1] > "9") {
echo "第2位必须为3-9.<br/>";
return false;
}
for ($i=2; $i<11; $i++) {
if ($phone[$i] < "0" || $phone[$i] > "9") {
echo "后9位必须是数字.<br/>";
return false;
}
}
return true; // 如果前面的代码块均没有return,则认为电话号码是有效的
}
使用正则表达式判断手机号码
function checkPhone($phone) {
$result = preg_match("/^1[3-9]\d{9}$/", $phone);
return $result;
}
获取请求数据的方式:
// 前端用GET请求发,后台用$_GET函数取,前端用POST请求发,后台用$_POST函数取
// $username = $_GET['username'];
// $password = $_GET['password'];
// $vcode = $_GET['vcode'];
$username = $_POST['username'];
$password = $_POST['password'];
$vcode = $_POST['vcode'];
Session部分
Session的声明与使用
Session的设置不同于Cookie,必须先启动,在PHP中必须调用session_start()。session_start()函数的语法格式如下:
Bool session_start(void) //创建Session,开始一个会话,进行Session初始化
注意:session_start()函数之前不能有任何输出
代码理解部分
session_start();
if ($_SESSION['islogin'] != 'true' || $_SESSION['role'] != 'editor') {
die("你无权新增文章");
}
session_start();
if ($_SESSION['islogin'] != 'true') {
die ("请先登录.");
当第一次访问网站时,Seesion_start()函数就会创建一个唯一的Session ID,并自动通过HTTP的响应头,将这个Session ID保存到客户端Cookie中。同时,也在服务器端创建一个以Session ID命名的文件,用于保存这个用户的会话信息。当同一个用户再次访问这个网站时,也会自动通过HTTP的请求头将Cookie中保存的Seesion ID再携带过来,这时Session_start()函数就不会再去分配一个新的Session ID,而是在服务器的硬盘中去寻找和这个Session ID同名的Session文件,将这之前为这个用户保存的会话信息读出,在当前脚本中应用,达到跟踪这个用户的目的。 Session以数组的形式使用,如:$_SESSION['session名']
代码理解部分
<?php
//启动session的初始化
session_start();
//注册session变量,赋值为一个用户的名称
$_SESSION["username"]="skygao";
//注册session变量,赋值为一个用户的ID
$_SESSION["uid"]=1;
?>
执行该脚本后,两个Session变量就会被保存在服务器端的某个文件中,该文件的位置是通过php.ini文件,在session.save_path属性指定的目录下。
代码理解部分
<?php
//第一步:开启Session并初始化
session_start();
//第二部:删除所有Session的变量,也可以用unset($_SESSION[XXX])逐个删除
$_SESSION = array();
//第三部:如果使用基于Cookie的session,使用setCookkie()删除包含Session ID的cookie
if(isset($_COOKIE[session_name()])) {
setCookie(session_name(), "", time()-42000, "/");
}
//第四部:最后彻底销毁session
session_destroy();
?>
session.cookie_path = / ; cookie的有效路径
session.cookie_domain = ; cookie的有效域
session.name = PHPSESSID; 用在cookie里的session的名字
session.save_handler = files ; 用于保存/取回数据的控制方式
session.save_path = /tmp ; 在 save_handler 设为文件时传给控制器的参数, 这是数据文件将保存的路径.
session.use_cookies = 1 ; 是否使用cookies
<?php
//开启session
session_start();
//在每个URL后面附加上参数,变量名为session_name()获取名称,值通过session_id()获取
echo '<a href="demo.php?'.session_name().'='.session_id().'">连接演示</a>';
?>
在使用Linux系统做服务器时,则在编辑PHP时如果使用了–enable-trans-sid配置选项,和运行时选项session.use_trans_sid都被激活,在客户端禁用Cookie时,相对URL将被自动修改为包含会话ID。如果没有这么配置,或者使用Windows系统作为服务器时,可以使用常量SID。该常量在会话启动时被定义,如果客户端没有发送适当的会话Cookie,则SID的格式为session_name=session_id,否则就为一个空字符串。因此可以无条件地将其嵌入到URL中去。在下例中使用两个脚本程序,演示了Session ID的传送方法。
<?php
session_start();
$_SESSION["username"]="admin";
echo "session ID:".session_id()."<br>";
?>
文件读写操作
代码理解部分
<?php
// 创建文件
$touch = ('./a.php');
var_dump($touch);
// 移动文件 重命名
$touch = rename('./a.php','./b.txt');
var_dump($touch);
//删除文件
$touch = unlink('./a.php');
// 获取文件大小
$filesize = filesize('./fa.jpg');
var_dump($filesize);
//判断是否是文件 判断文件为true 判断目录为false
$is_file = is_file('./test.php');
var_dump($is_file);
$is_file = is_file('./PHP');
var_dump($is_file);
// 判断文件是否存在,存在则删除
if(file_exists('./b.txt')){
echo "文件存在";
unlink('./b.txt');
echo "文件已删除";
}
else{
echo '文件不存在';
}
// 文件是否可执行
$is_executable = is_executable('./../xray_windows_amd64.exe');
var_dump($is_executable);
// 文件是否可写可读
$is_write = is_writeable('./test.php');
$is_read = is_readable('./test.php');
var_dump($is_write);
var_dump($is_read);
// 获取文件的创建时间
$time = filectime('./test.php');
var_dump(date('Y-m-d H:i:s',$time));
// 获取文件的修改时间
$time = filemtime('./test.php');
var_dump(date('Y-m-d H:i:s',$time));
// 获取文件上次访问时间
$time = fileatime('./ ');
var_dump(date('Y-m-d H:i:s',$time));
// 打开文件 读取文件 关闭文件 写入文件
$content = ''; // 声明一个空字符串
$file_open = fopen('./test.php','r'); // 只读文件
$file_write = fopen('./test.txt','w'); // w 是写入文件,如果文件不存在则会创建,如果文件有内容则会清空后再次写入
fwrite($file_write,'<?php phpinfo(); ?>');
fclose($file_write);
while(!feof($file_open)){ // feof 判断指针是否到文件末尾
//$content .= fread($file_open,1); // 一个字节一个字节读
$content = fgets($file_open); // 读取一行的内容
}
echo $content;
fclose($file_open);
// 读取文件 :打开、读取、关闭一步到位
$res = file_get_contents('./test.php');
echo $res;
// 写入文件
$file_write = file_put_contents('./test.txt','<?php phpinfo(); ?>'); // 以w方式写入文件
$file_write = file_put_contents('./test.txt','<?php phpinfo(); ?>',FILE_APPEND); // 在文本后追加语句
var_dump($file_write);
文件读写的步骤
1、打开文件:fopen
2、读写文件:fgets,fwrite
3、关闭文件:fclose
附加函数:
- 1、判断文件是否已经到达末尾:feof($fp)
- 2、一次性将文件所有内容读出:file_get_contents($filename)
- 3、使用file_get_contents还可以发送GET请求
- 4、使用file_put_contents一次性写入文件
- 5、获取当前文件指针所在位置:ftell
- 6、直接将文件指针指向某个位置:fseek
最基本的按行循环读取整份文件
$fp = fopen("E:/userpass.csv", "r");
while (!feof($fp)) {
$line = fgets($fp);
$line = str_replace("\n", "<br/>", $line);
echo $line;
}
fclose($fp);
往文件中写入内容
$fp = fopen("E:/userpass.csv", "a");
fwrite($fp, "\ntest,test123,login-fail");
fclose($fp);
使用file_get_contents直接读取文件内容
使用file_get_contents直接读取文件内容
header("content-type:text/html; charset='gbk'");
$content = file_get_contents("E:/Test.txt");
$content = iconv("GBK", "UTF-8", $content);
$content = str_replace("\n", "<br/>", $content);
echo $content;
$list = explode("\n", $content);
print_r($list);
使用file_get_contents发送GET请求访问网页
content = file_get_contents("http://www.woniunote.com/");
echo $content;
//是否可以用于下载一个文件、一张图片呢? 小任务,完成它,进而思考网页爬虫的设计思路。
$content = file_get_contents("http://www.woniunote.com/img/banner-1.jpg");
file_put_contents("E:\\test.jpg", $content);
使用file_put_contents一次性写入文件
拓展部分:
/*
* UTF-8处理中文时使用的是3字节,而GBK处理中文时是2个字节
* 11001011 01011011 01011110 10100101 01011110 10100101
*/
content = iconv("UTF-8", "GBK", "\nHello蜗牛哦");
// file_put_contents("E:\\Test.txt", $content, FILE_APPEND);
读取一个CSV文件(逗号分隔符),并且解析为二维数组
$content = file_get_contents("E:/userpass.csv");
$rows = explode("\n", $content);
代码理解部分
$list = array();
for ($i=1; $i<count($rows); $i++) {
$temp = explode(",", $rows[$i]);
array_push($list, $temp);
}
print_r($list);
使用PHP模拟tail -f实时查看文件内容
$fp = fopen("E:\\userpass.csv", "r");
fseek($fp, 32);
while ($line = fgets($fp)) {
echo $line . "<br/>";
}
fclose($fp);
@error_reporting(0);
set_time_limit(0);
$pos = 0;
while (true) {
$fp = fopen("./test.txt", "r");
fseek($fp, $pos);
while ($line = fgets($fp)) {
$line = iconv("GBK", "UTF-8", $line);
echo $line . "<br/>";
}
$pos = ftell($fp);
fclose($fp);
ob_flush();
flush();
sleep(2);
}
PHP操作JSON数据
代码理解部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JSON</title>
<script>
function json() {
// var users = ["张三", "李四", "王五", "赵六", "田七"];
// for (var i=0; i<users.length; i++) {
// document.write(users[i] + "<br/>");
// }
// var user1 = {"name":"张三", sex:"男", age:30, phone:"18012345678", addr:"成都"};
// document.write(user1.name);
// var user1 = {"name":"张三", sex:"男", age:30, phone:"18012345678", addr:"成都"};
// var user2 = {name:"李四", sex:"女", age:25, phone:"13012365659",addr:"重庆"};
// var users = [user1, user2];
// var users = [{"name":"张三", sex:"男", age:30, phone:"18012345678", addr:"成都"},
// {name:"李四", sex:"女", age:25, phone:"13012365659",addr:"重庆"}];
// document.write(users[1]['name']);
var users = {user1:["张三","男",30,"18012345678","成都", {province:'四川'}],
user2:["李四","女",25,"13012365659","重庆", {province:'重庆'}]};
// document.write(users.user2[3]);
document.write(users.user1[5].province);
}
</script>
</head>
<body>
<?php
// 引用common.php,如果之前已经引用则不再引用
// require_once('common.php');
// include_once('common.php');
// $conn = create_connection();
// $sql = "select articleid, viewcount, createtime from article where articleid < 10";
// $result = mysqli_query($conn, $sql);
// $data = mysqli_fetch_all($result, MYSQLI_ASSOC);
// echo json_encode($data);
$student01 = array('name'=>'张三', 'age'=>30, 'addr'=>'成都高新区', 'phone'=>'18812345678');
$student02 = array('name'=>'李中', 'age'=>30, 'addr'=>'成都高新区', 'phone'=>'18912345676');
$student03 = array('name'=>'王九', 'age'=>25, 'addr'=>'成都高新区', 'phone'=>'19812345678');
$student04 = array('name'=>'赵六', 'age'=>30, 'addr'=>'成都高新区', 'phone'=>'18112345679');
$student05 = array('name'=>'周七', 'age'=>27, 'addr'=>'成都高新区', 'phone'=>'18812345978');
$class01 = array($student01, $student02, $student03, $student04, $student05);
print_r($class01);
echo json_encode($class01); // JSON序列化:将对象转换成字符串
// JSON反序列化:把一个字符串再转换成对象
$string = '[{"name":"\u5f20\u4e09","age":30,"addr":"\u6210\u90fd\u9ad8\u65b0\u533a","phone":"18812345678"},{"name":"\u674e\u4e2d","age":30,"addr":"\u6210\u90fd\u9ad8\u65b0\u533a","phone":"18912345676"},{"name":"\u738b\u4e5d","age":25,"addr":"\u6210\u90fd\u9ad8\u65b0\u533a","phone":"19812345678"},{"name":"\u8d75\u516d","age":30,"addr":"\u6210\u90fd\u9ad8\u65b0\u533a","phone":"18112345679"},{"name":"\u5468\u4e03","age":27,"addr":"\u6210\u90fd\u9ad8\u65b0\u533a","phone":"18812345978"}]';
$array = json_decode($string);
print_r($array);
?>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="jquery-3.4.1.min.js"></script>
<title>通过JS动态渲染JSON数据</title>
<style>
table {
width: 800px;
margin: auto;
border: solid 1px green;
border-spacing: 0px;
}
td {
border: solid 1px gray;
height: 30px;
}
</style>
<script>
// window.onload = function() {
function list() {
$.get('list-json.php', function(data){
// 后台响应给前端的JSON数据,其content-type有可能是:
// 1、text/plain或text/html,此时必须用eval执行将其转成JS对象
// 2、application/json,则不需要eval,直接使用即可
var data = eval(data);
var content = "";
// data.forEach(function(article) {
data.forEach(article => {
content += "<tr>";
content += "<td>" + article['articleid'] + "</td>";
content += "<td>" + article['author'] + "</td>";
content += "<td>" + article['headline'] + "</td>";
content += "<td>" + article['viewcount'] + "</td>";
content += "<td>" + article['createtime'] + "</td>";
content += "<td><button>删除</button></td>";
content += "</tr>";
});
$("#articleTable").append(content);
$("#articleTable").css('display', '');
});
}
</script>
</head>
<body>
<button onclick="list()">加载</button>
<table id="articleTable" style="display: none;">
<tr>
<td>编号</td>
<td>作者</td>
<td>标题</td>
<td>次数</td>
<td>时间</td>
<td>操作</td>
</tr>
</table>
</body>
</html>
<?php
include_once('common.php');
$conn = create_connection();
$sql = "select articleid, author, headline, viewcount, createtime from article where articleid < 20";
$result = mysqli_query($conn, $sql);
$data = mysqli_fetch_all($result, MYSQLI_ASSOC);
echo json_encode($data);
?>
PHP读取XML数据
XML代码
<?xml version="1.0" encoding="utf8"?>
<class id="WNCDC085">
<student sequence="1">
<id>WNCD201703015</id>
<name>敬小越</name>
<sex>男</sex>
<age>24</age>
<degree>本科</degree>
<school>电子科技大学成都学院</school>
</student>
<student sequence="2">
<id>WNCD201703020</id>
<name>何小学</name>
<sex>男</sex>
<age>29</age>
<degree>本科</degree>
<school>成都理工大学</school>
</student>
<student sequence="3">
<id>WNCD201703025</id>
<name>杨小言</name>
<sex>女</sex>
<age>22</age>
<degree>大专</degree>
<school>四川华新现代职业学院</school>
</student>
</class>
读取class节点的属性id和对应的值
$nodes = $doc->getElementsByTagName('class');
echo $nodes->item(0)->nodeName;
echo $nodes->item(0)->attributes->item(0)->nodeName;
echo $nodes->item(0)->attributes->item(0)->nodeValue;
读取第二个学生的所有信息
$nodes = $doc->getElementsByTagName('student');
$childNodes = $nodes->item(1)->childNodes;
foreach ($childNodes as $node) {
echo $node->nodeValue . "<br/>";
}
读取所有学生的姓名
$nodes = $doc->getElementsByTagName("name");
foreach ($nodes as $node) {
echo $node->nodeValue . "<br/>";
}
将XML文件读取为PHP的二维数组
$nodes = $doc->getElementsByTagName("student");
$students = array();
foreach ($nodes as $k=>$v) {
$students[$k]['id'] = $v->getElementsByTagName('id')->item(0)->nodeValue;
$students[$k]['name'] = $v->getElementsByTagName('name')->item(0)->nodeValue;
$students[$k]['sex'] = $v->getElementsByTagName('sex')->item(0)->nodeValue;
$students[$k]['age'] = $v->getElementsByTagName('age')->item(0)->nodeValue;
$students[$k]['degree'] = $v->getElementsByTagName('degree')->item(0)->nodeValue;
$students[$k]['school'] = $v->getElementsByTagName('school')->item(0)->nodeValue;
}
print_r($students);
//适当优化,简化代码
$nodes = $doc->getElementsByTagName("student");
$students = array();
$tag = array('id', 'name', 'sex', 'age', 'degree', 'school');
foreach ($nodes as $k=>$v) {
foreach ($tag as $t) {
$students[$k][$t] = $v->getElementsByTagName($t)->item(0)->nodeValue;
}
}
print_r($students);
读取firewall.xml的所有端口信息
$doc->load('../demo/firewall.xml');
$nodes = $doc->getElementsByTagName('port');
foreach ($nodes as $node) {
$attr = $node->attributes;
echo $attr->item(1)->nodeValue . "<br/>";
}
XML更新与XPATH
修改节点的属性或值
$doc = new DOMDocument();
$doc->preserveWhiteSpace = false; // 不保留空白节点
$doc->formatOutput = true; // 格式化输出
$doc->load('./student.xml');
$nodes = $doc->getElementsByTagName('student');
修改节点的属性值
$nodes->item(2)->attributes->item(0)->nodeValue = '5';
修改节点的值
$nodes->item(2)->childNodes->item(1)->nodeValue = '杨大言';
foreach($nodes->item(2)->childNodes as $node) {
echo $node->nodeValue . "<br/>";
}
删除节点操作
// 删除一个节点:先找到父节点,再找到子节点,调用父节点的removeChild方法删除
$parent = $nodes->item(2);
$child = $parent->childNodes->item(4);
$parent->removeChild($child);
// // 直接找到要删除的节点自身,再向上一层找到父节点,再调用removeChild进行删除
$child = $doc->getElementsByTagName('degree')->item(2);
$child->parentNode->removeChild($child);
//
$doc->save('./student.xml');
将数组写入XML
// 先定义数组,也可以直接从数据库读取
$student01=array("id"=>"WNCD201703015", "name"=>"敬小越", "sex"=>"男", "age"=>"24", "degree"=>"本科", "school"=>"电子科技大学成都学院");
$student02=array("id"=>"WNCD201703020", "name"=>"何小学", "sex"=>"男", "age"=>"29", "degree"=>"本科", "school"=>"成都理工大学");
$student03=array("id"=>"WNCD201703025", "name"=>"杨小言", "sex"=>"女", "age"=>"22", "degree"=>"大专", "school"=>"四川华新现代职业学院");
$students = array($student01, $student02, $student03);
$doc = new DOMDocument('1.0', 'utf8');
$doc->preserveWhiteSpace = false;
$doc->formatOutput = true;
// 创建根节点 class 并设置 id 属性
$class = $doc->createElement('class');
$class->setAttribute('id', 'WNCDC085');
$doc->appendChild($class);
foreach ($students as $index => $student) {
// 为class节点添加student子节点
$nodeStudent = $doc->createElement('student');
$nodeStudent->setAttribute('sequence', $index+1);
$class->appendChild($nodeStudent);
// 为student节点添加id, name, sex等子节点
foreach ($student as $key => $value) {
$node = $doc->createElement($key);
$nodeStudent->appendChild($node);
// 为各子节点赋值
$nodeValue = $doc->createTextNode($value);
$node->appendChild($nodeValue);
}
}
$doc->save('./write.xml');
XPATH定位元素
$doc = new DOMDocument();
$doc->preserveWhiteSpace = false;
$doc->load('./student.xml');
$xpath = new DOMXPath($doc); // 实例化XPATH对象
// $expression = "/class/student[@sequence='1']/school";
// $expression = "/class/student[@sequence='2']/school";
// $expression = "//student[@sequence='3']/name";
// $expression = "//student[2]/name"; // 找第2个学生的姓名
$expression = "//student/school[contains(text(), '科技')]";
$nodes = $xpath->query($expression); // 返回的是找到的所有节点
echo $nodes->item(0)->nodeValue;
网页爬虫原理与实现
理论部分:
(1)XML与HTML本质上是相同的结构:DOMDocument可以处理XML,原则上来说也可以处理HTML
(2)爬虫主要是爬取网页的内容(基于HTTP和HTML的内容),可以爬取一个网站上的图片,文件,页面内容等。
(3)搜索引擎的工作原理;爬取网页内容,对内容进行分词,分词后建议索引(倒排索引),进行排序后提高服务。
(4)爬取的基本过程;给定一个网址,然后解析响应的HTML页面内容,并下载保存(HTML文件),然后解析其中的超链接或其他资源(比如 图片等),超链接就进行继续的访问和存储,图片就进行下载存档,基于新找到的超链接,又继续解析更多的超链接。
(5)技术层面的实现要点:
1.发送GET请求并获取响应的内容:file_get_contents
2.解析页面中的URL地址或资源地址:DOMDocument
3.继续访问解析出来的地址或资源:根据地址的特点分类和拼接,构建一个完成的URL地址库,继续访问,继续前两步。(广度优先 , 深度优先)
代码理解部分:
DOMDocumen
$content = file_get_contents("http://www.woniunote.com/");
$html = new DOMDocument();
$html->preserveWhiteSpace = false;
@$html->loadHTML($content);
$links = $html->getElementsByTagName('a');
$linkList = array();
foreach ($links as $link) {
// echo $link->nodeValue . "<br/>";
// echo $link->attributes->item(0)->nodeValue . "<br/>";
foreach ($link->attributes as $attr) {
if ($attr->nodeName == "href") {
// echo $attr->nodeValue . "<br/>";
// 利用 / 、 #、 http 三个特征来判断URL地址类型,并完成完整的地址拼接
if (strpos($attr->nodeValue, '/') == 0) {
array_push($linkList, 'http://www.woniunote.com' . $attr->nodeValue);
}
else if (strpos($attr->nodeValue, 'http://') == 0) {
array_push($linkList, $attr->nodeValue);
}
}
}
}
set_time_limit(0);
foreach ($linkList as $link) {
$filename = str_replace("http://www.woniunote.com/", "", $link);
$filename = str_replace("/", "-", $filename);
$content = file_get_contents($link);
file_put_contents("./download/html/$filename.html", $content);
echo "成功下载:$filename <br/>";
ob_flush();
flush();
sleep(0.5);
}
使用Simple HTML Dom库
// 使用Simple HTML Dom库
include_once "simple_html_dom.php";
$html = file_get_html('http://www.woniunote.com/');
// 查找所有的超链接
$links = $html->find('a');
foreach ($links as $link) {
echo $link->href . "<br/>";
}
// 查找所有图片地址
$images = $html->find('img');
foreach ($images as $image) {
$src = $image->src;
if (strpos($src, '/') == 0) {
$url = 'http://www.woniunote.com' . $src;
}
else if (strpos($src, 'http') == 0) {
$url = $src;
}
$filename = end(explode("/", $url));
$content = file_get_contents($url);
file_put_contents("./download/image/$filename", $content);
echo "图片 $filename 下载完成. <br/>";
ob_flush();
flush();
sleep(0.5);
}
// 使用其他的定位方式
// 使用类似于Xpath的方式来定位元素
$titles = $html->find("div[@class='title']");
$titles = $html->find("div[class='title']");
$titles = $html->find("div.title");
foreach ($titles as $title) {
// echo $title->innertext . "<br/>";
echo $title->plaintext . "<br/>";
// echo $title->outertext . "<br/>";
}
// 使用ID属性定位元素
$nodes = $html->find("input[@id='keyword']");
$nodes = $html->find("input#keyword");
$nodes = $html->find("#keyword");
foreach ($nodes as $node) {
echo $node->placeholder;
}
// 直接给定元素下标找对应某一个元素
$html = file_get_html('http://www.woniunote.com/article/609');
$node = $html->find("#content", 0);
echo $node->plaintext;
// 元素之间的层次关系
$titles = $html->find("div.title");
foreach ($titles as $title) {
echo $title->first_child()->innertext . "<br/>";
}
// 用完整个页面的DOM结构后,清空内存
$html->clear();
使用正则表达式
// 使用正则表达式如何解析页面元素
// 正则表达式是将一份HTML源码理解为一个长长的字符串,进而使用正则表达式进行字符串解析和匹配
// 设定左右边界来查找超链接或者其他元素
$content = file_get_contents('http://www.woniunote.com/');
// $pattern = '/<a href="(.*)"/'; // 贪婪模式 :匹配到最后一个
$pattern = '/<a href="(.+?)"/'; // 非贪婪模式 ;匹配到最靠前的一个
preg_match_all($pattern, $content, $result);
print_r($result[1]);
?>
面向对象基础
$name = '张三';
function test() {
// PHP中默认的变量是有作用域的,如果要在函数内部使用函数外的变量,则必须声明为全局变量
global $name;
echo "你好 $name";
}
test();
面向对象编程基础用法
// 定义类:People,单纯定义一个类,本身并不会真正解决问题
class People {
var $name = ''; // 不再称为变量,而是叫类属性
var $age = 0;
var $addr = '';
var $nation = '';
// 定义People类所具备的方法,默认情况下,方法的定义与函数完全一致
function talk() {
// 在类的定义中, $this 指类的具体实例
echo "$this->name 正在说话. <br/>";
}
function work() {
echo "$this->name 正在工作. <br/>";
}
}
// 实例化类People并进行属性和方法的调用
$p1 = new People();
$p1->name = "张三";
$p1->age = 30;
$p1->addr = "成都高新区";
$p1->nation = "汉族";
echo $p1->name . "<br/>";
$p1->talk();
// 一旦完成类的实例化,实例与实例之间并无关系,分布于不同的内存中
$p2 = new People();
$p2->name = "李四";
$p2->age = 25;
$p2->addr = "成都金牛区";
$p2->nation = "藏族";
echo $p2->addr . "<br/>";
$p2->work();
?>
利用面向对象的特性改造数据库操作
// class DB {
// // 为DB类定义数据库连接的必要属性
// var $host = '127.0.0.1';
// var $username = 'root';
// var $password = '123456';
// var $database = 'learn';
// // 定义一个方法,用于建立与数据库的连接
// private function create_connection() {
// $conn = mysqli_connect($this->host, $this->username, $this->password, $this->database)
// or die("数据库连接不成功.");
// mysqli_query($conn, "set names utf8");
// return $conn;
// }
// // 封装两个操作方法,一个用于查询,一个用于更新
// function query($sql) {
// $conn = $this->create_connection();
// $result = mysqli_query($conn, $sql);
// $rows = mysqli_fetch_all($result, MYSQLI_ASSOC);
// return $rows;
// }
// function modify($sql) {
// $conn = $this->create_connection();
// $result = mysqli_query($conn, $sql);
// if (! $result) {
// die("数据库更新操作不成功.");
// }
// }
// // 类的析构方法:当类的实例使用完并从内存中释放时,将会触发调用该方法
// function __destruct() {
// $conn = $this->create_connection();
// mysqli_close($conn);
// }
// }
class DB {
// 为DB类定义数据库连接的必要属性
// private $host = '127.0.0.1';
// private $username = 'root';
// private $password = '123456';
// private $database = 'learn';
var $host = '127.0.0.1';
var $username = 'root';
var $password = '123456';
var $database = 'learn';
// 将数据库连接对象定义为类属性
private $conn = null;
// 定义一个方法,用于建立与数据库的连接
private function create_connection() {
$this->conn = mysqli_connect($this->host, $this->username, $this->password, $this->database)
or die("数据库连接不成功.");
mysqli_query($this->conn, "set names utf8");
return $this->conn;
}
// 封装两个操作方法,一个用于查询,一个用于更新
function query($sql) {
$result = mysqli_query($this->conn, $sql);
$rows = mysqli_fetch_all($result, MYSQLI_ASSOC);
return $rows;
}
function modify($sql) {
$result = mysqli_query($this->conn, $sql);
if (! $result) {
die("数据库更新操作不成功.");
}
}
// 类的构造方法:当类在进行实例化时会触发执行该方法
function __construct($host='127.0.0.1', $username='root', $password='123456', $database='learn') {
$this->host = $host;
$this->username = $username;
$this->password = $password;
$this->database = $database;
echo "调用构造方法,并建立数据库的连接 <br/>";
$this->create_connection(); // 每一个实例化的过程,就会执行一次
}
// 类的析构方法:当类的实例使用完并从内存中释放时,将会触发调用该方法
function __destruct() {
echo "调用析构方法,并关闭数据库的连接 <br/>";
mysqli_close($this->conn);
}
// 当类进行序列化时自动调用,并且返回一个数组,包含要实例化的类属性
function __sleep() {
echo "DB类正在进行序列化. <br/>";
return array('host', 'username', 'password', 'database');
}
// 在类进行反序列时调用,并且可以在该方法中定义恢复类状态的代码,以便于让反序列化的实例可以正常调用方法。
function __wakeup() {
echo "DB类正在被反序列化. <br/>";
$this->create_connection(); // 恢复数据库的连接状态
}
}
封装,继承,多态
封装
/**
* 封装:public, private, protected
* 1. 默认情况下,所有属性和方法,在没有明确设置访问修饰符时,均为public
* 2. private 表示类私有,在类的定义中可以使用,而在实例和子类中均无法使用
* 3. protected 表示受类的保护,实例中不能直接使用,但是在子类中可以使用
*/
class People {
private $name = '王五'; // 定义类时,可以给属性一个初始值,使用了访问修饰符后,不再需要var
var $age = 0;
var $addr = '';
var $nation = '';
// 定义People类所具备的方法,默认情况下,方法的定义与函数完全一致
public function talk() {
// 在类的定义中, $this 指类的具体实例
echo "$this->name 正在说话. <br/>";
}
private function work() {
echo "$this->name 正在工作. <br/>";
}
// 公有方法调用私有方法
protected function eat($type='米饭') {
echo "$this->name 正在吃 $type <br/>";
$this->work();
}
// 针对私有属性,如何在实例中对其进行修改?设置一个公有方法,对类的私有属性进行修改或取值
// 以下两个方法是封装这个特性最经典的演示:公有方法操作私有属性。
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
$p = new People();
// $p->name = "张三"; // 实例无法使用类的私有属性
//echo $p-> . "<br/>";
$p->talk();
$p->setName('张三');
echo $p->getName() . "<br/>";
//$p->eat();
继承
// /**
// * 继承:子承父业、继承传统、发扬光大父类的属性和方法(非
// * 定义类:Man,让其继承父类People,则Man这个类就称为子类,可以继承私有)
// * 子类继承父类时,可以在子类调用protected修改的属性和方法,同时也可以覆盖或重写父类方法
// * 子类也可以在自己类的扩展或创建新的方法和属性
// * 关键字:final,如果一个类被final修饰,则该类不能被继承
// */
class Man extends People {
// Man这个类,什么都不做,People的所有非私有属性和方法均可以使用
// 父类中有的方法,在子类中可以进行覆盖,也称为“重写”,override
function work() {
// $this->eat();
parent::eat();
// 更加正统的做法,在子类中使用parent::调用父类的方法
echo "$this->name 正在工作 <br/>";
}
public function talk() {
echo "$this->name 正在说话. <br/>";
}
// 父类中不存在的方法,子类新建的方法(扩展)
public function drive() {
echo "$this->name 正在开车. <br/>";
}
}
$m = new Man();
// // echo $m->name; // 子类无法直接使用父类的私有属性
// // $m->work(); // 子类无法直接使用父类的私有方法
// // $m->talk();
// // 子类直接定义一个父类拥有的相同的属性,是可以正常工作的
$m->name = "子姓名";
echo $m->name;
$m->work();
$m->talk();
//$m->eat(); // 在子类的实例中,一样无法调用父类的protected方法
$m->drive();
多态
// 多态:多种形态
// 抽象类:只有类的方法中有一个方法使用abstract关键字定义,则该类就是抽象类,该方法就是抽象方法
// 抽象类的特点:不能被实例化,只能被继承,抽象方法不能有实现代码
// 接口:极端的抽象,只能有方法的定义,不能有方法的实现,通常用于定义一些规则
abstract class animal{
// function can(){
// echo "this function weill be re-write in the children. <br/>";
// }
abstract function can(); // 抽象方法不能实现代码,只能定义方法名和参数
// abstract function work();
function dosth() {
echo "做一些事情";
}
}
class cat extends animal{
function can(){
echo "I can climb. <br/>";
}
}
class dog extends animal{
function can(){
echo "I can swim. <br/>";
}
}
function test($obj){
$obj->can();
}
test(new cat()); // 传递cat的实例时,运行的就是cat的can的方法
test(new dog()); // 传递dog的实例时,运行的就是dog的can的方法
// $a = new animal(); // 抽象类不能被实例化
序列化和反序列化
序列化:
将对象转换成字符串: 便于储存,便于运输。
$student = array('name'=>'张三', 'age'=>30, 'addr'=>'成都高新区', 'phone'=>'18812345678');
echo serialize($student);
输出:a:4:{s:4:"name";s:6:"张三";s:3:"age";i:30;s:4:"addr";s:15:"成都高新区";s:5:"phone";s:11:"18812345678";}
只要符合序列化规则的字符串,无论是否由serialize函数生成,均可以被反序列化。
如果要序列化一个类,则最好在_sleep魔术方法明确指定类属性,序列化的过程。只包含类的属性,不包含类的方法。
反序列化
将一个字符串转换成对象 比如:
$source = 'a:4:{s:4:"name";s:9:"张三娃";s:3:"age";i:30;s:4:"addr";s:15:"成都高新区";s:5:"phone";s:11:"18812345679";}';
$student = unserialize($source); // 将字符串反序列化为数组
print_r($student);
反序列化类的构造当中,会调用类的析构方法,但是不会调用类的构造方法。
魔术方法
_sleep:在类进行序列化时调用,并用在里面需要明确定义序列化哪些类属性,以数组方式定义和返回。
_wakeuop():在类进行反序列化时调用,并且可以在该方法中定义恢复类状态的的代码,以便于让反序列化的实例可以正常调用方法。
// 当类进行序列化时自动调用,并且返回一个数组,包含要实例化的类属性
function __sleep() {
echo "DB类正在进行序列化. <br/>";
return array('host', 'username', 'password', 'database');
}
// 在类进行反序列时调用,并且可以在该方法中定义恢复类状态的代码,以便于让反序列化的实例可以正常调用方法。
function __wakeup() {
echo "DB类正在被反序列化. <br/>";
$this->create_connection(); // 恢复数据库的连接状态
}
}
反序列化漏洞
1.字符串变对象过程中,如果没有对字符串输入进行检查,很有可能注入恶意代码。
2.通常情况下,反序列化漏洞并非通过黑盒测试或者盲注的方式进行探测,而是通过代码评审的方式进行漏洞验证。
标签:function,content,name,age,基础,echo,学习,array,PHP From: https://www.cnblogs.com/Nige-W/p/16923007.html