diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/01_\345\272\217\350\250\200.md" "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/01_\345\272\217\350\250\200.md"
new file mode 100644
index 0000000000000000000000000000000000000000..b8bd4ba5ea08ae90046c0cce9fdf2edf68521ddf
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/01_\345\272\217\350\250\200.md"
@@ -0,0 +1,21 @@
+## 本节目标
+
+1. 最简单的api
+2. thinkphp的api
+3. api uri设计:简短、易读。
+3. api版本处理。
+4. 响应数据设计:json,xml,jsonp
+5. api文档编写
+
+## 序言
+
+前面我们编写了简单的api接口,只是返回了一个json格式。如果在实务中编写api接口,还有一些常见的实践经验:
+
+1. uri设计要简短、易读。
+2. api支持不同的版本。
+3. 请求api接口的数据格式是?
+3. 响应的数据格式除了json,还有xml和jsonp。
+4. api编写的时候需要测试,如果get还好,直接浏览器访问。如果是post请求就很麻烦了。怎样方便测试接口呢?
+5. api写好后,接收参数是什么?返回数据是什么?要让他人知晓,那么就需要编写api文档了。
+
+下面将针对这些实践的经验进行逐一解释。
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/02_url\350\256\276\350\256\241.md" "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/02_url\350\256\276\350\256\241.md"
new file mode 100644
index 0000000000000000000000000000000000000000..115f9f3c289b0d1ecba34caff1d2ceeda29b2061
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/02_url\350\256\276\350\256\241.md"
@@ -0,0 +1,56 @@
+## 本节目标
+
+1. 了解api接口的url设计。
+
+## url设计
+
+我们在提供api接口的时候,url可以说是首要的一个信息,url如果简短、易读,那么就很容易可以猜出这个api接口的含义。
+
+如果太过复杂,就需要很多的文档来补充说明了。
+
+**示例1**,下面这个api是什么作用呢?
+
+ http://www.example.com/article/article/
+
+我们知道文章,但是具体是文章什么,好像有点看不懂了。
+
+**示例2**:
+
+ http://www.example.com/article/list/
+
+现在可以看出应该是读取文章列表的地址。只是这个会给人疑问,这个地址到底是一个html页面,还是一个接口呢?
+
+**示例3**:
+
+ http://www.example.com/api/article/list/
+
+现在这个意思就比较明了了,是一个提供文章列表的api接口。这边二级域名是www,一般是指访问网站的主页。
+
+如果是专门的api服务,我们可以把域名修改为api的域名,这样就移除uri中的api了,形如:
+
+ http://api.example.com/article/list/
+
+这样的url在设计上就比较易读和简洁了。
+
+**更多的例子**:
+
+ http://api.example.com/article/add/
+ http://api.example.com/article/update/
+ http://api.example.com/article/detail/
+ http://api.example.com/article/search/
+
+思考:
+
+ 上面api分别表示什么意思呢?
+
+## 本节总结
+
+url设计要简短、易读,单词要见名识意。
+
+api url的常见格式:
+
+ http://api域名/模块名称/操作名称/
+
+
+
+
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/03_\347\211\210\346\234\254\350\256\276\350\256\241.md" "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/03_\347\211\210\346\234\254\350\256\276\350\256\241.md"
new file mode 100644
index 0000000000000000000000000000000000000000..2ca5436c71e1c93a7261348c1fb24aea00ab5a6c
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/03_\347\211\210\346\234\254\350\256\276\350\256\241.md"
@@ -0,0 +1,139 @@
+## 本节目标
+
+1. 了解api接口版本设计
+
+## api多版本支持
+
+api设计好的时候:接收参数和返回数据都已经确认。如果要更改数据格式怎么办?
+
+例如,我们之前计算了英文文章出现的单词列表,返回的数据格式如下:
+
+```php
+[
+ 'status' => 0,
+ 'message' => '',
+ 'data' => [
+ ['where', 'is', 'how']
+ ],
+]
+```
+
+如果现在还需要统计每个词出现的次数。那么可能需要改成如下结构:
+
+```php
+[
+ 'status' => 0,
+ 'message' => '',
+ 'data' => [
+ [
+ 'where' => 5,
+ 'is' => 1,
+ 'how' => 2,
+ ]
+ ],
+]
+```
+
+如果直接修改原来的代码,那么就会导致之前调用的接口的客户端出现错误。为了避免这个问题,可以使用版本号的设计。
+
+**版本号的设计思路**:
+
+新增加一个参数v表示版本的意思,默认值为1,表示版本1的意思,根据不同的版本定位到不同的方法。
+
+```php
+if ($v == 1) {
+ // 版本1的代码
+} else ($v == 2) {
+ // 版本1的代码
+}
+```
+
+**示例1**,以上面英文单词例子为例(基于thinkphp框架):
+
+第一个版本:
+
+```php
+public function word()
+{
+ $content = Request::param("content");
+ $validate = Validate::rule([
+ 'content|文章内容' => 'require|min:10|max:100',
+ ]);
+ if (!$validate->check(['content' => $content])) {
+ $data = [
+ 'status' => 1,
+ 'message' => $validate->getError(),
+ 'data' => [],
+ ];
+ return json($data);
+ }
+ $words = array_values(array_unique(
+ explode(" ", strtolower($content))
+ ));
+
+ $data = [
+ 'status' => 1,
+ 'message' => $validate->getError(),
+ 'data' => $words,
+ ];
+ return json($data);
+}
+```
+
+示例句子:
+
+ Whatever is worth doing is worth doing well.
+
+现在需要增加词频,设计一个v参数,可以区别版本:
+
+```php
+public function word()
+{
+ $v = Request::param("v", 1);
+ if ($v == 1) {
+ // 版本1的代码
+ } else if ($v == 2) {
+ $content = Request::param("content");
+ $validate = Validate::rule([
+ 'content|文章内容' => 'require|min:10|max:100',
+ ]);
+ if (!$validate->check(['content' => $content])) {
+ $data = [
+ 'status' => 1,
+ 'message' => $validate->getError(),
+ 'data' => [],
+ ];
+ return json($data);
+ }
+ $words = explode(" ", strtolower($content));
+ $result = [];
+ foreach ($words as $word) {
+ if (empty($result[$word])) {
+ $result[$word] = 0;
+ }
+ $result[$word]++;
+ }
+
+ $data = [
+ 'status' => 1,
+ 'message' => $validate->getError(),
+ 'data' => $result,
+ ];
+ return json($data);
+ }
+}
+```
+
+这样就不会影响原来的客户端调用,又可以增加新的调用。同时api接口的地址也不用修改。
+
+## 多版本支持维护成本
+
+如果一个接口提供过多版本,是不是会造成维护成本变大?
+
+所以当一个接口版本过多的时候,那么可以通过逐步废弃旧版本接口减少维护压力。
+
+## 本节总结
+
+1. api接口版本设计是为了兼容之前的客户端的调用。
+2. 在实现上通过设计版本号参数即可实现。
+3. api接口设计过多的版本,会导致维护困难,应当逐步废弃旧的版本。
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/04_\345\223\215\345\272\224\346\225\260\346\215\256\350\256\276\350\256\241_files/1.jpg" "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/04_\345\223\215\345\272\224\346\225\260\346\215\256\350\256\276\350\256\241_files/1.jpg"
new file mode 100644
index 0000000000000000000000000000000000000000..b9d34e7b6be157879a6d56fdcdcba70e648893aa
Binary files /dev/null and "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/04_\345\223\215\345\272\224\346\225\260\346\215\256\350\256\276\350\256\241_files/1.jpg" differ
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/04_\350\257\267\346\261\202\346\225\260\346\215\256\350\256\276\350\256\241.md" "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/04_\350\257\267\346\261\202\346\225\260\346\215\256\350\256\276\350\256\241.md"
new file mode 100644
index 0000000000000000000000000000000000000000..87dde520c960c71dd6c360fb1a7263e78212d968
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/04_\350\257\267\346\261\202\346\225\260\346\215\256\350\256\276\350\256\241.md"
@@ -0,0 +1,100 @@
+## 本节目标
+
+1. 熟悉读取数据请求数据设计。
+2. 熟悉写入数据请求数据设计。
+3. 了解restful风格的api请求
+
+## 请求数据设计
+
+前面我们设计了api的url,也设计了api的版本号。那么用户请求api接口,怎么传递参数呢?
+
+是用get,还是post?或者是其他方式呢?
+
+本节将就这个问题进行讲解。
+
+一般来讲,常规的请求参数设计就两种:
+
+1. 读取数据使用get请求,参数就在url后面。
+2. 写入数据使用post请求,参数放在http请求体。
+
+## 读取数据
+
+像文章列表、分类列表、搜索文章等等这样功能都是属于读取数据的,用get请求,参数接在url后面。
+
+**示例1**,获取文章列表,一般需要有页码和每页显示条目数:
+
+ GET http://api.example.com/article/list/?page=1&count=20
+
+其中:
+
+ page 表示页码。
+ count 表示条目数。
+
+**示例2**,获取文章详情,一般需要传递文章id参数:
+
+ GET http://api.example.com/article/detail/?id=1
+
+其中:
+
+ id 表示文章id。
+
+**示例3**:搜索文章,一般需要传递搜索词、页码和每页显示条目数:
+
+ GET http://api.example.com/article/list/?word=life&page=1&count=20
+
+## 写入数据
+
+像增加文章,修改文章和删除等这些操作都叫做写入数据。写入数据一般用post请求。
+
+**示例1**,增加文章,一般需要有文章标题、文章简介、文章内容等等:
+
+ POST http://api.example.com/article/add/
+
+ 表单数据: article_title=标题&article_intro=简介&article_content=内容
+
+这边采用post请求,表单的数据放在请求数据体里面。
+
+**示例2**,修改文章,一般需要有文章id、文章标题、文章简介、文章内容等等:
+
+ POST http://api.example.com/article/update/
+
+ 表单数据: article_id=1&article_title=标题&article_intro=简介&article_content=内容
+
+这边采用post请求,表单的数据放在请求数据体里面。
+
+**示例3**,删除文章,一般需要有文章id即可:
+
+ POST http://api.example.com/article/update/
+
+ 表单数据: article_id=1
+
+这边采用post请求,表单的数据放在请求数据体里面。
+
+## restful风格
+
+REST(Representational State Transfer)表述性状态转换,REST指的是一组架构约束条件和原则。
+
+如果一个架构符合REST的约束条件和原则,我们就称它为RESTful架构。
+
+GET:查询
+
+ GET /artile
+ GET /artile/1
+
+POST:创建单个资源。POST一般向“资源集合”型uri发起
+
+ POST /artile
+
+PUT:更新单个资源(全量),客户端提供完整的更新后的资源。与之对应的是 PATCH,PATCH 负责部分更新,客户端提供要更新的那些字段。PUT/PATCH一般向“单个资源”型uri发起
+
+ PUT /artile/1
+
+DELETE:删除
+
+ DELETE /artile/1
+
+这边对restful风格的api介绍并不全面,仅供参考。
+
+## 本节总结
+
+一般来讲读取数据使用get请求,写入数据使用post请求。
\ No newline at end of file
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/05_\345\223\215\345\272\224\346\225\260\346\215\256\350\256\276\350\256\241_ajax.md" "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/05_\345\223\215\345\272\224\346\225\260\346\215\256\350\256\276\350\256\241_ajax.md"
new file mode 100644
index 0000000000000000000000000000000000000000..1ccb1ea5e1bd2fb8f71461c124256da6215f07f0
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/05_\345\223\215\345\272\224\346\225\260\346\215\256\350\256\276\350\256\241_ajax.md"
@@ -0,0 +1,204 @@
+## 本节目标
+
+1. 熟悉ajax get请求。
+2. 熟悉ajax post请求。
+
+## 响应的数据格式
+
+前面我们设计了api的url,也设计了api的版本号,请求数据也进行了说明,本篇将对响应数据进行讲解。
+
+响应数据是指api接口返回给客户端的数据。
+
+响应的数据格式除了json之外,还有xml和jsonp。现在xml用的少,重点关注和json和jsonp就行了。
+
+## ajax异步请求(get)
+
+接口设计完成后,都是给其他应用调用的,最常见的就是web客户端(web前端)、安卓客户端、IOS客户端、其他应用服务端。
+
+**这边web客户端调用接口就是用ajax的技术**。ajax是属于javascript的知识体系,这边做一下简单的回顾。
+
+比如我们有一个登录表单:
+
+```html
+
+
+
+
+ 登录表单
+
+
+
+
+
+```
+
+当我们提交这个表单的时候页面会跳转到表单的提交地址,然后对账号密码进行检验,如果有问题,就返回登录页面。
+
+有没什么办法,可以在当前页面直接提交,而不进行跳转呢?
+
+这边就可以使用ajax技术,ajax语法格式:
+
+```js
+let xmlHttp = new XMLHttpRequest();
+xmlHttp.onreadystatechange = function () {
+ if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
+ console.log(xmlHttp.responseText);
+ }
+};
+xmlHttp.open("请求方法", "服务端url", true);
+xmlHttp.send();
+```
+
+其中:
+
+ 1. XMLHttpRequest 是发起异步请求的类,需要先实例化这个类的对象。
+ 2. onreadystatechange 声明一个事件,每当 readyState 改变时,就会触发 onreadystatechange 事件。
+ 3. open 表示开启一个请求,具体参数:请求方法(post,get)、请求url,是否是异步请求。
+ 4. send 表示发送请求。
+ 5. xmlHttp.status 表示http响应状态。
+ 6. xmlHttp.readyState 表示异步请求就绪状态。有5种,详见如下:
+
+xmlHttp.readyState 5种情况:
+
+ 0 (未初始化): (XMLHttpRequest)对象已经创建,但还没有调用open()方法。
+ 1 (载入):已经调用open() 方法,但尚未发送请求。
+ 2 (载入完成): 请求已经发送完成。
+ 3 (交互):可以接收到部分响应数据。
+ 4 (完成):已经接收到了全部数据,并且连接已经关闭。
+
+**示例1**,异步发送请求到服务端接口:/index.php?s=api/test/test/,并将返回数据显示在页面:
+
+```html
+
+
+
+
+ 一个演示ajax的静态页面
+
+
+
+请求服务端接口
+
+
+
+```
+
+服务端接口:
+
+```php
+public function test()
+{
+ return 'test 接口返回';
+}
+```
+
+运行后,点击按钮可以发现页面上显示了如下:
+
+ test 接口返回
+
+通过谷歌工具抓包查看,可以看有一个另外的请求:
+
+
+
+思考:
+
+ 假如我们要传递参数num=1,请问修改哪里?
+
+注意:
+
+ 这边我们把接口直接放在index(前台)应用下面,正常应用在前期一般不会拆分出单独的api应用。
+
+## ajax异步请求(post)
+
+前面我们使用ajax发起了get请求,当然ajax也可以发起post请求,发起post请求有一些不太一样。
+
+ajax post语法格式:
+
+```js
+let xmlHttp = new XMLHttpRequest();
+xmlHttp.onreadystatechange = function () {
+ if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
+ console.log(xmlHttp.responseText);
+ }
+};
+xmlHttp.open("POST", "服务端url", true);
+xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+xmlHttp.send("数据主体");
+```
+
+大部分和get请求类似,不一样的地方:
+
+ 1. 请求方法固定为POST。
+ 2. setRequestHeader 表示设置http请求头的方法。
+ 3. send方法增加数据主体。
+
+**示例1**,异步发送请求到服务端接口:/index.php?s=api/test/test/,并传入数据 name=盘古:
+
+```html
+
+
+
+
+ 一个演示ajax的静态页面
+
+
+
+请求服务端接口
+
+
+
+```
+
+服务端接口:
+
+```php
+public function test()
+{
+ $name = Request::param("name");
+ return '你好, ' . $name;
+}
+```
+
+运行后,点击按钮可以发现页面上显示了如下:
+
+ 你好, 盘古
+
+通过谷歌工具抓包查看,可以看有一个另外的请求:
+
+
+
+思考:
+
+ 如果需要再传入一个参数,age=123,请问修改哪里?
+
+## 本节总结
+
+web客户端使用ajax技术,可以在不刷新页面的情况下发起请求。
+
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/05_\345\223\215\345\272\224\346\225\260\346\215\256\350\256\276\350\256\241_ajax_files/1.jpg" "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/05_\345\223\215\345\272\224\346\225\260\346\215\256\350\256\276\350\256\241_ajax_files/1.jpg"
new file mode 100644
index 0000000000000000000000000000000000000000..ea78497b52b0aac2278a770b6170abf15b6c3dfb
Binary files /dev/null and "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/05_\345\223\215\345\272\224\346\225\260\346\215\256\350\256\276\350\256\241_ajax_files/1.jpg" differ
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/06_\345\223\215\345\272\224\346\225\260\346\215\256\350\256\276\350\256\241_json.md" "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/06_\345\223\215\345\272\224\346\225\260\346\215\256\350\256\276\350\256\241_json.md"
new file mode 100644
index 0000000000000000000000000000000000000000..7f77bb5243e437b43118702394dc37d7df60c649
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/06_\345\223\215\345\272\224\346\225\260\346\215\256\350\256\276\350\256\241_json.md"
@@ -0,0 +1,254 @@
+## 本节目标
+
+1. 熟悉接口返回json格式。
+2. 熟悉web客户端如何调用数据格式为json的接口。
+
+## json
+
+上面我们返回的数据是一个简单的字符串,在实务中为了方便区分请求的各种状况,一般都会定义状态、信息、数据等字段。
+
+因为json是键值对的数据格式,这时候用json格式就非常方便了,例如php返回json格式数据:
+
+```php
+$data = [
+ 'status' => 0, // 表示接口返回的状态
+ 'message' => '', // 表示接口返回的消息
+ 'data' => [ // 表示接口返回的数据
+ ],
+];
+header("Content-Type: application/json");
+echo json_encode($data);
+```
+
+其中:
+
+ $data 表示返回的数据,这边是一个数组。
+ status 表示状态,0表示没有出现错误。
+ message 表示返回的一些 提示信息,一般status > 0时有写入。
+ data 就表示返回的一些数据,比如文章列表、编辑文章结果等等。
+ 备注:实务中这边数据字段和格式并非都是这样,但是大体都类似,只是字段名不一样。
+ header 表示设置返回的数据格式为json格式,即Content-Type为application/json。
+ json_encode 表示将php数组编码为json格式的数据。
+
+注意:
+
+ 这边定义的字段是比较常见的字段,在实务中有很多命名方式,但是基本都表达了这些个意思。
+
+**示例1**,已知api接口返回当前服务器时间,编写并调用这个接口:
+
+服务端代码:
+
+```php
+public function test()
+{
+ $data = [
+ 'status' => 0,
+ 'message' => '',
+ 'data' => [
+ 'time' => date("Y-m-d H:i:s")
+ ],
+ ];
+ return json($data);
+}
+```
+
+其中服务端返回的是一个json格式,在客户端解析这个json结果:
+
+```html
+
+
+
+
+ 一个演示ajax的静态页面
+
+
+
+请求服务端接口
+
+
+
+```
+
+这里需要对 responseData.status 进行一个判断,如果大于0表示有错误发生的意思。
+
+**示例2**,设计api接口,传入长度参数,生成随机字符串(a-z0-9),并返回json格式:
+
+```php
+public function randStr()
+{
+ $length = Request::param("length");
+ $validate = Validate::rule([
+ 'length' => 'require|between:1,32',
+ ]);
+ if (!$validate->check(['length' => $length])) {
+ $data = [
+ 'status' => 1,
+ 'message' => $validate->getError(),
+ 'data' => [],
+ ];
+ return json($data);
+ }
+
+ $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
+ $charsLength = mb_strlen($chars);
+
+ $str = '';
+ for ($i = 0; $i < $length; $i++) {
+ $rand = mt_rand(0, $charsLength - 1);
+ $str .= $chars[$rand];
+ }
+
+ $data = [
+ 'status' => 0,
+ 'message' => '',
+ 'data' => [
+ 'str' => $str,
+ ],
+ ];
+ return json($data);
+}
+```
+
+其中:
+
+ 这边返回了json格式的数据。
+
+web客户端进行调用:
+
+```html
+
+
+
+
+ 一个演示ajax的静态页面
+
+
+
+这是一个生成随机字符串的应用(0-9a-z)。
+
+ 请输入生成的长度:
+
+
+开始生成
+
+
+
+```
+
+这边我们使用post请求,传递参数需要放在send方法里。
+
+**示例3**,blog系统中,设计api接口,查询文章列表,返回文章列表的数据,其中包含文章id、文章标题、文章分类、文章简介,增加时间,修改时间:
+
+这边使用blog系统进行演示:
+
+```php
+public function index()
+{
+ $articleList = ArticleModel::getList();
+
+ $articleData = [];
+ foreach ($articleList as $row) {
+ $articleData[] = [
+ 'article_id' => $row['article_id'],
+ 'article_title' => $row['article_title'],
+ 'category_name' => $row['category_name'],
+ 'intro' => $row['intro'],
+ 'add_time' => $row['add_time'],
+ ];
+ }
+ $data = [
+ 'status' => 0,
+ 'message' => '',
+ 'data' => [
+ 'articleData' => $articleData,
+ ],
+ ];
+
+ return json($data);
+}
+```
+
+其中:
+
+ 读取所有文章后,遍历存放到数组,最后返回json格式。
+
+设计了这个接口后,后台就可以进行异步调用了:
+
+```js
+let xmlHttp = new XMLHttpRequest();
+xmlHttp.onreadystatechange = function () {
+ if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
+ let data = JSON.parse(xmlHttp.responseText);
+ if (data.status > 0) {
+ window.alert("出现错误:" + data.message);
+ } else {
+ // 获取表格的内的html内容
+ let listHtml = document.getElementById('list').innerHTML;
+
+ // 遍历文章数据,拼接表格html代码
+ let articleData = data.data.articleData;
+ for (let i in articleData) {
+ console.log(articleData[i]);
+ let trString = '';
+ trString += ' ';
+ trString += '' + articleData[i].article_id + ' ';
+ trString += '' + articleData[i].article_title + ' ';
+ trString += '' + articleData[i].category_name + ' ';
+ trString += '' + articleData[i].intro + ' ';
+ trString += '' + articleData[i].add_time + ' ';
+ trString += '' + articleData[i].update_time + ' ';
+ trString += ' ';
+ trString += ' ';
+
+ listHtml += trString;
+ }
+
+ // 替换表格内容为相应的html
+ document.getElementById('list').innerHTML = listHtml;
+ }
+ }
+};
+xmlHttp.open("GET", "/api/article/index/", true);
+xmlHttp.send();
+```
+
+这边请求到文章接口后,就会遍历显示在页面上。其中增加时间和修改时间没有完成,请自行完善。
+
+## 本节总结
+
+api接口一般返回json格式的数据,在web客户端可以通过json格式数据的语法进行访问。
\ No newline at end of file
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/07_\345\223\215\345\272\224\346\225\260\346\215\256\350\256\276\350\256\241_jsonp.md" "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/07_\345\223\215\345\272\224\346\225\260\346\215\256\350\256\276\350\256\241_jsonp.md"
new file mode 100644
index 0000000000000000000000000000000000000000..30c230559a9be798c68551fcc7c8527e1d66c8ea
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/07_\345\223\215\345\272\224\346\225\260\346\215\256\350\256\276\350\256\241_jsonp.md"
@@ -0,0 +1,204 @@
+## 本节目标
+
+1. 熟悉为什么要用jsonp?
+2. 熟悉jsonp的数据格式。
+3. 熟悉客户端调用jsonp的方式。
+
+## 为什么要用jsonp
+
+前面我们讲解了ajax异步请求接口,接口返回json格式的处理方法。
+
+如果碰到web客户端地址和服务端地址不在同一个域的情况下,会出现跨域的问题。
+
+那么什么是跨域呢?我们用下面一个示例进行讲解。
+
+**示例1**,我们在localhost:8888下面制作客户端页面,访问tp项目接口,获取服务端当前时间:
+
+```html
+
+
+
+
+ 一个演示ajax的静态页面
+
+
+
+请求服务端接口
+
+
+
+```
+
+因为页面的访问地址是:
+
+ http://localhost:8888/test.html
+
+而请求的接口地址是:
+
+ http://localhost:8900/index.php?s=api/test/test
+
+**两个的端口不一致,这个称为跨域。除了端口不一致,如果域名不一致,那么也是跨域。**
+
+访问就会报如下的错误:
+
+
+
+随着前后端分离的流行,客户端和服务端域名或者端口不一致的情况非常常见,所以就有jsonp这样一种技术用来解决跨域问题。
+
+## jsonp
+
+jsonp(json with padding)是json的一种“使用模式”,主要用于解决主流浏览器的跨域数据访问的问题。
+
+jsonp的核心原理就是目标页面回调本地页面的方法,并带入参数。
+
+使用jsonp总结有3步:
+
+ 1. 前端页面定义好相关的回调方法。
+ 2. 服务端返回的内容是调用第1步定义好的方法。
+ 3. 前端页面以js的方式引入第2步的内容。
+
+**示例1**,使用jsonp的方式在页面上显示服务端返回的内容:
+
+1) 前端页面:
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+其中:
+
+ 定义了show方法,显示内容在id="content"的div内。
+
+2) 服务端(基于thinkphp)页面:
+
+```php
+public function content()
+{
+ $content = "这个是服务端返回的数据";
+ return "show('" . $content . "');";
+}
+```
+
+其中:
+
+ 服务端输出show()这样一个字符串,其实就是调用js的方法;
+
+3) 前端以js的方式引入服务端页面:
+
+```html
+
+```
+
+这个时候访问前端页面,可以看到页面上显示了:这个是服务端返回的数据。这样的字眼了。
+
+**改进方案,show方法由前端传递**:
+
+前面这边show方法是服务端写死的,一般来讲后端并知道前端需要调用什么方法,所以这个参数可以由前端进行传递,后端获取就可以了。
+
+```php
+public function content()
+{
+ $callback = Request::param("callback"); // 获取传递的方法
+ $content = "这个是服务端返回的数据";
+ return $callback . "('" . $content . "');";
+}
+```
+
+thinkphp中,可以使用jsonp方法直接进行:
+
+```php
+public function content()
+{
+ $content = "这个是服务端返回的数据";
+ return jsonp($content); // 自动获取callback这个参数,并输出。
+}
+```
+
+## json和jsonp结合
+
+前面介绍了json和jsonp格式的返回数据,当然这边两种也可以结合在一起。
+
+其实就是把jsonp返回的数据用json格式代替就可以了:
+
+```php
+public function content()
+{
+ $data = [
+ 'status' => 0,
+ 'message' => '',
+ 'data' => [
+ 'content' => "这个是服务端返回的数据",
+ ],
+ ];
+ return jsonp($data);
+}
+```
+
+因为这边改成了返回json格式,前端就需要相应调整回调方法了:
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+## 本节总结
+
+jsonp格式主要是用来解决跨域问题,当然不跨域也可以使用。
+
+jsonp的三步骤:
+
+ 1. 前端页面定义好相关的回调方法。
+ 2. 服务端返回的内容是调用第1步定义好的方法。
+ 3. 前端页面以js的方式引入第2步的内容。
+
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/07_\345\223\215\345\272\224\346\225\260\346\215\256\350\256\276\350\256\241_jsonp_files/1.jpg" "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/07_\345\223\215\345\272\224\346\225\260\346\215\256\350\256\276\350\256\241_jsonp_files/1.jpg"
new file mode 100644
index 0000000000000000000000000000000000000000..aefdd7159a8bb001aaa067b64c3eeb83e9d10171
Binary files /dev/null and "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/07_\345\223\215\345\272\224\346\225\260\346\215\256\350\256\276\350\256\241_jsonp_files/1.jpg" differ
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/08_\347\274\226\345\206\231api\346\226\207\346\241\243.md" "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/08_\347\274\226\345\206\231api\346\226\207\346\241\243.md"
new file mode 100644
index 0000000000000000000000000000000000000000..4621af6be441307e61abf8fd52f4e12a5506492b
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/08_\347\274\226\345\206\231api\346\226\207\346\241\243.md"
@@ -0,0 +1,128 @@
+## 本节目标
+
+1. 熟悉api接口文档编写
+
+## api接口文档
+
+前面我们设计了也开发了不少api接口。我们自己知道接口干了啥事,也知道如何调用。
+
+只是如果我们要把接口提供给其他人使用,其他人要怎么知道调用呢?
+
+这会我们就可以统一编写文档对api接口进行说明,俗称api文档。
+
+## api接口文档要素
+
+基本来看,文档至少需要如下5个要素:
+
+ 1. 接口用途
+ 2. 接口地址
+ 3. 请求方式
+ 4. 请求参数
+ 5. 返回数据
+
+这样使用者才能正常调用这个接口。
+
+**示例1**,已知接口返回服务器当前时间,编写api:
+
+接口用途:获取当前系统时间戳。
+
+接口地址:http://localhost:8900/api/system/time/
+
+请求方式:get
+
+请求参数:无
+
+返回数据:
+
+```
+{
+ "status": 0, // 状态
+ "message": "", // 信息提示
+ "data": { // 返回数据
+ "time": "2021-05-06 21:09:20" // 时间
+ }
+}
+```
+
+**示例2**,已知接口返回随机字符串,编写api文档:
+
+接口用户:生成随机字符串。
+
+接口地址:http://localhost:8900/api/tool/randstring/
+
+请求方式:post
+
+请求参数:
+
+ 1. length 正整数,1~32 随机字符串长度。
+
+返回数据:
+
+```
+// 接口正常返回
+{
+ "status": 0,
+ "message": "",
+ "data": {
+ "string": "w4kejv3vrptgj2vikt4v3u0l9e57kn3c" // 随机字符串
+ }
+}
+
+// 参数错误返回格式
+{
+ "status": 1,
+ "message": "length只能在 1 - 32 之间",
+ "data": [ ]
+}
+```
+
+在接口少的时候,我们可以使用文本工具和软件来编写api文档,随着接口越来越多,协作人员越来越多,有一个统一的管理平台会好些。
+
+下面我们介绍一款平台showdoc,实现接口的管理。
+
+## 开源文档管理工具showdoc
+
+showdoc官网:
+
+ https://www.showdoc.com.cn/
+
+我们可以在官网上直接编辑api文档。也可以通过客户端工具进行编辑,还支持模拟请求。
+
+几个步骤:
+
+ 1. 下载 runapi-1.0.0.exe,并安装。
+ 2. 创建项目
+ 3. 新建接口
+ 4. 获取项目文档链接
+
+下面详细讲解每个步骤:
+
+1)下载 runapi
+
+下载地址:
+
+ https://www.showdoc.com.cn/runapi?page_id=30291
+
+下载完成后直接安装即可。
+
+2)创建项目,并进入。
+
+
+
+3)新建接口
+
+
+
+并填写相关的信息
+
+
+
+4)通过项目获取相关链接
+
+
+
+这样就可以通过浏览器进行访问了。并且其他人也可以访问,方便团队之间协作了。
+
+## 本节总结
+
+api文档就是将api的使用方式写出来,通过编写api文档可以很方便的实现团队之间的协作。
\ No newline at end of file
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/08_\347\274\226\345\206\231api\346\226\207\346\241\243_files/1.jpg" "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/08_\347\274\226\345\206\231api\346\226\207\346\241\243_files/1.jpg"
new file mode 100644
index 0000000000000000000000000000000000000000..3502f8130934d81894ab3e5e468dc6b1e0d7b33e
Binary files /dev/null and "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/08_\347\274\226\345\206\231api\346\226\207\346\241\243_files/1.jpg" differ
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/08_\347\274\226\345\206\231api\346\226\207\346\241\243_files/2.jpg" "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/08_\347\274\226\345\206\231api\346\226\207\346\241\243_files/2.jpg"
new file mode 100644
index 0000000000000000000000000000000000000000..b5063b1836b9201ace5349dc589783bea9a03094
Binary files /dev/null and "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/08_\347\274\226\345\206\231api\346\226\207\346\241\243_files/2.jpg" differ
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/08_\347\274\226\345\206\231api\346\226\207\346\241\243_files/3.jpg" "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/08_\347\274\226\345\206\231api\346\226\207\346\241\243_files/3.jpg"
new file mode 100644
index 0000000000000000000000000000000000000000..10f059e4177f3e872a3a8235a6c119499772c490
Binary files /dev/null and "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/08_\347\274\226\345\206\231api\346\226\207\346\241\243_files/3.jpg" differ
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/08_\347\274\226\345\206\231api\346\226\207\346\241\243_files/4.jpg" "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/08_\347\274\226\345\206\231api\346\226\207\346\241\243_files/4.jpg"
new file mode 100644
index 0000000000000000000000000000000000000000..defbc9956744a57ab60ceff2ab146b3e35386d92
Binary files /dev/null and "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/08_\347\274\226\345\206\231api\346\226\207\346\241\243_files/4.jpg" differ
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/80_\347\273\203\344\271\240\351\242\230.md" "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/80_\347\273\203\344\271\240\351\242\230.md"
new file mode 100644
index 0000000000000000000000000000000000000000..20880ce670770e8f1777bb4a2b1ea18c1e542a2f
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/03_webapi\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221/80_\347\273\203\344\271\240\351\242\230.md"
@@ -0,0 +1,32 @@
+## url设计
+
+1. 已知需要开发分类模块的增删改查,设计相关的接口url。
+2. 已知需要开发文章模块的增删改查,设计相关的接口url。
+3. 已知登录功能需要使用接口实现,设计相关的接口url。
+
+## 版本设计
+
+1. 接第一章节练习题第2题,现在需要改进接口,移除首尾的空格再计算长度,请使用版本设计的方式改进。
+2. 接第一章节练习题第4题,现在需要改进接口,返回如下数据:
+
+```
+[
+ 'status' => 0,
+ 'message' => '',
+ 'data' => [
+ 'where' => 5,
+ 'is' => 1,
+ 'how' => 2,
+ ],
+]
+```
+
+请使用版本设计的方式改进。
+
+## 响应数据设计
+
+1. 设计表单页面,用户可以输入字符串,然后使用ajax调用服务端接口计算长度,并把结果显示在页面上。
+2. 设计表单页面,用户可以输入英文文章,然后使用ajax调用服务端接口统计词频,并把结果显示在页面上。
+3. 设计表单页面,用户可以输入数字,然后使用ajax调用服务端斐波那契接口,判断是否是斐波那契数,并把结果显示在页面上。
+4. 设计表单页面,用户可以输入身份证,然后使用ajax调用服务端身份证分析接口,计算年龄和性别,并把结果显示在页面上。
+5. 改进jsonp章节的第一个示例,使用jsonp的方式解决跨域问题,并将服务器时间显示到页面上。
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/\350\257\276\345\240\202\347\273\203\344\271\240.txt" "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/\350\257\276\345\240\202\347\273\203\344\271\240.txt"
new file mode 100644
index 0000000000000000000000000000000000000000..f02d70f851bd43d7e444c4f6b8a088cd7f4216d0
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/2019\347\272\247\350\256\241\345\272\224\347\217\255_webapi_20210510/\350\257\276\345\240\202\347\273\203\344\271\240.txt"
@@ -0,0 +1,2 @@
+1. 03_webapiƺͿ/80_ϰ.md url 1 ~ 3
+2. 03_webapiƺͿ/80_ϰ.md 汾 1 ~ 2
\ No newline at end of file
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/.example.env" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/.example.env"
new file mode 100644
index 0000000000000000000000000000000000000000..c27f74caea59e0bc78bae1941793a6ac34c85a9c
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/.example.env"
@@ -0,0 +1 @@
+APP_DEBUG = true
[APP]
DEFAULT_TIMEZONE = Asia/Shanghai
[DATABASE]
TYPE = mysql
HOSTNAME = 127.0.0.1
DATABASE = test
USERNAME = username
PASSWORD = password
HOSTPORT = 3306
CHARSET = utf8
DEBUG = true
[LANG]
default_lang = zh-cn
\ No newline at end of file
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/.gitignore" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/.gitignore"
new file mode 100644
index 0000000000000000000000000000000000000000..d465120e74b813c80d55c418ed3cab757a22033c
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/.gitignore"
@@ -0,0 +1,5 @@
+/.idea
+/.vscode
+/vendor
+*.log
+.env
\ No newline at end of file
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/.travis.yml" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/.travis.yml"
new file mode 100644
index 0000000000000000000000000000000000000000..36f7b6f90dafe374d0eca306886df83f09ff13a9
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/.travis.yml"
@@ -0,0 +1,42 @@
+sudo: false
+
+language: php
+
+branches:
+ only:
+ - stable
+
+cache:
+ directories:
+ - $HOME/.composer/cache
+
+before_install:
+ - composer self-update
+
+install:
+ - composer install --no-dev --no-interaction --ignore-platform-reqs
+ - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Core.zip .
+ - composer require --update-no-dev --no-interaction "topthink/think-image:^1.0"
+ - composer require --update-no-dev --no-interaction "topthink/think-migration:^1.0"
+ - composer require --update-no-dev --no-interaction "topthink/think-captcha:^1.0"
+ - composer require --update-no-dev --no-interaction "topthink/think-mongo:^1.0"
+ - composer require --update-no-dev --no-interaction "topthink/think-worker:^1.0"
+ - composer require --update-no-dev --no-interaction "topthink/think-helper:^1.0"
+ - composer require --update-no-dev --no-interaction "topthink/think-queue:^1.0"
+ - composer require --update-no-dev --no-interaction "topthink/think-angular:^1.0"
+ - composer require --dev --update-no-dev --no-interaction "topthink/think-testing:^1.0"
+ - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Full.zip .
+
+script:
+ - php think unit
+
+deploy:
+ provider: releases
+ api_key:
+ secure: TSF6bnl2JYN72UQOORAJYL+CqIryP2gHVKt6grfveQ7d9rleAEoxlq6PWxbvTI4jZ5nrPpUcBUpWIJHNgVcs+bzLFtyh5THaLqm39uCgBbrW7M8rI26L8sBh/6nsdtGgdeQrO/cLu31QoTzbwuz1WfAVoCdCkOSZeXyT/CclH99qV6RYyQYqaD2wpRjrhA5O4fSsEkiPVuk0GaOogFlrQHx+C+lHnf6pa1KxEoN1A0UxxVfGX6K4y5g4WQDO5zT4bLeubkWOXK0G51XSvACDOZVIyLdjApaOFTwamPcD3S1tfvuxRWWvsCD5ljFvb2kSmx5BIBNwN80MzuBmrGIC27XLGOxyMerwKxB6DskNUO9PflKHDPI61DRq0FTy1fv70SFMSiAtUv9aJRT41NQh9iJJ0vC8dl+xcxrWIjU1GG6+l/ZcRqVx9V1VuGQsLKndGhja7SQ+X1slHl76fRq223sMOql7MFCd0vvvxVQ2V39CcFKao/LB1aPH3VhODDEyxwx6aXoTznvC/QPepgWsHOWQzKj9ftsgDbsNiyFlXL4cu8DWUty6rQy8zT2b4O8b1xjcwSUCsy+auEjBamzQkMJFNlZAIUrukL/NbUhQU37TAbwsFyz7X0E/u/VMle/nBCNAzgkMwAUjiHM6FqrKKBRWFbPrSIixjfjkCnrMEPw=
+ file:
+ - ThinkPHP_Core.zip
+ - ThinkPHP_Full.zip
+ skip_cleanup: true
+ on:
+ tags: true
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/LICENSE.txt" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/LICENSE.txt"
new file mode 100644
index 0000000000000000000000000000000000000000..574a39c401ff71ffcb90d15edb906b8046c7661b
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/LICENSE.txt"
@@ -0,0 +1,32 @@
+
+ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
+版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn)
+All rights reserved。
+ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
+
+Apache Licence是著名的非盈利开源组织Apache采用的协议。
+该协议和BSD类似,鼓励代码共享和尊重原作者的著作权,
+允许代码修改,再作为开源或商业软件发布。需要满足
+的条件:
+1. 需要给代码的用户一份Apache Licence ;
+2. 如果你修改了代码,需要在被修改的文件中说明;
+3. 在延伸的代码中(修改和有源代码衍生的代码中)需要
+带有原来代码中的协议,商标,专利声明和其他原来作者规
+定需要包含的说明;
+4. 如果再发布的产品中包含一个Notice文件,则在Notice文
+件中需要带有本协议内容。你可以在Notice中增加自己的
+许可,但不可以表现为对Apache Licence构成更改。
+具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/README.md" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/README.md"
new file mode 100644
index 0000000000000000000000000000000000000000..2929dad091236d93f73380bd02d6a0bbb58b5b2f
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/README.md"
@@ -0,0 +1,56 @@
+ThinkPHP 6.0
+===============
+
+> 运行环境要求PHP7.1+,兼容PHP8.0。
+
+[官方应用服务市场](https://market.topthink.com) | [`ThinkAPI`——官方统一API服务](https://docs.topthink.com/think-api)
+
+ThinkPHPV6.0版本由[亿速云](https://www.yisu.com/)独家赞助发布。
+
+## 主要新特性
+
+* 采用`PHP7`强类型(严格模式)
+* 支持更多的`PSR`规范
+* 原生多应用支持
+* 更强大和易用的查询
+* 全新的事件系统
+* 模型事件和数据库事件统一纳入事件系统
+* 模板引擎分离出核心
+* 内部功能中间件化
+* SESSION/Cookie机制改进
+* 对Swoole以及协程支持改进
+* 对IDE更加友好
+* 统一和精简大量用法
+
+## 安装
+
+~~~
+composer create-project topthink/think tp 6.0.*
+~~~
+
+如果需要更新框架使用
+~~~
+composer update topthink/framework
+~~~
+
+## 文档
+
+[完全开发手册](https://www.kancloud.cn/manual/thinkphp6_0/content)
+
+## 参与开发
+
+请参阅 [ThinkPHP 核心框架包](https://github.com/top-think/framework)。
+
+## 版权信息
+
+ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
+
+本项目包含的第三方源码和二进制文件之版权信息另行标注。
+
+版权所有Copyright © 2006-2020 by ThinkPHP (http://thinkphp.cn)
+
+All rights reserved。
+
+ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
+
+更多细节参阅 [LICENSE.txt](LICENSE.txt)
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/common.php" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/common.php"
new file mode 100644
index 0000000000000000000000000000000000000000..124361568ff89529382ad44b04b53d6fd7543152
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/common.php"
@@ -0,0 +1,2 @@
+$adminList]);
+ }
+ public function add(){
+ return View::fetch();
+ }
+ public function addSave()
+ {
+ $params = Request::param();
+ $rule = Validate::rule([
+ 'admin_name|管理员名称'=>'require|min:2|max:50',
+ 'admin_email|管理员邮箱'=>'require|min:8|max:100',
+ 'admin_password|管理员密码'=>'require|min:6|max:100'
+ ]);
+ if (!$rule->check($params)){
+ return View::fetch('public/tips_error',['massage'=>$rule->getError()]);
+ }
+ if ($params['admin_password']!=$params['admin_password2']){
+ echo '两次密码错误';
+ exit();
+ }
+ $name=AdminModel::where('category_name','=',$params['category_name'])->find();
+ if ($name){
+ echo "用户名已存在"."返回上一页 ";
+ exit();
+ }
+ $params['update_time']=time();
+ $params['add_time']=time();
+ $result=AdminModel::create($params);
+ $addr='Admin';
+ return View::fetch('public/tips',['result'=>$result,
+ 'addr'=>$addr
+ ]);
+
+ }
+ public function edit(){
+ $params=Request::param('admin_id') ?? '';
+ $admin=AdminModel::find($params);
+// if (empty($params['admin_id'])){
+// echo "找不到管理员"."返回管理员列表 ";
+// exit();
+// }
+ return View::fetch('',['admin'=>$admin]);
+ }
+ public function editSave(){
+ $params=Request::param();
+ $rule = Validate::rule([
+ 'admin_name|管理员名称'=>'require|min:2|max:50',
+ 'admin_email|管理员邮箱'=>'require|min:8|max:100',
+ 'admin_password|管理员密码'=>'require|min:6|max:100',
+ 'admin_password2|确认密码'=>'require|min:6|max:100'
+ ]);
+
+ if (!$rule->check($params)){
+ return View::fetch('public/tips_error',['massage'=>$rule->getError()]);
+ }
+ $admin=AdminModel::find($params['admin_id']);
+ $admin['admin_name']=$params['admin_name'];
+// $admin['admin_email']=$params['admin_email'];
+ $admin['admin_password']=$params['admin_password'];
+ $admin['update_time']=time();
+ $result=$admin->save();
+ $addr='Admin';
+ return View::fetch('public/tips',['result'=>$result,
+ 'addr'=>$addr
+ ]);
+ }
+}
\ No newline at end of file
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/controller/Article.php" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/controller/Article.php"
new file mode 100644
index 0000000000000000000000000000000000000000..bfc0691e41254c748f019a92a2443e02be4dde71
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/controller/Article.php"
@@ -0,0 +1,116 @@
+1,//每页显示几条数据
+ 'query'=>$queryParams//实际上页面所有的get参数
+ ]);
+ //第一种
+// $articleList=ArticleModel::select();
+//
+// foreach ($articleList as &$item){
+// $CategoryList=CategoryModel::find($item['category_id']);
+// $item['category_name']=$CategoryList['category_name'];
+//// View::assign('',$CategoryList);
+// }
+// unset($item);
+// return View::fetch('',['articleList'=>$articleList]);
+ //第二种
+// $articleList=ArticleModel::select();
+ foreach ($articleList as $item){
+ $CategoryList=CategoryModel::find($item['category_id']);
+ $item['category_name']=$CategoryList['category_name'];
+ }
+// unset($item);
+ View::assign('articleList',$articleList);
+ return View::fetch();
+ }
+ public function add(){
+ $categotyList=CategoryModel::select();
+ return View::fetch('',['categoryList'=>$categotyList]);
+ }
+ public function addSave(){
+ $params=Request::param();
+ $rule=Validate::rule([
+ 'article_title|文章标题'=>'require|min:2|max:45',
+ 'category_id|分类'=>'require|between:1,'.PHP_INT_MAX,
+ 'intro|文章简介'=>'require|min:10|max:255',
+ 'content|文章内容'=>'require|min:10|max:255'
+ ]);
+ if(!$rule->check($params)){
+ return View::fetch('public/tips_error',['massage'=>$rule->getError()]);
+ }
+ $params['update_time']=time();
+ $params['add_time']=time();
+ $result=ArticleModel::create($params);
+ $addr='Article';
+ return View::fetch('public/tips',['result'=>$result,
+ 'addr'=>$addr
+ ]);
+ }
+ public function edit(){
+ $params=Request::param('article_id');
+ $article=ArticleModel::find($params);
+// View::assign('articleList',$article);
+ $categoryList=CategoryModel::select();
+ View::assign([
+ 'categoryList'=>$categoryList,
+ 'article'=>$article
+ ]);
+// if (empty($params['article_id'])){
+// echo "找不到文章"."返回文章列表 ";
+// exit();
+// }
+ return View::fetch();
+ }
+ public function editSave(){
+ $params=Request::param();
+ $rule=Validate::rule([
+ 'article_title|文章标题'=>'require|min:2|max:45',
+ 'category_id|分类'=>'require|between:1,'.PHP_INT_MAX,
+ 'intro|文章简介'=>'require|min:10|max:255',
+ 'content|文章内容'=>'require|min:10|max:255'
+ ]);
+ if(!$rule->check($params)){
+ return View::fetch('public/tips_error',['massage'=>$rule->getError()]);
+ }
+
+ $Article=ArticleModel::find($params['article_id']);
+ $Article['article_title']=$params['article_title'];
+ $Article['category_id']=$params['category_id'];
+ $Article['intro']=$params['intro'];
+ $Article['content']=$params['content'];
+ $Article['update_time']=time();
+ $result=$Article->save();
+ $addr='Article';
+ return View::fetch('public/tips',['result'=>$result,
+ 'addr'=>$addr
+ ]);
+ }
+ public function delete(){
+ $params=Request::param('article_id');
+ $result=ArticleModel::destroy($params);
+ $addr='Article';
+ return View::fetch('public/tips',['result'=>$result,
+ 'addr'=>$addr
+ ]);
+ }
+}
\ No newline at end of file
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/controller/Category.php" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/controller/Category.php"
new file mode 100644
index 0000000000000000000000000000000000000000..8f5c04967be96a314fecba09933bab235f892507
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/controller/Category.php"
@@ -0,0 +1,102 @@
+1,//每页显示几条数据
+ 'query'=>$queryParams//实际上页面所有的get参数
+ ]);
+// $return=CategoryModel::select();
+ View::assign('return',$return);
+// return View::fetch('',['return'=>$return]);
+ return View::fetch();
+ }
+ public function add(){
+ return View::fetch();
+ }
+ public function addSave(){
+ $params=Request::param();
+ $rule=Validate::rule([
+ 'category_name|分类名称'=>'require|min:2|max:45',
+ 'category_desc|分类描述'=>'require|min:10|max:255'
+ ]);
+ $name=CategoryModel::where('category_name','=',$params['category_name'])->find();
+ if ($name){
+ echo "用户名已存在"."返回上一页 ";
+ exit();
+ }
+ if(!$rule->check($params)){
+ return View::fetch('public/tips_error',['massage'=>$rule->getError()]);
+ }
+ $params['update_time']=time();
+ $params['add_time']=time();
+ $result=CategoryModel::create($params);
+ $addr='Category';
+ return View::fetch('public/tips',['result'=>$result,
+ 'addr'=>$addr
+ ]);
+
+
+ }
+ public function edit(){
+ $params=Request::param('category_id');
+ $category=CategoryModel::find($params);
+// if (empty($params['category_id'])){
+// echo "找不到分类"."返回分类列表 ";
+// exit();
+// }
+ return View::fetch('',['category'=>$category]);
+ }
+ public function editSave(){
+ $params=Request::param();
+ $rule=Validate::rule([
+ 'category_name|分类名称'=>'require|min:2|max:45',
+ 'category_desc|分类描述'=>'require|min:10|max:255'
+ ]);
+ if(!$rule->check($params)){
+ return View::fetch('public/tips_error',['massage'=>$rule->getError()]);
+ }
+ $category=CategoryModel::find($params['category_id']);
+ $category['category_name']=$params['category_name'];
+ $category['category_desc']=$params['category_desc'];
+ $category['update_time']=time();
+ $result=$category->save();
+ $addr='Category';
+ return View::fetch('public/tips',['result'=>$result,
+ 'addr'=>$addr
+ ]);
+
+ }
+
+ public function delete()
+ {
+ $params = Request::param('category_id');
+ $article =ArticleModel::find($params);
+ if ($article) {
+ echo "分类下面有文章" . "返回列表页 ";
+ exit();
+ }
+ $result = CategoryModel::destroy($params);
+ $addr='Category';
+ return View::fetch('public/tips',['result'=>$result,
+ 'addr'=>$addr
+ ]);
+ }
+}
\ No newline at end of file
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/controller/Index.php" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/controller/Index.php"
new file mode 100644
index 0000000000000000000000000000000000000000..677cfdd769a13e3a88e5ce221c799c49820d1cae
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/controller/Index.php"
@@ -0,0 +1,12 @@
+返回上一页";
+ exit();
+ }
+ if (empty($params['admin_password'])){
+ echo "密码不能为空"."返回上一页 ";
+ exit();
+ }
+ $admin=AdminModel::where("admin_email","=",$params['admin_email'])->find();
+ $salt = "0w37qVYCCu#SV7s4x3ctMNwQS@&4Hc";
+ $adminPassword = md5($salt. md5($salt . $params['admin_password'] . $salt) . $salt);
+ if($admin['admin_password']==$adminPassword){
+ session('admin_name',$admin['admin_name']);
+ session('admin_email',$params['admin_email']);
+ session('admin_password',$params['admin_password']);
+ echo "登录成功"."前往文章列表页面 ";
+ }else{
+ echo "密码错误"."返回上一页 ";
+ exit();
+ }
+ }
+ public function logout(){
+ session('admin_email','');
+ session('admin_email','');
+ session('admin_password','');
+ echo "登出成功"."前往登录页面 ";
+ exit();
+ }
+}
\ No newline at end of file
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/event.php" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/event.php"
new file mode 100644
index 0000000000000000000000000000000000000000..4eff8908bd643cd6072b9fde6ee38ca4ad6f04ad
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/event.php"
@@ -0,0 +1,5 @@
+pathinfo())) {//获取地址
+ if (empty(session("admin_email"))){
+ return redirect('/index.php?s=admin/Login/index');
+ }
+ }
+ $response=$next($request);
+
+ return $response;
+ }
+ public function end(Response $response){
+
+ }
+}
\ No newline at end of file
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Admin/add.phtml" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Admin/add.phtml"
new file mode 100644
index 0000000000000000000000000000000000000000..1396a39203379bceef65e232abf2f6aedb6c919d
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Admin/add.phtml"
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Admin/edit.phtml" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Admin/edit.phtml"
new file mode 100644
index 0000000000000000000000000000000000000000..3826d902c9d837e86f2df91b2c9d10172c067c5d
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Admin/edit.phtml"
@@ -0,0 +1,41 @@
+
+
+
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Admin/index.phtml" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Admin/index.phtml"
new file mode 100644
index 0000000000000000000000000000000000000000..807c852ac07179ea91951368dd45d295124bdbbe
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Admin/index.phtml"
@@ -0,0 +1,42 @@
+
+
+
\ No newline at end of file
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Article/add.phtml" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Article/add.phtml"
new file mode 100644
index 0000000000000000000000000000000000000000..e9e57cdc8e1e09c9b04113825e9288ac95267d9c
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Article/add.phtml"
@@ -0,0 +1,52 @@
+
+
+
+
\ No newline at end of file
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Article/edit.phtml" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Article/edit.phtml"
new file mode 100644
index 0000000000000000000000000000000000000000..9413752ae5e8cc4a153a09898e986b0966276ae2
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Article/edit.phtml"
@@ -0,0 +1,53 @@
+
+
+
+
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Article/index.phtml" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Article/index.phtml"
new file mode 100644
index 0000000000000000000000000000000000000000..ee247f01858879f7b7894d47d99dd1300c5f881a
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Article/index.phtml"
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+ render() ?>
+
+
+
+
+
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Category/add.phtml" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Category/add.phtml"
new file mode 100644
index 0000000000000000000000000000000000000000..a5ec462d78bb96ea4d8640b39067d4b80a858bf3
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Category/add.phtml"
@@ -0,0 +1,34 @@
+
+
+
\ No newline at end of file
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Category/edit.phtml" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Category/edit.phtml"
new file mode 100644
index 0000000000000000000000000000000000000000..2febdb22d8dda6201d3e27d99c5d62719b2be012
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Category/edit.phtml"
@@ -0,0 +1,40 @@
+
+
+
\ No newline at end of file
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Category/index.phtml" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Category/index.phtml"
new file mode 100644
index 0000000000000000000000000000000000000000..69c31066f8301ad3dce726c37f6be7c12b158916
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Category/index.phtml"
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+ render() ?>
+
+
+
+
+
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Login/index.phtml" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Login/index.phtml"
new file mode 100644
index 0000000000000000000000000000000000000000..0e8a4d917c7c3b1544ff9f8e24d23777551fd76e
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/Login/index.phtml"
@@ -0,0 +1,33 @@
+
+
+
+
+ 登录
+
+
+
+
+
+
diff --git "a/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/public/fool.phtml" "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/public/fool.phtml"
new file mode 100644
index 0000000000000000000000000000000000000000..6cd1c4bb227e91d90b4d8059fb0421efd017af6d
--- /dev/null
+++ "b/\350\224\241\346\226\207\351\276\231/5.10/blog/app/admin/view/public/fool.phtml"
@@ -0,0 +1,4 @@
+
+
+