php复习总结
2022-04-29 22:23:55 13 举报
AI智能生成
登录查看完整内容
php复习
作者其他创作
大纲/内容
c应用
java应用
程序如何进行
C/S系统
B/S系统
HTMLJavaScriptCSSWebSocketWebGL等
客户端
浏览端web技术
认识web系统
<html><head> <meta charset=\"utf-8\"> //页面编号 <title>HTML Test</title> //浏览器显示的标题</head><script> function showMsg() { alert('hello'); } </script> //一个Javascript函数<body> <h1>Hello world</h1> <a href=\"http://www.w3school.com.cn\">This is a link</a> <p></p> //链接 <img src=\"/notice.jpg\" onclick=\"showMsg();\"/> <p></p> //图片,点击图片弹出窗口显示hello <video width=\"640\" height=\"480\" controls=\"controls\"> <source src=\"/media/movie.mp4\" type=\"video/mp4\" /> </video> //定义的视频</body></html>
代码简单分析
HTTP与静态页面
<a href='http://www.otherdomain.com/upload/12/windows.iso'> Windows ISO 下载</a><img src='http://www.picturestore.com/user/fff/desk.jpg'>
带域(域口+端口)的绝对路径
<img src='/upload/12/3345.jpg'>
不带域的绝对路径
<a href='iso/windows.iso'> Windows ISO 下载</a><img src='fff/desk.jpg'>
子主题
相对路径
url介绍
这种技术可以用任何的编程语言编写服务器端的程序,用于动态生成HTML文件。search.exe 对应的URL是 http://www.test.com/search.exe 就可以通过如同 http://www.test.com/search.exe?userid=1333 的方式来查询用户id为 1333 的用户的订单。
CGI
!!!php作为动态页面生成技术,运行在服务器端,因此浏览器永远只能得到php运行后的结果,不可能得到php的源代码。
PHP
动态web网页
网站的根:DOCUMENT_ROOT
只能把php文件放在网站根对应的目录中。网站根之外的文件http服务器一般是不能访问的,或者说对浏览器是不可见的
网站根不是在php.ini中配置,而是在http服务器中配置。根据http服务器的不同,配置文件也不同。
配置PHP
初识php
浏览器通过浏览器访问php页面时得到的时php运行后的结果
php和html代码都混在一个文件里面,文件后缀是php
标签<?php...?>来标注php代码的部分
php运行时会至上而下解析,遇见非php代码按照原样返回给浏览器
遇到php代码部分,php代码打印结果会放在php代码所在位置
<h1>这是第一个程序</h1><h1> <?php echo 'Hello world!'; ?></h1> //echo类似于c语言的print
<?= $str?> 是另外一段php的标注,这是简单的标注打印方式,和 <?php echo $str ?> 效果相同,但是更简单
一个PHP文件可以间隔穿插多个HTML代码和PHP代码,只需要使用标签说明那些是PHP代码
<h1>这是第二个程序</h1><?php$str = 'Hello world!';?><h1> <?= $str ?></h1>
标签标注php代码
因为PHP可以写HTTP协议的Head部分和Payload部分,而返回的HTML代码部分是在Payload部分当中的。因此有些写head缓冲区的函数必须放在HTML输出之前,例如 header 函数,set_cookie 函数等。
PHP缓冲区
PHP没有一个编译成可执行文件(如EXE文件)的过程。PHP的源代码被PHP解析器直接运行,程序一行行按顺序运行。
PHP是动态语言(相对静态语言而言)。和静态语言C比较,PHP是若类型语言,变量声明可以不指定类型,变量的类型在运行的时候根据赋值的类型确定;同时PHP没有类是C的内存管理机制,不用关心内存回收的问题;PHP最有用的数据结构,数组,容量是可变的。
PHP语言特性
一个php文件(程序)在收到request的时候被载入到内存中开始执行,一直到response后结束运行,被从内存中销毁,这就是PHP程序的生命周期。
把需要保存的变量进行持久化处理,例如存入到数据库,或者是写入文件
使用 Session 保存这些变量,有过期时间
使用cookie 保存这些变量,有过期时间
要在一次请求后保持一些变量的值
当多次请求统一PHP程序的时候,每一次都是一个独立的运行,其中的变量会在每一次执行后销毁
PHP程序的生命周期
第一个PHP程序
变量声明也可以不用指定类型,与c和Java不同
变量名区分大小写
$+变量名
bool(布尔型)
int(整型)
float(浮点型,也称作double)
string(字符串)
标量类型
array(数组)
object(对象)
callable(可调用)不掌握
iterable(可迭代)不掌握
复合类型
resource(资源)
NULL(无类型)
特殊类型
数据类型
<?php$a = 'hello';$$a = 'world';?>
变量的变量
<?php$string1 = \"mingribook\"; //声明变量$string1$string2 = $string1; //使用$string1来初始化$string2$string1 = \"mrbccd\"; //改变变量$string1的值echo $string2; //输出变量$string2的值
引用赋值
这里两个 $example 变量,一个在函数外部(全局变量),一个在函数内部(局部变量),其实是两个不同的变量,虽然名字相同。
<?php$example = \"在…………函数外\";\t\t\t\t\t\t//声明全局变量function example(){ $example = \"……在函数内……\";\t\t\t\t\t//声明局部变量 echo \"在函数内输出的内容是:$example.<br>\";\t //输出局部变量}example();\t\t\t\t //调用函数,输出变量值echo \"在函数外输出的内容是:$example.<br>\";\t //输出全局变量
全局变量的说明:全局变量可以在程序中的任何地方访问,但是在用户自定义函数内部是不可用的。想在用户自定义函数内部使用全局变量,要使用global关键字声明。
在函数内部声明全局变量的时候,不能同时对变量赋值,需要先申明,再赋值。
<?php$hr = \"黄蓉\"; //声明全局变量$hrfunction lxt(){ $gj = \"郭靖\"; //声明局部变量$gj echo $gj . \"<br>\"; //输出局部变量的值 global $hr; //利用关键字global在函数内部定义全局变量 echo $hr . \"<br>\"; //输出全局变量的值}lxt();
全局与局部变量
静态变量的应用:在博客中使用静态变量记录浏览者的人数,每一次用户访问和离开时,都能够保留目前浏览者的人数。在聊天室中也可以用静态变量来记录用户的聊天内容。
可以把函数的静态变量作为全局变量来理解,只不过只能在函数内部是可见的。
静态变量
变量作用域
unset 函数:销毁指定的变量
检查与摧毁变量
is_array — 检测变量是否是数组is_bool — 检测变量是否是布尔值is_double — is_float 的别名is_float — 检测变量是否是浮点型is_int — 检测变量是否是整数is_integer — is_int 的别名is_long — is_int 的别名is_null — 检测变量是否为 nullis_numeric — 检测变量是否为数字或数字字符串is_object — 检测变量是否是一个对象is_real — is_float 的别名is_string — 检测变量是否是字符串
判断变量类型
<?php$foo = \"1\"; // $foo 是字符串 (ASCII 49)$foo *= 2; // $foo 现在是一个整数 (2)$foo = $foo * 1.3; // $foo 现在是一个浮点数 (2.6)$foo = 5 * \"10 Little Piggies\"; // $foo 是整数 (50)$foo = 5 * \"10 Small Pigs\"; // $foo 是整数 (50)?>
自动类型转换
在要转换的变量之前加上用括号括起来的目标类型。<
强制类型转换
所有其它值都被认为是 true(包括任何资源 和 NAN)。
当转换为 bool 时,以下值被认为是 false:布尔值 false 本身整型值 0(零)浮点型值 0.0(零)-0.0(零)空字符串,以及字符串 “0”不包括任何元素的数组特殊类型 NULL(包括尚未赋值的变量)由无属性的空元素创建 SimpleXML 对象,也就是既没有子节点也没有属性的元素。
布尔值
__GET[ ]__POST[ ]__COOKIE[ ]__SESSION[ ]__FILES[ ]上述的变量全部都是以数组的方式访问的
预定义变量
变量
使用 const 关键字定义常量时,只能包含标量数据(bool、int、float 、string)。可以将常量定义为一个表达式,也可以定义为一个 array。
如果常量名是动态的,也可以用函数 constant() 来获取常量的值。用 get_defined_constants() 可以获得所有已定义的常量列表。
常量前面没有美元符号($);常量可以不用理会变量的作用域而在任何地方定义和访问;常量一旦定义就不能被重新定义或者取消定义;常量只能计算标量值或数组。不掌握
在面向过程中,定义常量使用 define() 函数,在类中使用 const 关键字定义。
常量
__LINE__ 文件中的当前行号。__FILE__ 文件的完整路径和文件名。如果用在被包含文件中,则返回被包含的文件名。__DIR__ 文件所在的目录。如果用在被包括文件中,则返回被包括的文件所在的目录。
魔术常量
TRUEFALSENULL
预定义常量
变量与常量
要表达一个单引号自身,需在它的前面加个反斜线(\\)来转义。要表达一个反斜线自身,则用两个反斜线(\\\\)。其它任何方式的反斜线都会被当成反斜线本身:也就是说如果想使用其它转义序列例如 \ 或者 \,并不代表任何特殊含义,就单纯是这两个字符本身。
<?phpecho 'this is a simple string';// 可以录入多行echo 'You can also have embedded newlines instrings this way as it isokay to do';// 输出: Arnold once said: \"I'll be back\"echo 'Arnold once said: \"I\\'ll be back\"';// 输出: You deleted C:\\*.*?echo 'You deleted C:\\\\*.*?';// 输出: You deleted C:\\*.*?echo 'You deleted C:\\*.*?';// 输出: This will not expand: \ a newlineecho 'This will not expand: \ a newline';// 输出: Variables do not $expand $eitherecho 'Variables do not $expand $either';?>
在单引号字符串中的变量和特殊字符的转义序列将不会被替换。
单引号字符串
如果字符串是包围在双引号(“)中, PHP 将对特殊的字符进行解析
双引号字符串
字符串可以用 '.'(点)运算符连接起来,注意 '+'(加号)运算符没有这个功能。更多信息参考字符串运算符。
+为运算加法
结果为:3568.13
<?phpecho \"00123.13\"+\"3445AB\";
字符串可以直接参与任何类型数值计算,php会自动先把字符串转换成合适的数值类型。
字符串连接
去掉字符串首尾的特殊字符:trim ltrim rtrim 函数,P83转义、还原字符串数据:主要掌握 addslashes函数 P84字符串长度:strlen 函数 P87截取字符串:substr 函数 P89格式化字符串格式化字符串:string_number_format 函数 P97分割字符串:explode() 函数 P98合成字符串:implode 函数 P99
其他字符串操作函数
字符串
可以用短数组语法 [] 替代 array() 。<?php$array = array( \"foo\" => \"bar\
短数组语法对比
如果在数组定义时多个元素都使用相同键名,那么只有最后一个会被使用,其它的元素都会被覆盖。
PHP 数组可以同时含有 int 和 string 类型的键名,因为 PHP 实际并不区分索引数组和关联数组。
输出:array(7) { [1]=> string(1) \"g\" [-1]=> string(1) \"d\" [\"01\"]=> string(1) \"e\" [\"1.5\"]=> string(1) \"f\" [0]=> string(1) \"h\" [\"\"]=> string(1) \"j\" [2]=> string(1) \"l\"}
结果:string(3) \"bar\"int(24)string(3) \"foo\"
<?php$array = array( \"foo\" => \"bar\
数组单元可以通过 array[key] 语法来访问
如上所述,如果给出方括号但没有指定键名,则取当前最大 int 索引值,新的键名将是该值加上 1(但是最小为 0)。如果当前还没有 int 索引,则键名将为 0 。
用方括号的语法修改/新建
统计数组元素个数:P126查询数组中指定元素:P127获取数组中最后一个元素(数组堆栈使用):P128向数组中添加元素(数组堆栈使用):P129删除数组中重复元素:P129
数组操作函数
array()
数组
PHP函数没有返回类型的说明,即使是没有返回也不能用void进行说明;一个函数可以使用return返回,也可以不使用return返回;函数可以返回任意类型的数据,同一函数因为条件不同,返回的类型可以不一致;函数可以有缺省参数;函数可以有值传递和引用传递,引用传递类似C的传指针;变量函数是PHP的一个特点,可以使用类似变量的变量方式访问函数。
函数
php基础
GET与POST方法
与FORM交互
php与页面交互
上传文件使用一个form,上传控件使用 type 为 file 的input 控件,当然,我们还需要一个提交按钮
注意form中 enctype 这个属性是必须的
action 为空表示上传的URL就是当前页面的URL
上传一个文件后,所有form内的控件内容会通过post方法提交到url指定的页面;
PHP的超级变量$_FILES 中有所有上传文件的内容,我们通过print_r看看这个数组中有什么
1
$_FILES 数组是一个二维数组,包含了上传文件的所有信息
name:上传文件的原始文件名
type表示上传文件的类型,这个类型是一个MIME表述字符串
tmp_name是上传文件的临时文件,这个位置一般在php.ini文件中设置,或者使用操作系统的临时文件目录;
error表示上传是否有错误,没有错误是0;
size是上传文件的大小
其中[userfile]是一个文件信息的一维数组,对应的名称是HTML中设置的上传控件
把上传的临时文件移动到相应的位置,同时需要对文件名改名
因为临时文件是不需要有扩展名的,而最后保存最好加上文件名。如果上传的文件需要长久的保存,使用 move_uploaded_file 函数是必须的,因为临时文件会被系统定期清理
参数1:临时文件的绝路路径,这里使用 $_FILES['userfile']['tmp_name'] 就可以得到
使用文件的原始文件名并不是个好注意。因为如果新上传的文件和以前的文件同名,可能会覆盖以前的文件。所以可以考虑使用一个唯一的文件名来存放。
使用绝对路径,但是同样不是一个好注意,会给你程序的交付带来麻烦。例如你的程序需要安装到另外一台服务器,绝对路径可能和现有服务器有很大差别。
如何生成唯一的文件名?有很多方式,可以使用时间,或者是一个叫做 uniqid 的函数。另外,需要获取上传文件的扩展名有很多方法,扩展名前面是‘.’可以使用 explode 来把文件名字符串拆分成数组,数组的最后一个元素就是扩展名。
参数2:要移动到的目标位置和文件名:例子中我们使用了文件的原始文件名 $_FILES['userfile']['name'] 没有加路径。这是一个相对路径表达方式,意思是和当前php文件在一个路径下。当然你也可以使用其他路径,并改变文件名
两个参数
move_uploaded_file
$FILES数组
<form enctype=\"multipart/form-data\" action=\"\" method=\"POST\"> 选择上传文件 <input name=\"userfile\" type=\"file\" /> <input type=\"submit\" value=\"上传\" /> font color=\"#e57373\
文件上传
读取一个文本文件到数组
<pre><?php$lines = file('file.txt');print_r($lines);?></pre>
file函数
两个嵌套循环的写法,循环中又有HTML代码,又有PHP代码
读取并显示csv文件
JSON是一种轻量级的数据交换格式
{ \"user\": \"Danny\
通过浏览器提交一个留言,在 msg 目录中得到一个Json文件
json_decode 返回的数据类型不是array,而是stdClass Object(一个对象)。你不能像使用数组一样使用对象,例如:$msg['user']是不正确的,应该换成 $msg→user 来取值;
读取JSON文件
json格式
文件读写
文件上传与读写
HTTP的非保持连接状态
使用GET请求
user
pwd
使用POST方法发送用户名和密码给服务器。这时,4、5行代码执行
使用GET方法访问
<!-- 如何保存用户的状态 --><?phpif (@$_POST['user']){ setcookie(\"user\
域
路径
两种基本属性
有效期是cookie可以存活到将来的一个时间,如果超过这个时间,cookie就会被浏览器删除。这种机制进一步保证安全性,例如有些网站,如果你停止刷新,过了一段时间再访问就需要重新鉴权。
时效性
可以通过cooke来存放用户名和密码
Cookie
这个时间在php.ini中进行设置。时间一到,session就会从服务器删除。session的好处就是关键信息保存在服务器,进一步提升了安全性。
鉴别客户的页面第一行用 session_start()
<?phpsession_start();if (@$_POST['user']) { $_SESSION['user'] = $_POST['user']; $_SESSION['pass'] = $_POST['pwd'];}?>
在PHP种使用session
Session
使用 session_start 函数开启session,然后你就可以对session进行读写操作了
检测seesion中是否有键名为uid的值
如果uid这个值没有,那么使用 header 函数生成一个http头的重定向url。当浏览器读取到这个重定向后,立即刷新到重定向指定的url(通过get方法),这里就是登陆页面 login.php。跳转中的url是一个相对路径
header函数必须在任何HTML输出前使用
<?php@session_start();if (!$_SESSION['uid']){ header('Location:login.php');}?>
用户登录
如果未登录 _protected.php 检测 $_SESSION[uid] 为假,会重新定向到 login.php 页面
如果登录了,就显示 Session 的用户信息
include_once 函数包含了 _protected.php 文件进来。
<?phpinclude_once('_protected.php');?><h1>这里是需要登陆才能访问的页面</h1><h2>欢迎你:<?= $_SESSION['name'] ?></h2><h2>你的用户ID是:<?= $_SESSION['uid'] ?></h2><a href=\"_doLogout.php\">退出登陆--注销</a>
登录用户才能访问的网站
直接使用 session_destroy 函数销毁 session ,并重定向到 login.php 页面
<?phpsession_start();session_destroy();header('Location:login.php');?>
退出用户界面
<?phpsession_start();if ($_SESSION['uid']){ header('Location:user.php');}?>
已经登录通过url进入
使用Session
Cookie与Session
$this→name 这个整体表示一个成员变量,不能写成 $this→$this。
如果在当前的代码块中,不存在和成员变量同名的局部变量,那么 $this 是可以省略的
类中的常量定义和普通常量(非类常量)的定义是不一样的
常量的调用使用 类名::常量名;这个语法结构需要注意,类名前面没有$的符号,因为类本身不是一个实体,而是一个抽象的定义
<?phpclass SportObject{ const BOOK_TYPE = '计算机图书'; public $object_name; //图书名称 function setObjectName($name) { //声明方法setObjectName() $this->object_name = $name; //设置成员变量值 } function getObjectName() { //声明方法getObjectName() return $this->object_name; }}$c_book = new SportObject(); //实例化对象$c_book->setObjectName(\"PHP类\"); //调用方法setObjectNameecho SportObject::BOOK_TYPE . \"->\"; //输出常量BOOK_TYPEecho $c_book->getObjectName(); //调用方法getObjectName
类中的常量
构造函数和普通函数一样,可以有缺省参数
老版本的PHP可以使用与类名相同的函数名来作为构造函数(类似Java的方式),新版本的PHP已经不推荐,并有可能出现一些问题
构造函数
析构的含义是在对象被销毁前调用的最后一个函数,用于进行一些善后处理
要销毁一个对象,可以像销毁一个变量一样,使用 unset 函数
析构函数
类的定义与使用
子类型的定义使用 extends 关键字
get_class 返回一个对象所属类型的字符串,如果参数中描述的变量不是对象,返回 false
<?phpclass example{ function exam() { if (isset($this)) { echo '$this的值为:' . get_class($this); } else { echo '$this未定义'; } }}$class_name = new example();$class_name->exam();?>
$this 与 get_class
操作用在类的内部,分别用来调用类中的静态变量和父类的构造方法。
注意:常量是类的一个属性,并不是对象特有的;类是一个抽象定义,前面不能使用$,否则就是变量了。
<?phpclass Book{ const NAME = 'computer';\t\t\t\t\t\t\t//常量NAME function __construct() {\t\t\t\t\t\t\t\t//构造方法 echo '本月图书类冠军为:' . Book::NAME . ' ';\t\t//输出默认值 }}echo Book::NAME;
可以用于访问静态成员,类常量,还可以用于覆盖类中的属性和方法。当在类定义之外引用到这些项目时,要使用类名。可以通过变量来引用类,该变量的值不能是关键字(如 self,parent 和 static)
范围解析操作符(::)
没有修饰则为public
public:公开,任何外部或者是子类型都可以访问;private:私有,只能本类型访问;protected:本类型和子类型访问
访问控制修饰
类外部调用使用 类名::静态成员;类内部调用使用 self::静态成员
静态方法和静态变量
被修饰的类不能扩展子类;被修饰的方法不能在子类中覆盖
final关键词
<?php class SportObject { } class MyBook extends SportObject { private $type; } $cBook = new MyBook(); if ($cBook instanceof MyBook) echo '对象$cBook属于MyBook类<br>'; if ($cBook instanceof SportObject) echo '对象$cBook属于SportObject类<br>';
对象类型检测
继承和多态
在给不可访问(protected 或 private)或不存在的属性赋值时,_ _set() 会被调用
读取不可访问(protected 或 private)或不存在的属性的值时,_ _get() 会被调用
属性重载只能在对象中进行。在静态方法中,这些魔术方法将不会被调用。所以这些方法都不能被 声明为 static
访问了一个不存在的类成员变量,这时14行输出;通过15行对一个不存在的变量进行赋值(写操作)会触发_ _set 函数
_ _set()和_ _get()方法
在对象中调用一个不可访问方法时,_ _call() 会被调用
_ _call()方法
魔术方法
面向对象编程
一对一
关系建在多中
两张表
一对多
关系加一张表
三张表
多对多
数据库实体关系
基于web的管理
在 HeidiSQL 中使用 文件→运行SQL文件 可以加载一个数据库脚本,并运行
导入数据库
数据库维护
<?phpif (!$conn = mysqli_connect(\"127.0.0.1\
数据查询
<form name=\"intFrom\" method=\"post\" action=\"index_ok.php\"> <table width=\"60%\" border=\"1\"> <tr> <td>书名:</td> <td><input type=\"text\" name=\"bookname\"></td> </tr> <td colspan=\"2\"> <input type=\"hidden\" name=\"action\" value=\"insert\"> <input type=\"submit\" name=\"Submit\" value=\"添加\"> <input type=\"reset\" name=\"reset\" value=\"重置\"> </td> </tr> </table></form>
数据插入
<?phpinclude_once(\"conn.php\"); //包含数据库连接文件if ($_GET['action'] == \"update\") { //判断地址栏参数action的值是否等于update $sqlstr = \"select * from tb_demo02 where id = \
<?phpinclude_once(\"conn.php\");?><table width=\"60%\" border=\"1\"> <tr> <td width=\"5%\">id</td> <td width=\"30%\">书名</td> <td width=\"10%\">价格</td> <td width=\"20%\">出版时间</td> <td width=\"10%\">类别</td> <td width=\"10%\">操作</td> </tr> <?php $sqlstr = \"select * from tb_demo02 order by id\
update
数据更新
<?phpinclude_once(\"conn.php\");\t\t\t\t\t\t\t//连接数据库if ($_POST['action'] == \"delall\") {\t\t\t\t\t\t//判断是否执行删除操作 if (count($_POST['chk']) <= 0) {\t\t\t\t\t\t//判断提交的删除记录是否为空 echo \"<script>alert('请选择记录');history.go(-1);</script>\"; } else { for ($i = 0; $i < count($_POST['chk']); $i++) {\t\t//for语句循环读取复选框提交的值, $sqlstr = \"delete from tb_demo02 where id = \
<script> //删除确认 function del() { if (!window.confirm('是否要删除数据??')) return false; } //全部选择/取消 function chek() { debugger; var leng = this.form1.chk.length; if (leng == undefined) { leng = 1; if (!form1.chk.checked) document.form1.chk.checked = true; else document.form1.chk.checked = false; } else { for (var i = 0; i < leng; i++) { if (!form1.chk[i].checked) document.form1.chk[i].checked = true; else document.form1.chk[i].checked = false; } } return false; }</script><?phpinclude_once(\"conn.php\");?><table border=\"1\"> <form name=\"form1\" id=\"form1\" method=\"post\" action=\"delete.php\"> <tr> <td> </td> <td>id</td> <td>书名</td> <td>价格</td> <td>出版时间</td> <td>类别</td> </tr> <?php $sqlstr1 = \"select * from tb_demo02 order by id\
数据删除
使用函数访问数据库
生成了一个叫做dsn的字符串,这个字符串是说明所连接数据库服务器的类型、主机地址、数据库(选择的数据库)等信息的
建立一个数据库连接
准备SQL查询字符串,并在对象上面调用prepare函数执行SQL;prepare返回的是一个准备好的SQL执行对象,需要在该对象上调用execute真正执行sql;执行完sql后,可以在prepare返回的的对象上面使用fetch方法逐个提取行
$dsn = \"$dbms:host=$host;dbname=$dbName\
PDO::FETCH_ASSOC:关联数组PDO::FETCH_NUM:索引数组PDO::FETCH_BOTH :关联数组和索引数组PDO::FETCH_OBJ:对象
fetch
查询
$dsn = \"$dbms:host=$host;dbname=$dbName;port=3306\
使用命名参数的方式
使用索引数组的方式
插入数据
删除和修改
PDO数据抽象层
数据库应用
php复习总结
0 条评论
回复 删除
下一页