响应状态码

码号 含义
1xx 消息
2xx 成功
3xx 重定向
4xx 客户端错误
5xx 服务器错误
状态码 状态码英文名称 中文描述
100 Continue 继续。客户端应继续其请求
101 Switching Protocols 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议
200 OK 请求成功。一般用于GET与POST请求
201 Created 已创建。成功请求并创建了新的资源
202 Accepted 已接受。已经接受请求,但未处理完成
203 Non-Authoritative Information 非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本
204 No Content 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档
205 Reset Content 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域
206 Partial Content 部分内容。服务器成功处理了部分GET请求
300 Multiple Choices 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
301 Moved Permanently 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302 Found 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
303 See Other 查看其它地址。与301类似。使用GET和POST请求查看
304 Not Modified 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
305 Use Proxy 使用代理。所请求的资源必须通过代理访问
306 Unused 已经被废弃的HTTP状态码
307 Temporary Redirect 临时重定向。与302类似。使用GET请求重定向
400 Bad Request 客户端请求的语法错误,服务器无法理解
401 Unauthorized 请求要求用户的身份认证
402 Payment Required 保留,将来使用
403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求
404 Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置”您所请求的资源无法找到”的个性页面
405 Method Not Allowed 客户端请求中的方法被禁止
406 Not Acceptable 服务器无法根据客户端请求的内容特性完成请求
407 Proxy Authentication Required 请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权
408 Request Time-out 服务器等待客户端发送的请求时间过长,超时
409 Conflict 服务器完成客户端的 PUT 请求时可能返回此代码,服务器处理请求时发生了冲突
410 Gone 客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置
411 Length Required 服务器无法处理客户端发送的不带Content-Length的请求信息
412 Precondition Failed 客户端请求信息的先决条件错误
413 Request Entity Too Large 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息
414 Request-URI Too Large 请求的URI过长(URI通常为网址),服务器无法处理
415 Unsupported Media Type 服务器无法处理请求附带的媒体格式
416 Requested range not satisfiable 客户端请求的范围无效
417 Expectation Failed 服务器无法满足Expect的请求头信息
500 Internal Server Error 服务器内部错误,无法完成请求
501 Not Implemented 服务器不支持请求的功能,无法完成请求
502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
503 Service Unavailable 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中
504 Gateway Time-out 充当网关或代理的服务器,未及时从远端服务器获取请求
505 HTTP Version not supported 服务器不支持请求的HTTP协议的版本,无法完成处理

常用

$_SERVER["REMOTE_ADDR"];         //地址
$_SERVER['HTTP_USER_AGENT'];    //主机    

PHP函数

函数 解释
array_merge 合并数组
array_keys 获取键
implode(“,”, $arr) 以,分离
preg_match(正则,字符串,数组)
print_r($data, $return = false)
ctype_alnum ( string $text ) : bool 字母和数字组合
strtolower
array_slice ( $array , $offset [, int $length = NULL [, bool $preserve_keys = false ]] ) 数组挑选一部分
serialize 产生一个可存储的值的表示
mt_rand(int min, int max) mt_rand()

MYSQL

报错

show variables like'%time_zone';

set global time_zone = '+8:00';

PHP语法

基础

//连接数据库
$connect = mysqli_connect(host,username,password,dbname,port,socket);
//选择数据库
mysqli_select_db(connection,dbname);
//错误信息
mysqli_error($connect);
// 设置编码,防止中文乱码
mysqli_query($conn , "set names utf8");

//sql查询
mysqli_query($connect,"SQL 语句");    //( , ,MYSQLI_USE_RESULT)(如果需要检索大量数据,请使用这个)        
//结果集处理
$row = mysqli_fetch_array($result, MYSQL_NUM);    //MYSQL_NUM MYSQL_ASSOC  MYSQL_BOTH
mysqli_fetch_object();
while($row = mysqli_fetch_assoc($result))
{
    echo "<tr><td> {$row['runoob_id']}</td> ".
         "<td>{$row['runoob_title']} </td> ".
         "</tr>";
}
//关闭
mysqli_free_result($result);
mysqli_close();

事务


<?php
$dbhost = 'localhost:3306';  // mysql服务器主机地址
$dbuser = 'root';            // mysql用户名
$dbpass = '123456';          // mysql用户名密码
$conn = mysqli_connect($dbhost, $dbuser, $dbpass);
if(! $conn )
{
    die('连接失败: ' . mysqli_error($conn));
}
// 设置编码,防止中文乱码
mysqli_query($conn, "set names utf8");
mysqli_select_db( $conn, 'RUNOOB' );
mysqli_query($conn, "SET AUTOCOMMIT=0"); // 设置为不自动提交,因为MYSQL默认立即执行
mysqli_begin_transaction($conn);            // 开始事务定义

if(!mysqli_query($conn, "insert into runoob_transaction_test (id) values(8)"))
{
    mysqli_query($conn, "ROLLBACK");     // 判断当执行失败时回滚
}

if(!mysqli_query($conn, "insert into runoob_transaction_test (id) values(9)"))
{
    mysqli_query($conn, "ROLLBACK");      // 判断执行失败时回滚
}
mysqli_commit($conn);            //执行事务
mysqli_close($conn);
?>

MYSQL数据类型

数值类型

类型 大小 范围(有符号) 范围(无符号) 用途
TINYINT 1 byte (-128,127) (0,255) 小整数值
SMALLINT 2 bytes (-32 768,32 767) (0,65 535) 大整数值
MEDIUMINT 3 bytes (-8 388 608,8 388 607) (0,16 777 215) 大整数值
INT或INTEGER 4 bytes (-2 147 483 648,2 147 483 647) (0,4 294 967 295) 大整数值
BIGINT 8 bytes (-9,223,372,036,854,775,808,9 223 372 036 854 775 807) (0,18 446 744 073 709 551 615) 极大整数值
FLOAT 4 bytes (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) 0,(1.175 494 351 E-38,3.402 823 466 E+38) 单精度 浮点数值
DOUBLE 8 bytes (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 双精度 浮点数值
DECIMAL 对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2 依赖于M和D的值 依赖于M和D的值 小数值

时间类型

类型 大小 ( bytes) 范围 格式 用途
DATE 3 1000-01-01/9999-12-31 YYYY-MM-DD 日期值
TIME 3 ‘-838:59:59’/‘838:59:59’ HH:MM:SS 时间值或持续时间
YEAR 1 1901/2155 YYYY 年份值
DATETIME 8 1000-01-01 00:00:00/9999-12-31 23:59:59 YYYY-MM-DD HH:MM:SS 混合日期和时间值
TIMESTAMP 4 1970-01-01 00:00:00/2038 结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 YYYYMMDD HHMMSS 混合日期和时间值,时间戳

字符串类型

类型 大小 用途
CHAR 0-255 bytes 定长字符串
VARCHAR 0-65535 bytes 变长字符串
TINYBLOB 0-255 bytes 不超过 255 个字符的二进制字符串
TINYTEXT 0-255 bytes 短文本字符串
BLOB 0-65 535 bytes 二进制形式的长文本数据
TEXT 0-65 535 bytes 长文本数据
MEDIUMBLOB 0-16 777 215 bytes 二进制形式的中等长度文本数据
MEDIUMTEXT 0-16 777 215 bytes 中等长度文本数据
LONGBLOB 0-4 294 967 295 bytes 二进制形式的极大文本数据
LONGTEXT 0-4 294 967 295 bytes 极大文本数据

MYSQL语句

创建表

CREATE TABLE IF NOT EXISTS `runoob_tbl`(
   `runoob_id` INT UNSIGNED AUTO_INCREMENT, #UNSIGNED 无符号的
   `runoob_title` VARCHAR(100) NOT NULL DEFAULT '标题' COMMENT '标题',
   `runoob_author` VARCHAR(40) NOT NULL,
   `submission_date` DATE,
   PRIMARY KEY ( `runoob_id` )
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

binary

字符串区分大小写

SELECT * from runoob_tbl WHERE BINARY runoob_author='RUNOOB.COM';

WITH ROLLUP

分组统计总数

SELECT name, SUM(singin) as singin_count FROM  employee_tbl GROUP BY name WITH ROLLUP;

连接

  • INNER JOIN(内连接,或等值连接):获取两个表中字段匹配关系的记录。
  • LEFT JOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录。
  • RIGHT JOIN(右连接): 与 LEFT JOIN 相反,用于获取右表所有记录,即使左表没有对应匹配的记录。
SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a INNER JOIN tcount_tbl b ON a.runoob_author = b.runoob_author;

正则表达式

模式 描述
^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 ‘\n’ 或 ‘\r’ 之后的位置。
$ 匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 ‘\n’ 或 ‘\r’ 之前的位置。
. 匹配除 “\n” 之外的任何单个字符。要匹配包括 ‘\n’ 在内的任何字符,请使用象 ‘[.\n]’ 的模式。
[…] 字符集合。匹配所包含的任意一个字符。例如, ‘[abc]’ 可以匹配 “plain” 中的 ‘a’。
[^…] 负值字符集合。匹配未包含的任意字符。例如, ‘[^abc]’ 可以匹配 “plain” 中的’p’。
p1|p2|p3 匹配 p1 或 p2 或 p3。例如,’z|food’ 能匹配 “z” 或 “food”。’(z|f)ood’ 则匹配 “zood” 或 “food”。
* 匹配前面的子表达式零次或多次。例如,zo* 能匹配 “z” 以及 “zoo”。* 等价于{0,}。
+ 匹配前面的子表达式一次或多次。例如,’zo+’ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等价于 {1,}。
{n} n 是一个非负整数。匹配确定的 n 次。例如,’o{2}’ 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的两个 o。
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。

REGEXP

SELECT name FROM person_tbl WHERE name REGEXP 'mar'; #包含mar
#查找name字段中以元音字符开头或以'ok'字符串结尾的所有数据:
SELECT name FROM person_tbl WHERE name REGEXP '^[aeiou]|ok$';

after

当我们需要修改数据表名或者修改数据表字段时,就需要使用到MySQL ALTER命令。

#删除列
ALTER TABLE student  DROP username;
#添加列
ALTER TABLE student ADD score INT AFTER username;
#修改字段名称
ALTER TABLE student MODIFY score CHAR(10);
#修改字段名称属性
ALTER TABLE student CHANGE j j INT;
#修改默认值
ALTER TABLE student ALTER i SET DEFAULT 1000;
#删除默认值
ALTER TABLE student ALTER i DROP DEFAULT;
#表的信息
show table status like 'tp_admin'\G;
#修改表名
ALTER TABLE student1 RENAME TO student;
#修改自增
ALTER TABLE t AUTO_INCREMENT = 100;

show

show databases;
show tables;
show create table student;
SHOW COLUMNS FROM student;
#查看表的状态
SHOW TABLE STATUS;
#表的结构
desc tp_admin;
#索引
show index from mytable;
SHOW INDEX FROM mytable; \G

事务

ACID

原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。

  • 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
  • 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
  • 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
  • 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

事务控制语句

  • BEGINSTART TRANSACTION 显式地开启一个事务;
  • COMMIT 也可以使用 COMMIT WORK,不过二者是等价的。COMMIT 会提交事务,并使已对数据库进行的所有修改成为永久性的;
  • ROLLBACK 也可以使用 ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
  • SAVEPOINT identifier,SAVEPOINT 允许在事务中创建一个保存点,一个事务中可以有多个 SAVEPOINT;
  • RELEASE SAVEPOINT identifier 删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;
  • ROLLBACK TO identifier 把事务回滚到标记点;
  • SET TRANSACTION 用来设置事务的隔离级别。InnoDB 存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE。

事务处理

1、用 BEGIN, ROLLBACK, COMMIT来实现

  • BEGIN 开始一个事务
  • ROLLBACK 事务回滚
  • COMMIT 事务确认

2、直接用 SET 来改变 MySQL 的自动提交模式:

  • SET AUTOCOMMIT=0 禁止自动提交
  • SET AUTOCOMMIT=1 开启自动提交

索引

MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。

索引分单列索引组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索引包含多个列。

虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。

建立索引会占用磁盘空间的索引文件。

普通索引

创建索引

CREATE INDEX indexName ON mytable(username(length)); 
#如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length。

修改表结构(添加索引)

ALTER table tableName ADD INDEX indexName(columnName)

创建表的时候直接指定

CREATE TABLE mytable(   
    ID INT NOT NULL,    
    username VARCHAR(16) NOT NULL,   
    INDEX [indexName] (username(length))  
);  

删除索引的语法

DROP INDEX [indexName] ON mytable; 

主键索引

primary key

唯一索引

unique key

避免重复列出现,它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:

创建索引

CREATE UNIQUE INDEX indexName ON mytable(username(length)) 

修改表结构

ALTER table mytable ADD UNIQUE [indexName] (username(length))

创建表的时候直接指定

CREATE TABLE mytable(  
    ID INT NOT NULL,   
    username VARCHAR(16) NOT NULL,  
    UNIQUE [indexName] (username(length))  
);  

常规索引

默认

全文索引

快速定位数据

UTOOLS1589175057534.png

使用ALTER 命令添加和删除索引

有四种方式来添加数据表的索引:

  • ALTER TABLE tbl_name ADD PRIMARY KEY (column_list):

    该语句添加一个主键,这意味着索引值必须是唯一的,且不能为NULL。

  • ALTER TABLE tbl_name ADD UNIQUE index_name (column_list): 这条语句创建索引的值必须是唯一的(除了NULL外,NULL可能会出现多次)。

  • ALTER TABLE tbl_name ADD INDEX index_name (column_list): 添加普通索引,索引值可出现多次。

  • ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list):该语句指定了索引为 FULLTEXT ,用于全文索引。

引擎

myisam: 节约空间、速度快

innodb:安全性高、事务处理、多表多用户操作

数据

导出数据

SELECT * FROM runoob_tbl 
    -> INTO OUTFILE '/tmp/runoob.txt';
#导出表    
mysqldump -uroot -p db table_name > dump.sql;
#导出数据库
mysqldump -uroot -p db > dump.sql;
#导出所有数据库
mysqldump -uroot -p --all-databases > database_dump.sql;

导入数据

#1.
mysql -u root -p root database_name < dump.sql;
#2. 将导出的数据直接导入到远程的服务器
$ mysqldump -u root -p database_name \
       | mysql -h other-host.com database_name
#3. source
mysql> create database abc;      # 创建数据库
mysql> use abc;                  # 使用已创建的数据库 
mysql> set names utf8;           # 设置编码
mysql> source /home/abc/abc.sql  # 导入备份数据库

# 解压到tar
my.ini的文件中的max_allowed_packet的值设为 1G
mysql -uroot -proot dangxiao_0424 < F:\database备份\tar\dangxiao-hnust_ps_edu-20210403-010001.tar
user database_name
source F:\database备份\tar\dangxiao-hnust_ps_edu-20210403-010001.tar 好一些
实在不行就用navicat导入

函数

函数 解释
DATE_FORMAT(d,f) SELECT DATE_FORMAT(‘2011-11-11 11:11:11’,’%Y-%m-%d %r’) -> 2011-11-11 11:11:11 AM
date(my_data) 2011-11-11 11:11:11 => 2011-11-11

cURL

解析慢

php中curl解析dns太慢的大坑:

https://www.itshutong.com/articles/282/a-big-hole-in-php-where-curl-parsing-dns-is-too-slow

$url = 'http://example.com';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_NOBODY, TRUE); // 不输出内容
curl_exec($ch);
if (!curl_errno($ch)) {
    $info = curl_getinfo($ch);
    var_dump($info); // 打印curl信息
}
$url = 'http://example.com';
$url_arr = parse_url($url);
$host = $url_arr['host'];
$ip = gethostbyname($host); // 获取ip
$ch = curl_init();
// 指定ip
curl_setopt($ch, CURLOPT_URL, str_replace($host, $ip, $url));
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Host: {$host}"));
curl_setopt($ch, CURLOPT_NOBODY, TRUE);
curl_exec($ch);
if (!curl_errno($ch)) {
    $info = curl_getinfo($ch);
    var_dump($info);
}

https://www.imooc.com/video/2026

确认能使用 php i

UTOOLS1589260437911.png

使用curl

#1.初始化curl
curl_init();
#2.发送请求并返回
curl_exec();
#3.关闭
curl_close();


// 创建新的 cURL 资源
$ch = curl_init();
// 设置 URL 和相应的选项
curl_setopt($ch, CURLOPT_URL, "http://www.example.com/");
//curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, 0);
// 抓取 URL 并把它传递给浏览器
curl_exec($ch);
// 关闭 cURL 资源,并且释放系统资源
curl_close($ch);


$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://www.baidu.com");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
echo str_replace("百度", "明月", $result);    

    //post
    $data = "theCityCode=钦州&theUserID=52f4586ff1e94b669da8784c541304a7";
    $ch = curl_init();
      curl_setopt($ch, CURLOPT_URL, "http://ws.webxml.com.cn/WebServices/WeatherWS.asmx/getWeather");
      curl_setopt($ch, CURLOPT_POST, 1);
      curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    //不打印头部信息
      curl_setopt($ch, CURLOPT_HEADER, 0);

//https
date_default_timezone_set("PRC");//使用cookie,设置时区
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
//1错误 0正确
curl_errno($ch);
//获取错误
curl_error($ch);

php -f test.php >test.html

执行代码

登录


<?php
/**
 * 慕课网视频教学
 * 代码实例-PHP-cURL实战
 * 实例描述:登录慕课网并下载个人空间页面
 * 自定义实现页面链接跳转抓取
 * 
 */
$data='username=demo_peter@126.com&password=123qwe&remember=1';
$curlobj = curl_init();            // 初始化
curl_setopt($curlobj, CURLOPT_URL, "http://www.imooc.com/user/login");        // 设置访问网页的URL
curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, true);            // 执行之后不直接打印出来

// Cookie相关设置,这部分设置需要在所有会话开始之前设置
date_default_timezone_set('PRC'); // 使用Cookie时,必须先设置时区
curl_setopt($curlobj, CURLOPT_COOKIESESSION, TRUE); 
curl_setopt($curlobj, CURLOPT_HEADER, 0); 
// 注释掉这行,因为这个设置必须关闭安全模式 以及关闭open_basedir,对服务器安全不利
//curl_setopt($curlobj, CURLOPT_FOLLOWLOCATION, 1);  

curl_setopt($curlobj, CURLOPT_POST, 1);  
curl_setopt($curlobj, CURLOPT_POSTFIELDS, $data);  
curl_setopt($curlobj, CURLOPT_HTTPHEADER, array("application/x-www-form-urlencoded; charset=utf-8", 
    "Content-length: ".strlen($data)
    )); 
curl_exec($curlobj);    // 执行
curl_setopt($curlobj, CURLOPT_URL, "http://www.imooc.com/space/index");
curl_setopt($curlobj, CURLOPT_POST, 0);  
curl_setopt($curlobj, CURLOPT_HTTPHEADER, array("Content-type: text/xml"
    )); 
$output=curl_redir_exec($curlobj);    // 执行
curl_close($curlobj);            // 关闭cURL
echo $output;

/**
 * 自定义实现页面链接跳转抓取
 */
function curl_redir_exec($ch,$debug="") 
{ 
    static $curl_loops = 0; 
    static $curl_max_loops = 20; 

    if ($curl_loops++ >= $curl_max_loops) 
    { 
        $curl_loops = 0; 
        return FALSE; 
    } 
    curl_setopt($ch, CURLOPT_HEADER, true); // 开启header才能够抓取到重定向到的新URL
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
    $data = curl_exec($ch); 
    // 分割返回的内容
    $h_len = curl_getinfo($ch, CURLINFO_HEADER_SIZE); 
    $header = substr($data,0,$h_len);
    $data = substr($data,$h_len - 1);

    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); 
    if ($http_code == 301 || $http_code == 302) { 
        $matches = array(); 
        preg_match('/Location:(.*?)\n/', $header, $matches); 
        $url = @parse_url(trim(array_pop($matches))); 
        // print_r($url); 
        if (!$url) 
        { 
            //couldn't process the url to redirect to 
            $curl_loops = 0; 
            return $data; 
        } 
        $last_url = parse_url(curl_getinfo($ch, CURLINFO_EFFECTIVE_URL)); 
        if (!isset($url['scheme'])) 
            $url['scheme'] = $last_url['scheme']; 
        if (!isset($url['host'])) 
            $url['host'] = $last_url['host']; 
        if (!isset($url['path'])) 
            $url['path'] = $last_url['path'];

        $new_url = $url['scheme'] . '://' . $url['host'] . $url['path'] . (isset($url['query'])?'?'.$url['query']:''); 
        curl_setopt($ch, CURLOPT_URL, $new_url); 

        return curl_redir_exec($ch); 
    } else { 
        $curl_loops=0; 
        return $data; 
    } 
} 
?>

JQuery

函数

blur

//姓名过滤空格
$("#name-up").blur(function(){
    this.value = this.value.replace(/\s/g, "");
});

trigger

$("#password").keyup(function(event){
    if(event.keyCode == 13 && this.value) $("#verify").trigger("focus");
});

$.fn

//这是一个自调函数,函数定义好之后自动执行。(function(){})表示一个匿名函数,而后面紧跟着的()表示立即调用此函数。而且()也是向函数传递参数的地方。
(function(){})();

//
$.fn._warning = function ( str ){
    if( str ){
        this.closest("div").addClass("has-warning").next("p").text( str );
    }else{
        this.closest("div").removeClass("has-warning").next("p").text("");
    }
}
//$.fn.abc()是对jQuery扩展了一个abc()方法,在每一个jquery实例都可以引用这个方法
$("#username-up").blur(function(){
    var $this = $(this);
    var username = $this.val().replace(/\s/g, "");//过滤空格
    $this.val( username );
    if( !$.isNumeric( username ) ){
        $this._warning("请使用科大学号或工号进行注册");
    }else{
        $this._warning();
    }

$.ajaxSetup

$.ajaxSetup({
  "error":function(){alert("连接超时,请重试");},        //请求失败自动执行
  "timeout":10000
});

选择器

closest

this.closest("div").removeClass("has-warning").next("p").text("");

难点

头像上传

dataTables

日程

5-17

这几天没怎么能看系统,我也不知道我在干啥。。好像就只学了正则,看了一下linux的笔记。。试了一下编译配置PHP相关环境,给同学弄一下javaweb作业,弄了一天的hexo博客。。。目前都还没看到管理端,只看到修改头像那块。。

5-22

学长,这个删除的话,对已有的成绩不会有啥影响,但是要是删除正在考试的题就有问题了,得另外判断一下;
另外这个删除是要真的删除还是假的删除(好像有个题目status标志位还没用),如果直接删除的话,对以前考试的个人记录的复查可能有点问题(记录了所有考试答题的题号,如果要复查成绩对题目复查的话可能会找不到);如果给标志位做删除的话,得多改其他地方(考试取题号的方法,以及管理员题目的显示等),得多检查很多

PHPExcel

https://www.cnblogs.com/rxbook/p/9449887.html

https://blog.csdn.net/weixin_36230821/article/details/112023879

创建Excel

private function _excel_create(){
        //引入PHPExcel库,全局设置
        import("Home.Util.PHPExcel");
        //PHPExcel cell缓存设置
        $cache_type = I('get.cache_type');//缓存类型
        $cache_size = I('get.cache_size');//内存限制大小
        if( $cache_size ){
            $cacheSettings = array('memoryCacheSize'=> $cache_size.'MB' );
        }else{
            $cacheSettings = array('memoryCacheSize'=>'4MB');
        }
        switch ( $cache_type )
        {
        case '1':
            $cacheMethod = \PHPExcel_CachedObjectStorageFactory::cache_in_memory_serialized;
            break;//调试信息:13,454kb 2.3000s
        case '2':
            $cacheMethod = \PHPExcel_CachedObjectStorageFactory::cache_in_memory_gzip;
            break;//调试信息:11,739kb 3.3957s
        case '3':
            $cacheMethod = \PHPExcel_CachedObjectStorageFactory::cache_to_phpTemp;
            break;//调试信息:14,182kb 2.7436s
        case '4':
            $cacheMethod = \PHPExcel_CachedObjectStorageFactory::cache_to_discISAM;
            break;//调试信息:14,212kb 2.6088s
        default:
            $cacheMethod = \PHPExcel_CachedObjectStorageFactory::cache_in_memory;
            //调试信息:19,649kb 1.0534s
        }
        \PHPExcel_Settings::setCacheStorageMethod($cacheMethod, $cacheSettings);

        ini_set('memory_limit','512M');
        set_time_limit(0);


        $Excel = new \PHPExcel();
        $file_inf = $Excel->getProperties();
        $file_inf->setCreator ("http://www.hechanglin.cn");
        $file_inf->setLastModifiedBy("HNUST-PartySchool");
        $file_inf->setTitle("HNUST");
        return $Excel;
    }

设置默认样式

private function _sheet_set_default_style( &$Sheet ){
        $G_Style = $Sheet->getDefaultStyle();
        $G_Font = $G_Style->getFont();
        $G_Font->getColor()->setARGB('FF000000');
        $G_Font->setName('仿宋_GB2312');//$G_Font->setSize(11);
        $G_Alignment = $G_Style->getAlignment();
        $G_Alignment ->setVertical  (\PHPExcel_Style_Alignment::VERTICAL_CENTER);
        $G_Alignment ->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
        $G_Alignment ->setWrapText(true);//打开\n换行
        //设置打印页边距
        $G_PageMargins = $Sheet->getPageMargins();
        $G_PageMargins ->setTop(0.6);
        $G_PageMargins ->setRight(0.3);
        $G_PageMargins ->setLeft(0.3);
        $G_PageMargins ->setBottom(0.4);

        //设置打印页面居中
        $G_PageSetup = $Sheet->getPageSetup();
        $G_PageSetup ->setHorizontalCentered(true);
      //$G_PageSetup ->setVerticalCentered(true);
        $G_PageSetup ->setFitToWidth(1);//设置打印所有列到一页,
        $G_PageSetup ->setFitToHeight(0);//设置打印                        高度不限
      //$G_PageSetup ->setOrientation(\PHPExcel_Worksheet_PageSetup:: ORIENTATION_LANDSCAPE);//设置页面打印方向
        $G_PageSetup ->setPaperSize(\PHPExcel_Worksheet_PageSetup:: PAPERSIZE_A4);//设置纸张类型--A4纸大小
    }

下载文件

private function _excel_save( $Excel,$FileName ){
        $FileName = $FileName.".xls";

        //单元格保护,没密码不允许修改
        //$Excel->getSheet(0)->getProtection()->setSheet(true);
        //$Excel->getSheet(0)->protectCells('A1:C22', 'PHPExcel');
        //$Excel->getSecurity()->setLockWindows(true);
        //$Excel->getSecurity()->setLockStructure(true);
        //$Excel->getSecurity()->setWorkbookPassword("pseduos");
        //$Excel->getActiveSheet()->getProtection()->setPassword('PHPExcel');
        //$Excel->getActiveSheet()->getProtection()->setSheet(true);
        //http头设置, 生成excel文件
        $objWriter = \PHPExcel_IOFactory::createWriter($Excel, 'Excel5');
        header("Content-Type: application/force-download");
        header("Content-Type: application/octet-stream");
        header("Content-Type: application/download");
        header("Content-Disposition:inline;filename=".$FileName );
        header("Content-Transfer-Encoding: binary");
        header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
        header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
        header("Pragma: no-cache");
        $objWriter->save('php://output');
//      $objWriter->save('phoutput.xls');
        exit;
    }

导出题库

/**
     * 导出题库
     */
    private function admin_problem_bank() {
        $Excel = $this->_excel_create();
        $Sheet = $Excel->getActiveSheet();
        //设置表格默认样式 和 打印样式
        $this->_sheet_set_default_style( $Sheet );
        $Table_col = array(
            "A"=> array( "width"=>6,  "field"=>"problem_id",        "name"=>"ID"     ),
            "B"=> array( "width"=>20, "field"=>"range",       "name"=>"适用范围" ),
            "C"=> array( "width"=>15, "field"=>"type",        "name"=>"题型"     ),
            "D"=> array( "width"=>50, "field"=>"description",        "name"=>"题目"     ),
            "E"=> array( "width"=>20, "field"=>"a",         "name"=>"答案A"     ),
            "F"=> array( "width"=>20, "field"=>"b",         "name"=>"答案B"     ),
            "G"=> array( "width"=>20, "field"=>"c",         "name"=>"答案C"   ),
            "H"=> array( "width"=>20, "field"=>"d",         "name"=>"答案D"   ),
            "I"=> array( "width"=>20, "field"=>"e",         "name"=>"答案E"     ),
            "J"=> array( "width"=>13, "field"=>"answer",         "name"=>"正确答案"   ),
            "K"=> array( "width"=>14, "field"=>"correctRate",          "name"=>"正确率"     )
        );
        $question_title_col = 'D'; // 题目是C列
        $col_end = 'K'; // 最后一列的列号
        $row_pointer = 1; // 目前在表格的行号

        // 1. 全局标题
        $Table_title = '入党考试题库汇总' . date('y-m-d');
        $Sheet->setCellValueExplicit('A1', $Table_title ,\PHPExcel_Cell_DataType::TYPE_STRING);
        $Sheet->mergeCells('A1:'.$col_end.'1'); //合并单元格
        $row_pointer++;
        // 2. 设置表格表头
        foreach($Table_col as $k_col => $str){
            $Sheet->setCellValue($k_col.$row_pointer ,$str["name"]);
        }
        // 3. 题库填入
        $problemBank = M('exam_problem')->select();
        $SUIT_RANGE = [
            'suit_act' => '入党积极分子',
            'suit_dev' => '发展对象',
            'suit_pre' => '预备党员'
        ];
        foreach ($problemBank as $colNum => $problem) { // 写入每道题目信息
            $row_pointer++;
            $problem['range'] = ''; // 适用范围:入党积极分子,发展对象,预备党员
            $suitNum = 0; // 控制是否换行
            // 适用范围
            foreach ($SUIT_RANGE as $sceneField => $sceneName) {
                if($problem[$sceneField] == 1) { // 适用,添加
                    $suitNum ++;
                    if($suitNum != 1) { // 有多个,换行
                        $problem['range'] .= ',';
                    }
                    $problem['range'] .= $sceneName;
                }
            }
            // 题型
            if($problem['type'] == 'single') {
                $problem['type'] = "单选";
            } else if($problem['type'] == 'trueorfalse') {
                $problem['type'] = "判断";
            } else if($problem['type'] == 'multiple') {
                $problem['type'] = "多选";
            }
            // 题目
            $problem['description'] = "    " . $problem['description'];// 题目标题,空两格
            // 正确率
            $problem['correctRate'] = number_format($problem['correct'] / $problem['submit'], 2); // 保留一位小数
            // 判断题
            if($problem['type'] == 'trueorfalse') { // 判断题,答案为对错
                $problem['answer'] =  $problem['answer'] == 'A' ? "对" : "错";
            }
            // 写入表格
            foreach( $Table_col as $attrKey => $value ){ // 获取题目对应属性,并写入表格
                $Sheet->setCellValueExplicit($attrKey.$row_pointer, $problem[ $value['field'] ], \PHPExcel_Cell_DataType::TYPE_STRING);//强制设置数据类型,避免电话号码被科学计数化
            }
//            $Sheet->setCellValue("A".$row_pointer, $t_order_num++);//数据首行序号 (在最后添加,避免被$user_v空数据覆盖)
        }
        //===========================样式设置====================================
        // 设置列表宽度
        foreach($Table_col as $key => $val){
            $Sheet->getColumnDimension($key)->setWidth($val["width"]);
        }
        // 默认行高度
        $Sheet->getDefaultRowDimension()->setRowHeight(60);
        // 设置边框
        $row_main_start = 2;
        $groupStyle = $Sheet->getStyle('A'.$row_main_start);
        $borderStyle = \PHPExcel_Style_Border::BORDER_THIN;
        $groupStyle->applyFromArray([
            'borders' => [
                'top'    => ['style' => $borderStyle],
                'right'  => ['style' => $borderStyle],
                'bottom' => ['style' => $borderStyle],
                'left'   => ['style' => $borderStyle]
            ]
        ]);
        $Sheet->duplicateStyle($groupStyle, 'A' . $row_main_start . ':' . $col_end . $row_pointer); // 题库全部设置边框 A1:B10
        // 第一行,标题样式
        $A1_font = $Sheet->getStyle('A1')->getFont();
        $A1_font ->setSize(20);
        $A1_font ->setBold(true);
        // 第二行,表格标题
        $Sheet->getRowDimension(2)->setRowHeight(30);
        foreach($Table_col as $k_col => $str){
            $row2_font = $Sheet->getStyle($k_col . '2')->getFont();
            $row2_font->setSize(14);
            $row2_font ->setBold(true);

        }
        // 题目居左对齐
        for($i = 3; $i < $row_pointer; $i++) {
            $Sheet // 设置居左
                ->getStyle($question_title_col. $i) // 'C3'
                ->getAlignment()
                ->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
        }
        G('end');
        $Sheet->setTitle( G('begin','end','m')."kb ".G('begin','end')."s" );
        $FileName = $Table_title;
        $this->_excel_save( $Excel, $FileName );
    }

实战

开启调试模式、数据库配置

作弊

select psedu_user_entry.name as '姓名' , psedu_exam_answer.create_time as '考试时间', psedu_exam_answer.modify_time as '提交时间' 
from psedu_exam_answer
LEFT JOIN psedu_user_entry 
    on psedu_user_entry.entry_id = psedu_exam_answer.entry_id 
where psedu_exam_answer.entry_id = 49677 

删除用户

$("#table tbody").on('click','.manage-del',function(){
  var row=table.row($(this).parents("tr"));
  var data=row.data();
  if(confirm("删除“"+data["m_name"]+"”账号将会删除“"+data["academy_name"]+"”的所有信息,与“"+data["academy_name"]+"”所有有关的信息将不可访问!如果不是非常必要,请不要删除!\n  是否要删除?")){
    if(!confirm("请再一次确认是否删除?")){
      return false;//多次确认
    }
  }else{
    return false;//多次确认
  }
//var data=table.row($(this).parents("tr")).data();
  var postData={
    "menu":"manage_edit",
    "method":"del",
    "data":JSON.stringify(data),
  }

  $.ajax({
    "url":"{:U("api")}",
    "data":postData,
    "type":"post",
    "success":function(response){
      if(response.status==200){
        $("#ajax-message").html(response.message);
        row.remove().draw();
      }
      else{
        $("#ajax-message").html(response.message?response.message:"操作失败");
      }
      $("#ajax-message-modal").modal();
    },
  });

挑选题目

先从数据库得到所有题号,再shuffle打乱,选取array_slice一部分数组,通过implode(“,”, $arr)

protected function get_random_problem_set($lib, $type, $number){
        $sql['type']=$type;
        $sql[$lib]=1;
        $tmp = M("ExamProblem")->cache(true,3600)->where($sql)->getField("problem_id",true);    
        shuffle($tmp);
        return array_slice($tmp, 0, (int)$number);
}

$tmp=$this->get_random_problem_set($exam_lib,'single',50);
                $randStr=implode(",",$tmp);
                $map['problem_id']  = array('in',$randStr);
                $problem_single=M('exam_problem')->where($map)->select();

// 传入数组作为查询条件
Db::table('think_user')->where([
    'name'    =>    'thinkphp',
    'status'=>    [1, 2]
])->select(); 

//SELECT * FROM think_user WHERE `name`='thinkphp' AND status IN (1, 2)

检查正确

题目展示

problem_151[ ]

$an=array();
$dataList=array();
foreach($_POST as $key=>$val) {
    if(strpos($key,'problem')===false) continue;
    $key=str_replace('problem_','',$key);
    $an['problem_id']=(int)$key;
    if( is_array( $val) ){
        $anstr='';
        foreach($val as $k){
            $anstr.=$k;
        }
        $an['answer']=$anstr;
    }else{
        $an['answer']=$val;
    }
    $dataList[]=$an;
}

cookie保存题目

<div>
    UM_distinctid=171ed5bb4b5369-03279684c7050e8-4c302e7f-144000-171ed5bb4b62bf; CNZZDATA1266253577=1294373742-1588821737-%7C1590044189; PHPSESSID=sojse6670q7q9r9uuoq9btorj6; 18_1_problem_41=C; 18_1_problem_42=A; 18_1_problem_44=C; 18_1_problem_46=A; 18_1_problem_50=A; 18_1_problem_57=A; 18_1_problem_84=C; 18_1_problem_97=A; 18_1_problem_13=B; 18_1_problem_1240[]=DE; 18_2_problem_13=A; 18_2_problem_25=A; 18_2_problem_29=B; 18_2_undefined=; 18_2_problem_31=A; 18_2_problem_39=B; 18_2_problem_311[]=D; 18_2_problem_308[]=D; 18_2_problem_1240[]=ABCDE

    单选题:
    cookie  " 18_1_problem_44=C"
    多选题:
    cookie  " 18_2_problem_1240[]=ABCDE"

    prop() checked
    input[name='problem_308[]'][value='D']

</div>
<script>


var aCookie = document.cookie.split(";");
        for (var i = 0; i < aCookie.length; i++) {
            var aCrumb = aCookie[i].split("=");  
            var cookie_name=aCrumb[0];
            var cookie_value=aCrumb[1];
            if(cookie_name.indexOf("{$exam_id}_{$exam_round}_") >= 0){
                cookie_name=cookie_name.replace("{$exam_id}_{$exam_round}_","");
                if(cookie_name.indexOf("problem_") >= 0 )   
                {
                    if(cookie_name.indexOf("[]") > 0 ){
                        for(var ii=0; ii<cookie_value.length; ii++) {
                            $("input[name='"+cookie_name.trim()+"'][value='"+ cookie_value.charAt(ii) +"']").prop("checked",true);
                        }
                    }else{
                        $("input[name='"+cookie_name.trim()+"'][value='"+ cookie_value +"']").prop("checked",true);
                    }
                }
            }

        }
</script>

API

if(method_exists($this,$target)){   
    call_user_func( array( &$this, $target)); 
}

部署

sudo -Hu www-data git pull

ctrl o 回车保存

ctrl x退出

延长redis

<?php 
    $redis = new Redis(); 
    $redis->connect('127.0.0.1', 6379); //连接Redis
    $redis->auth('mpsedu'); //密码验证
    $redis->select(1);//选择数据库1

    $exam_id =  20; // 考试 ID 
    $academy_id = 5; // 学院 ID 
    $round = 1; // 第几次考试 

    //$exams =  $redis->keys("exam*");//输出value
    for($academy_id = 1 ; $academy_id <= 25 ; ++$academy_id) {
        $exam = 'exam:'.$exam_id.':'.$academy_id.':'.$round;
        $status =  $redis->hgetall($exam);
        if($status != NULL) {
            $data['static'] = 1;
            $data['start'] =  "2020-05-22 22:30:36";
            $data['end'] = NULL;
            $redis->hmset($exam,$data);
            var_dump($redis->hgetall($exam)) ; 
        }

    }
    echo "执行完毕" ;
select 1

keys exam:22*  // 查看考试redis

hgetall exam:20:5:1  // 考试学期、学院、第几次考试

del exam:22:5:1 // 重置考试
hdel exam:22:5:1 static start end // 重置考试

//延迟考试时间:
hset exam:22:5:1 start time + 10 
hset exam:22:5:1 start "2020-10-27 14:10:00"
hset exam:22:5:1 start "2020-10-27 15:10:00"

// static 1开启,static 2关闭
hset exam:22:5:1 static 2

hgetall exam:22:5:1
hgetall "exam:23:16:1"
hgetall "exam:23:22:1"
hgetall "exam:23:7:1"
hgetall "exam:23:2:1"
hgetall "exam:23:14:1"
hgetall "exam:23:19:1"
hgetall "exam:23:10:1"
hgetall "exam:23:3:1"
hgetall "exam:23:18:1"
hgetall "exam:23:13:1"
hgetall "exam:23:15:1"
hgetall "exam:23:5:1"
hgetall "exam:23:12:1"
hgetall "exam:23:4:1"
hgetall "exam:23:11:1"
hgetall "exam:23:8:1"
hgetall "exam:23:20:1"
hgetall "exam:23:9:1"
hgetall "exam:23:1:1"
hgetall "exam:23:6:1"
hgetall "exam:23:17:1"



hgetall "exam:23:16:2"
hgetall "exam:23:22:2"
hgetall "exam:23:7:2"
hgetall "exam:23:2:2"
hgetall "exam:23:14:2"
hgetall "exam:23:19:2"
hgetall "exam:23:10:2"
hgetall "exam:23:3:2"
hgetall "exam:23:18:2"
hgetall "exam:23:13:2"
hgetall "exam:23:15:2"
hgetall "exam:23:5:2"
hgetall "exam:23:12:2"
hgetall "exam:23:4:2"
hgetall "exam:23:11:2"
hgetall "exam:23:8:2"
hgetall "exam:23:20:2"
hgetall "exam:23:9:2"
hgetall "exam:23:1:2"
hgetall "exam:23:6:2"
hgetall "exam:23:17:2"

Thinkphp

将数据库表导入config

class Config extends Model
{
    public function load()
    {
        $config = [];
        $data = $this->all();
        foreach ($data as $item) {
          $config[$item['method']] = $item['value'];
        }
        config('system', $config);
    }
}