一、php语言的基础
基本定义
php是运行在服务器端的,而html、css、js都是运行在浏览器上的,为WEb后台编程。php语法混合了C、java、Perl语言的特点,语法灵活,与其他编程语言有很多不同之处。
常量
称为符号常量。在PHP中使用define()函数来定义符号常量,符号常量一旦定义就不能再修改其值。另外,使用defined()函数可以判断一个符号常量是否已被定义。例如:
define("SITE","网页设计学习网",true); //定义符号常量SITE,不区分大小写
echo (defined("PI")); //如果已被定义则返回"1"
?>
变量
是指程序运行过程中其值可以变化的量,变量包括变量名、变量值和变量的数据类型三要素。PHP 的变量是一种弱类型变量,即 PHP 变量无特定数据类型,不需要事先声明,并可以通过赋值将其初始化为任何数据类型,也可以通过赋值随意改变变量的数据类型。下面是一些变量声明(定义)和赋值的例子:
$num=10+2*9; //该变量为数值型变量
$_date="2013-9-8"; //该变量为字符串变量,PHP无日期型数据类型
$bol=true; //该变量为布尔型变量
$num='赋值字符串'; //通过赋值改变变量的数据类型
$str1=$num+$_date;
var_dump($num,$_date,$bol); // var_dump函数可输出变量的类型
?>
说明:
① PHP变量必须以"$"开头
② 变量使用前不需要声明,PHP中也没有声明变量的语句;
③ 变量名不能以数字或其他字符开头,其他字符包括@、#等。例如xm,_id,sfzh 都是合法的变量名,而-id,57zhao,zh fen都是非法的变量名;
④ 变量名长度应小于255个字符,不能使用系统关键字作为变量名。
变量的作用域和生存期
变量的作用域
变量的作用域是指该变量在程序中可以被使用的范围。对于 PHP 变量,如果变量是定义在函数内部的,则只有这个函数内的代码才可以使用该变量 ,这样的变量称为"局部变量"。如果变量是定义在所有函数外的变量,则其作用域是,整个 PHP 文件减去用户自定义的函数内部,称为"全局变量"。例如:
"; //该变量为全局变量
function fun(){
echo $a; //调用函数也不会输出"全局变量"
$a="局部变量、"; //该变量为局部变量
echo $a;
}
fun(); //输出"局部变量"
echo $a; //输出"全局变量" ?>
输出结果为"局部变量、全局变量"。
可见函数内不能访问函数外定义的变量。
如果一定要在函数内部引用外部定义的全局变量,或者在函数外部引用函数内部定义的局部变量。可以使用global关键字:
变量的生存期表示该变量在什么时间范围内存在。全局变量的生存期从它被定义那一刻起到整个脚本代码执行结束为止;局部变量的生存期从它被定义开始到该函数运行结束为止。
可变变量 是一种特殊的变量,这种变量的名称不是预先定义的,而是动态地设置和使用 。可变变量一般是使用一个变量的值作为另一个变量的名称。可变变量直观上看就是在变量名前加一个"$",
例如:
$b = '一个变量'; //定义变量$b
echo $$a; //$$a就是一个可变变量,相当于$b
$b = '变化后';
echo $$a; //通过可变变量输出变量$b的值
$a = 'c';
echo $$a; //相当于输出变量$c的值
?>
输出结果是"一个变量变化后"。
由于没有给$c 赋值,第三条 echo 语句不会输出任何内容。
引用赋值
从 PHP4.0 开始,提供了"引用赋值"功能,即新变量引用原始变量的地址,修改新变量的值将影响原始变量,反之亦然。引用赋值使得不同的变量名可以访问同一个变量内容。使用引用 赋值的方法是:在将要赋值的原始变量前加一个"&"符号。例如:
$a="hello "; //$a赋值为hello
$b=&$a; //变量$b引用$a的地址
echo $a; //输出结果为hello
$b="world "; //修改$b的值,$a的值将一起变化
echo $a; //输出结果为world
$a="cup"; //修改$a的值,$b的值将一起变化
echo $b; //输出结果为cup
?>
#引用赋值后,两个变量指向同一个地址单元,改变任意一个变量的值(即地址中的内容),另一个变量值也会随之改变。
字符串转换为数值型的原则是:从字符串开头取出整数或浮点数,如果开头不是数字的话,就是0。布尔型的True会转换成数值1,False转成数值0。
运算符
连接运算符
PHP 中连接运算符只有一个,即".",它用于将两个字符串连接起来,组成一个新字符串。如果连接运算符左右两边任一操作数或两个操作数都不是字符串类型,那么会将操作数先转换成字符串,再执行连接操作。
$a='PHP'. 5; //$a的值为PHP5,注意数字和"."之间要用空格隔开
$b='PHP'.'5'; //$b的值为PHP5
$c="PHP".True; //$c的值为PHP1
$d=5 . 'PHP'; //$d的值为5PHP
如果"."的左右有数字,注意将"."和数字用空格隔开。
"."是强制连接运算符,不管左右两边是什么数据类型,都会执行连接运算。
赋值运算符
最基本的赋值运算符是"=",它用于对变量赋值,因此它的左边只能是变量,而不能是表达式。例如,a=3+5,b=c=9 都是合法的。此外,PHP 还支持像 C 语言那样的赋值运算符与其他运算符的缩写形式,如"+="、".="、"\&="、"\|="等。例如a+=3 等价于a=a +3,a.=3等价于a=$a. 3。
比较运算符
比较运算符会比较其左右两边,PHP 规定字符串的前后必须加上单引号(')或双引号("),例如"这是一个字符串"、'另一个字符串'、'5'、'ab'、''(空字符串)都是合法的字符串。但单、双引号不能混用,如'day"则是非法的。
如果字符串中出现单引号(')或双引号("),则需要使用转义字符(\'或\")来输出,例如:
echo 'I\'m a boy'; //输出结果为I'm a boy
单引号字符串和双引号字符串
单引号表示包含的是纯粹的字符串,而双引号中可以包含字符串和变量名。双引号中如果包含变量名则会被当成变量,会自动被替换成变量值,单引号中的变量名则不会被当成变量,而是把变量名当成普通字符输出。
数组
数组是按一定顺序排列,具有某种数据类型的一组变量的集合。数组中的每个元素都是一个变量,它可以用数组名和唯一的索引(又称"下标"或"键名")来标识。
PHP中创建数组有两种方法:① 使用array()函数创建;② 直接给数组元素赋值。
1.使用array()函数创建数组
PHP 的数组不需要定义,可以直接创建。创建数组一般使用 array()函数,假设要创建一个包含4个元素的一维数组,简单形式是:
$citys=array( "长沙","衡阳","常德","湘潭");
该数组的长度为 4,各个数组元素的索引值分别为 0、1、2、3,如$citys[1]表示第 2 个数组元素。
如果要自行给每个元素的索引赋值,可以使用完整形式定义:
$citys=array('cs'=>'长沙','hy'=>'衡阳','cd'=>'常德','xt'=>'湘潭');
完整形式增加了对数组元素索引的赋值,这时各个数组元素的索引值分别为 cs、hy、cd、xt,如citys\[hy\]表示第2个数组元素(注意此时不能再使用citys[1]访问该数组元素)。
2.直接给数组元素赋值创建数组
也可以创建一个空数组,然后再给每个数组元素赋值。例如:
$citys=array( ); //创建空数组,该语句可省略
$citys[1]="长沙"; $citys[3]="常德"; $citys[]="湘潭";
print_r ($citys); //打印数组
上述代码输出结果为:
Array ( [1] => 长沙 [3] => 常德 [4] => 湘潭 )
可见,如果给数组元素赋值时不写该元素的索引值,则该数组元素默认的索引值为数组中最大的索引值加1。如果数组中没有正整数形式的索引值,则默认的索引值为0.
返问数组
数组元素也是变量,访问单个数组元素最简单的方法就是通过"数组名[索引]"的形式访问,
例如i=citys[3]、echo $citys[1]。也可以使用大括号访问数组元素,例如echo citys{3}。
如果要访问所有数组元素,可以使用foreach语句遍历数组。
添加、删除、修改数组元素
如果给已存在的数组元素赋值,将修改这个数组元素的值;给不存在的数组元素赋值,将添加新的数组元素;而要删除数组元素,一般使用unset()方法。例如:
$arr[0]=66; //修改数组元素
$arr[1]='长沙'; //修改数组元素
unset($arr[2]); //删除数组元素
$arr[]=55; //添加数组元素
$arr[5]=88; //添加数组元素
print_r ($arr); ?>
运行结果为:
Array ( [0] => 66 [1] => 长沙 [3] => 44 [4] => 55 [5] => 88 )
注意删除的元素索引不会被新添加的数组元素占用。
函数
explode()函数
explode()通过切分一个具有特定格式的字符串而形成一个一维数组,数组中的每个元素就是一个子串。语法为explode(separator, string[,limit]),
例如:
$arr=explode(" ",$str); //通过切分生成数组$arr
print_r($arr); ?>
输出结果为:
Array ( [0] => 湖南 [1] => 湖北 [2] => 广东 [3] => 河南 )
说明:
(1)explode的分隔符可以是空格等一切字符,但不能为空字符串""。
(2)limit参数可限制返回数组元素的个数。
implode()函数
implode()使用连接符将数组中的元素连接起来形成一个字符串,它实现了与 explode()相反的功能,例如:
$link=implode("--",$grade);
echo $link; //输出A--C--D--B ?>
range()函数
range()可以快速创建一个从参数start到end的数字数组或字符数组,语法为
array range(mixed start, mixed end),例如:
print_r($score); //输出Array ( [0] => 2 [1] => 3 [2] => 5 )
$score=range('D','A'); //等价于$score=array('D', 'C', 'B','A');
排序函数
排序函数中 a 表示 association,表示排序过程中保持"键值对"的对应关系不变。r表示reverse,表示按降序进行排序。k表示key,表示按照数组元素的"键"进行排序。
如下:
sort($pic); //将sort依次换成asort,rsort,arsort
print_r ($pic); ?>
输出结果依次为:
Array ( [0] => img01.gif [1] => img1.gif [2] => img10.gif [3] => img12.gif [4] =>img2.gif )
Array ( [4] => img01.gif [3] => img1.gif [1] => img10.gif [0] => img12.gif [2] =>img2.gif )
Array ( [0] => img2.gif [1] => img12.gif [2] => img10.gif [3] => img1.gif [4] =>img01.gif )
Array ( [2] => img2.gif [0] => img12.gif [1] => img10.gif [3] => img1.gif [4] =>img01.gif )
natsort 函数是用"自然排序"的算法对数组 arr 元素的值进行升序。
gut:
数组,例如:
'blue','red','b'=>'blue','green', 't'=>'red');
result=array_unique(color);
print_r($result); //输出Array([a] => blue [0] => red [1] => green)?>
搜索函数
搜索函数用来检查数组中是否存在某个值或某个键名,假设示例数组为$color=array('a'=>'blue','red','green','red')。
数组搜索函数及功能
如果想检查数组中是否含有某个键名,可以用 array_search()函数;如果想获取所有匹配的键名,则应该使用array_keys()函数,并设置search参数。
list函数
list()函数可以用数组中的元素为一组变量赋值,从而通过数组得到一组变量。语法格式为:
void list(var1, var2,..., var n)=array arr
list要求数组arr中所有键为数字,并要求数字键从0开始连续递增, 例如:
$arr=explode(" ",$str); //$arr=array ([0]=>湖南 [1]=>湖北 [2]=>广东 [3]=>河南)
list($s1,$s2,$s3)=$arr; //$s1='湖南',$s2='湖北',$s3='广东'
echo $s1."
".$s2."".$s3.""; ?>
extract函数
extract()函数能利用一个数组生成一组变量,其中变量名为数组元素的键名,变量值为数组元素的值。如果生成的变量名和已有的变量名冲突,则可以使用其第 2个参数按一组规则来处理。
compact函数
compact函数利用一组变量返回一个数组,它实现了和extract函数相反的功能。数组元素的键名为变量名,数组元素的值为变量值。
如下:
"长沙","hy"=>"衡阳",cd=>"常德",xt=>"湘潭");
extract($citys); //$cs='长沙',$hy='衡阳',$cd='常德',$xt='湘潭'
echo $xt; //输出湘潭
$newcitys=compact('cs','cd','xt'); //用变量组成数组
print_r($newcitys); //输出array([cs]=>长沙 [cd]=>常德 [xt]=>湘潭) ?>
二、例题
[LitCTF 2023]PHP是世界上最好的语言!!
随便点点,发现了语法错误
试试printf('123456');
使用命令查询,flag在根目录中。
system('ls');
system('ls /');
system('cat /flag');
最后就得到了flag
[SWPUCTF 2022 新生赛]ez_ez_php
很简单的PHP题目
详细分析一下:
error_reporting(0)
不显示任何错误;
if (isset($_GET['file'])) {
检查是否有个file的get参数;
if ( substr($_GET["file"], 0, 3) === "php" ) {
这行代码使用substr()
函数获取"file"参数的前3个字符,并与字符串"php"进行比较。如果相等,则执行以下代码。
echo "Nice!!!";
这行代码输出字符串"Nice!!!"
include($_GET["file"]);
这行代码使用include()
函数将"file"参数传递给PHP解析器,并包含/执行指定的文件。
else { 如果"file"参数不以"php"开头,则执行以下代码。
echo "Hacker!!"; 输出字符串"Hacker!!"。
} else { 如果没有传递"file"参数,则执行以下代码。
highlight_file(FILE); 使用highlight_file()函数将当前文件的源代码输出到浏览器。
ctfshow___web89
拿到题目打开后是这个,
那就来仔细研究一下,
include("flag.php");
包含一个flag.php文件
highlight_file(__FILE__);
显示当前文件的源代码
if(isset($_GET['num'])){
$num = $_GET['num'];
if(preg_match("/[0-9]/", $num)){
die("no no no!");
}
先检查是否有个get请求的num参数,然后将get请求的num参数的值赋给变量num,接下来是个正则表达式,检查变量num中是否含有数字0~9,如果有,则输出no,no,no!
if(intval($num)){
echo $flag;
}
这里面有个intval函数,
作用:将变量转化为整数型。这个函数尝试从变量值的开头解析出一个整数,直到遇到它不能识别为整数的一部分的字符为止。如果字符串的开头是数字,那么 intval()会解析并返回这个整数值;如果字符串的开头不是数字,那么 intval会返回 0。
实例:
// 字符串开头是数字
echo intval("42"); // 输出 42
echo intval("42 apples"); // 输出 42
// 字符串开头不是数字
echo intval("apples"); // 输出 0
// 浮点数
echo intval(42.17); // 输出 42
echo intval(42.99); // 输出 42
// 十六进制字符串
echo intval("0x1A"); // 输出 26(因为 0x1A 是十六进制的 26)
// 字符串中的空格和符号
echo intval(" 42"); // 输出 42
echo intval("42px"); // 输出 42
// 数组(只转换第一个元素)
echo intval(array("123", "456")); // 输出 123
// 布尔值
echo intval(true); // 输出 1
echo intval(false); // 输出 0
// 空字符串和 null
echo intval(""); // 输出 0
echo intval(null); // 输出 0
那么,就是绕过数字0到9,而且要保证intval($num)返回的值不为0,就想到了用数组来绕过,
num[]=0,就可以了。
ctfshow__web90
这个题目与89题很相似,大体情况就是:
如果 num 的值严格等于"4476",则输出"no no no!"并终止执行;
如果 num 转换为整数并以 0 作为基数进行转换后等于 4476,则输出 $flag 的值
补充:intval()函数的第二个参数是基数(base),这里设置为0
意味着intval()会自动检测输入字符串的格式,并尝试将其转换为十进制整数。
那么,解题思路:直接传递"4476"
会被阻止,但intval()在基数为0时会尝试将字符串转换为整型,我们可以利用这一点来绕过直接比较。例如,"010574"
(八进制)或"0x117c"
(十六进制)在转换为十进制时都等于4476。
ctfshow__93
根据该代码可以知道:
比较90题,这里的正则表达式:/[a-z]/过滤了小写字母。那么直接用八进制就可以了。
ctfshow__94
这里可以看到有个strpos函数:
**strpos()**函数在 PHP 中用于查找字符串首次出现的位置。如果找到了字符串,它会返回首次出现的索引(位置),索引计数从 0 开始。如果没有找到字符串,则返回 false
。
要注意,strpos()
是区分大小写的。如果要进行不区分大小写的搜索,可以使用 stripos()
函数,而且第一位不能为0
那么就可以使用小数
ctfshow__97
分析:检查是否通过post传递a和b两个参数,这是通过isset()函数实现的,该函数用于检查变量是否已设置且非NULL。然后保证a和b的值不同但是两个要有相同的md5加密,就可以得flag。
里面涉及到了,PHP的弱比较和强比较,但是并不是真正的弱比较,md5的绕过。
1、对于php强比较和弱比较:md5(),sha1()函数无法处理数组,如果传入的为数组,会返回NULL,两个数组经过加密后得到的都是NULL,也就是相等的。
2、对于某些特殊的字符串加密后得到的密文以0e开头,PHP会当作科学计数法来处理,也就是0的n次方,得到的值比较的时候都相同。
常见加密后密文以0e开头的字符串:
md5:
240610708:0e462097431906509019562988736854
QLTHNDT:0e405967825401955372549139051580
QNKCDZO:0e830400451993494058024219903391
PJNPDWY:0e291529052894702774557631701704
NWWKITQ:0e763082070976038347657360817689
NOOPCJF:0e818888003657176127862245791911
MMHUWUV:0e701732711630150438129209816536
MAUXXQC:0e478478466848439040434801845361
sha1:
10932435112: 0e07766915004133176347055865026311692244
aaroZmOk: 0e66507019969427134894567494305185566735
aaK1STfY: 0e76658526655756207688271159624026011393
aaO8zKZF: 0e89257456677279068558073954252716165668
aa3OFF9m: 0e36977786278517984959260394024281014729
0e1290633704: 0e19985187802402577070739524195726831799
先简单来说,md()和sha1()无法处理数组,那么就利用这个a[]=1&b[]=2,
就可以得到了flag。
利用特殊字符来做的话,
md5的强碰撞,需要两者的MD5值相同,
比如:
这是16进制的
0e306561559aa787d00bc6f70bbdfe3404cf03659e704f8534c00ffb659c4c8740cc942feb2da115a3f4155cbb8607497386656d7d1f34a42059d78f5a8dd1ef
0e306561559aa787d00bc6f70bbdfe3404cf03659e744f8534c00ffb659c4c8740cc942feb2da115a3f415dcbb8607497386656d7d1f34a42059d78f5a8dd1ef
两个的MD5都为:
cee9a457e790cf20d4bdaa6d69f01e41
重点:
两个16进制不同,但MD5相同
4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa200a8284bf36e8e4b55b35f427593d849676da0d1555d8360fb5f07fea2
4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa202a8284bf36e8e4b55b35f427593d849676da0d1d55d8360fb5f07fea2
cee9a457e790cf20d4bdaa6d69f01e41
但是还有问题,16进制里面含有不可见的字符,我们采用url编码
就是以下的内容。
a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2&b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2
也可以得到了flag。
ctfshow__98
ctfshow__101
代码审计:
引出flag.php,v1,v2,v3都是通过_get输入,而$v0是检验三者是否还都是数字,然后出现了很多的需要过滤的东西。
查询后,要使用反射类方法
反射,通过一个对象来获取所需类的内容。PHP中含有强大的反射API,PHP的反射,我们要知道用反射获取类的信息,直接使用echo new reflectionclass。
php reflectionclass API 这个是php5以后才有的功能,
$class = new ReflectionClass('Person'); // 建立 Person这个类的反射类
$instance = class-\>newInstanceArgs(args); // 相当于实例化Person 类
最终:payload:?v1=2&v2=echo new reflectionclass &v3=;
但是少了一位,自己爆破的,然后还有0x2d要替换成"-"
ctfshow__102
先来看看,substr()函数
三、php+MySQL制作网站
首先是登录页面制作,先看想想基本流程
HTTP协议与状态
用简单的话来理解,用户从一个页面跳转到另外一个页面时,由于HTTP协议是无状态协议的,也就是说当一个用户请求一个页面后再请求另外一个页面时,HTTP将无法告诉我们这两个请求是来自于同一个用户,所以不能记录上一个页面用户的状态,PHP变量的作用范围也局限于同一个PHP文件,它也不能记录上一个页面用户的状态。
会话技术
php服务器如何跟踪一个客户端用户的状态,一般需要有一种机制来跟踪和记录用户在该网站所进行的活动,就叫做会话技术。
Session技术和Cookie
其中,Cookie是种在远程浏览器端储存数据并以此来跟踪和识别用户的机制。Session则是将信息放在服务器端的会话技术。
两者最大的不同在于Cookie将信息存放在客户端,Session将数据存放在服务器中。
具体过程:
当程序需要为某个客户端的请求创建一个Session的时候,服务器首先检查这个客户端的请求里是否已包含了一个Session标识,称为session id,如果已包含一个session id,则说明以前已经为此客户端创建过Session,服务器就按照session id把这个Session检索出来使用(如果检索不到,可以会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并生成一个与此session相关联的session id,session id的值应该是一个不会重复、不容易被找到规律造价。
Session的使用:
<? php
session_start O; /开启Session
$_SESSION['name]=张三; "/向Session添加数据(字符串)
$_SESSION[info]=array (张三,'男'); //向Session添加数据(数组)
if (! isset ($ SESSION[ count'])){ //判断Session中是否存在count
$_SESSION['count'] =0;
} else (
$ SESSION['count']++;
}
unset ($_SESSION['name']):
$SESSION=array O:
session _destroy ();
? >
$_SESSION=array ()方式可以删除Session中的所有数据,Session文件存在,但是它一个空文件,可以通过Session_destroy ()函数来到目的。
过程:
先写一个用户登录页面login.html,
<form method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="text" name="password"?><br>
<input type="submit" value="登录">
</form>
接受用户登录页面和接受用户登录表单数据的login.php
<? php
$error=array ();//保存错误信息
if (! empty ($ POST)) //判断有无表单提交4.
ض /有表单提交,接收用户表单提交的数据
S Susername=isset ($_POST['username'])? trim ($ POSTJ'username'D):"
Sраssw0rd=іssеt ($_РОSТ[раsswоrd']) ? trіm ($_РОSТ[раsswоrd']): "';
header (Content-Type: text/html; charset=utf-8'): //设置连接数据库的参数
$servername= "localhost", //设置MYsQL数据库所在的服务器名
$dbusername ="root", //设置使用MYsQL数据库的用户名
$dbpassword =""; //设置用户的密码13. $dbname="db_shop": //设置要连接的数据库的名称
/使用构造方法创建连接并选择数据库
15. $mysqli= new MySQLI ($servername, $dbusername, $dbpassword, $dbname, 3306'); 16. "检测连接17. f ($mуsqlі->сопnесt_еrrоr) {
18. die ("连接失败,出错信息为:".$mysqli->connect_error); 19.
20. $mysqli->query ("set names utf8"): //告知MysQL服务器使用utf8编码进行通信
21. $sql="select * from tb_user where username='$username"; 22. if ($rs=$mysqli->query ($sql)) 23.
24. $row=$rs->fetch assoc O; 25. if ($roW['password']==$password)
<? php
$error=array ();//保存错误信息
if (! empty ($ POST)) //判断有无表单提交4.
{ //表单提交,接收用户表单提交的数据
$username=isset ($_POST['username'])? trim ($ POSTJ'username'D):"
$раssw0rd=іssеt ($_РОSТ[раsswоrd']) ? trіm ($_РОSТ[раsswоrd']): "';
header (Content-Type: text/html; charset=utf-8'):
//设置连接数据库的参数
$servername= "localhost", //设置MYsQL数据库所在的服务器名11. $dbusername ="root", //设置使用MYsQL数据库的用户名
$dbpassword =""; //设置用户的密码13. $dbname="db_shop": //设置要连接的数据库的名称
//使用构造方法创建连接并选择数据库
$mysqli= new MySQLI ($servername, $dbusername, $dbpassword, $dbname, 3306');
//检测连接
if ($mуsqlі->сопnесt_еrrоr) {
die ("连接失败,出错信息为:".$mysqli->connect_error);
}
$mysqli->query ("set names utf8"): //告知MysQL服务器使用utf8编码进行通信
$sql="select * from tb_user where username='$username";
if ($rs=$mysqli->query ($sql))
{
$row=$rs->fetch assoc ();
if ($roW['password']==$password)
{
session_start ();
$_SESSION['userinfo']=arry(
'id'=>$row['uid'],
'uername'=>$username
);
header ('Location: index.php'); //跳转到登录控制中心
die;
}
else
{
$error[]="用户名不存在或密码错误";
}
}
require ("login_html.php");
<form method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="text" name="password"?><br>
<input type="submit" value="登录">
</form>
//登录失败时显示错误信息
<?php if (! empty ($error)) {?>
<div>
<ul>
<? php
foreach ($error as $key =>$value)
echo "<li> $value</li>";
}
?>
</ul>
</div>
<? php } ?>
//判断用户是否已经登录
<? php
session_start ();
if (isset ($_SESSION['userinfo']))
//用户信息是否存在
{
$login=true;
$userinfo=$_SESSION['userinfo'];
}
else
{
$login=false;
}
require ("index_html.php");
//用户退出
session_start ();
if (isset ($_GET['action']) && ($_GET['action']) =='logout') {
unset ($_SESSION['userinfo'];
if (empty ($_SESSION))session_destroy ();
Header ('Loaction: login.php');
die;
}
<? php } ?>
<div> 用户中心 </div>
<? php if ($login): ?>
<?php echo $userinfo['username']; ?>您好! <a href=? action=logout">注销</a>
<?php esle: ?>
您还没有登录,请先< a href="login.php">登录</a>!
<? php endif; ?>
文件上传
PHP实现文件上传的原理:
使用文件上传表单,将文件提交后,数据将本地上传到服务器的临时目录,然后通过其内置函数将临时目录的数据移动到要放的地方。
PHP实现文件上传的函数有三个:Copy、is_uploaded_file,move_uploaded_file
copy函数的作用是拷贝文件,语法格式:
bool copy (string $source,string $dest)
上传原理:post给Copy函数,再通过Copy函数将文件复制到服务器上。
is_uploaded_file函数的作用是判断文件