PHP学习笔记

本文是笔者在对PHP进行了解性的学习时所记录的笔记,在撰写过程中大量使用了AI,但也并非完全地将AI的输出进行简单的复制粘贴。
由于此前笔者有过C++的学习经历,故本文会较为注重PHP与C++不同的地方,而两者相似之处通常一笔带过,不作赘述。
由于笔者水平有限,难免会有错漏。
若有纰漏,欢迎读者的批评与指正!

变量

变量以$符号开头,后面跟变量名

命名规则与C++类似

$name="Alice"; //字符串
$age = 25; //整数
$is_student = true; //布尔值

数据类型

PHP主要的数据类型如下

  • 整数
  • 浮点数
  • 布尔值
  • 字符串
  • 数组
  • 对象
  • NULL

PHP是动态类型语言(弱类型语言),不需要显式声明变量类型

数据类型的转换

数字和字符串可以相互自动进行类型转换

对于布尔值,非0数字和非空字符串会被转换为true,其余转换为false

布尔值转换为字符串会先转换成整型1或0

也可以用显示的强制转换,如(int)$var

或者使用函数

intval();//参数传入要转换的值,返回转换后的结果
floatval();
strval();
boolval();

php中数组和对象可以相互转化,

转换后数组的键会变成对象的属性,数组的值会变成属性的值,如果键是整数,则这个键会变成字符串

使用 $obj = (object)$array;来转换

如果数组中有嵌套的数组,也会一并被转换成对象

对象也可以用(array)转换成数组,但只能把public的属性转换出来,而且不能嵌套转换对象的属性对象

运算符

php与C++运算符不同之处在于

php有===与!==严格比较运算符,要求比较的两者值相等(或可以转换)并且类型也相同

php使用.来拼接字符串,也可以用.=来拼接

php支持短路运算符??,又叫做null合并运算符

$value = $a ?? 'default'; //如果$a为null 则返回后面的值'default'

其作用是将null值去除

php的字符串支持++,但只有空字符串支持–

其作用是将字符串最后一个字符进行++(ASCII意义上的)

对于空字符串,支持++和–,则会先转换成数字0,再+1或-1

数组

PHP的数组可以同时包含多种类型的元素

PHP有两种数组,一种是索引数组,一种是关联数组(键值对数组,类似c++的map,python的dict)

索引数组的定义

$clolrs = array("red","green","blue"); // 索引数组使用array()函数定义
$fruits = ["apple","banana","cherry"]; // 索引数组使用短数组语法 与Python类似
$Array = []; // 空数组

元素访问

echo $fruits[0]; // 输出 apple

关联数组的定义

php的关联数组的key只能是整型或字符串,如果使用了布尔值、浮点数,也会分别被自动转为整型和字符串

类似地,关联数组也可以用短数组语法

$person = array("name"=>"Alice","age"=>25); //关联数组 array()
$person = ["name"=>"Alice","age"=>25]; //关联数组 短数组语法

多维数组的定义与访问

$student = [
	["name"=>"Alice","age"=>20],
	["name"=>"Bob","age"=>22],
	["name"=>"Charlie","age"=>21]
]; //甚至可以将两种数组混用

echo $student[0][age]; //输出 20

一种插入元素的方法

$arr[] = 5; //往数组末尾插入5

非连续的索引

php的数组允许非连续的索引,并且count的结果仍为实际上数组元素的个数

操作数组的内置函数 这些函数不是成员函数

$arr = [1,2,3]; //已经声明并初始化了一个数组$arr
echo count($arr); //计数:输出 3
unset(arr[2]); //删除索引为2的元素

字符串

单引号字面量定义的字符串

echo 'Hello, $name'; //原样输出Hello, $name

变量不被解析,只有\\和\'这两个转义字符有效

双引号字面量定义的字符串

变量会被解析,转义字符会生效

字符串与布尔值

字符串可以被隐式转换为布尔值

空字符串为false 非空字符串为true

$str1=""; //false
$str2=" "; //true
$str3="   "; //true
$str4="hahaha"; //true

字符串拼接

使用.符号拼接,与C++中使用+不同

$greet_words="Hello, ".$name; //将字符串"Hello, "和变量$name存储的字符串拼接

类似地,也可以使用.=来拼接字符串

$name="Charry";
$name.="Brown"; //$name变为"CharryBrown"

控制与循环语句

if与C++一致

if (条件1) {
    // 当条件1为真时执行的代码
} else if (条件2) {
    // 当条件1为假且条件2为真时执行的代码
} else {
    // 当条件1和条件2都为假时执行的代码
}

while()与C++一致 值得注意的是,php的整型可以被隐式转换成布尔值,因此可以使用类似while($n--)的语法

while($n--)
{
	echo $n;
}

switch与C++一致

switch(变量)
{
	case1:
		break;
	case2:
		break;
	default:
		//...
}

php的for不能像C++一样使用for(…in…)语法

类似地,可以使用foreach

foreach($array as $value)
{
	//$value将会遍历赋值$array中的对象
}

还可以同时遍历键和值

foreach($array as $key => $value)
{
	//$key... $value...
}

函数

php没有主函数,函数和顶级流程代码都写作顶级语句

函数使用function定义,将C++中原本返回值类型的地方换成了function

function greet($name) //定义
{
	return "Hello,".$name;
}

echo greet("Alice"); //调用

实际上,自php7开始,也支持指定返回值类型和参数类型,但具体的写法仍与C++不同

function add(int $a,int $b):int
{
	return $a+$b;
}

php的函数签名包括函数名参数列表返回值类型

简单地说,就是包括了函数声明语句

如这句话:function add(int $a, int $b): int就囊括了函数签名的全部内容

如果返回值类型、参数类型没有指定,就不会被包括

php的函数不支持重载,即使函数签名不同,这点与C++不同

函数也支持默认值,其规则与C++类似,有默认值的参数要在没默认值的参数前

function greet(int $times,string $name = "Guest"): string {
    while($times--)
    {
        echo "Hello, $name!"."<br>";
    }
}

超全局变量

PHP中有一种超全局变量,可以在脚本的任何位置访问,不需要global关键字

有一些超全局变量与http请求有关

$_GET

$_GET用于收集通过URL查询字符串传递的变量,适用于HTTP GET方法

//假如下面的代码写在了index.php
//并且通过了这个URL访问这个php:index.php?name=Alice&age=25
$name=$_GET['name'];
$age=$_GET['age'];

http get方法传递的参数已经被存储在一个叫$_GET的关联数组

其键和值都是字符串 即使传递前不是字符串,但是经过了这样的方式传递,在传递前会被自动转换为字符串

可能需要配合parseInt()等函数来使用

parseInt()

httpspecialchars(<要转换的字符串>) //这个函数可以将特殊字符转换为html实体,防止html注入

所谓将特殊字符转换为html实体的意思是:

本来< >等字符在html中是有特殊效果的,想要显示原本的字符,需要用&lt;等HTML字符实体

为了避免有人通过输入的字符串来干扰你的网页,你需要事先用这样的方法把这些字符变成字符实体

这样这些字符就不会起到其在html中的特殊效果

$_POST

类似地,通过POST方法传递的参数也被存储在了一个叫_POST的关联数组

$name = $_POST['name']; //获取POST请求中的name参数

$_COOKIE

访问客户端发送的cookie内容,与前者类似

$_REQUEST

这个可以同时访问$_GET,$_POST,$_COOKIE的变量,相当于是一个整合了三者内容的关联数组

$_FILES

可以访问通过HTTP POST方法上传的文件

//一个简单的示例
$fileName = $_FILES['file']['name']; //获取上传文件的名称

类与对象

php中有类似C++中的类

类的定义与C++相似,但又有一定的不同

abstract class Animal
{
	//属性的声明 属性的权限写在前面
	protected $name;  //public protected privete等权限与C++中一致
	protected $age;   //但是写法不同
	
	//构造函数 定义方法与C++中不同
	public function __construct($name)
	{
		$this->name = $name; //在类成员函数使用成员属性 也必须使用-> 这点与C++不太一样
	}
    
    //成员函数 权限写在前面
 	public function getInfo()
    {
        return "Name: ".$this->name.", Age: ".$this->age;
    }
    
    //纯抽象(纯虚)方法 在子类中必须要将其重载
    abstract public function makeSound();

	
}

一个子类Dog

class Dog extends Animal
{
	private $breed; //私有属性
    
    //构造函数的重载
    public function __construct($name,$age,$breed)
    {
        parent::__construct($name,$age); //调用父类的构造函数
        $this->breed = $breed;
    }
    
    //重载了父类的纯抽象方法
    public function makeSound()
    {
        return "Woof! Woof!";
    }
    
    public function getBreed()
    {
        return $this->breed; //自己独有的方法 获取Breed狗的品种信息
    }
    
    public function getInfo()
    {
        return parrent::getInfo().", Breed: ".this->$breed; //重载了父类的方法
    }
    
}

创建对象和使用

$dog = new Dog("Wong",3,"Black"); //Dog类变量引用Dog类对象

echo $dog->makeSound();
  • abstract的类是抽象类,不能被实现
  • abstract与C++中的virtual并不相同,abstract标记的方法是抽象方法,也就是C++中的纯抽象函数,必须不能有具体实现,在非抽象子类中必须实现
  • 只有abstract的类,才能有abstract的方法
  • 实例化的子类对象,如果普通的方法没有重载,则调用父类的方法(与C++一致)
  • 由于PHP中不能指定变量类型,所以不像C++中有父类变量引用(或者父类指针指向)子类对象这种用法,也不会有因此产生的一些特性
  • PHP不支持多重继承
//方式一
class Animal{
    public function makeSound() {
        return "Some sound";
    }
}

class Dog extends Animal{
    public function makeSound()
    {
        return "Woof!";
    }
}

//方式二
abstract class Animal{
    abstract public function makeSound() {
        return "Some sound";
    }
}

class Dog extends Animal{
    public function makeSound()
    {
        return "Woof!";
    }
}

接口

php不支持多重继承,采用接口的方式来实现类似的效果

<?php
    interface Animal{
        public function makeSound(); //interface 接口的方法必须不能有实现 并且属性一定是public
    }

    interface Pet{
        public function play();
    }

    class Dog implements Animal,Pet{ //使用implements(v.实现)关键字来表明该类要实现这两个接口
        public function makeSound()
        {
            return "Woof!"; //在接口的子类中 必须实现方法
        }
        public function play()
        {
            return "Playing fetch!";
        }
    }

    $dog = new Dog();
    echo $dog->makeSound()."<br>"; //html网页环境 使用<br>换行
    echo $dog->play();
?>

接口与抽象类类似,但不同之处在于

  • 一个class可以implements多个接口,而一个class不能extends多个抽象类
  • 接口中的每一个方法都不能有实现(方法一定没有函数体),而抽象类可以
  • 接口中的每一个方法属性必须是public,而抽象类可以是其他的属性

接口还可以有子接口,继承父接口

子接口继承父接口,可以继承多个父接口,这与类的不能多重继承不同

若要实现子接口,必须要实现子接口和父接口的所有方法

特征trait

使用关键字trait可以定义特征trait

    trait CanFly
    {
        private function deepfly()
        {
            echo "Flying!";
        }
        public function fly()
        {
            $this->deepfly();
        }

    }
    trait CanSwim
    {
        public function swim()
        {
            echo "Swimming!";
        }
    }
    class Bird
    {
        use CanFly,CanSwim;
    }

    $bird = new Bird();
    $bird->fly();

使用use关键字在类中引入trait,相当于在类中复用了trait中声明的方法

trait可以使用extends关键字继承其他的trait

trait中的方法可以被将其引入的class和将其继承的trait重写,但属性不能改变

前置声明后置实现

php不支持前向声明,函数、类等被使用之前必须先实现

而且也不能只写声明不写实现,除非是abstrat函数

引入其他php

require和include可以用于引入其他的php文件

如果被引入的php文件中有return语句

则require或include将会返回该文件return语句返回的对象/变量

当文件被引入时,其中的函数、类、变量等都会被引入到当前文件的全局作用域

require与include的主要区别在于对错误的处理不同

require引入文件出错,会产生致命错误,使得脚本停止执行

include引入文件出错,会产生警告,但脚本继续执行

$config = include "config.php";
$server_config = require "server_config.php"

如果没有返回值,也可以不用变量 c o n f i g , config, configserver_config来接收

php与MySQL

使用拓展MySQLi,可以在php中对MySQL数据库进行操作

连接数据库

$mysqli = new mysqli("地址","用户名","密码","要操作的数据库","端口(也可以省略)");

如果连接失败

$mysqli -> connect_error //值为真

查询

使用数据库对象的成员方法query来查询,传入查询语句作为参数

返回查询结果对象

$result = $mysqli->query("SELECT * FROM users");

结果对象可以使用成员方法fetch_assoc(),这个方法每使用一次,都会返回查询结果的下一行,如果全部行都返回过了,就返回null,这个特性使得它可以与while语句搭配使用

每一行通常都是一个关联数组,以表头为键

while($row = $result->fetch_assoc())
{
    print_r($row);
}

预处理语句

预处理语句是把一条SQL语句中的参数分离出来,但是又和字符串拼接不同,可以避免SQL注入

使用有三个步骤

  • 使用prepare()准备一个SQL语句,把要替换的参数替换为?
  • 使用bind_param()将参数绑定到SQL语句中
  • 使用execute()执行SQL语句
$stmt = $mysqli->prepare("SELECT * FROM users WHERE id = ?");

$id = 1;

$stmt->bind_param("i",$id);//i表示整型 后面是实际的参数

$stmt->execute(); //执行语句

$result = $stmt->get_result(); //获取结果

$stmt->close(); //关闭查询语句

在bind_param()中,常用的类型字符包括:

  • i:表示整数(integer)
  • d:表示双精度浮点数(double)
  • s:表示字符串(string)
  • b:表示二进制数据(blob)

如果有多个参数,直接拼起来,例如:

$stmt->bind_param("ss", $name, $email);

插入数据

$stmt = $mysqli->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
$stmt->bind_param("ss", $name, $email);

$name = 'John';
$email = 'john@example.com';
$stmt->execute();

更新数据

$stmt = $mysqli->prepare("UPDATE users SET email = ? WHERE id = ?");
$stmt->bind_param("si", $email, $id);

$email = 'newemail@example.com';
$id = 1;
$stmt->execute();

删除数据

$stmt = $mysqli->prepare("DELETE FROM users WHERE id = ?");
$stmt->bind_param("i", $id);

$id = 1;
$stmt->execute();

事务

事务是一组sql语句,其特点是执行要么全部成功,要么全部失败

$mysqli->begin_transaction(); //开始事务 此后该数据库对象执行的语句都被视作事务中的语句

try {
    // 执行第一条 SQL 语句
    $sql1 = "INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')";
    $mysqli->query($sql1);

    // 执行第二条 SQL 语句 也可以使用预处理语句
    $stmt = $mysqli->prepare("INSERT INTO orders (user_id ,product_id) VALUES (LAST_INSERT_ID(),?)");
    $product_id = 1;
    $stmt->bind_param("i",$product_id);
    $stmt->execute();
    

    // 提交事务
    $mysqli->commit();
    echo "Transaction completed successfully.";
} catch (Exception $e) { //如果发生错误,则可以用数据库对象的rollback()回滚事务
    // 回滚事务
    $mysqli->rollback();
    echo "Transaction failed: " . $e->getMessage();
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值