前言
最近在学习文件上传漏洞,因此接触到大量的php代码,借此机会系统地学习了一下php,整理记录如下
文章目录
一、超级全局变量
Ⅰ. 全局变量
序号 | 变量名 | 描述 |
---|---|---|
1 | $_GET | 收集来自method="get" 表单中的值 |
2 | $_POST | 收集来自method="post" 表单中的值 |
3 | $_COOKIE | 存储cookie信息,常用于识别用户 |
4 | $_REQUEST | 包含了$_GET 、$_POST 和$_COOKIE |
5 | $_GLOBALS | 存有全局变量的全局组合数组 |
6 | $_SESSION | 存储session信息 |
7 | $_FILES | 用来获取通过POST方法上传文件的相关信息 |
8 | $_SERVER | 服务器和执行环境的信息 |
9 | _ENV | 环境变量 |
Ⅱ. $_GET
<!-- 测试表单 -->
<html>
<head>
<meta charset="utf-8">
<title>PHP</title>
</head>
<body>
<form action="" method="get">
frist_name: <input type="text" name="name">
last_name: <input type="text" name="school">
<input type="submit" value="提交">
</form>
</body>
</html>
<?php
// 当$_GET非空时,打印$_GET
if(!empty($_GET)){
print_r($_GET);
}
?>
Ⅲ. $_POST
<!-- 测试表单 -->
<html>
<head>
<meta charset="utf-8">
<title>PHP</title>
</head>
<body>
<form action="" method="post">
first_name: <input type="text" name="name">
last_name: <input type="text" name="school">
<input type="submit" value="提交">
</form>
</body>
</html>
<?php
if(!empty($_POST)){
print_r($_POST);
}
?>
Ⅱ. $_REQUEST
<!-- 测试表单 -->
<html>
<head>
<meta charset="utf-8">
<title>PHP</title>
</head>
<body>
<form action="" method="get">
first_name_a: <input type="text" name="first_name_a">
last_name_a: <input type="text" name="last_name_a">
<input type="submit" value="提交b">
</form>
<hr/ >
<form action="" method="post">
first_name_b: <input type="text" name="first_name_b">
last_name_b: <input type="text" name="last_name_b">
<input type="submit" value="提交b">
</form>
<hr/ >
</body>
</html>
<?php
if(!empty($_REQUEST)){
print_r($_REQUEST);
}
?>
Ⅲ. $_GLOBALS
<!-- 测试表单 -->
<html>
<head>
<meta charset="utf-8">
<title>PHP</title>
</head>
<body>
<form action="" method="post">
first_name: <input type="text" name="name">
last_name: <input type="text" name="school">
<input type="submit" value="提交">
</form>
</body>
</html>
<?php
$var = 'the_var';
print_r($GLOBALS);
?>
二、面向对象
Ⅰ. 基本知识
1. 创建类
<?php
class className{
// 代码块
}
?>
2. 对象
对象:类的一个实例
调用一个类生成一个实例的过程:实例化
<?php
class className{
// 代码块
}
$ obj_1 = new className();
$ obj_2 = new className();
// 此处的$obj_1, $obj_2为成员变量
?>
3. 成员变量(类属性)
<?php
class className{
public $name;
public $age;
// 此处的$name, $age为成员变量
}
$obj_1 = new className();
$obj_2 = new className();
?>
4. 成员方法
<?php
class className{
public $name;
public $age;
public function fun_1(){
return $this->name."<hr/>";
}
public function fun_2(){
return $this->age."<hr/>";
}
// 此处的$fun_1, $fun_2为成员方法
// $this是伪变量, 代表当前实例
}
$obj_1 = new className();
$obj_2 = new className();
echo $obj_1->fun_1();
echo $obj_2->fun_2();
?>
5. 魔术方法
序号 | 方法名 | 描述 |
---|---|---|
1 | __construct | 构造方法 |
2 | __destruct | 析构方法 |
<?php
class className{
public $name;
public $age;
public function __construct($name, $age){
$this->name = $name;
$this->age = $age;
}
// 这里的__construct()在调用类"刚刚开始"时,接受实例化时传入的参数,并将其赋值给某些成员变量
public function fun_1(){
return $this->name."<hr/>";
}
public function fun_2(){
return $this->age."<hr/>";
}
public function __destruct(){
echo '类调用结束,即将关闭';
}
// 这里的__destruct()在调用类"即将结束前"执行
}
$obj_1 = new className('Alice', 18);
$obj_2 = new className('Bob', 19);
echo $obj_1->fun_1();
echo $obj_2->fun_2();
?>
Ⅱ. 类的三大特性
- 继承:一个类型的对象获得另一个类型的对象的属性和方法
- 封装:指将客观事物抽象成类,每个类对自身的数据和方法实行保护
- 多态:指同一个实体同时具有多种形式,主要体现在类的继承体系中
1. 继承
- 使用
extends
来继承父类 - 在子类中使用
parent::
来访问父类
<?php
class className{
public $name;
public $age;
public $sex;
public function __construct($name, $age, $sex){
$this->name = $name;
$this->age = $age;
$this->sex = $sex;
}
public function fun_1(){
return $this->name."<hr/>";
}
public function fun_2(){
return $this->age."<hr/>";
}
public function fun_3(){
return $this->sex."<hr/>";
}
public function __destruct(){
echo '类调用结束,即将关闭';
}
}
// 子类继承父类
class newClassName_1 extends className{
}
// 实例化
$obj_3 = new newClassName_1('Cindy', 20, 'Female');
echo $obj_3->fun_3();
?>
2. 封装(访问控制)
public
:关键词定义在类内、子类及类外都可见protected
:关键词定义在类内、子类可见,在类外不可见private
:关键词定义在类内可见,在子类和类外均不可见
<?php
class className{
public $name;
// 在类内、子类及类外都可见
protected $age;
// 在类内、子类可见,在类外不可见
private $sex;
// 在类内可见,在子类和类外均不可见
public function __construct($name, $age, $sex){
$this->name = $name;
$this->age = $age;
$this->sex = $sex;
}
public function fun_1(){
return $this->name."<hr/>";
}
public function fun_2(){
return $this->age."<hr/>";
}
public function fun_3(){
return $this->sex."<hr/>";
}
public function __destruct(){
echo '类调用结束'."<hr/>";
}
}
?>
3. 多态
- 实现多态的前提是要先继承,再覆盖(也叫重写)父类方法
<?php
class className{
public $name;
public $age;
public $sex;
public function __construct($name, $age, $sex){
$this->name = $name;
$this->age = $age;
$this->sex = $sex;
}
public function fun_1(){
return $this->name."<hr/>";
}
public function fun_2(){
return $this->age."<hr/>";
}
public function fun_3(){
return $this->sex."<hr/>";
}
public function __destruct(){
echo '类调用结束,即将关闭';
}
}
// 子类继承父类,再覆盖父类的方法
class newClassName_2 extends className{
public function fun_1(){
return "我的名字是"."$this->name"."<hr/>";
}
public function fun_2(){
return "我的名字是"."$this->age"."<hr/>";
}
public function fun_3(){
return "我的性别是"."$this->sex"."<hr/>";
}
}
// 实例化
$obj_4 = new newClassName_2('Dell', 21, 'Male');
echo $obj_4->fun_3();
?>
Ⅲ. 更多内容
1. 静态成员(static)
- 使用
static
来定义静态成员 - 可以不用实例化便可调用类的静态成员
- 使用
class_name::
来访问类静态成员
<?php
class className{
public $name;
public $age;
public $sex;
public static $hobby;
// 静态变量$hobby
public function __construct($name, $age, $sex){
$this->name = $name;
$this->age = $age;
$this->sex = $sex;
}
public function fun_1(){
return $this->name."<hr/>";
}
public function fun_2(){
return $this->age."<hr/>";
}
public function fun_3(){
return $this->sex."<hr/>";
}
public static function fun_4(){
return className::$hobby."<hr/>";
}
// 静态方法fun_4()
public function __destruct(){
echo '类调用结束,即将关闭';
}
}
// 可以直接在类的外部对$hobby赋值
className::$hobby = 'read';
echo "<hr/>";
}
// 可以直接在类的外部调用fun_4()
echo className::fun_4();
?>
2. 抽象类(abstract)
- 抽象方法不能有具体的内容,只需要声明了它需要哪些参数
- 当一个类中存在至少一个被声明为抽象方法的方法时,这个类就是抽象类
- 抽象类不能被实例化,只能被子类继承。但子类继承抽象类时,必须重写父类中的所有抽象方法
- 这些被重写的抽象方法的访问控制不能比父类的更严格(可以同等严格,或更宽松)
- 使用
abstract
来定义抽象方法/抽象类
<?php
abstract class className{
public $name;
public $age;
public $sex;
public function __construct($name, $age, $sex){
$this->name = $name;
$this->age = $age;
$this->sex = $sex;
}
public function fun_1(){
return $this->name."<hr/>";
}
public function fun_2(){
return $this->age."<hr/>";
}
public function fun_3(){
return $this->sex."<hr/>";
}
abstract protected function fun_4($input);
// fun_4()是className()类中的一个抽象方法, 访问控制是protected,不具有具体功能,但要求传入一个$input参数
public function __destruct(){
echo '类调用结束,即将关闭';
}
}
// 子类在继承抽象父类时,重写其中的抽象方法fun_4()
// 可以保留或放宽其访问控制,但不能变得更严格。例如,这里可以使用父类的protected,或是比其更宽松的public,但不能使用更严格的private。
class newClassName extends className{
public function fun_4($input){
return $input."<hr/>";
}
}
$obj = new newClassName("Alice", 18, "Female");
echo $obj->fun_4("test");
?>
3. 接口(interface)
- 先使用
interface
来定义一个接口,接口包含一些固定的方法,不过此时不用定义这些方法的具体内容 - 使用
implements
来为类指定一个接口,在这之后,类就必须要实现这个接口中包含的方法
<?php
// 使用interface来定义一个接口aInterface
interface aInterface{
public function add($a, $b);
public function minus($a, $b);
}
// 使用implements操作符为className()类来指定一个接口aInterface
// 如此,该类中必须要实现以下所有的方法:
// public function add($a, $b);
// public function minus($a, $b);
class className implements aInterface{
public function add($a, $b){
return $a + $b;
}
public function minus($a, $b){
if($a >= $b){
$c = $a - $b;
}
else{
$c = $b - $a;
}
return $c;
}
}
$obj = new className();
echo $obj->add(9, 8);
echo "<hr/>";
echo $obj->minus(10, -34);
?>
- 接口常量:用
const
创建一个常量,在类中访问时使用interface_name::constant_name
来调用
<?php
interface aInterface{
const CONS = "我是一个接口常量";
public function add($a, $b);
}
class className implements aInterface{
// 在类中直接使用接口常量
public $cons = aInterface::CONS;
public function add($a, $b){
return $a + $b;
}
}
$obj = new className();
echo $obj->cons;
?>
4. final
关键字(final类、final方法)
- 若一个类被声明为final,那么它就不能被继承
<?php
final class className{
public function fun(){
return "我是一个函数";
}
}
class newClassName extends className{
static public function fun(){
}
}
echo newClassName::fun();
// 运行会返回以下报错:类newClassName不能从fianl类className那里继承
// Fatal error: Class newClassName may not inherit from final class (className)
?>
- 若一个类中的某个方法被声明为final,那么它就不能被重写
<?php
class className{
final public function fun(){
return "我没有被重写";
}
}
class newClassName extends className{
static public function fun(){
return "我重写了fun()";
}
}
echo newClassName::fun();
// 运行会返回以下报错:不能覆盖className中的fianl方法fun()
// Fatal error: Cannot override final method className::fun()
?>
5. 命名空间
- 命名空间用于解决全局空间内所有常量、类,及函数它们名字之间的冲突
- 命名空间内不能包含变量,它们不能被绑定到某个命名空间中
- 同一命名空间内的成员不能重名,但处于不同命名空间的成员们可以重名(可以类比于文件系统的目录:同一目录路径下的文件不能重名)
- 使用
namespace
来声明命名空间
使用以下方式(作为一条独立的语句)定义命名空间时,其范围会在到达下一个命名空间前收拢
<?php
namespace a;
function fun(){
return '我是在命名空间 a 里的fun()'.'<hr/>';
}
namespace b;
function fun(){
return '我是在命名空间 b 里的fun()'.'<hr/>';
}
// 在同一个.php中,只要定义了命名空间,那么命名空间之外不能存在代码,否则会报错Fatal error: No code may exist outside of namespace {}
// 我们可以把"全局代码"放在一个没有名字的命名空间中,如下
namespace {
echo a\fun();
echo b\fun();
}
?>
php官方文档更推荐使用以下方式(使用大括号{}),{}就是命名空间的范围
<?php
namespace c{
function fun(){
return '我是在命名空间 c 里的fun()'.'<hr/>';
}
}
namespace d{
function fun(){
return '我是在命名空间 d 里的fun()'.'<hr/>';
}
}
namespace {
echo c\fun();
echo d\fun();
}
?>
子命名空间:类比于文件系统中的文件夹,用
\
来反映命名空间之间的父子关系
<?php
//
namespace c{
function fun(){
return '我是在命名空间 c 里的fun()'.'<hr/>';
}
}
namespace c\e{
function fun(){
return '我是在命名空间 c 的子命名空间 e 里的fun()'.'<hr/>';
}
}
namespace d\e{
function fun(){
return '我是在命名空间 d 的子命名空间 e 里的fun()'.'<hr/>';
}
}
namespace {
echo c\fun();
echo c\e\fun();
echo d\e\fun();
}
?>
可以使用
use
和as
关键字来为命名空间设置别名
<?php
namespace a\b{
function fun(){
return "我是一个函数"."<hr/>";
}
}
namespace{
use a\b as space;
echo space\fun();
}
?>
以下实例使用
use
和as
关键字来解决引入文件重名的问题
<?php
// 假设'a\'和'b\'下各有一个'c.php'(都有一个fun()来返回特定字符串,但具体内容不相同)
// require关键字用于引入文件
require 'a\c.php';
require 'b\c.php';
// 为a\c和b\c分别赋予别名x, y
use a\c as x;
use b\c as y;
echo x\fun();
echo y\fun();
}
?>