PHP学习杂记

┌    ┐     11.10

  85讲  HTTP 协议深讲

1.  $_SERVER[‘XXXXXXX’]  获取想获取的网络资源

2. print_r($_SERVER);打印出所有的网络资源

3. print_r 函数,打印

4. 封杀IP访问:if($_SERVER[‘REMOTE_ADDR’]==”XXXXXX”){

    进行处理。。。。

Header(“Location: err.php”)}

5. Get post 的区别:post get 安全 ;传输数据大小不一样;

6. 防盗链例子:

a) 盗链网站<a href="localhost:8082/import.php">查看某一个网页</a>

b) 正规网站<html><body>

c)   <a href="import.php">查看账号</a>

d) 

e)  </body>

f) </html>

g) <?php   刘送杰的私有领地   ?>

7.页面跳转:a.php ---->header(“Location: b.php”)-->header(“Location: c.php”),一直跳转;还可以跳转到外网去

a) <?php

b) header("Location: b.php");

c) 

d) ?>

e) <?php

f) 

g)  header("Location: http://www.baidu.com");

h) 

i) ?>

8.Refresh:1;url=http//www.baidu.com    间隔多少秒才刷新页面或者跳转页面;

9.php程序打开文件

a) 先打开文件,判断文件是否存在 $fp=fopen(“a.txt”,”r+”);

b) 操作文件

c) 关闭文件fclose($fp);

<?php

 

//.演示下载图片先死去活来

$file_name="dl_033.gif";

//1.打开文件。读入图片

if(!file_exists($file_name)){

echo "文件不存在";

return;

}

$fp=fopen($file_name,"r") ;

 

//获取下载文件大小

$file_size=filesize($file_name);

echo"文件大小:$file_size";

 

?>

下载过程:

<?php

 

//.演示下载图片先死去活来

$file_name="1.jpg";

//1.打开文件。读入图片

if(!file_exists($file_name)){

echo "文件不存在";

return;

}

$fp=fopen($file_name,"r") ;

 

//获取下载文件大小

$file_size=filesize($fp);

 

//返回文件

header("Content-type:application/octet-stream");

//按照字节大小返回

header("Accept-Range:byte");

//告诉文件大小

header("Accept-Length:$file_size");

//返回文件名。。中文需要转码

header("Content_Disposition:attachment;filename=".$file_name);

//向客户端会送数据

$buffer="1024";

//判断文件是否结束

while(!feof($fp)){

$file_data=fread($fp,$buffer);

echo $file_data;

 

}

fclose($fp);

?>

 

文件下载函数

<?php

//对函数说明:文件名,下载文件夹路径“/xxx/xxx/”。但是要在站点下面

 

function down_file($file_name,$file_sub_dir){

//.演示下载图片先死去活来

$file_name="中文.jpg";

//中文乱码问题,对中文进行处理,进行转码成gb2312

$file_name=iconv("utf-8","gb2312",$file_name);

//更改路径了,所有下载文件全部在一个下载文件夹下面

//相对路径

//$file_path="./down/".$file_name;

//绝对路径..会快一些

$file_path=$_SERVER['DOCUMENT_ROOT'].$file_sub_dir.$file_name;

//文件下载列表

 

 

//1.打开文件。读入图片

if(!file_exists($file_path)){

echo "文件不存在";

return;

}

$fp=fopen($file_path,"r") ;

 

//获取下载文件大小

$file_size=filesize($file_path);

if($file_size>30){

echo " <script language='javascript'>window.alert('文件太大')</script>";

return;

}

//返回文件

header("Content-type:application/octet-stream");

//按照字节大小返回

header("Accept-Range:byte");

//告诉文件大小

header("Accept-Length:$file_size");

//返回文件名。。中文需要转码

header("Content_Disposition:attachment;filename=".$file_name);

//向客户端会送数据

$buffer="1024";

//为了下载的安全,我们最好做一个文件字节的读取器

$file_count=0;

//判断文件是否结束

while(!feof($fp)&&($file_size-$file_count>0)){

$file_data=fread($fp,$buffer);

//统计多了多少个字节

$file_count+=$bufffer;

echo $file_data;

 

}

fclose($fp);

}

 

//测试函数

down_file("中文.jpg","/down/");

?>

222

<?php

//对函数说明

//参数说明:$file_name 文件名

function down_file($file_name,$file_sub_path){

/*相对路径方法代码

$file_name="顺明.jpg"'

//对中文进行转码,由utf-8转码成gb2312

$file_name=iconv("utf-8","gb2312",$file_name);

//相对路径

$file_path="./down/".$file_name;

if(!file_exists($file_path)){

echo "文件不存在";

return;

}

$fp=fopen($file_name,"r");

 

$file_size=filesize($file_path);

if()

//返回的文件

header("Content_type:application/octet-stream");

//按照字节大小返回

header("Accept-Ranges:bytes");

//返回文件大小

header("Accept-Length:$file_size");

//这里弹出对话框,对应的文件名

header("Accept-Disposition:attachment;filename=".$file_name"");

 

//向客户端返回数据

$buffer=1024;

//为了下载安全,我们最好做一个文件字节计数器

$file_count=0;

while(!feof($fp)&&($file_size-file_count>0)){

$file_data=fread($fp,$buffer);

$file_count+=$buffer;

echo $file_data;

fclose($fp);

*/

 

//对中文进行转码,由utf-8转码成gb2312

$file_name=iconv("utf-8","gb2312",$file_name);

//绝对路径方法代码

$file_path=$_SERVER['DOCUMENT_ROOT']."./down/".$file_name;

if(!file_exists($file_path)){

echo "文件不存在";

return;

}

$fp=fopen($file_name,"r");

//获取下载文件的大小

$file_size=filesize($file_path);

if($file_size>1024){

echo"<script language='javascript'>window.alert('文件过大')</script>";

return

}

//返回的文件

header("Content_type:application/octet-stream");

//按照字节大小返回

header("Accept-Ranges:bytes");

//返回文件大小

header("Accept-Length:$file_size");

//这里弹出对话框,对应的文件名

header("Accept-Disposition:attachment;filename=".$file_name"");

 

//向客户端返回数据

$buffer=1024;

//为了下载安全,我们最好做一个文件字节计数器

$file_count=0;

while(!feof($fp)&&($file_size-file_count>0)){

$file_data=fread($fp,$buffer);

$file_count+=$buffer;

echo $file_data;

}

}

fclose($fp);

?>

 

FileDownlist.php

<meta http-type="content-type" content="text/html;charset=utf-8">

<?php

 

header("Content-type:text/html;charset=utf-8");

?>

<a href='filedownprocess.php?filename=dl_033.gif'>单击下载</a><img src='dl_033.gif'><br><br>

<a href='filedownprocess.php?filename=dl_033.gif'>单击下载</a><img src='dl_033.gif'><br><br>

<a href='filedownprocess.php?filename=dl_033.gif'>单击下载</a><img src='dl_033.gif'><br><br>

<a href='filedownprocess.php?filename=dl_033.gif'>单击下载</a><img src='dl_033.gif'><br><br>

<a href='filedownprocess.php?filename=dl_033.gif'>单击下载</a><img src='dl_033.gif'><br><br>

<a href='filedownprocess.php?filename=dl_033.gif'>单击下载</a><img src='dl_033.gif'><br><br>

 

filedownprocess.php

<?php

require "filedownService.php";

header("Content-type:text/html;charset=utf-8");

$file_name=$_REQUEST['filename'];

 

down_file($file_name,"/down/");

?>

filedownService.php

<?php

//对函数说明:文件名,下载文件夹路径“/xxx/xxx/”。但是要在站点下面

 

function down_file($file_name,$file_sub_dir){

//.演示下载图片先死去活来

$file_name="中文.jpg";

//中文乱码问题,对中文进行处理,进行转码成gb2312

$file_name=iconv("utf-8","gb2312",$file_name);

//更改路径了,所有下载文件全部在一个下载文件夹下面

//相对路径

//$file_path="./down/".$file_name;

//绝对路径..会快一些

$file_path=$_SERVER['DOCUMENT_ROOT'].$file_sub_dir.$file_name;

//文件下载列表

 

 

//1.打开文件。读入图片

if(!file_exists($file_path)){

echo "文件不存在";

return;

}

$fp=fopen($file_path,"r") ;

 

//获取下载文件大小

$file_size=filesize($file_path);

if($file_size>3081024*1024){

echo " <script language='javascript'>window.alert('文件太大')</script>";

return;

}

//返回文件

header("Content-type:application/octet-stream");

//按照字节大小返回

header("Accept-Range:byte");

//告诉文件大小

header("Accept-Length:$file_size");

//返回文件名。。中文需要转码

header("Content_Disposition:attachment;filename=".$file_name);

//向客户端会送数据

$buffer="1024";

//为了下载的安全,我们最好做一个文件字节的读取器

$file_count=0;

//判断文件是否结束

while(!feof($fp)&&($file_size-$file_count>0)){

$file_data=fread($fp,$buffer);

//统计多了多少个字节

$file_count+=$bufffer;

echo $file_data;

}

fclose($fp);

}

//测试函数

//down_file("中文.jpg","/down/");

?>

 

 

 

11.10 晚上   数据库编程 mysql  mysqlli  pdo

mysql扩展库: 其实就是一套函数

mysql扩展库 与mysql 数据库的区别:,一个是函数(操作),一个是数据

 

11.11

1.启动数据库 net start mysql

2.连接数据库 mysql -h localhost -u root -p;(mysql -h IP地址 -u 账户 -p)

Enter password: 123456789;

3.查看数据库: show databases; 创建数据库: create databases test1;

4.选择数据库: use test1;

5.查看数据库里面的表 show tables;

6.创建表:create table user1; 删除表: delete table user1;

7.插入数据: insert into user1(name,passwd,email,age) values('zs',md5(123456),'[email protected]',23);

8.查看数据:select * from user1;

9.Delete from user1 where id=5;

10.Php程序 操作数据库

<?php

 

// php 去操作mysql

//步骤如下:

//1.建立连接

$conn=mysql_connect("127.0.0.1","root","123456789"); //IP地址服务器名称,mysql账户,mysql密码

if(!$conn){

die("连接数据库失败!".mysql_error());

}else {

echo "数据库连接成功<br><br>";

}

 

//2. 选择数据库

mysql_select_db("test");

 

//3.设置操作编码(可有可无)

//4.发送操作指令:ddl,dml,dql,dt1  ;

$sql="select * from user1";

//函数,向数据库发送一个语句,并且返回一个结果集$res ,就是一张表

$res=mysql_query($sql,$conn);

//var_dump($res);

//5.接收返回的结果集,并处理,(显示)

//mysql_fetch_row函数会一次取出$res结果集的下一行数据,赋值给$row

//$row数组,随便你怎么取数;

while($row=mysql_fetch_row($res)){

//第一种取法:

//echo "<br> $row[0]--$row[1]--$row[2]";

//echo "<br>";

//var_dump($row);全部打印出来了,

//第二种取法:

foreach($row as $key=>$val){

echo"--$val";

}

echo "<br>";

}

 

/* array(5) { [0]=> string(1) "1" [1]=> string(2) "zs" [2]=> string(32) "e10adc3949ba59abbe56e057f20f883e" [3]=> string(12) "[email protected]" [4]=> string(2) "23" }    */

 

//6. 释放资源内存,必须释放!!!关闭连接

mysql_free_result($res); //必须的

mysql_close($conn)    //这个可有可无,因为mysql会在没有连接以后自动关闭的

?>

 

11.$res获取行数据的时候,处理mysql_fetch_row($res) ,还有三种方法

A)mysql_fetch_row($res)    索引数组

B)mysql_fetch_assoc($res)   关联数组

C)Mysql_fetch_ayyay($res) 返回索引数组和关联数组(两套同时存在)

D)Mysql_fetch_object($res) 把一行数据当作一个对象

 

12.一个增删改,查的例子

<?php

//演示对user1表进行增、删、改、查等操作;

$conn=mysql_connect("localhost","root","123456789");

if(!$conn){

die("数据库连接失败!".mysql_error());

}else{

echo "数据库连接成功";

echo"<br>";

}

mysql_select_db("test",$conn) or die(mysql_error());

mysql_query("set names utf8");

//插入数据

//$sql="insert into user1(name,passwd,email,age) values('小明',md5(1234),'[email protected]',25)";

//删除数据

//$sql="delete from user1 where id=6";

//修改数据

$sql="update user1 set age=1 where id=7";

 

 

//如果是dml操作,则返回bool值,true  of false ;

$res=mysql_query($sql,$conn);

if(!$res){

die( "操作失败!".mysql_error());

}

//看看有几条数据

if(mysql_affected_rows($conn)>0){

echo "操作成功!";

}else{

echo "没有影响到行数";

}

 

mysql_close($conn);

 

?>

 

13.把以上的操作封装成一个mysqlhelp

 

 

 

 

 

 

 

11.13

获取一个表的内部信息

<?php

//获取一个表名,然后获取表的信息,打印出来

Function show_table_info($table_nam3){

//连接数据库

$conn=connect(“localhost”,”root”,”123456789”);

If(!$conn){

die(“连接数据库失败”.mysql_error());

}

//选择数据库

Mysql_select_db(“test”);

设置查询出来的数据为utf8字符集

Mysql_query(“set names utf8”);

//查询语句

$sql=”select * from $table_name”;

//根据函数输入查询语句,并且返回结果集

$res=mysql_query($sql);

 

//我要知道总共有多少行,多少列

$row=mysql_affected_rows($conn);

$colums=mysql_num_fields($res);

/*

$row=mysql_affected_rows($conn);

$cloums=mysql_num_fields($res);

$row=mysql_fetch_rows($res);

Echo “$row[$i]”; */

 

Echo “<table border=1><tr>”;

For($i=0;$i<$colums;$i++){

$field_name=mysql_field_name($res,$i);

Echo”<th>$field_name</th>”;

 

}

Echo “</tr>”;

While($row=mysql_fetch_rows($res)){

Echo “<tr>”;

For($i=0;$i<$colums;$i++){

Echo “<th>$row[$i]</th>”;

}

Echo”</tr>”;

}

Echo “</table>”;

 

}

show_tab_info("user1");

?>

 

11.14日,中英文字典同时实现   第93---》》实现变种+熟练

 

94讲:

<?php

//先解决编码问题

Header(“content-type:text/html;charset=utf-8”);

//创建对象,

$mysqli=new mysqli(“localhost”,”root”,”123456789”,”test”);

//判断成功与否

If($mysql->connect_error){

Die(“连接失败”.$mysqli->connect_error);

}

//操作数据库

$sql=”select * from user1”;

$res=$mysqli->query($sql)

//显示返回结果集

While($row=$res->fetch_row()){

Foreach($row as $key=>$val){

Echo “--$val”;

}

Echo”<br>”;

}

//关闭资源

$res->free();

Mysqli->close();

 

?>

 

95

 

97讲  mysqli 批量添加删除

97mysqli 事物控制、事物处理

1.开启一个事物:start transaction

2.做一个保存点: savepoint 保存点名称

3.执行操作

4.可以回滚/可以提交

4.1如果没有问题就提交

4.2如果有问题则回滚

 

 

11.15晚上  mysqli 预处理技术stmt

<?php

//1.创建mysqli对象

$mysqli=new mysqli(“localhost”,”root”,”123456789”,”test”);

//2.创建预编译对象

$sql=”insert into user1(name,passwd,eamil,age) values(?,?,?,?)”;

$mysqli_stmt=$mysqli->prepare($sql);

//3.绑定参数

$name=”小倩”;

$passwd=”xiaoqian”;

$email=[email protected];

$age=”200”;

//4.将绑定的参数-> 给? 赋值,这里类型和顺序要对应

$mysqli_stmt->bind_param(“sssi”,$name,$passwd,$eamil,$age);

//5.执行

$b=$mysqli_stmt->execute();

[3-5是可以重复的,所以实现预编译,多次发送数据

//3.绑定参数

$name=”老妖”;

$passwd=”laoyao”;

$email=[email protected];

$age=”250”;

//4.将绑定的参数-> 给? 赋值,这里类型和顺序要对应

$mysqli_stmt->bind_param(“sssi”,$name,$passwd,$eamil,$age);

//5.执行

$b=$mysqli_stmt->execute();

 

]

//6.判断

If(!$b){

Die(“执行失败”.$mysqli_stmt->error);

}else{

Echo “执行成功”;

}

//7.释放

$mysqli->close();

 

 

?>

 

11.16超全局数组

1.$_GET  用于传送超链接内容或者表单

test.php

<?php

echo "<a href='a.php?city=北京好&name=xiaoming'>传送数据</a>";

?>

a.php

<?php

echo "<pre>";

echo print_r($_GET);

echo "</pre>";

 

//如果想取出具体哪个,则去具体名字

echo $_GET['name'];

?>

2.$_POST 传送表单内容 通过http POST 方法传递的数据被封装在$_POST超全局中

注意表单的有些细节

3.$_REQUST

$_REQUST中可以包括:$_GET,$_POST.$_COOKIE数组的信息,可以理解为二维的

 

102

1. $_SERVER 包含 hhtp协议(客户端)浏览器带来的信息,还有一个服务器本身的信息

2.$_ENV 获取环境变量

 

11.17日  103讲 雇员管理系统

培养项目的感觉,

认识MVC模式

规划项目

融合知识点,php基础、html,数据库,开发模式,cookie

 

开发:使用原型开发

需求分析--->>>设计阶段-->>编码阶段--->>>测试阶段--->>发布维护阶段

需求阶段: 需求设计人员/项目经理,架构师    与客户(领导)交流听取意见,让他听意见。引导他。---->>>形成需求文档

设计阶段:技术人员(架构师-->>组长-->>程序员)--->>>设计数据库

开发阶段: 组长,程序员(基本工资+项目提成);跟好项目

测试阶段:测试人员

发布阶段:发布到对方服务器,实施工程师,去实施,

评估一个程序员技术:  工作年龄 -->>>>做过的项目

美工(ps画图)---->>>>网页前端人员《html[原型]--->>>客户 ---->>>>程序员

 

开发文档:

一.需求分析

1开发: 美工处理出来界面模型,给客户看一看

2.需求分析:

二.时序图

三.界面设计

四.编写代码

1.设计数据库。

管理员表 admin

员工表emp

先建立数据库:empmanage

 

再建立表

 

管理员表

admin

 

create table admin(

id int primary key,

name varchar(64) not null,

password varchar(128) not null

);

 

insert into admin values(100,'admin',md5('admin'));

 

雇员表

emp

 

create table emp(

id int primary key auto_increment,

name varchar(64) not null,

grade tinyint, /*1表示一级工 */

email varchar(64) not null,

salary float

);

 

 

insert into emp(id,name,grade,email,salary)values(1,'liusongjie',1,'[email protected]',200);

insert into emp(id,name,grade,email,salary)values(2,'liusongjie1',3,'[email protected]',205);

insert into emp(id,name,grade,email,salary)values(3,'liusongjie2',2,'[email protected]',205);

insert into emp(id,name,grade,email,salary)values(4,'liusongjie3',2,'[email protected]',205);

insert into emp(id,name,grade,email,salary)values(5,'liusongjie4',3,'[email protected]',205);

insert into emp(id,name,grade,email,salary)values(6,'liusongjie5',3,'[email protected]',205);

insert into emp(id,name,grade,email,salary)values(7,'liusongjie6',3,'[email protected]',205);

insert into emp(id,name,grade,email,salary)values(8,'liusongjie7',3,'[email protected]',205);

insert into emp(id,name,grade,email,salary)values(9,'liusongjie8',3,'[email protected]',205);

 

 

创建到mysql数据库中

1.先建立数据库:create empmanage;

2.use empmanage;

3.简表

4.添加数据

五.代码阶段:

1.准备素材:图片,静态页面,flash,文字。。。。

 

创建一个项目empManage

 

创建程序框架图

 

 

 

 

 

 

 

1.不要到数据库去验证,就可以登陆成功,如果不成功,给出提示

/*     //1.第一种简单验证方式

if($id=="100"&&$password=="123"){

header("Location:empManage.php");

exit();

}else{

header("location:login.php?errno=1");

exit();

}

*/

2.要求数据库验证,判断该用户是否存在或者密码是否正确

//第二种,防止注入攻击型

//1,先连接数据库

$conn=mysql_connect("localhost","root","123456789");

if(!$conn){

die("连接失败".mysql_errno());

}

//设置数据库的编码形式

mysql_query("set names utf8",$conn) or die(mysql_errno());

//选择数据库

mysql_select_db("empmanage",$conn)or die(mysql_errno());

//发生sql语句,验证

//防止sql注入攻击

//变换验证逻辑

$sql="select password,name from admin where id=$id";

//1.通过输入的id来获取数据库的秘密,然后再和输入的密码比对;

$res=mysql_query($sql);

if($row=mysql_fetch_assoc($res)){

//查询到,则取出数据库密码

if($row['password']==md5($password)){

//说明合法

$name=$row['name'];

header("Location:empManage.php?name=$name");

//如果要跳转,带上exit();有利于快速结束

exit();

}

}

header("Location:login.php?errno=1");

exit();

mysql_free_result($res);

mysql_close($conn);

3.3.在管理页面实现显示登陆人的名字

echo "欢迎".$_GET['name']."登录成功!";

4.在用户管理界面empList.php显示所有的雇员信息

5.分页显示雇员信息

思路: 分页有几个变量

$pageNow->显示第几页,用户输入或者选择

$pageCount->共有几页

$rowCount->共有多少条记录(从数据库获取)

$pageSize->每页显示多少条记录(程序中定义)

 

$sql="select * from emp limit 3,3";

6.分页显示:

$pageSize=3;//定义每页显示数据条数的数量

$rowCount=0;//代表从数据库抓取的总数据记录条数

$pageNow=1;//当前显示哪个页面。由用户指定

If(!empty($pageNow=$_GET[‘pageNow’])){

$pageNow=$_GET[‘pageName’];

}

$pageCount=0;//计算出总共有多少页

$sql=”select count(id) from emp”;

$res=mysqli_query($sql);

If($row=mysql_fetch_row[$res]){

//取出总数据行数

$rowCount=$row[0];

}

//计算出共有多少页

$pageCount=ceil($rowCount/$pageSize);

//控制查询的数据条数从什么时候显示在什么页面

$sql=”select * from emp limit “.($pageNow-1)*$pageSize.”,$pageSize”;

$res2=mysql_query($sql,$conn);

//制作显示表格

echo "<table border='1' width='700px'>";

//显示表头,可以固定写死,也可以通过查询出来显示

echo "<tr><th>id</th><th>name</th><th>grade</th><th>email</th><th>salary</th>

<th>删除用户</th><th>修改用户</th></tr>";

//循环显示信息

while($row=mysql_fetch_assoc($res2)){

echo "<tr><td>{$row['id']}</td><td>{$row['name']}</td>

<td>{$row['grade']}</td><td>{$row['email']}</td><td>{$row['salary']}</td>

<td><a href='#'>删除用户</a></td><td><a href='#'>管理用户</a></td></tr>";

}

echo "<h1>雇员信息列表</h1>";

echo "</table>";

//控制打出页面的超链接

For($i=1;$i<=$pageCount;$i++){

Echo <a href=empList.php?pageNow=$i>$i</a>;

}

7.测试sql语句的效率

比如:测试分页的效率,在实际开发中,数据量很大的,需要进行测试,

Mysql 自我复制

insert into emp(name,grade,email,salary) select name,grade,email,salary from emp;

 

批量复制:加入

insert into emp(name,grade,email,salary) select name,grade,email,salary from emp;

delete from emp(name,grade,email,salary) select name,grade,email,salary from emp;

批量删除:

DELETE FROM emp WHERE grade=2 ORDER BY grade LIMIT 100000;

8.页面跳转功能

if($pageNow>1){

$prePage=$pageNow-1;

echo "<a href='empList.php?pageNow=$prePage'>上一页</a> ";

}

if($pageNow<$pageCount){

$nextPage=$pageNow+1;

echo "<a href='empList.php?pageNow=$nextPage'>下一页</a> ";

}

echo "当前页{$pageNow}/{$pageCount}";

//指定跳转到某页

echo "<br><br>";

?>

<form action="empList.php">

跳转到:<input type="text" name="pageNow">

<input type="submit" value="go">

</form>

 

10.网站结构问题

 Model1模式  ,分层模式,

MVC模式 ,  zend framework,  thinkphp

软件开发三个阶段:Model1模式 ->>分层mv->>mvc模式

Model1模式 :界面和业务在一个页面,

分层模式:界面也业务分开,->结构清晰,有利于开发

mvc模式;

 

 

11.关于析构函数和构造函数的犯错问题:

前面是两个下划线 __  两个!!!

<?php

class BaseClass {

   function __construct() {

       print "In BaseClass constructor\n";

   }

}

class SubClass extends BaseClass {

   function __construct() {

       parent::__construct();

       print "In SubClass constructor\n";

   }

}

class OtherSubClass extends BaseClass {

    // inherits BaseClass's constructor

}

// In BaseClass constructor

$obj = new BaseClass();

// In BaseClass constructor

// In SubClass constructor

$obj = new SubClass();

// In BaseClass constructor

$obj = new OtherSubClass();

?>

 

验证码功能:

<tr><td><input type="text" name="checkcode"></td><td><img src="checkCode.php" onclick="this.src='checkCode.php?aa='Math.random()''"></td></tr>

 

116-122讲解cookiesession 知识点,防止攻击,增加确认,增加验证码功能

123讲,php的文件编程

1.打开文件:fopen()   查看文件详细信息:fstat 关闭文件:fclose

2.读取文件

<?php

$file_path="test.txt";

 

//第一种读取方法

/*

if(file_exists($file_path)){

$fp=fopen($file_path,"a+");

$con=fread($fp,filesize($file_path));

echo "文件内容是:<br>";

//替换符:替换掉换行符等等

$con=str_replace("\r\n","<br/>",$con);

echo $con;

}else{

echo "文件不存在";

}

*/

//第二种读取方法

/*$con=file_get_contents($file_path);

$con=str_replace("\r\n","<br/>",$con);

echo $con;

*/

 

//第三种方法

$fp=fopen($file_path,"a+");

$buffer=1024;

$str="";

while(!feof($fp)){

//

$str.=fread($fp,$buffer);

$con=str_replace("\r\n","<br/>",$str);

echo $con;

}

fclose(fp)

?>

把用户名/密码/数据库等等。封装到一个db.ini文件中,然后读取就行

Db.ini {

host=192.168.1.3

user=admin

password=123

}

然后写调用代码:

<?php

 

$arr1=parse_ini_file("db.ini");

//print_r($con)

mysql_connect($arr1['host'],$arr1['user'],$arr1['password']);

?>

 

3.写文件第一种方法

<?php

$file_path="test.txt";

if(file_exists($file_path)){

$fp=fopen($file_path,"w+");

$conn="\r\nhello你好!!";

for($i=0;$i<10;$i++){

fwrite($fp,$conn);

}

}else{

}

echo "添加成功!";

fclose($fp);

?>

第二种方法

$file_path="test.txt";

$conn="hello北京你好!\r\n";

//封装的函数

file_put_contents($file_path,$conn,FILE_APPEND);

 

echo "添加成功!";

fclose($fp);

4.文件的拷贝

<?php

//中文转码问题

$file_path=iconv("UTF-8","gb2312","C:\\Apache24\\htdocs\\example\\file\\.jpg");

//尽量用英文字符名称

if(!copy($file_path,"d:\\11.jpg")){

echo "error";

}else{

echo "success!";

}

?>

5.文件的下载:参看http课程 87讲和88

6.文件创建与删除,文件夹的创建与删除

<?php

//6.文件创建与删除,文件夹的创建与删除

//1.创建文件夹

//可以先判断是否存在

/*

if(!is_dir("d:/shunping2")){

if(mkdir("d:/shunping2")){

echo "创建文件夹success!";

}else{

echo "error!";

}

}else{

echo "该文件夹已经有了";

}   */

//创建多个连级文件夹

/*

$path="D:/shunping3/aa/bb";

if(!is_dir($path)){

if(mkdir($path,0777,true)){

echo "创建文件夹ok";

}else{

echo "创建文件夹error";

}

}else{

echo "该文件夹有了";

} */

//删除文件夹。。但是这个函数的缺点就是存在子文件或者文件夹则无法使用

/*if(rmdir("D:/shunping3")){

echo "删除成功";

}else{

echo "shanchu失败";

}  */

//4.文件是创建, 最简单

 /*  $file_path="D:/shunping3/aa.txt";

$fp=fopen($file_path,"w+");//w +  代表,不存在就去创建

fwrite($fp,"hello! world!!!ooo");

echo "chuangj  ok!";

fclose($fp);  */

//5.s删除文件

$file_path="D:/shunping3/aa.txt";

if(is_file($file_path)){

if(unlink($file_path)){

echo "删除success";

}else{

echo "删除error";

}

}else{

echo "文件不存在";

}

?>

 

124讲  php文件编程,实际运用

Upload.php 文件上传界面

注意事项

一.<!--文件上传,一定要注意1.enctype="multipart/form-data",2.method post  -->

<form enctype="multipart/form-data" method="post" action ="??" name="myform">

二.<input type=file name=mufile>

三.<input type=submit value=上传文件>

四.特殊情况处理哦

<?php

 

//接收提交用户的用户

$username=$_POST['username'];

$fileintro=$_POST['fileintro'];

 

echo "$username<br>$fileintro<br>";

 

//接收文件   需要使用到 $_FILES 超全局数组,二维的!!!

/*echo"<pre>";

print_r($_FILES);

echo"</pre>"; */

 

//获取文件的大小,,限制大小

$file_size=$_FILES['myfile']['size'];

if($file_size>2*1024*1024){

echo "上传文件太大,请选择小于2M的文件!"; ///可以选择弹出对话框 用javascript实现

exit();

}

//获取文件的类型,,,限制类型

$file_type=$_FILES['myfile']['type'];

if($file_type!='image/jpeg' && $file_type!='pjpeg'&&$file_type!='image/jpg'){   ///扩散其他类型

echo "只支持jpg类型文件上传";

exit();

}

//防止覆盖已经存在的,所以要随时建立动态文件或者动态文件夹

 

//判断是否上传ok

if(is_uploaded_file($_FILES['myfile']['tmp_name'])){

//上传成功,把文件转存到自己的新位置

$uploaded_file=$_FILES['myfile']['tmp_name'];

  //防止覆盖已经存在的,所以要随时建立动态文件或者动态文件夹,使用函数实现!!

  //第一种,用用户名命名,防止用户名相同

$user_path=$_SERVER['DOCUMENT_ROOT']."/file/up/".$username;

$user_path=iconv("utf-8","gb2312",$user_path);

//判断该用户是否已经存在文件夹

if(!file_exists($user_path)){

mkdir($user_path);

}

//防止覆盖已经存在的,所以要随时建立动态文件或者动态文件夹,使用函数实现!!

//第二种,动态命名,防止覆盖同一个用户文件名相同的文件

//$move_to_file=$user_path."/".$_FILES['myfile']['name'];  //很多细节

$file_true_name=$_FILES['myfile']['name'];

//substr 函数截取你想截取的字符,strrpos判断你想截取的字符最后出现的位置

$move_to_file=$user_path."/".time().rand(1,1000).substr($file_true_name,strrpos($file_true_name,"."));

//echo $uploaded_file."||".$move_to_file;

  //防止覆盖已经存在的,所以要随时建立动态文件或者动态文件夹,使用函数实现!!

 if( move_uploaded_file($uploaded_file,iconv("UTF-8","gb2312","$move_to_file"))){

echo $_FILE['myfile']['name']."上传ok";

 }else{

echo "上传失败!";

 }

 

}else{

echo "未上传任何文件!";

}

?>

 

 

127讲  php 绘图技术

Php绘图技术步骤

1.创建画布

2.绘制图形:利用自带GD库。(圆,直线,扇形,柱状图,饼状图)

3.输出图像或者到网页/另存为

4.销毁图片,释放内存

 

网站常用图片格式:gif  ,  jpg  , jpeg  ,  png ,  bmp  ,

 

 

画图基础

<?php

// 1.创建画布

//默认背景是黑色

$im=imagecreatetruecolor(400,300);

 

//2.绘制图形:利用自带GD库。(圆,直线,扇形,柱状图,饼状图)

//创建颜色

$red=imagecolorallocate($im,255,0,0);

 

//画一个圆函数imageellipse ,也可以变椭圆,改变宽和高就行 imageellipse($im,20,20,40,20,$red);

//imageellipse($im,20,20,20,20,$red);

//直线imageline

//imageline($im,0,0,60,60,$red);

//矩形

//imagerectangle($im,0,0,40,50,$red);

//实心矩形

//imagefilledrectangle($im,0,0,40,50,$red);

//弧线 ,就是在椭圆上面截取一部分0-360里面取

//imagearc($im,100,100,100,150,0,60,$red);

//扇形,就是填充弧形,但是带一个参数,什么样的形状

//imagefilledarc($im,100,100,100,150,0,60,$red,IMG_ARC_PIE);

//拷贝图片到画布

//1.加载图片

//$srcImage=imagecreatefromjpeg("1.jpg");

//拷贝图片到目标画布

//imagecopy($im,$srcImage,0,0,0,0,206,71);

//图片上面写字

$str="hello world,你好";

//imagestring($im,5,0,0,"hello ,world",$red);

imagettftext($im,10,0,50,$red,"STCAIYUN.TTF",$str);

 

 

//3.输出图像或者到网页/另存为

header("content-type:image/png");

//echo 3;exit();

imagepng($im);

//4.销毁图片,释放内存 -->

//imagedestory($im);

 

?>

 

131讲   画一个3D椭圆

 

<?php

 

//分析思路,先画扇形

//也可以封装成一个函数,传位置参数和循环参数就行

//1.画布

$im=imagecreatetruecolor(400,300);

//背景色

$white=imagecolorallocate($im,255,255,255);

imagefill($im,0,0,$white);

 

//2.创建颜色

$red=imagecolorallocate($im,255,0,0);

$darkred=imagecolorallocate($im,144,0,0);

$blue=imagecolorallocate($im,0,0,128);

$darkblue=imagecolorallocate($im,0,0,80);

$gary=imagecolorallocate($im,192,192,192);

$darkgary=imagecolorallocate($im,144,144,144);

//画扇形图形-----》》》》

/*imagefilledarc($im,100,50,100,50,0,45,$blue,IMG_ARC_PIE);

imagefilledarc($im,100,50,100,50,45,85,$gary,IMG_ARC_PIE);

imagefilledarc($im,100,50,100,50,85,360,$red,IMG_ARC_PIE);  */

//画扇形图形-----》》》》立体感就是多个叠加在一起的

for($i=60;$i>=50;$i--){

imagefilledarc($im,100,$i,100,50,0,45,$darkblue,IMG_ARC_PIE);

imagefilledarc($im,100,$i,100,50,45,85,$darkgary,IMG_ARC_PIE);

imagefilledarc($im,100,$i,100,50,85,360,$darkred,IMG_ARC_PIE);

}

//在上面加一个盖

imagefilledarc($im,100,50,100,50,0,45,$blue,IMG_ARC_PIE);

imagefilledarc($im,100,50,100,50,45,85,$gary,IMG_ARC_PIE);

imagefilledarc($im,100,50,100,50,85,360,$red,IMG_ARC_PIE);

 

//3.显示tux

header("content-type:image/png");

imagepng($im);

//4.销毁图片,释放内存 -->

imagedestory($im);

?>

 

132讲 投票统计图,,用数据库实现动态的

133讲,图片验证码

 

<?php

//使用php绘图技术,画出验证码

$checkCode="";

for($i=0;$i<4;$i++){

//随机产生一个1-15的数,用dechex函数变成16进制数

$checkCode.=dechex(rand(1,15));

}

//存入session,后面使用

session_start();

$_SESSION['checkcode']=$checkCode;

//1.创建画布

$image1=imagecreatetruecolor(150,50);

$red=imagecolorallocate($image1,255,255,255);

//画出干扰线, 位置可以变换+长短可以变换,颜色可以变换

for($i=0;$i<20;$i++){

imageline($image1,rand(0,100),rand(0,30),rand(0,100),rand(0,30),imagecolorallocate($image1,rand(0,255),rand(0,255),rand(0,255)));

}

//imagestring函数加字+变换出现位置,+变换字体大小

imagestring($image1,rand(1,5),rand(0,80),rand(0,30),$checkCode,$red);

//显示

header("content-type:image/png");

imagepng($image1);

//销毁

imagedestory($image1);

 

?>

 

LoginPhp  调用,动态并且变化

 

请输入验证码:<img src="checkcode.php" onclick="this.src='checkcode.php?aa=+Math.random()'">

 

 

 

134讲  XML技术基础

 

 

147讲  网上支付

区别:   易宝支付,直接打给银行, 支付宝不是直接打给银行

 

1.易宝申请注册 测试账号和密钥

账号:$p1_MerId=10001126856;

密钥:$merchantKey=69c1522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4P1;

1.刚开始测试支付最好使用我们提供的测试商户帐号及配套的密钥:

merchantID=10000432521

keyValue=8UPp0KE8sq73zVP370vko7C39403rtK1YwX40Td6irH216036H27Eb12792t

 

2.易宝支付发文档:

3.开发: 写界面

4.关键技术:如何生成一个hmac签名串!!!hmac算法!

 

 

155讲  smarty 获取变量

静态变量   ++  配置文件的动态变量  +  post/get/server session 中的值

静态:

<?php

require_once "./libs/Smarty.class.php";

 

//创建一个smarty对象

$smarty=new Smarty;

$smarty->left_delimiter="<{";

$smarty->right_delimiter="}>";

//取字符串

$smarty->assign("aa","hello");

//取整数

$smarty->assign("bb",567);

//小数

$smarty->assign("cc",567.77);

//存放一维数组,一般是从数据库提取

//1,索引数组

$arr1=array('北京','上海','天津');

//2,关联数组

$arr2=array('city1'=>'北京','city2'=>'上海','city3'=>'天津');

//3.索引的二维数组,一般是从数据库提起,这里是模拟

$arr3=array(array('北京','上海','天津'),array('小倩','采臣','老妖'));

 

//4,二维数组的关联数组

$arr4=array(array('id'=>'a001','email'=>'[email protected]','age'=>60),array('id'=>'a002','email'=>'[email protected]','age'=>66));

 

$arr5=array('emp1'=>array('id'=>'a001','email'=>'[email protected]','age'=>60),'emp2'=>array('id'=>'a002','email'=>'[email protected]','age'=>66));

class Master{

var $name;

var $address;

}

$master->name="顺平";

$master->address="盘丝洞";

 

//对象的分配

class Dog{

var $name;

var $age;

var $color;

var $arr;//一维数组

var $arr2;//二维数组

var $master;//类

function __construct($name,$age,$color,$arr,$arr4){

$this->name=$name;

$this->age=$age;

$this->color=$color;

$this->arr=$arr;

$this->arr2=$arr4;

}

}

 

//实例化一个对象

$dog1 =new Dog("小明",5,"红色",$arr1,$arr4);

$dog1->master=$master;

 

 

$smarty->assign("arr1",$arr1);

$smarty->assign("arr2",$arr2);

$smarty->assign("arr3",$arr3);

$smarty->assign("arr4",$arr4);

$smarty->assign("arr5",$arr5);

$smarty->assign("dog1",$dog1);

 

//显示

$smarty->display("test.tpl");

 

?>

 

动态:配置文件中获取

title='我的第一个网站'

bgcolor='green'

 

 

获取方法

<{config_load file='../config/my.conf'}>

<h1><{#title#}></h1>

<h1>数据显示</h1>

<body bgcolor='<{#bgcolor#}>'>

<hr/>

<br/>*****字符串******</br>

<{$aa}>

<hr/>

<br/>*****整数数字******</br>

<{$bb}>

<hr/>

<br/>*****小数字******</br>

<{$cc}>

<hr/>

<br/>*****索引数组******</br>

<{$arr1[0]}>||<{$arr1[1]}>||<{$arr1[2]}>||<{$arr1[3]}>

<hr/>

<br/>*****关联数组******</br>

<{$arr2.city1}>||<{$arr2.city2}>||<{$arr2.city3}>

<hr/>

<br/>*****二维数组的索引数组******</br>

<{*   做注释  $arr3[0][0] 表示取出arr3二维数组的第一个数组元素中的第一个元素    *}>

<{$arr3[0][0]}>||<{$arr3[0][1]}>||<{$arr3[0][2]}>||<{$arr3[1][0]}>

 

<hr/>

<br/>*****二维数组的关联数组方式取法******</br>

<{$arr4[0].email}>||<{$arr4[0].age}>

<{$arr5.emp2.email}>

 

<hr/>

<br/>*****取出对象的值的取法******</br>

<{$dog1->age}>||<{$dog1->color}>||<{$dog1->name}>

 

<hr/>

<br/>*****取出对象的数组的取法******</br>

取出对象的普通属性:<{$dog1->name}><br/>

取出对象的数组属性:<{$dog1->arr[0]}><br/>

取出对象的二维数组属性:<{$dog1->arr2[0].email}><br/>

<br/>*****取出对象的对象属性******</br>

<{$dog1->master->name}>

 

</body>

 

 

post /get /server /session 在的值

直接取就是,但是有模板

<{$smarty.get.username}>

<{$smarty.post.XXXXX}>

<{$smarty.server.SERVER_NAME}>

 

 

157 讲   smarty   内建函数    自定义函数  +  块注册方式函数

 

两个:Foreach   if else

自定义

function test1($args){

$str="";

 

for($i=0;$i<$args['times'];$i++){

$str.="<br/><font  size='".$args['size']."' color='".$args['color']."'>".$args['con']."</font>";

}

return $str;

}

 

//还得注册一下函数!!1

$smarty->register_function("hsp","test1");

块注册函数

 

 

158 讲  自定义函数之 插件  

插件其实就是一个函数,写在一个系统目录下面的,调用这个函数

smarty\libs\plugins   下面写插件

文件名命名格式有要求  +++  函数定义格式有要求

Functuin.hsp.php    + function smarty_function_hsp($args,&$smart){

 

 

}

 

自定义插件函数

文件名: function.自定义函数.php  然后在模板里面调用就行了

函数名字:function  smarty_function_自定义($参数,&$smarty)

<?php

function  smarty_function_hsp($args,&$smart){

$str="";

 

for($i=0;$i<$args['times'];$i++){

$str.="<br/><font  size='".$args['size']."' color='".$args['color']."'>".$args['con']."</font>";

}

return $str;

}

 

 

?>

 

 

 

自定义一个块插件函数  也有固定的格式

 

文件名: block.自定义块函数.php  然后在模板里面调用就行了

函数名字:function  smarty_block_自定义块函数名($参数,$参数2&$smarty)

<?Php

 

<?php

function smarty_block_test2($args,$con,&$smarty){

$str="";

for($i=0;$i<$args['times'];$i++){

$str.="<br/><font  size='".$args['size']."' color='".$args['color']."'>".$con."</font>";

}

return $str;

}

?>

 

159 讲  smarty  +  mvc  综合应用  : 内部留言本

不能配置虚拟主机,安装视频步骤来,开启apache虚拟主机 ,导致apache 不能重启!

要么是代码问题,要么的配置问题

 

http://www.cnblogs.com/catprayer/archive/2010/10/30/1865308.html  

 

 

 

163讲   smarty 语法细节

 

1. 基本运算

2. 变量调节器(相当于函数)运用   ,可以自定义变量调节器,以插件形式给出,在pugins 目录下面,

文件名: modifier.xxxx.php

函数名: function smarty_modifier_XXX()

 

 

 

 

53讲   获取文本框中的值

如何用JavaScript得到网页input中输入的value

在页面中我们最常见的页面元素就是input了,但是我们如何用JavaScript得到网页input中输入的

 

value值呢,其实很简单,方法也不止一种,据我总结比较常用的就是下面的两种方法,闲话不多说了,

 

下面那就来看看我说的方法吧:

方法一、

Java代码 复制代码 收藏代码

<html>   

 <head>   

 <script language="javascript">   

  function print(){   

   var a=myform.name.value;   

   alert(a);   

  }   

 </script>   

 </head>   

 <body>   

  <form name="myform">   

   <input type="text" name="name" id="nn" />   

   <input type="button" name="button" value="获取" onclick="print()" />   

  </form>     

 </body>   

</html>  

这是获取网页input值的方法之一,给from一个名字然后在JavaScript的地方就可以用form的名字来调

 

form表单里input元素的value属性可以得到值,并把值赋给a,最后用JavaScriptalert()打印方法

 

打印出来。

 

方法二、

Java代码 复制代码 收藏代码

<html>   

 <head>   

 <script language="javascript">   

  function print(){   

   var a=document.getElementByIdx_x("nn").value;   

   alert(a);   

  }   

 </script>   

 </head>   

 <body>   

  <form>   

   <input type="text" name="name" id="nn" />   

   <input type="button" name="button" value="获取" onclick="print()" />   

  </form>     

 </body>   

</html>

 

方法三

<html>

<head>

<title></title>

<script type="text/javascript">

function js(){

var x=document.getElementById("11").value;

window.alert (x);

}

</script>

</head>

<body>

 <textarea  id="11"rows="10" cols="20">       </textarea>  <br>

     <input id="mytest" name="mytest" type="button" onClick="js()" value="测试"/>  

</body>

</html>

 

 

54讲 正则表达式

匹配四个连续的数字

<html>

<head>

<title></title>

<script type="text/javascript">

function js(){

var con=document.getElementById("11").value;

//window.alert (x);

//var myReg=/(\d){4}/gi;  //这是一个正则表达式

var myReg=new RegExp("(\\d){4}","gi");  //这是一个正则表达式

while(res=myReg.exec(con)){

window.alert("找到"+res[0]);

}

}

</script>

</head>

<body>

 <textarea  id="11"rows="10" cols="20">       </textarea>  <br>

     <input id="mytest" name="mytest" type="button" onClick="js()" value="测试"/>  

</body>

</html>

 

正则表达式RegExp对象的方法:

1.exec()方法 ,一直找那个串,一直找

2.test()方法,找到返回true,没有找到返回false

function js(){

var con=document.getElementById("11").value;

var myreg=/abc/gi;

if(myreg.test(con)){

window.alert("abc");

}else{

window.alert("没有有abc");

}

}

 

正则表达式的String对象的方法

Match方法

function test2(){

var con=document.getElementById("11").value;

var myreg=/abc/gi;

 

res=con.match(myreg);

for(var i=0;i<res.length;i++){

window.alert(i+"-"+res[0]);

}

}

Replace方法

function test3(){

var con=document.getElementById("11").value;

//把四个数换成一句话:这里有四个数

var myreg=/(\d){4}/gi;

var newCon=con.replace(myreg,"这里有四个数");

document.getElementById("11").value=newCon;

}

Var myreg=/(\d)(\d)\2\1/gi;

子表达式,捕获,反向应用

function test5(){

var con=document.getElementById("11").value;

//var myreg=/(\d)(\d)\2\1/gi;  ///1221  2332   匹配这样d

//var myreg=/(\d)\1(\d)\2(\d)\3(\d)\4/gi;   ///匹配aabbcc

var myreg=/(\d)(\d)\2\2\1/gi; //匹配addda;

//匹配 12348-333999111 这样的编号

var myreg=/(\d){5}-(\d)\2\2(\d)\3\3(\d)\4\4/gi;

while(res=myreg.exec(con)){

window.alert(res[0]);

}

}

 

//限定符

function test6(){

var con=document.getElementById("11").value;

//var myreg=/a+/gi; //匹配addda;

//var myreg=/a1?/gi;

//var myreg=/[a-z]{2}/gi;

var myreg=/[^a-z]/gi;

while(res=myreg.exec(con)){

window.alert(res[0]);

}

}

\d  =[0-9] 0-9

\D  =[^0-9]

\w =[a-zA-Z0-9_]

\W  =[^a-zA-Z0-9_]

\s  =空白字符

\S  =非空白字符

.   \n之外所有字符

 

 

邮箱验证:

//邮箱验证

function test7(){

var con=document.getElementById("11").value;

var myreg=/[a-zA-Z0-9_-]+@([a-zA-Z0-9]+\.)+(com|cn|net|org)$/gi;

while(res=myreg.exec(con)){

window.alert(res[0]);

}

}

给出答案:

//邮箱验证

function test7(){

var con=document.getElementById("11").value;

var myreg=/^[a-zA-Z0-9_-]+@([a-zA-Z0-9]+\.)+(com|cn|net|org)$/gi;

必须用户名打头,com|cn|org结尾,中间只有一个@符号

if(myreg.test(con)){

window.alert("是电子邮件");

}else{

window.alert("不是电子邮件");

}

}

 

//验证一个域名

function test8(){

var con=document.getElementById("11").value;

myreg=/^(http)\:\/\/([a-zA-Z0-9]+\.)+(com|cn|net|org)$/gi;

//var myreg=//gi;

if(myreg.test(con)){

window.alert("是合法网站");

}else{

window.alert("不是合法网站");

}

}

//验证网址

function test8(){

var con=document.getElementById("11").value;

var myreg=/(http\:\/\/)?([\w.]+)(\/[\w- \.\/\?%&=]*)?/gi; //验证网址

if(myreg.test(con)){

window.alert("是合法网站");

}else{

window.alert("不是合法网站");

}

}

 

 

 

2017.04.19

1.phpMAdmin 怎么使用与打开

答:把phpMyAdmin 安装在apache的目录下面。然后点击打开,输入用户名:root, 密码:123456789就行。

2.

猜你喜欢

转载自blog.csdn.net/qq_27300101/article/details/80782887
今日推荐