0%

这样的话,证明,贪心算法是不能以最少的颜色解决所有的图着色问题的,啊…那怎么找出最少的颜色啊???有一个坏消息:

目前,大概是只能选择深度优先搜索了。。。摸摸毛,没有关系,网上的回溯算法很多,也很简单,但是我可以做更多的优化,关键是网上好像都没有预着色的步骤,所以这里可以创新一下。

数独问题的图搜索策略

深度优先搜索,出现无解的情况进行回溯,回溯到上一级继续进行尝试。

具体步骤
  1. 把起始节点S放到一个叫做OPEN的未扩展节点表中(简称OPEN表).如果此节点为一目标节点,则得到一个解
  2. 建立一个叫做 CLOSED的已扩展节点表简称 CLOSED表)其初始为空表
  3. 如果OPEN为一空表,则失败退出.
  4. 把第一个节点(节点n)从OPEN表移到CLOSED表
  5. 如果节点n的深度等于最大深度,则转向(3).
  6. 扩展节点n产生其全部后裔,并把它们放入OPEN表的前头.如果没有后裔,则转向(3)
  7. 如果后继节点中有任一个为目标节点,则求得一个解.成功退出;否则,转向(3).
主要函数

search(c):参数c为单元格地址,给定一个c对该单元格所在行、列,所在小九宮格已有数字进行判断,返回还允许填入的数字,用有效数字序列的字符串格式表示,比如返回“1356”,表示该单元格还可以填入1、3、5、6中任一数字,返回“”,表示该单元格无数可填,此时检查OPEN表,若空,则失败退出,在递归程序中返回上一级。

idea

图着色可以应用到多面体的面着色

PHP与数据库中的查询

查询构造器

典型用法:

1
2
3
4
5
6
$rows = (new \yii\db\Query())
->select(['id', 'email'])
->from('user')
->where(['last_name' => 'Smith'])
->limit(10)
->all();

上面的代码将会生成并执行如下的SQL语句,其中 :last_name 参数绑定了 字符串 'Smith'

1
2
3
4
SELECT `id`, `email` 
FROM `user`
WHERE `last_name` = :last_name
LIMIT 10
创建查询
1
2
3
4
5
6
7
8
$query->select(['user.id AS user_id', 'email']);
// 等同于:
$query->select(['user_id' => 'user.id', 'email']);
// 等同于:
$query->select('user.id AS user_id, email');

// SELECT * FROM `user`
$query->from('user');

SQL 语句当中的 WHERE 子句:

  • 字符串格式,例如:'status=1'
  • 哈希格式,例如: ['status' => 1, 'type' => 2]
  • 操作符格式,例如:['like', 'name', 'test']
  • 对象格式,例如:new LikeCondition('name', 'LIKE', 'test')
1
2
3
4
5
6
7
$query->where('status=1');

// 或使用参数绑定来绑定动态参数值
$query->where('status=:status', [':status' => $status]);

// 原生 SQL 在日期字段上使用 MySQL YEAR() 函数
$query->where('YEAR(somedate) = 2015');

千万不要像如下的例子一样直接在条件语句当中嵌入变量,特别是当这些变量来源于终端用户输入的时候, 因为这样我们的软件将很容易受到 SQL 注入的攻击。(嘘~我的代码里就这样写过,悄咪咪的)

1
2
// 危险!千万别这样干,除非你非常的确定 $status 是一个整型数值。
$query->where("status=$status");
1
2
3
4
5
6
7
8
9
10
$status = 10;
$search = 'yii';

$query->where(['status' => $status]);

if (!empty($search)) {
$query->andWhere(['like', 'title', $search]);
}
//如果 $search 不为空,那么将会生成如下 SQL 语句:
... WHERE (`status` = 10) AND (`title` LIKE '%yii%')

这次作业中的查询主要用了like操作符:

like:第一个操作数应为一个字段名称或 DB 表达式, 第二个操作数可以使字符串或数组, 代表第一个操作数需要模糊查询的值。比如,[‘like’, ‘name’, ‘tester’] 会生成 name LIKE ‘%tester%’。 如果范围值是一个数组,那么将会生成用 AND 串联起来的 多个 like 语句。例如,[‘like’, ‘name’, [‘test’, ‘sample’]] 将会生成 name LIKE ‘%test%’ AND name LIKE ‘%sample%’

过滤条件

filterWhere()用于通常需要忽略用户输入的空值。

andfilterWhere()类似于andWhere()

使用yii\helpers\Html::submitButton() 方法生成提交按钮

2018年6月三套六级题目的作文与翻译已经学习完了,今天再粗略地过一遍短语和句型,做下笔记方便以后查找。

  1. 成为不可或缺的一部分 become an integral part of
  2. 开车上下班 drive to and from work
  3. 交通拥堵和停车位不足的问题日益严峻 more prevalent traffic gridlock and inadequate parking space
  4. 出台新规 roll out new rules
  5. 限制 rein in
  6. 新能源汽车 new energy vehicles
  7. 采取一些措施,支持… take some measure to support
  8. 促使…做… prompted … to … / drive … to…

It is an undeniable fact that …

lay a solid foundation for

commercial activities

plays a crucial role in boosting an organization

To begin with

have passion for work

achieve mutual consensus, build harmonious cooperation and have effective communication

is beneficial to

create a pleasant working atmosphere

not surprisingly

spur continuous development of the individuals

Taking into account

arrive at a conclusion that it is sensible for

keep in mind

a win-win situation

  1. 最大最快的高速铁路网 the largest and fastest high-speed rail network
  2. 高铁 the CRH(China Railway High-Speed) train
  3. 高铁站 high-speed rail station
  4. 高铁列车的突出优势在于准时 the outstanding advantage of the CRH train is punctuality
  5. 基本不受天气的影响 is basically not affected by weather
  6. 乘高铁上下班 commute by CRH train

have a major influence on a kid’s development

is crucial and indispensable in maintaining the relationship

only when a student … is he or she willing to

look to the teacher for guidance and support

are weary of

drop out of school

transform their whole life

has the full trust of sb.

is motivated to

consciousness and initiative of learning

The credibility between teachers and students is not something that can built in a day

comprehend the students’ actual demands and offer timely help

be respectful to

is a must

  1. 最主要的交通工具 the leading means of transportation
  2. 中国城乡 China’s cities and villages
  3. 一度被称为“自行车王国” was once called “the Kingdom of Bicycles”
  4. 随着城市交通拥堵和空气污染日益严重 with traffic congestion and air pollution becoming more and more serious
  5. 中国企业家 China’s entrepreneurs
  6. 共享单车(shared bikes)的商业模式 business model of bike-sharing
  7. 出行 get around
  8. 自行车道 bike lanes

Today, in the context of this era featured by increasing commercialization and digitalization,

mutually-trusted relations

particularly important

take a leading role in

be honest with

has a dishonest attitude toward

lack purchasing confidence in

bring huge economic loss to the business

side effect

The collapse of Sanlu Mike Power Company

a testament to

the incident of poisonous milk

exerted devasting consequences on

the proliferation of counterfeit goods

lose confidence in domestic products

have no alternative but to

resort to foreign brands

it is high time for us to strengthen

promote the healthy development of …

####事务

作业要求写含事务应用的删除操作,这描述,总觉得不是很清晰,是在PHP里写事务还是在MySQL里写呢?最开始考虑到MySQL没法存事务,所以我是改写了delete()函数,代码如下:

Path:common\models\Borrow.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public function delete()
{
$db = Yii::$app->db;
$transaction = $db->beginTransaction();
try {
$result = $this->deleteInternal();
if ($result === false) {
$db->createCommand('INSERT INTO audit_borrow VALUES(user(),now(),0)')->execute();
$transaction->rollBack();
} else {
$db->createCommand('INSERT INTO audit_borrow VALUES(user(),now(),1)')->execute();
$transaction->commit();
}
} catch(\Exception $e) {
$transaction->rollBack();
throw $e;
} catch(\Throwable $e) {
$transaction->rollBack();
throw $e;
}
}

后来想到可以在存储过程里写事务,这样的话应该会更符合要求吧。在这之前还是要先学一下事务的写法:

  • 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。
  • 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
  • 事务用来管理 insert,update,delete 语句

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_delete`(IN `newborwid` CHAR(2), IN `username` CHAR(20))
DETERMINISTIC
BEGIN
DECLARE t_error INTEGER;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET t_error = 1;
START TRANSACTION;
-- 由于有外键约束,要注意下面两句的先后顺序!
INSERT INTO audit_borrow VALUES(username,now(),newborwid);
DELETE FROM borrow where borwid=newborwid;
IF t_error = 1 THEN
ROLLBACK;
ELSE
COMMIT;
END IF;
select newborwid;
END$$
DELIMITER ;

我们建立的数据库一般都是 InnoDB 数据库,其上建立的表是事务性表,也就是事务安全的。这时,若SQL语句或触发器执行失败,MySQL 会回滚事务,有:

①如果 BEFORE 触发器执行失败,SQL 无法正确执行②SQL 执行失败时,AFTER 型触发器不会触发③AFTER 类型的触发器执行失败,SQL 会回滚。

declare handler声明异常处理

1
2
3
4
5
6
7
8
9
10
11
DECLARE
-- 处理类型 继续或退出
{EXIT | CONTINUE}
HANDLER FOR
-- 触发条件
{error-number | SQLSTATE error-string | condition}
-- 错误触发的操作
SQL statement

-- example:
declare continue handler for SQLEXCEPTION set L_error=1;

发生错误的条件有:

1、MYSQL错误代码

2、ANSI-standard SQLSTATE code

3、命名条件。可使用系统内置的SQLEXCEPTION,SQLWARNING和NOT FOUND

参考文章

嗯,好了,外键约束真是令人头大。最开始因为在audit_borrow和audit_equipment上加了外键约束,导致borrow和equipment, category的删除插入总是出问题。现在,重新写事务:(因为要涉及多张表,上面那个不符合要求)

Path:backend\controllers\CategoryController.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public function actionDelete($id)
{

$username=Yii::$app->user->identity->username;
$model = $this->findModel($id);
if (!$model->load(Yii::$app->request->post())) {

$command= Yii::$app->db
->createCommand('call proc_delete(:p0,:p1)')
->bindValues([":p0" =>$model->catid,":p1"=>$username]);
$res=$command->execute();
if($res>=0)
{
return $this->redirect(['index']);
}
}
return $this->redirect(['index']);
}

数据库存储过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_delete`(IN `newcatid` CHAR(2), IN `username` CHAR(20))
DETERMINISTIC
BEGIN
DECLARE t_error INTEGER;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET t_error = 1;
START TRANSACTION;
INSERT INTO audit_category VALUES(username,now(),newcatid);
DELETE FROM borrow where eqpid IN(
SELECT eqpid from equipment where equipment.catid=newcatid
);
DELETE FROM equipment where catid=newcatid;
DELETE FROM category where catid=newcatid;
IF t_error = 1 THEN
ROLLBACK;
ELSE
COMMIT;
END IF;
select newcatid;
END$$
DELIMITER ;
注意写分号!!!

字符串拼接

1
CONCAT(new.catid,"000")

注:如果if条件为NULL的话,会走else if语句

前期准备

参考网上代码,自己和自己之间为0,不算相连,需要修改—>主要原因是有这一句:if (edges[i][j] && vertexes[j].color == nowcol)

结构体:关于边的信息,保存在bool型的二维数组里;只定义顶点结构。顶点的信息有:行、列、颜色;行和列换成序号吧,更普遍一些。自己到自己,算相连吗……先,算上,不行再改。

目前connectSudo()已经能正确地返回Sudo的顶点连接信息了。接下来,开始读取顶点的信息吧。嗯,现在getVertex(int n, int m)可以读取需要预着色的点了,无颜色的点色号为-1,返回顶点的数组。getEdges(int n,int x)读取边的信息,有n个顶点x条边,注意输入的是x条边,但矩阵应是对称矩阵,有2x个位置要改变。返回bool型二维数组。接下来,需要准备一些图形的数据了。输入顶点数n,预着色点数m,边数x,颜色总数colornum,两个文件存放数据:

  1. 顶点的信息:m行,每行有两个整数,分别是顶点编号和颜色
  2. 边的信息:x行,每一行分别是两个点的序号,表示这两点相连

算法设计

贪心算法

贪心原则:把一个颜色用到不再能用了为止。

扫描所有未着色的顶点集,对其中的每个顶点,确定是否与已着新颜色的任何顶点都不相邻。若不相邻,则着色。

WelchPowell文件里的代码为什么在着色之前要将顶点按照度数递减的次序排序呢?

目前代码对graph1中的数据进行了测试,无误。graph1中存的是17条边的信息。主要代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
void printVertex(vertex* ver,int n)
{
for (int i = 0; i < n; i++)
cout << ver[i].index << " " << ver[i].color << "\n";
}

//构造顶点信息,预着色
vertex* getVertexes(int n, int m)
{
vertex* vertexes = new vertex[n];
for (int i = 0; i < n; i++)
{//n为顶点个数,m为已着色的顶点数
vertexes[i].index = i;
vertexes[i].color = -1;//-1表示未着色
}
int tmp1 = 0, tmp2 = -1;//需要着色的顶点序号和色号
for (int i = 0; i < m; i++)
{
cin >> tmp1 >> tmp2;
vertexes[tmp1].color = tmp2;
}
return vertexes;
}
//构造边的信息
bool** getEdges(int n,int x)
{
ifstream read;
read.open("graph1.txt");
bool** edges = new bool*[n];
for (int i = 0; i < n; i++)
edges[i] = new bool[n];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
edges[i][j] = 0;
int tmp1 = 0, tmp2 = 0;
for (int i = 0; i < x; i++)
{
read >> tmp1 >> tmp2;
edges[tmp1][tmp2] = 1;
edges[tmp2][tmp1] = 1;
}
read.close();
return edges;
}
//使用贪心算法为图着色
void colorGraph(int n,int m,int x,int colornum)
{//n为顶点个数,m为预着色的点的个数,x为边的条数,colornum为颜色数
vertex* vertexes = getVertexes(n,m);
bool** edges = getEdges(n, x);
int notcolor = n - m;//未着色的点的个数
int nowcol = 0;
while (notcolor){
for (int i = 0; i < n; ++i){
if (vertexes[i].color == -1){// 当前顶点未着色
bool flag = 1;
for (int j = 0; j < n; ++j) {
if (edges[i][j] && vertexes[j].color == nowcol){
flag = 0;
break;
}
}
if (flag) { vertexes[i].color = nowcol; --notcolor; }
}
}
++nowcol;
}
cout << nowcol << "\n";
printVertex(vertexes, n);
}
void testSudo()
{
//connectSudo();
printSudoVertex(getVertexes(81,9));
}
int main()
{
colorGraph(8,0,17,4);
system("pause");
return 0;
}

测试数据

无预着色:

graph1.txt(8个点,0个预着色点,17条边,4个颜色)

graph2.txt(7个点,0个预着色,12条边,4个颜色)

graph3.txt(4个点,0个预着色,5条边,4个颜色)

graph4.txt(6个点,0个预着色,7条边,2个颜色)

(以上数据测试无误,撒花~~~)
预着色:

graph5.txt(6个点,3个预着色,6条边,2个颜色)

color5.txt

graph6.txt(7个点,2个预着色,12条边,7个颜色)

color6.txt

哦豁,graph6出问题了,去debug吧 .-_-.

嗯,还好,输入数据的问题,不是程序的问题,数据已修正。

(以上数据测试无误,撒花~~~)

Sudo

需要先对connectSudo()做一些修改,edge[i][i]应该为false。

然后,现在,先去准备一些Sudo(注意顶点下标和色号都是从0开始的噢!)

这里的测试大概会出问题了,因为贪心算法目光短浅(贪心算法不足以解决所有的数独问题,因为我们没有考虑到每一个位置可能填上的所有数字,而只是贪心地填上当前满足条件的数字,所以之后的其他空格就不一定有数可填了),准备好……

好了,果然,用了11种颜色。纪念一下我失败的代码,下一篇里该做修改了~_~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#include<bits/stdc++.h>
struct vertex{
int index,color;
};
using namespace std;
void printSudoEdges(bool** edges, int n)
{
ofstream write;
write.open("sudoConnection.txt");
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
write << edges[i][j] << " ";
write << "\n";
}
write.close();
}
void printSudoVertex(vertex* ver)
{
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
cout <<setw(4)<< ver[9 * i + j].color << " ";
cout << "\n";
}
}
//构造数独的边
bool** connectSudo()
{
int n = 81;//数独有81个顶点
bool** edges = new bool*[81];
for (int i = 0; i < 81; i++)
edges[i] = new bool[81];
for (int i = 0; i < 81; i++)
for (int j = 0; j < 81; j++)
edges[i][j] = 0;
//同行同列相连
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
int cur_index = i * 9 + j;
for (int k = j+1; k < 9; k++)
{
edges[cur_index][i * 9 + k] = 1;//行相连
edges[i * 9 + k][cur_index] = 1;
}
for (int k = i+1; k < 9; k++)
{
edges[cur_index][j + k * 9] = 1;//列相连
edges[j + k * 9][cur_index] = 1;
}

}
}
//同宫相连
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 3; j++)
{
for (int k = 0; k < 3; k++)
{
int cur_index = 9 * i + 3 * j + k;
for (int p = j+1; p < 3; p++)
{
//同宫同列
edges[cur_index][9 * i + 3 * p + k] = 1;
edges[9 * i + 3 * p + k][cur_index] = 1;
}
for (int q = k+1; q < 3; q++)
{
//同宫同行
edges[cur_index][9 * i + 3 * j + q] = 1;
edges[cur_index][9 * i + 3 * j + q] = 1;
}
}
}
}

printSudoEdges(edges, 81);
return edges;
}
void printVertex(vertex* ver,int n)
{
for (int i = 0; i < n; i++)
cout << ver[i].index << " " << ver[i].color << "\n";
}

//构造顶点信息,预着色
vertex* getVertexes(int n, int m, const char* filename)
{

vertex* vertexes = new vertex[n];
for (int i = 0; i < n; i++)
{//n为顶点个数,m为已着色的顶点数
vertexes[i].index = i;
vertexes[i].color = -1;//-1表示未着色
}
int tmp1 = 0, tmp2 = -1;//需要着色的顶点序号和色号
if (m > 0)
{
ifstream read;
read.open(filename);
for (int i = 0; i < m; i++)
{
read >> tmp1 >> tmp2;
vertexes[tmp1].color = tmp2;
}
read.close();
}
return vertexes;
}
//构造边的信息
bool** getEdges(int n,int x,const char* filename)
{
ifstream read;
read.open(filename);
bool** edges = new bool*[n];
for (int i = 0; i < n; i++)
edges[i] = new bool[n];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
edges[i][j] = 0;
int tmp1 = 0, tmp2 = 0;
for (int i = 0; i < x; i++)
{
read >> tmp1 >> tmp2;
edges[tmp1][tmp2] = 1;
edges[tmp2][tmp1] = 1;
}
read.close();
return edges;
}
//使用贪心算法为图着色
void colorGraph(int n,int m,int colornum, vertex* vertexes, bool** edges)
{
int notcolor = n - m;//未着色的点的个数
int nowcol = 0;
while (notcolor){
for (int i = 0; i < n; ++i){
if (vertexes[i].color == -1){// 当前顶点未着色
bool flag = 1;
for (int j = 0; j < n; ++j) {
if (edges[i][j] && vertexes[j].color == nowcol){
flag = 0;
break;
}
}
if (flag) { vertexes[i].color = nowcol; --notcolor; }
}
}
++nowcol;
}
if (colornum < nowcol)
{
cout << "Failed" << "\n";
return;
}
cout << nowcol << "\n";
printVertex(vertexes, n);
}
void testSudo()
{
//connectSudo();
//printSudoVertex(getVertexes(81,30,"sudoColor1.txt"));
colorGraph(81, 30, 9, getVertexes(81, 30, "sudoColor1.txt"), connectSudo());
}
void testGraph(int n, int m, int x, int colornum, const char* colorfile, const char* graphfile)
{
//n为顶点个数,m为预着色的点的个数,x为边的条数,colornum为颜色数
vertex* vertexes = getVertexes(n, m, colorfile);
bool** edges = getEdges(n, x, graphfile);
colorGraph(n,m,colornum,vertexes, edges);
}
int main()
{
//testGraph(7,2,12,7,"graph6.txt","color6.txt");
testSudo();
system("pause");
return 0;
}

PHP调用mysql存储过程

请忽略我在第五篇笔记里的胡言乱语,现在的存储过程正常啦 哈哈哈

MySQL里的存储过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_update`(IN `newcatid` CHAR(2), IN `newprice` FLOAT)
DETERMINISTIC
BEGIN
IF(select count(*) from borrow,equipment,category
where borrow.eqpid=equipment.eqpid and equipment.catid=category.catid and category.catid=newcatid group by category.catid
)<5
THEN
UPDATE category set price=newprice where catid=newcatid;
ELSE
UPDATE category set price=(newprice*0.9) where catid=newcatid;
end if;
select newcatid,newprice;
END$$
DELIMITER ;

这是一个在更新时调用的存储过程,PHP里想调用存储过程,要改写控制器里的actionUpdate()函数:

Path: backend\controllers\CategoryController.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post())) {

$command= Yii::$app->db
->createCommand('call proc_update(:p0,:p1)')
->bindValues([":p0" =>$model->catid, ":p1" =>$model->price]);
$res=$command->execute();
if($res>=0)
{
return $this->redirect(['view', 'id' => $model->catid]);
}
}
return $this->render('update', [
'model' => $model,
]);
}

另外哈,createCommand()里的sql语句出问题的话,要学会解决呀~~比如去掉某一个空格,故意让这个句子出错,然后去看报错信息里的sql语句有什么问题,为什么在MySQL里不起作用。

yii框架中的数据库访问对象

连接数据库

首先要创建数据库连接,语法很好查到。因为数据库连接经常使用,所以在一开始就一应用组件的方式来配置它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
return [
// ...
'components' => [
// ...
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=example',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
],
],
// ...
];

之后就可以通过语句 Yii::$app->db 来使用数据库连接了。如果应用需要访问多个数据库,可以配置多个DB应用组件。dsn属性用来指明它的数据源名称,不用的数据库有不同的dsn格式,随用随查。

执行SQL语句

主要分三步:创建command,绑定参数(可选),调用SQL执行方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 返回多行. 每行都是列名和值的关联数组.
// 如果该查询没有结果则返回空数组
$posts = Yii::$app->db->createCommand('SELECT * FROM post')->queryAll();

// 返回一行 (第一行)
// 如果该查询没有结果则返回 false
$post = Yii::$app->db->createCommand('SELECT * FROM post WHERE id=1')->queryOne();

// 返回一列 (第一列)
// 如果该查询没有结果则返回空数组
$titles = Yii::$app->db->createCommand('SELECT title FROM post')->queryColumn();

// 返回一个标量值
// 如果该查询没有结果则返回 false
$count = Yii::$app->db->createCommand('SELECT COUNT(*) FROM post')->queryScalar();

所有从数据库取得的数据都被表现为字符串。使用绑定参数的方法可以防止 SQL 注入攻击。在 SQL 语句中,可以嵌入一个或多个参数占位符。 一个参数占位符是以冒号开头的字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$post = Yii::$app->db->createCommand('SELECT * FROM post WHERE id=:id AND status=:status')
->bindValue(':id', $_GET['id'])
->bindValue(':status', 1)
->queryOne();

#或使用:

$params = [':id' => $_GET['id'], ':status' => 1];

$post = Yii::$app->db->createCommand('SELECT * FROM post WHERE id=:id AND status=:status')
->bindValues($params)
->queryOne();

$post = Yii::$app->db->createCommand('SELECT * FROM post WHERE id=:id AND status=:status', $params)
->queryOne();

bindValue():绑定一个参数值
bindValues():在一次调用中绑定多个参数值

可以使用不同参数多次执行。

执行非查询语句,即不取回数据的语句,调用excute()方法,返回执行 SQL 所影响到的行数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Yii::$app->db->createCommand('UPDATE post SET status=1 WHERE id=1')
->execute();

// INSERT (table name, column values)
Yii::$app->db->createCommand()->insert('user', [
'name' => 'Sam',
'age' => 30,
])->execute();

// UPDATE (table name, column values, condition)
Yii::$app->db->createCommand()->update('user', ['status' => 1], 'age > 30')->execute();

// DELETE (table name, condition)
Yii::$app->db->createCommand()->delete('user', 'status = 0')->execute();

今日不属于六级内容,是为了英语课的任务而学习的话剧台词

Narrator D:

Yes, in a sense, he kills her by rejecting her love. Aphrodite, the goddess of love, heard her crying for her unrequited love and was kind to her, for Echo had been a true lover. Quietly and painlessly, Echo pined away and died. But her voice live on, lingering among the rocks and answering faintly whenever Narcissus or another called.

Yes, that’s Echo, and that’s how she is always remembered. The fate of Narcissus was now in the hands of Aphrodite.

I’m afraid so.

No, he just sits by its side day after day, looking at the only face in the world he loved but could not win. He pined away just as Echo did. Slowly Narcissus faded away, and at last his heart broke.

A white circle of petals round a yellow center.

notes

Narrator [ˈnæreɪtər] n. 旁白

Aphrodite [ˌæfrəˈdaɪti] n. 阿芙罗狄蒂(爱与美的女神)

unrequited [ˌʌnrɪˈkwaɪtɪd] adj. 没有回报的;单方面的;单相思的

pine away [paɪn əˈweɪ] 消瘦,憔悴

linger [ˈlɪŋɡər] v. 继续保存;流连;徘徊;磨蹭;持续看(或思考)

faintly [‘feɪntli] adv.淡淡;隐约地;有气无力地;昏

Narcissus [nɑːrˈsɪsəs] n. 水仙花;那喀索斯


birdie [ˈbɜːrdi] n. 小鸟

nymph [nɪmf] n. 仙女;若虫

Epilogue [ˈepɪlɔːɡ] n. 终章;

Scene II

Narrator C: (Looking anxiously at their back) Oh, does he kill her?

Narrator D: Yes, in a sense. He kills her by rejecting her love.

Narrator C: So Echo dies?

Narrator D: Aphrodite, the goddess of love, heard her crying for her unrequited love and was kind to her, for Echo had been a true lover. Quietly and painlessly, Echo pined away and died. But her voice lived on, lingering among the rocks and answering faintly whenever Narcissus or another called.

Narrator C: So when we hear an echo in the mountains or in caves, that’s Echo’s voice.

Narrator D: Yes, that’s Echo, and that’s how she is always remembered.

Narrator C: And Narcissus? Was he ever punished for his rude behavior?

Narrator D: The fate of Narcissus was now in the hands of Aphrodite!

Scene I

Narrator C: He’s gone off the deep end, hasn’t he?

Narrator D: I’m afraid so.

Narrator C: Does he ever leave the pool?

Narrator D: No, he just sits by its side day after day, looking at the only face in the world he loved but could not win. He pined away just as Echo did. Slowly Narcissus faded away, and at last his heart broke.

想给自己鼓个掌嘻嘻嘻~~我好像终于开始学会看错误信息了,最起码,看到满眼的红色错误不是畏惧而是开始找原因了~

目的

我在上一篇笔记中已经写好了mySql中的存储过程,并且现在在mySql中调用该存储过程也没有问题了,现在,我想要通过PHP调用该存储过程。主要是参数的设定不太好处理,需要从表单拿数据,在提交修改的表单之后,会得到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$_GET = [
'r' => 'category/update',
'id' => 'c1',
];

$_POST = [
'_csrf-backend' => '9ueFt7KZe6r4VcicSw6wY4APsVfqiA8RtZwzfESZSQGFn7XExdozxr8ku9F6PeUk5HaCYKjMS3WB9lcjENIfUw==',
'Category' => [
'catid' => 'c1',
'catname' => '篮球',
'price' => '99',
],
];

$_COOKIE = [
'advanced-backend' => 'pgnho9lendv91620mh8550ev5p',
'_identity-backend' => 'c8280c8419576224c687b72352e3857f7a00c329ecb950cd464196e40ab17045a:2:{i:0;s:17:"_identity-backend";i:1;s:46:"[2,"duWP0ncSYE-Rp1HhKBb8ncPdZULCl7yd",2592000]";}',
'_csrf-backend' => '6e9b91d151f1e7590262068eb1f645cd9440d436961faaefed7c4e0996111199a:2:{i:0;s:13:"_csrf-backend";i:1;s:32:"sx0swCHlGqsM13UGdy37BDDd4jd_TKVR";}',
];

$_SESSION = [
'__flash' => [],
'__returnUrl' => '/yii2/sport_equipment/backend/web/',
'__id' => 2,
];

然后PHP代码中经过判断,调用update()函数,在这里,想要获取catid和price,使用如下语句:

1
2
3
4
5
$Category  = $_POST['Category'];
$tmpcatid=$Category['catid'];
$price=$Category['price'];
var_dump($catname,$price); #查看结果
exit(0);

从得到的结果中看出,我们已经成功获取参数啦~

1
string(2) "c1" string(3) "120"

然后就方便了:

1
2
3
$db = Yii::$app->db;
$db->createCommand("set @p0=$catid,@p0=$price")->execute();
$db->createCommand("call pro_update(@p0,@p1)")->execute();

好吧,问题又来了——catid现在的值是c1,但实际上我应该给@p0的是‘c1’,报错信息:

1
2
3
4
5
6
7
8
9
10
11
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'c1' in 'field list'
The SQL being executed was: set @p0=c1,@p0=99
Error Info: Array
(
[0] => 42S22
[1] => 1054
[2] => Unknown column 'c1' in 'field list'
)

Caused by: PDOException
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'c1' in 'field list'

所以大概是要用到php的字符串连接了

语法:

1
2
3
4
5
6
$s1='i';
$s2=' love ';
$s3='u';
$s4=$s1.$s2.$s3.$s4;

$catid="'".$tmpcatid."'";

最后的问题在于,我发现这句话没有起作用哇…这可如何是好,留到明天解决吧…至少这个command在MySQL里的执行是没有问题的了,大概是要换一种PHP的写法哦(Path:common\models\Category.php)

1
$db->createCommand("SET @p0=$catid; SET @p1=$price; CALL `proc_update`(@p0, @p1);")->execute();

试了另外一种方法,还是不行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

$Category = $_POST['Category'];
$tmpcatid=$Category['catid'];
$price=$Category['price'];

$catid="'".$tmpcatid."'";

// $conn = mysqli_connect('localhost','root','') or die("MYSQL_connect:".mysql_errno());
// $query = "SET @p0=$catid; SET @p1=$price; CALL `proc_update`(@p0, @p1);";
// $query_e = explode(';','$query');
// foreach ($query_e as $k =>$v)
// {
// mysqli_query($conn,$query_e[$k]);
// }

// $db = Yii::$app->db;
// $db->createCommand("SET @p0=$catid; SET @p1=$price; CALL `proc_update`(@p0, @p1);")->execute();

未解….

作为补偿,在这里记一下PHP中单引号和双引号的区别:

PHP中单引号和双引号的区别

在PHP中,字符串的定义可以使用英文单引号’ ‘,也可以使用英文双引号” “。一般情况下两者通用的。但双引号内部变量会解析,单引号则不解析。双引号中的变量($var)和特殊字符(\r\n之类)会被转义。单引号中的内容不会被转义,总被认为是普通字符,因此效率更高。

1
2
3
$str='hello';
echo "str is $str"; //运行结果: str is hello
echo 'str is $str'; //运行结果: str is str

看颜色也就能看出区别吧。

在写今天的正经内容之前,我真的是要吐槽一下我的英语水平(也有可能是打字水平)!!!Yii报错:

Getting unknown property: common\models\Vborrow::browid

吓得我从vborrow, vborrowSearch, vborrowController, vborrow/index找了半天,原来是拼写错误!!”borw”不是”brow”!我觉得这个错误和sxr同学的”model”—“module”有异曲同工之妙……

mySql的存储过程

语法

事先用“DELIMITER $$”或“DELIMITER //”声明当前段分隔符,让编译器把两个”//“之间的内容当做存储过程的代码,不会执行这些代码;“DELIMITER ;”的意为把分隔符还原。

1
2
3
4
5
6
7
8
9
10
delimiter $$  #将语句的结束符号从分号;临时改为两个$$(可以是自定义)
CREATE PROCEDURE delete_matches(IN p_playerno INTEGER) #声明存储过程
BEGIN
SET @p_in=1; #变量赋值
DECLARE l_int int unsigned default 4000000; #变量定义
DELETE FROM MATCHES WHERE playerno = p_playerno;
END$$ #存储过程开始和结束符号
elimiter; #将语句的结束符号恢复为分号

call sp_name[(传参)];#调用存储过程

然后问题就来了,我在mySql里写的存储过程,是要更新某一个值,没有语法错误,成功执行了,但是结果显示影响了0行。

1
set @p0='c1',@p1='120' call proc_update(@p0,@p1)

错误的代码大概会在我交完作业之后放上来。大概的函数体是:

1
2
3
4
5
6
7
8
begin
if(/*condition*/)
then
update -- statement1
else
update -- statement2
end if;
end

经过测试,这么写的话,不管是什么condition,两个statement都没有执行。


上面都是废话。直接写解决方法吧——

存储过程中要有打印,比如在end if后面加

1
2
select @p0,@p1
#select 1 都可以

参数名要改成

1
2
3
@p0,@p1
#而不能是
@catid,@price

不知道为什么,试了很久,这样改的时候就正常工作了。

另外补充,MySQL中的注释有三种:
1
2
3
-- 一般用于单行注释(注意 -- 后面要有空格!)
/*Information ,一般用于多行注释 */
#Information

Translation (30 minutes)

自行车曾经是中国城乡最主要的交通工具,中国一度被称为“自行车王国”。如今,随着城市交通拥堵和空气污染日益严重,骑自行车又开始流行起来。近来,中国企业家将移动互联网 技术与传统自行车结合在一起,发明了一种称为共享单车(shared bikes)的商业模式。共享单车的出现使骑车出行更加方便,人们仅需一部手机就可以随时使用共享单车。为了鼓励人们骑车出行,很多城市修建了自行车道。现在,越来越多的中国人也喜欢通过骑车健身。

Bicycles used to be the leading means of transportation in China’s cities and villages , and China was once called “the Kingdom of Bicycles”. Nowadays, with traffic congestion and air pollution becoming more and more serious in cities, riding a bicycle is becoming popular again. Recently, China’s entrepreneurs have combined mobile Internet technologies with bicyclescombined mobile Internet technologies with bicycles and invented the business model of bike-sharingbusiness model of bike-sharing. The appearance of shared bikes has made it more convenient for people to get around, and people can ride bikes at any time only with the help of a mobile phone. To encourage people to travel by bike, many cities have built bike lanes. Now, more and more Chinese people like exercising by riding bikes.

notes

今天的笔记可能过于鲜艳,是因为我顺便熟悉了一下Markdown修改字体颜色、大小、格式的语法:

1
2
3
4
5
6
7
8
9
10
11
<font 更改语法>文字内容</font>
更改语法包括:
color=#0099ff 更改字体颜色
face="黑体" 更改字体
size= 7 更改字体大小

<font face="微软雅黑">我是微软雅黑</font>
<font face="STCAIYUN">我是华文彩云</font>
<font color=#0099ff size=6 face="黑体">color=#0099ff size=72 face="黑体"</font>

效果如下:
我是微软雅黑
我是华文彩云
color=#0099ff size=6 face=”黑体”

以下是今天的英语内容

经过我再次阅读范文,我觉得文中都是正常水平,没有需要特意学习的,背就是了 哈哈哈哈