├── .gitignore
├── 1.1序言.md
├── 1.2关于作者.md
├── 1.3本书源码.md
├── 1.4反馈纠错.md
├── 1.5安全指南.md
├── 1.6捐助作者.md
├── 12.1专有名词索引.md
├── 12.3老读者升级指南.md
├── 2.1编辑器选用.md
├── 2.2命令行工具.md
├── 2.3开发环境搭建.md
├── 2.4浏览器选择.md
├── 2.5第一个应用.md
├── 2.6Git工作流.md
├── 3.1章节说明.md
├── 3.2静态页面.md
├── 3.3Think命令.md
├── 3.4小结.md
├── 4.1章节说明.md
├── 4.2样式美化.md
├── 4.3局部视图.md
├── 4.4路由链接.md
├── 4.5用户注册页面.md
├── 4.6集中视图.md
├── 4.7小结.md
├── 5.1章节说明.md
├── 5.2数据库迁移.md
├── 5.3查看数据表.md
├── 5.4模型文件.md
├── 5.5小结.md
├── 6.1章节说明.md
├── 6.2注册表单.md
├── 6.3用户数据验证.md
├── 6.4注册失败错误信息.md
├── 6.5注册成功.md
├── 6.6小结.md
├── 7.1章节说明.md
├── 7.2会话.md
├── 7.3用户登录.md
├── 7.4退出.md
├── 7.5小结.md
├── 8.1章节说明.md
├── 8.2重构代码.md
├── 8.3更新用户.md
├── 8.4权限系统.md
├── 8.5列出所有用户.md
├── 8.6删除用户.md
├── 8.7访客模式.md
├── 8.8优化前端.md
├── 8.9小结.md
├── 9.1章节说明.md
├── 9.2微博模型.md
├── 9.3显示微博.md
├── 9.4发布微博.md
├── 9.5微博数据流.md
├── README.md
├── SUMMARY.md
├── book.json
├── cover.jpg
├── images
├── 1516383654686.jpg
├── GIF.gif
├── Router-MVC-DB.svg.png
├── TIM截图20180121181857.png
├── TIM截图20180129165617.png
└── screenshot_1516529870045.png
├── style
└── website.css
├── 第一章.基础信息.md
├── 第七章.会话管理.md
├── 第三章.构建页面.md
├── 第九章.微博CRUD.md
├── 第二章.开发环境布置.md
├── 第五章.用户模型.md
├── 第八章.用户CRUD.md
├── 第六章.用户注册.md
└── 第四章.优化页面.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode
--------------------------------------------------------------------------------
/1.1序言.md:
--------------------------------------------------------------------------------
1 | # ThinkPHP 5.1 入门教程
2 |
3 | 本书将教你使用现代工具流构建一个类似微博的应用。 通过本书,你将会学到如 HTML、CSS、JavaScript、PHP、ThinkPHP 等 Web 开发的相关基础知识。除此之外,编辑器使用、开发环境搭建、Git、Composer、Bootstrap 前端框架在本书中也会使用, 本书代码严格 PSR 规范编写,使用这些知识将会为你以后的 Web 开发生涯奠定结实的基础,无论在大型项目或是个人练手作品都能有一个好的开发习惯和规范。
4 |
5 | ## 安全提示
6 | 截至本文更新日期 2018-12-22,PHP 5.6 及 PHP 7.0 在 2019-01-01 将正式停止维护,请开发时不要使用老版本的 PHP.
7 |
8 | ## 协助交流
9 |
10 | QQ群: 685083718
--------------------------------------------------------------------------------
/1.2关于作者.md:
--------------------------------------------------------------------------------
1 | # 作者: AGD
2 |
3 | AGD 是数据网站 EpicData 的创始人
4 | 浏览我们的开源项目:
5 | * https://github.com/EpicLearn
6 | * https://github.com/OpenEpicData
7 | * https://gamer.epicdata.net
8 |
9 | 通过下列方式找到作者
10 | * Github -- https://github.com/AGDholo
11 | * 邮箱 -- agdholo@gmail.com
--------------------------------------------------------------------------------
/1.3本书源码.md:
--------------------------------------------------------------------------------
1 | # 源码地址
2 |
3 | 书籍源码: https://github.com/EpicLearn/ThinkPHP5.1-Web-Actual-combat
4 | 作品源码: https://github.com/EpicLearn/ThinkPHP5.1-Web-Actual-combat-code
5 |
6 | ## 授权协议
7 |
8 | 
本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。
9 |
10 | ~~~txt
11 | 本书后端源码基于 MIT 协议发布
12 | Copyright 2019 AGD
13 |
14 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
15 |
16 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 | ~~~
--------------------------------------------------------------------------------
/1.4反馈纠错.md:
--------------------------------------------------------------------------------
1 | # 遇到问题怎么办
2 |
3 | 1. 先检查自己的代码是否有语法、逻辑等基本错误。
4 | 2. 请使用 Google 或者 Bing 搜索,如果中文搜不到解决方案, 进入 Google 翻译 翻译成英文再搜索, 请不要使用百度等其他搜索引擎
5 | 3. 加入 QQ 群:685083718 进行询问
6 |
7 | ## 如何提问
8 |
9 | 1. 请确保你已经在搜索引擎中使用中英文仔细的搜索并且阅读。
10 | 2. 提问时,应该完整的描述问题并提供 相关代码片段 和 错误信息。
11 |
12 | ## 建议反馈
13 |
14 | 加入 QQ 群:685083718 或者发送邮件至 agdholo@gmail.com 反馈
--------------------------------------------------------------------------------
/1.5安全指南.md:
--------------------------------------------------------------------------------
1 | # PHP 版本
2 |
3 | 请在 2019 年使用 PHP 7.2, 并且计划 2019 中期切换到 PHP 7.3
4 | 到目前为止(2018-01-19),PHP 7.2 已经发布快两个月了。
5 | 7.1 以下版本已进入 LTS 养老末期,使用低版本的 PHP 意味着没有官方的安全维护,
6 | 也无法使用新特性和更快的速度(例如 PHP 内置加密操作 PASSWORD_HASH() 仅支持 PHP >= 5.5 ,
7 | 和大多数软件一样,PHP 通常会提供 LTS 长期支持和维护,
8 | 但是因为无法知道安全补丁的版本号,不像 Windows 操作系统一样,安全补丁有据可查, 这会使得产品的安全性大大降低。
9 | 因此,如果你是新开的项目,请使用 PHP 最新版本,而过旧的项目也要尝试重构更新。
10 |
11 | ## 依赖管理
12 |
13 | > Composer 安装、配置及使用请参考本书 第二章:2.3 开发环境搭建
14 |
15 | Composer: https://getcomposer.org/ 在 PHP 生态中是重要的一环,大部分的扩展包都是通过 Composer 进行管理。
16 | 如果你是手动下载扩展包并进行手动加载,那么在大型应用上,你无法检测某个框架是否过时,
17 | 也无法知晓某个框架的重大安全漏洞并及时更新到最新版本,过老的版本是非常不安全的。
18 |
19 | ## HTTPS 和浏览器安全
20 |
21 | HTTPS,一种通过计算机网络进行安全通信的传输协议
22 | 在 2018 年,所有现代安全的浏览器已经不在接受 HTTP,用户打开 HTTP 协议的网站时,
23 | 浏览器会警告该网站的连接不安全。
24 | 不过你可以从各大云厂商免费的申请一个 TLS 证书, 或者使用 Let's Encrypt certificate authority: https://letsencrypt.org/ .
25 |
26 | ## 开发安全的 PHP 程序
27 |
28 | 避免 PHP 程序存在 SQL 注入
29 | 如果你是自己编写 SQL 代码, 请确保使用 prepared 语句,
30 | 并且从网络或文件系统提供的信息都作为参数传递, 而不是字符串拼接的形式。
31 | 此外,确保你没有使用 模拟的 prepared 语句: https://stackoverflow.com/questions/134099 .
32 |
33 | ## 文件上传处理
34 |
35 | 接受未知来源的问题,意味着这些文件可能恶意攻击服务器,
36 | 请保证服务器文件权限不超过 775,
37 | 上传的新文件应该是 只读或读写,
38 | 不要在网站根目录保存文件,
39 | 同大多数 PHP 框架一样,不在根目录运行 index.php 目的是为恶意代码提供最少的执行环境,
40 | 例如:
41 |
42 | ` /var/www/example.com-uploaded/ `
43 |
44 | 或者直接将文件往下移动一个层级
45 |
46 | ` /var/www/example.com/public `
47 |
48 | ## 跨站请求伪造
49 |
50 | 跨站请求伪造(CSRF)是一种混淆的代理攻击,通过诱导用户的浏览器代表攻击者执行恶意的 HTTP 请求(使用的是该用户的权限).
51 | 首先使用 HTTPS,没有 HTTPS 的话,任何保护都是脆弱的,因为所有数据都是明文传输。
52 | 如果你是用的是现代 PHP 框架,请在框架中开启 CSRF 验证
53 | 如果你是原生用户,只需要:
54 |
55 | * 增加基本的 Challenge-response authentication。
56 | * 为每个表单添加一个隐藏的表单属性。
57 | * 填充一个密码安全的随机值(称为令牌).
58 | * 验证是否提供了隐藏的表单属性,以及是否匹配上期望值。
59 |
60 | ## 密码散列
61 |
62 | >安全的密码存储曾经是一个激烈争论的话题,但现在实现起来相当微不足道
63 |
64 | ~~~~
65 | $hash = password_hash($password, PASSWORD_DEFAULT);
66 | if (password_verify($password, $hash)) {
67 | // Authenticated.
68 | if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
69 | // Rehash, update database.
70 | }
71 | }
72 | ~~~~
73 |
74 | 甚至不需要知道在后台使用什么算法,因为如果你使用最新版本的 PHP ,你也将使用当前最新的技术,用户的密码将会自动进行升级(只要有新的默认算法可用).
75 | 无论你做什么,都不要做 WordPress 所做的事情
76 | WordPress 并不使用 bcrypt 来储存密码,而是使用 MD5,
77 | 要理解为什么,首先查看 这个代码片段 以及 这一个
78 | 如果 $this->portable_hashes 设置为TRUE,则会调用 $this->crypt_private()
79 | 因此,HashPassword 可以大大简化为以下片段:
80 |
81 | ~~~~
82 | function HashPassword($password)
83 | {
84 | if ( strlen( $password ) > 4096 ) {
85 | return '*';
86 | }
87 | /* these steps are skipped */
88 | $random = $this->get_random_bytes(6);
89 | $hash =
90 | $this->crypt_private($password,
91 | $this->gensalt_private($random));
92 | if (strlen($hash) == 34)
93 | return $hash;
94 | return '*';
95 | }
96 | ~~~~
97 |
--------------------------------------------------------------------------------
/1.6捐助作者.md:
--------------------------------------------------------------------------------
1 | # 本书为免费书籍,如果你觉得对你的工作学习有帮助,可以请我喝杯咖啡
2 |
3 | 
4 |
5 | ## 捐赠列表
6 |
7 | 本书的发展离不开这些小伙伴的帮助,如果您也出了一份力,请发送支付宝账户或订单号及时间至 agdholo@gmail.com,也可以加入QQ群: 685083718 进行交流反馈。
8 |
9 | 捐赠人 | 金额
10 | ------------ | -------------
11 | 梁子 | 支付宝 ¥66
12 | 土包子_152******01 | 支付宝 ¥50
13 | *海富 | 支付宝 ¥10
14 | [@满满](https://www.kancloud.cn/@alimanman) | 看云 ¥20
15 | [@ihaiyan](https://www.kancloud.cn/@ihaiyan) | 看云 ¥10
16 | [@yhpp](https://www.kancloud.cn/@yhpp) | 看云 ¥10
17 | [@carbon](https://www.kancloud.cn/@carbon) | 看云 ¥10
18 | [@xiaoshaoye](https://www.kancloud.cn/@xiaoshaoye) | 看云 ¥5
19 | [@kwokzc](https://www.kancloud.cn/@kwokzc) | 看云 ¥5
20 | [@ZOMBIE](https://www.kancloud.cn/@zombie2019) | 看云 ¥5
21 | [@jinxun](https://www.kancloud.cn/@jinxun) | 看云 ¥1
--------------------------------------------------------------------------------
/12.1专有名词索引.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AGDholo/ThinkPHP5.1-Web-Actual-combat/45f6b0d02d7785d44581daa01a3d9d84aa1acd70/12.1专有名词索引.md
--------------------------------------------------------------------------------
/12.3老读者升级指南.md:
--------------------------------------------------------------------------------
1 | 笔者不建议通过逐步更新文件的方式进行升级,
2 | 0. 请注意,由于 composer.lock 锁定了版本,在 thinkphp 5.x/5.1.x 12 月 9 日之前的版本,存在安全漏洞,使用 composer install 之后请务必使用 composer update
3 | 1. 删除已经存在的书籍程序代码.
4 | 2. 进入 [https://github.com/EpicLearn/ThinkPHP5.1-Web-Actual-combat-code/releases](https://github.com/EpicLearn/ThinkPHP5.1-Web-Actual-combat-code/releases) 下载你当时学到的章节
5 | 3. 解压到前面删除代码的位置
6 | 4. 打开命令行工具, CD 至目录,运行 composer install 以及 composer update
7 | 5. 打开 config/database.php 填写你的数据库信息
8 | 6. 运行迁移 php think migrate:run
9 | 5. 访问你在 Hosts 里设置的链接,即可使用
--------------------------------------------------------------------------------
/2.1编辑器选用.md:
--------------------------------------------------------------------------------
1 | # 现代的编辑器
2 |
3 | > 为什么要选用现代的编辑器
4 |
5 | 对于新手而言,更需要的是一把配件齐全并且及时更新的武器, 方便开发的同时降低使用难度,并且培养现代化的工作环境, 养成一个好的开发习惯远远大于熟练掌握奇淫技巧来使用各类编辑器。
6 | 以下是一些编辑器名词概览:
7 |
8 | * VScode
9 | * Atom
10 | * SublimeText
11 | * Vim
12 | * PHPStorm
13 |
14 | > 本书的代码编写、命令行环境、Git 使用全部通过 VScode 进行,为了你的学习体验,建议与笔者的开发环境一致。
15 |
16 | 本书涉及的软件都在官方网站进行下载安装,请不要使用未知来源的软件,如 百度云 或 各种网站 上下载的版本。
17 | 这对你的应用和开发环境有潜在危害。
18 | 为什么有危害? XcodeGhost 事件: https://baike.baidu.com/item/XcodeGhost
19 |
20 | ## VScode 特点
21 |
22 | * 全中文支持
23 | * 跨平台支持
24 | * 扩展部署在 微软云 上,不需要 科学上网 即可安装
25 | * 由全球最大的操作系统、宇宙级 IDE Visual Studio 开发公司 微软 提供
26 | * 快速的迭代更新
27 | * 对 TypeScript 提供第一方支持
28 | * 版本控制,应用调试一气呵成,几个简单的操作方可使用
29 | * 打开速度极快,在大文件测试下稳居第一
30 |
31 | ## 如何安装
32 |
33 | 前往 VScode: https://code.visualstudio.com/ 官方网站 下载安装。
34 | 安装时请务必勾选如图内容:
35 |
36 | 
37 |
38 | 完成后重启操作系统。
--------------------------------------------------------------------------------
/2.2命令行工具.md:
--------------------------------------------------------------------------------
1 | # Git
2 |
3 | > 本书使用 Git 管理代码和进行版本控制。
4 | 会涉及一些简单命令,不用担心,如果你完全按照本书的步骤进行,那完全不用担心!
5 |
6 | 本书涉及的软件都在官方网站进行下载安装,请不要使用未知来源的软件,如 百度云 或 各种网站 上下载的版本。
7 | 这对你的应用和开发环境有潜在危害。
8 | 为什么有危害? XcodeGhost 事件: https://baike.baidu.com/item/XcodeGhost
9 |
10 | ## 下载安装
11 |
12 | 进入 Git 官方网站: https://git-scm.com/ 下载安装
13 | 安装时请不要改动安装路径,这可能会导致系统环境变量无法生效。
14 |
15 | ## 验证 Git 配置
16 |
17 | 打开 PowerShell/CMD ,键入
18 | `git --version`
19 | 若成功输出类似 `git version 2.16.0.windows.2,Git` 环境变量已启用
20 | 若未成功输出,请转到本书 2.3 开发环境搭建 参考配置 PHP 环境变量的方式配置 Git
21 |
22 | ## PowerShell/CMD
23 |
24 | Windows 环境中已经自带了 PowerShell/CMD ,不需要额外安装。
--------------------------------------------------------------------------------
/2.3开发环境搭建.md:
--------------------------------------------------------------------------------
1 | # 宝塔面板
2 |
3 | > 警告:本书所用的宝塔面板年代久远,5.x Windows 版本已经停止维护,本书下面的一大堆废话可忽略,但是以下的安装步骤仍然可用(不推荐)
4 | > 你可以参考本书作者编写的另一个环境搭建指南:https://learn.epicdata.net/development-environment-construction-guide/
5 | > 宝塔面板是非强制性的,你也可以使用你自己喜欢的面板
6 |
7 | 本书所有操作环境都使用 宝塔面板 ,为了避免不一样的麻烦,请和笔者保持一致。
8 | 本书涉及的软件都在官方网站进行下载安装,请不要使用未知来源的软件,如 百度云 或 各种网站 上下载的版本。
9 |
10 | 宝塔面板 是笔者线下和线上都在使用的一键部署及管理工具。 选用它主要有几点:
11 |
12 | * 对新手及其友好,不需要掌握运作原理,也不需要掌握各类文件配置方法,只需要一条命令/一个安装包,即可实现部署
13 | * 全中文化支持,所有设置选项都简单易读
14 | * 商业支持,已经和阿里云达成合作,线上环境稳定,可以投入生产环境
15 | * 更新频率高,各种补丁和新特性都会第一时间发布
16 |
17 | ## 安装宝塔面板
18 |
19 | 1. 进入 宝塔面板官网 ,选择 Windows 版,下载解压安装。
20 | 2. 安装完成后请点击 顶部栏-> 环境 ,安装所需软件(Nginx PHP Mysql).
21 |
22 | ## 配置 PHP
23 |
24 | 找到安装 宝塔面板 的根目录并且进入 `%:\BtSoft >>> %:\BtSoft\WebSoft\php\7.1`
25 | 在本地计算机进入: 控制面板-> 系统和安全-> 系统
26 |
27 | 1. 点击左侧栏: 高级系统设置-> 环境变量
28 | 2. 编辑下方 系统变量 的 Path-> 新建-> 将前面打开的路径复制进去-> 保存并重启计算机
29 |
30 | ## Composer
31 |
32 | 打开 PowerShell/CMD 命令行工具,键入 php -v,出现所示的类似语句表示 php 环境正确配置:
33 |
34 | ~~~~
35 | PHP 7.1.2 (cli) (built: Feb 14 2017 21:38:39) ( NTS MSVC14 (Visual C++ 2015) x86 )
36 | Copyright (c) 1997-2017 The PHP Group
37 | Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
38 | ~~~~
39 |
40 | 若出现 `无法将“php”项识别为 cmdlet、函数、脚本文件或可运行程序的名称` 则环境变量没有正确配置,请检查路径并重新修改(保存后请务必重启计算机)
41 |
42 | ## 安装 Composer
43 |
44 | 依次键入以下命令:
45 |
46 | 1. 直接下载 composer.phar,地址:https://dl.laravel-china.org/composer.phar
47 | 2. 把下载的 composer.phar 放到 PHP 安装目录
48 | 3. 新建 composer.bat, 添加如下内容,并保存:@php "%~dp0composer.phar" %*
49 | 4. 键入 `composer --version` 查看是否正确安装
50 |
51 | ## 配置镜像加速
52 |
53 | 众所周知的原因,Composer 在国内使用原生下载链接速度缓慢,键入命令即可使用,国外用户请忽略:
54 | `composer config -g repo.packagist composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/`
--------------------------------------------------------------------------------
/2.4浏览器选择.md:
--------------------------------------------------------------------------------
1 | # 现代的浏览器
2 |
3 | 截至本书编写时间(2018年),前端的生产力成几何倍数的增长,使用老旧的浏览器意味着你无法使用更多的新特性,以及可能存在的严重安全漏洞。
4 | 以下是一些浏览器名词概览:
5 |
6 | * Chrome
7 | * Firefox
8 | * ~~IE~~
9 | * ~~360 浏览器~~
10 | * ~~QQ 浏览器~~
11 |
12 | > 如果你的网络支持,请优先选用 Chrome,不要使用 IE 所有版本的浏览器。
--------------------------------------------------------------------------------
/2.5第一个应用.md:
--------------------------------------------------------------------------------
1 | # 创建第一个网站
2 |
3 | 打开 宝塔面板 ,选择顶部栏的 Web 面板,第一次使用会提示安装,并再次点击
4 |
5 | 1. 选择进入内网网址也就是 `http://127.0.0.1:888` 并设置相关账号密码。
6 | 2. 点击左侧栏 “网站” 按钮,并选择 “添加站点” .
7 | 3. 在弹出框内输入你想访问的域名(推荐后缀结尾为 ".test",例如 thinkphp.test),并选择数据库(mysql),PHP(使用最高版本) .
8 | 4. 如图所示:
9 |
10 | 
11 |
12 | ## Hosts
13 |
14 | Hosts 的作用是 将指定域名 转发到特定 IP 上,例如
15 | `thinkphp.test 127.0.0.2`
16 | 当我们访问 thinkphp.test 时,实际上是访问了 127.0.0.2 这个 IP,通过这样,我们就可以在本地实现自定义域名访问。
17 |
18 | ## 修改 Hosts
19 |
20 | 1. 打开 资源管理器 ,在地址栏键入:%SystemRoot%\System32\drivers\etc\ .
21 | 2. 请右键 文件 hosts 并找到 属性 -> 安全,选择你登录的用户名,点击 编辑 ,勾选 写入 .
22 | 3. 再次右键 文件 hosts 选择 Open With Code .
23 | 4. 添加一行:thinkphp.test 127.0.0.2 并保存。
24 | 5. 打开浏览器,在地址栏键入 `http://thinkphp.test` ,此时出现 宝塔面板 的欢迎界面表示成功。
25 |
26 | ## 安装 ThinkPHP
27 |
28 | >禁止将 public/index.php 移动到根目录,这是不安全的,详细内容请参阅本书 1.5 安全指南 .
29 |
30 | 1. 打开 资源管理器 ,找到你创建网站的目录,全选并且删除。
31 | 2. 右键当前目录,选择: Open With Code .
32 | 3. 按下组合键: Ctrl+Shift+` 打开终端。
33 |
34 | 在终端中键入:
35 | `composer create-project topthink/think .`
36 |
37 | 打开浏览器,在地址栏键入 `http://thinkphp.test/public` ,此时出现 ThinkPHP 的欢迎界面表示成功。
38 |
39 | ## 链接优化
40 |
41 | 1. 打开 宝塔 Web 面板。
42 | 2. 点击左侧栏 “网站” 按钮,并点击右侧你创建网站的 “设置” 按钮。
43 | 3. 选择 “网站目录”-> “运行目录”-> “public” 并保存。
44 | 4. 选择 “伪静态” 键入下列代码并保存:
45 |
46 | ~~~~ nginx
47 | location / {
48 | if (!-e $request_filename) {
49 | rewrite ^(.*)$ /index.php?s=/$1 last;
50 | }
51 | }
52 | ~~~~
53 |
54 | 以上操作的作用:
55 |
56 | 1. 隐藏 /Public
57 | 2. 隐藏 /index.php/
58 |
59 | 现在,只需要访问 `http://thinkphp.test` 就大功告成!
--------------------------------------------------------------------------------
/2.6Git工作流.md:
--------------------------------------------------------------------------------
1 | # Git 是什么
2 | >Git 是 Linux 的创始人 Linus Torvalds 开源的一款分布式版本控制系统,以帮助开发者更好的对项目进行版本管理。
3 | 简单来说,是一套集中进行 提交、回滚、发布 的工具。Git 应该是每一位开发者的标配。
4 | 本书也将使用 Git 进行版本控制,安装过程请参阅章节 2.2 命令行工具 .
5 |
6 | ## 基本设置
7 |
8 | 1. 使用 VScode 打开上个章节创建的 网站目录。
9 | 2. 按下 Ctrl+Shift+G-> 看到顶部栏文字 “源代码管理” 右侧的一个小按钮-> 点击并初始化版本库-> 选择 网站根目录,并确定-> 你现在可以看到 VScode 中有一大排目录出现了
10 | 3. 在顶部消息栏中键入 “初始化 ThinkPHP” 并点击 ✔ 图标
11 | 4. 按下 Ctrl+Shift+P -> 键入 git
12 |
13 | ## Git 与 GitHub
14 |
15 | 1. 进入 GitHub 官方网站: https://github.com/ 并注册账号。
16 | 2. 点击 头像右边 + -> New repository,填写好对应的名称,点击绿色 [Create repository] 按钮完成创建。
17 | 3. 进入到刚刚创建的项目,找到蓝色背景的内容,我们会看到 [Quick setup — if you’ve done this kind of thing before] 一行,并将中间的链接进行复制。
18 |
19 | ## 线下与线上连接
20 |
21 | 返回 VScode 并打开终端,键入
22 | ~~~
23 | git config --global user.name "xxx" // 输入在 GitHub 创建的用户名
24 | git config --global user.email "xxx" // 输入在 GitHub 创建的邮箱地址
25 | git remote add github https://github.com//xxxxx // 请填写刚刚复制的地址
26 | ~~~
27 |
28 | 按下 `Ctrl+Shift+G` ,点击顶部栏 “源代码管理” 文字最右边的按钮,选择 “全部提交” ,键入提交内容,然后再次点击这个按钮,选择 “推送到” 选择弹出框下面的远程地址。
29 |
30 | 现在,在浏览器中浏览刚刚创建的项目地址,提交的文件已全部更新。
31 |
--------------------------------------------------------------------------------
/3.1章节说明.md:
--------------------------------------------------------------------------------
1 | # 章节说明
2 | >请使用 VScode 打开 第二章 创建的应用,本章的内容基于上一章节
3 |
4 | 从本章开始,我们就进入了 ThinkPHP 开发应用的第一步,构建最简单的静态页面。
--------------------------------------------------------------------------------
/3.2静态页面.md:
--------------------------------------------------------------------------------
1 | # 配置路由
2 |
3 | 当我们进入一条链接时,应用程序做了以下处理:
4 | 1. 路由寻找 URL 对应的控制器。
5 | 2. 控制台将指定的方法进行操作。
6 | 3. 渲染给模板。
7 |
8 | ## ThinkPHP 的路由
9 |
10 | 打开 route/route.php 看到这条语句,将路由做如下修改:
11 |
12 | ~~~
13 | /* route/route.php */
14 | ~~Route::get('hello/:name', 'index/hello');~~
15 | Route::get('hello', 'index/hello');
16 | ~~~
17 |
18 | 以上命令的功能:
19 |
20 | * Route:: 注册路由静态方法
21 | * get 请求方式
22 | * 'hello' 请求 URL
23 | * 'index/hello' 响应默认控制器中 hello 方法 (`application/index/controller/Index.php/:function hello`)
24 |
25 | 目录: `application/index/controller/` 为默认控制器的根目录,当我们在路由中书写时,如果只使用默认控制器,只用写入 控制器文件名/方法
26 | > 并不推荐使用省略的方法使用路由语句,这是难以维护的。
27 |
28 | 你应该使用: `'index/index/hello' //模块(index)/控制器(controller)/index.php/:function hello `
29 |
30 | 打开上述控制器文件,找到 `hello` 方法并修改为:
31 |
32 | ~~~~
33 | /* application/index/controller/Index.php/:function hello */
34 | ~~public function hello($name = 'ThinkPHP5')~~
35 | public function hello()
36 | {
37 | ~~return 'hello,' . $name;~~
38 | return 'hello world'
39 | }
40 | ~~~~
41 |
42 | 打开浏览器,访问 `http://thinkphp.test/hello` 则会出现 `hello world`,一个简单的 GET 路由就完成了。
43 |
44 | ## 在路由中直接输出
45 |
46 | 在阅读本小节之前,首先要知道一个概念 闭包: http://php.net/manual/zh/functions.anonymous.php
47 | 稍作了解之后,我们来学习在路由中使用闭包。
48 | 打开路由文件,将刚才的语句进行修改:
49 |
50 | ~~~~
51 | /* route/route.php */
52 | ~~Route::get('hello', 'index/index/hello');~~
53 | Route::get('hello', function() {
54 | return 'hello closures';
55 | });
56 | ~~~~
57 |
58 | 这时候再刷新浏览器,输出语句就变成了 `hello closures`
59 | 这就是路由中闭包的基本用法。
60 |
61 | ## 在控制器中响应模板
62 |
63 | 现在请删除刚才的闭包语句,重新写入:
64 |
65 | ~~~~
66 | /* route/route.php */
67 | ~~Route::get('hello', function() {
68 | return 'hello closures';
69 | });~~
70 | Route::get('hello', 'index/index/hello');
71 | ~~~~
72 |
73 | 进入路由对应的控制器,修改代码:
74 |
75 | ~~~~
76 | /* application/index/controller/Index.php/:function hello */
77 | public function hello()
78 | {
79 | ~~return 'hello world';~~
80 | return view();
81 | }
82 | ~~~~
83 |
84 | > return view(); 是一个助手函数,表示响应对应的模板。
85 |
86 | 如果 view() 中未添加任何参数,则会响应到默认路径:
87 |
88 | `当前模块/view/当前控制器名(小写)/当前操作(小写).html`
89 | `application/index(当前模块)/view/index(当前控制器名)/hello.html(当前操作)`
90 |
91 | 1. 我们创建对应路径的对应文件 `application/index/view/index/hello.html` 并写入 `hello view `
92 | 2. 再次刷新浏览器,输出语句就变成了 `hello view `
93 |
94 | ## 在路由闭包操作中响应模板
95 | >在实际的开发中,如果我们只是不进行任何操作的响应一个模板文件,那么使用控制器实在是有点大材小用,这时候,就需要在路由中直接输出。
96 |
97 | 打开路由文件,将刚才的语句进行修改
98 |
99 | ~~~~
100 | /* route/route.php */
101 | ~~Route::get('hello', 'index/index/hello');~~
102 | Route::get('hello', function() {
103 | return view('index@index/hello');
104 | });
105 | ~~~~
106 |
107 | 这条语句表示该路由会渲染 `index` 模块下面的 `view/index/hello.html` 模板文件输出。
108 | 1. 进入到对应的模板文件,将 `hello view` 修改为 `hello router view`
109 | 2. 再次刷新浏览器,输出语句就变成了 `hello router view `
110 |
111 | ## 为路由提供参数
112 |
113 | 我们在第一次对路由文件进行修改的时候,将 `Route::get('hello/:name', 'index/index/hello');` 变为了 `Route::get('hello', 'index/index/hello');`
114 | 其中,删除了 `:name` 这几个字符, `:name` 就是本节提到的 参数
115 |
116 | 将刚才写入的闭包语句改为:
117 |
118 | ~~~~
119 | /* route/route.php */
120 | Route::get('hello/:name', function ($name) {
121 | return 'Hello,' . $name;
122 | });
123 | ~~~~
124 |
125 | `function($name)` 将 `$name` 赋值为 `:name `
126 | 如果我们进入 `http://thinkphp/hello/param`,那么就会输出 `hello param`
127 |
128 | ## 创建第一个静态页面
129 |
130 | 请删除所有路由语句和 index 模块 (`application/[index/]`)
131 |
132 | 打开路由文件,写入语句:
133 |
134 | ~~~~
135 | /* route/route.php */
136 | Route::get('', 'welcome/index/home');
137 | Route::get('/help', 'welcome/index/help');
138 | Route::get('/about', 'welcome/index/about');
139 | ~~~~
140 |
141 | 创建控制器文件: `application/welcome/controller/Index.php`
142 | 在创建好的控制器文件中写入:
143 |
144 | ~~~~
145 | /* application/welcome/controller/Index.php */
146 | namespace app\welcome\controller;
147 | use think\Controller;
148 | class Index extends Controller
149 | {
150 | public function home()
151 | {
152 | return '主页';
153 | }
154 | public function help()
155 | {
156 | return '帮助';
157 | }
158 | public function about()
159 | {
160 | return '关于';
161 | }
162 | }
163 | ~~~~
164 |
165 | * `namespace` 代表的是 命名空间,你可以把它理解成路径,不同的 `namespace` 代表着不同的路径, 只有正确路径下的操作才能被找到。
166 | * `use` 是使用 php 各种类的一个操作,如果我们想要使用其他封装好的类,仅仅 `use` 对应的文件就行了。
167 | * `class Index extends Controller` 表示当前的 Index(如果我们创建在控制器下的是 `AnyThing.php`,那么我们就要使用 `AnyThing` 而不是 `Index`) 类继承了 `Controller` 类,如果继承,就可以使用 `Controller` 中的所有公共方法。
168 |
169 | 现在你访问
170 |
171 | ~~~
172 | http://thinkphp.test
173 | http://thinkphp.test/help
174 | http://thinkphp.test/about
175 | ~~~
176 |
177 | 那对应就会显示 主页、帮助、关于。
178 |
179 | ## 渲染视图
180 | > 我们在前面的内容中已经学习了 在控制器中响应视图、在路由中响应视图, 现在只需要将 `return ''` 改为 `return view()` 即可
181 |
182 | 现在来创建模板,路径:`application/welcome/view/index`,分别创建:
183 | * home.html
184 | * help.html
185 | * about.html
186 |
187 | ~~~~
188 | application/welcome/view/index/home.html
189 |
190 |
191 |
192 | thinkphp.test
193 |
194 |
195 | 主页
196 |
197 |
198 | ~~~~
199 |
200 | ~~~~
201 | application/welcome/view/index/help.html
202 |
203 |
204 |
205 | thinkphp.test
206 |
207 |
208 | 帮助
209 |
210 |
211 | ~~~~
212 |
213 | ~~~~
214 | application/welcome/view/index/about.html
215 |
216 |
217 |
218 | thinkphp.test
219 |
220 |
221 | 关于
222 |
223 |
224 | ~~~~
225 |
226 | 这时候再刷新浏览器,响应的就是视图文件了。
227 |
228 | ## 公共视图
229 | >如果我们每次都在模板中写入完整且重复的语句,那样的工作量是巨大且低维护性的,那么现在就需要将视图的公共部分拆分出来。
230 |
231 | 1. 现在请创建一个公共模板的文件夹:`application/welcome/view/_layout`
232 | 2. 并在该目录下创建一个 `default.html` 的文件并写入
233 |
234 | ~~~~
235 |
236 |
237 |
238 | thinkphp.test
239 |
240 |
241 | {block name="content"}正文{/block}
242 |
243 |
244 | ~~~~
245 |
246 | 然后点开 `home.html`,将内容修改为:
247 |
248 | ~~~~
249 | {extend name="_layout/default" /}
250 | {block name="content"}
251 | 主页
252 | {/block}
253 | ~~~~
254 |
255 | 其他两个页面也像这样修改,只是 content 里的文字变化一下。
256 | 修改完成后,刷新浏览器,现在模板成功的继承并且输出了!
--------------------------------------------------------------------------------
/3.3Think命令.md:
--------------------------------------------------------------------------------
1 | # Think 命令
2 | >Think 命令是 ThinkPHP 出品的一款控制台程序,包括不限于进行 生成模块、创建类库、清除缓存、生成缓存、创建模型等操作。
3 |
4 | 以后的章节所有能够使用命令行的都不再手动创建文件。
5 | 详细文档请参考: https://www.kancloud.cn/manual/thinkphp5_1/354138
--------------------------------------------------------------------------------
/3.4小结.md:
--------------------------------------------------------------------------------
1 | # 小结
2 |
3 | 本章为大家介绍了路由的一些基本操作,控制器对视图文件的控制以及视图的继承,也了解到了 Think 命令,我们将在下一章优化应用样式。
4 |
5 | ## 同步代码
6 |
7 | 别忘了 Git 这个工具,按下 Ctrl+Shift+G,键入更新的消息之后点击提交,并在多选栏中选择 推送到,进入 GitHub 查看线上代码是否同步
--------------------------------------------------------------------------------
/4.1章节说明.md:
--------------------------------------------------------------------------------
1 | # 章节说明
2 | > 请使用 VScode 打开 第三章 创建的应用,本章的内容基于上一章节
3 |
4 | 本章将优化第三章创建的页面样式,为之后的开发做准备。
--------------------------------------------------------------------------------
/4.2样式美化.md:
--------------------------------------------------------------------------------
1 | # 使用 Blade 模板
2 |
3 | > Blade 是构建 Laravel 应用所创建的一套模板引擎,众所周知,Laravel 的开发以优雅为名, 我们现在将使用 Blade 进行 ThinkPHP 视图页面的优雅开发。
4 |
5 | 你可以在 Laravel 中文文档: https://laravel-china.org/docs/laravel/5.7/blade/ 查看详细的语法解释
6 |
7 | ## 安装 Blade
8 |
9 | 请按下 Ctrl+Shift+` (请确保在网站根目录 thinkphp.test) 并切换到终端 , 并键入命令:
10 | `composer require luoyy/think-blade`
11 |
12 | 进入 `config/template` , 将 return 里的内容进行替换:
13 |
14 | ~~~~ config
15 | // 模板引擎类型
16 | 'type' => 'Blade',
17 | // 视图基础目录(集中式)
18 | 'view_base' => '',
19 | // 模板起始路径
20 | 'view_path' => '',
21 | // 模板文件名分隔符
22 | 'view_depr' => DIRECTORY_SEPARATOR,
23 | // 模板文件后缀
24 | 'view_suffix' => 'blade.php',
25 | 'cache' => [
26 | 'cache_subdir' => false,
27 | 'prefix' => '',
28 | ],
29 | 'tpl_replace_string' => [],
30 | ~~~~
31 |
32 | 进入到上一章所编写的视图层目录 `application/welcome/view`,将所有 `.html` 后缀修改为 `.blade.php`
33 |
34 | ## 测试 blade
35 |
36 | 打开视图层的 `application/welcome/view/index/home.blade.php` 并删除全部内容,键入 {{ time() }}
37 | 进入 `http://thinkphp.test` 若出现 一长串 时间戳,则表示 Blade 模板安装成功.
38 |
39 | ## 重写视图
40 |
41 | >请删除所有视图页面的内容
42 |
43 | 在 `/public/static` 下增加 `/css/app.css`, `/js/app.js`, 并更改 `default.blade.php`
44 |
45 | ~~~~ blade
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | @yield('title') -- ThinkPHP 入门教程
56 |
58 |
59 |
60 |
61 |
90 |
91 | @yield('content')
92 |
93 |
95 |
97 |
99 |
100 |
101 |
102 | ~~~~
103 |
104 | 看到代码顶部的 `@yield('title')` 指令是用来显示指定部分的内容.
105 | 同样的,我们在模板继承 `default.blade.php` 之后,只需要使用 `@section('title)` 即可继承并使用.
106 | 找到视图路径 `view/index`, 将下面的模板文件统一加上代码:
107 |
108 | ~~~~ blade
109 | @extends('_layout.default')
110 | // 对应继承路径:_layout/default.blade.php
111 | ~~~~
112 |
113 | `@extends` 指继承整个模板文件,而在 `Blade` 中,我们不再使用 `/` 来分割路径,而是使用 `.`
114 | 接着,打开 `home.blade.php`, 我们添加一些欢迎界面.
115 |
116 | ~~~~ blade
117 | @extends('_layout.default')
118 | @section('title', '主页')
119 | @section('content')
120 |
121 |
122 |
欢迎你,我的朋友
123 |
124 |
125 | @stop
126 | ~~~~
127 |
128 | 访问 `http://thinkphp.test`, 一个全新的欢迎页面呈现在眼前.
--------------------------------------------------------------------------------
/4.3局部视图.md:
--------------------------------------------------------------------------------
1 | # 局部视图
2 |
3 | 回到 `default.blade.php`, 如果将所有代码都堆积到 `default.blade.php`, 可读性会变得极差,并且为以后的维护增加阻碍. 所以我们需要将 `header` 单独拆分,成为一个独立的模板文件.
4 |
5 | ## 头部视图
6 |
7 | 在 `view/_layout` 下创建 `header.blade.php` 和 `footer.blade.php`
8 | 并将 `default.blade.php` 文件中 `` `` 的内容全部剪切到 `header.blade.php` `footer.blade.php`
9 | 将 `default.blade.php` 中 `
` 替换为:
10 |
11 | ~~~~ blade
12 | @include('_layout.header')
13 |
14 | @yield('content')
15 |
16 | @include('_layout.footer')
17 | ~~~~
18 |
19 | `@include` 是 `Blade` 模板引擎中视图引用方法.
--------------------------------------------------------------------------------
/4.4路由链接.md:
--------------------------------------------------------------------------------
1 | # 路由链接
2 |
3 | 请打开 `view/_layout/header.blade.php`
4 | 我们找到 `a` 标签中的 `href=""`, `href=""` 中的地址就是用户点击后跳转的地址.
5 | 现在给对应的 主页、帮助、关于添上相应的链接:
6 |
7 | ~~~~ blade
8 | href="/"
9 | href="/help"
10 | href="/about"
11 | ~~~~
12 |
13 | 现在我们访问 `http://thinkphp.test` 点击顶部栏的文字就可以访问到对应的地址了.
14 | 可是有一个问题,如果我们更改了路由中的链接,那么模板中的所有地址也要一一修改,这在一个大型项目中是不允许出现的,所以使用 `URL 生成`,就能很好的解决这个问题.
15 |
16 | ## URL 生成
17 |
18 | 找到上面修改的链接,分别更改为:
19 |
20 | ~~~~ blade
21 | {{ url('welcome/index/home') }}
22 | {{ url('welcome/index/help') }}
23 | {{ url('welcome/index/about') }}
24 | ~~~~
--------------------------------------------------------------------------------
/4.5用户注册页面.md:
--------------------------------------------------------------------------------
1 | # 注册路由
2 |
3 | > 本章只是书写前端的静态页面,不涉及数据库操作
4 | 打开 `route/router.php`,添加
5 |
6 | ~~~~ php
7 | Route::get('/signup', 'user/auth/create');
8 | ~~~~
9 |
10 | 现在我们要创建一个单独的 user 模块来处理用户功能,而 auth 控制器则集中处理验证方面的问题.
11 |
12 | ## 生成控制器
13 |
14 | 请按下 Ctrl+Shift+` 并切换到终端
15 | 使用 Think 命令来生成控制器:
16 |
17 | ~~~~ shell
18 | // 默认生成 资源控制器
19 | php think make:controller user/Auth
20 | ~~~~
21 |
22 | 打开 `application/user/Auth.php`,并找到 `create()` 方法,键入:
23 |
24 | ~~~~ php
25 | return view();
26 | ~~~~
27 |
28 | 现在再创建一个视图文件:`application/user/view/auth/create.blade.php`,如果你不清楚路径为什么会这样,请回到本书 3.2 静态页面 仔细阅读.
29 |
30 | ~~~~ blade
31 | @extends('_layout.default')
32 | @section('title', '注册')
33 | @section('content')
34 |
39 | @stop
40 | ~~~~
41 |
42 | 并且把 `welcome/view/_layout` 文件夹复制到 `user/view/`
43 | 现在按下 `Ctrl+Shift+F`,并在第一个框中填写:`注册`
44 | 第二个框中填写 `注册`
45 | 然后点击框框右边的按钮进行全局替换并保存.
--------------------------------------------------------------------------------
/4.6集中视图.md:
--------------------------------------------------------------------------------
1 | # 集中视图
2 |
3 | > 在 4.5 小节中我们复制了一遍 _layout 文件夹,这样做对开发其实是百害无一利的,我们现在设置 模板配置文件 让视图单独的保存起来。
4 |
5 | ## 修改配置
6 |
7 | 进入 `/app/config/template.php` 修改代码
8 |
9 | ~~~~ php
10 | // 视图基础目录(集中式)
11 | ~'view_base' => '',~
12 | 'view_base' => Env::get('ROOT_PATH') . 'resources' . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR,
13 | // 模板起始路径
14 | ~'view_path' => '',~
15 | 'view_path' => Env::get('ROOT_PATH') . 'resources' . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR
16 | ~~~~
17 |
18 | ## 增加目录
19 |
20 | 创建文件夹 `/resources/views/`
21 | 并在 `views` 目录下创建文件 `_layout` 和 `welcome/index` 复制先前在模块 `view` 中创建的文件到以上目录就行,完成后删除前面章节提到的所有在模块下创建的 `view` 文件.
22 |
23 | 目录结构如图所示:
24 | 
25 |
26 | 现在打开浏览器,进入 `http://thinkphp.test`,看看是否正常输出了.
--------------------------------------------------------------------------------
/4.7小结.md:
--------------------------------------------------------------------------------
1 | # 小结
2 |
3 | 本章使用 `Composer` 安装了第一个模板扩展,同时在模板的基础上学习了 继承、链接优化 等操作,并使用命令行创建控制器,下一章将开始使用模型创建连接数据库开发用户逻辑功能.
4 |
5 | ## 同步代码
6 |
7 | 别忘了 `Git` 这个工具,按下 `Ctrl+Shift+G`,键入更新的消息之后点击提交,并在多选栏中选择 推送到,进入 `GitHub` 查看线上代码是否同步.
--------------------------------------------------------------------------------
/5.1章节说明.md:
--------------------------------------------------------------------------------
1 | # 章节说明
2 |
3 | >请使用 VScode 打开 第四章 创建的应用,本章的内容基于上一章节.
4 |
5 | 在前几个章节的开发中,我们只用到了 `MVC` 中的 `VC`,也就是 `控制器-视图`,没有提到 `M-Model(模型)`,本章我们将构建一个基本的 用户模型来实现用户数据的操作,并了解 `ThinkPHP` 如何进行 `CRUD`.在后面的开发中我们还会加上用户注册和登录功能,并进行权限验证,接着我们将通过邮件发送构建最后的激活和找回功能.
--------------------------------------------------------------------------------
/5.2数据库迁移.md:
--------------------------------------------------------------------------------
1 | # 数据库迁移
2 |
3 | 在 `ThinkPHP` 中,我们使用 `think-migration` 管理数据表结构,你可以把他看作是在数据库中的版本控制,我们使用该工具每次的操作都会有详细的时间进行记录,同样的,也可以无缝回滚或者修改.
4 |
5 | ## 迁移的好处
6 |
7 | * 协同开发避免出错
8 | * 数据表版本控制
9 | * 部署简单方便
10 |
11 | ## 安装 think-migration
12 |
13 | 请按下 Ctrl+Shift+` 并切换到终端(请确保在网站根目录 thinkphp.test).
14 | 我们将使用 `Composer` 引入扩展 `think-migration`,键入命令:
15 |
16 | ~~~~ shell
17 | composer require topthink/think-migration
18 | ~~~~
19 |
20 | ## 使用 think-migration
21 |
22 | ~~~~ shell
23 | /* 创建迁移表 */
24 | php think migrate:create Users
25 |
26 | /* 弹出提示:Create migrations directory?[是否创建新目录?] */
27 | 键入:y
28 | ~~~~
29 |
30 | 这时候看到根目录,程序为我们创建了一个 `database/migrations` 的目录,并且创建了一个以时间戳开头的 User 文件.
31 | 进入创建好的 User 文件,修改代码:
32 |
33 | ~~~~ php
34 | use think\migration\Migrator;
35 | use think\migration\db\Column;
36 | class Users extends Migrator
37 | {
38 | /**
39 | * Migrate Up.
40 | */
41 | public function up()
42 | {
43 | // create the table
44 | $table = $this->table('users');
45 | $table->addColumn('name', 'string')
46 | ->addColumn('email', 'string')
47 | ->addColumn('password', 'string')
48 | ->addColumn('avatar', 'string', ['null' => true, 'default'=>NULL, 'comment'=>'用户头像'])
49 | ->addColumn('god', 'boolean', ['default'=>FALSE, 'comment'=>'管理员'])
50 | ->addTimestamps('created_at', 'updated_at')
51 | ->addIndex('email', ['unique' => true])
52 | ->addIndex('god')
53 | ->create();
54 | }
55 | /**
56 | * Migrate Down.
57 | */
58 | public function down()
59 | {
60 | $this->dropTable('users');
61 | }
62 | }
63 | ~~~~
64 |
65 | 我们来看看这段代码干了什么:
66 |
67 | * addColumn 字面意思,添加一列.
68 | * addColumn('字段名', '值类型', '数组来表示 长度限制、默认值、注释等').
69 | * $this->dropTable 字面意思,删除表.
70 | * function up() 运行迁移时做的动作.
71 | * function down() 回滚迁移时做的动作.
72 |
73 | 详细文档请查阅:数据库迁移文档: http://docs.phinx.org/
74 |
75 | ## 运行迁移
76 |
77 | 打开 `/config/database.php` 将对应的 数据库名、密码等 填写为宝塔面板上的值,如果提示权限被拒绝,将数据库密码换成 `root` 密码.
78 | 请按下 Ctrl+Shift+` 并切换到终端(请确保在网站根目录 thinkphp.test).
79 | 键入命令:
80 |
81 | ~~~~ shell
82 | php think migrate:run
83 | ~~~~
84 |
85 | 这时候再打开 `PHPMyAdmin`,就有会看见迁移的数据表.
86 | 同样的,如果你键入命令:
87 |
88 | ~~~~ shell
89 | php think migrate:rollback
90 | ~~~~
91 |
92 | 则会回滚到上一步的操作.
--------------------------------------------------------------------------------
/5.3查看数据表.md:
--------------------------------------------------------------------------------
1 | # 章节说明
2 |
3 | 在实际的线上环境中,如果我们使用宝塔面板,`PHPMyAdmin` 是最好的选择,面板已经为我们准备好了必要的环境,我们只需要进入 `Web` 面板即可管理.
4 |
5 | 面板中数据库连接方式:
6 |
7 | * Host: 127.0.0.1
8 | * Port: 3306
9 | * database_name: 创建的表名
10 | * database_password: 对应表的密码
11 |
12 | ## PHPMyAdmin 的使用
13 |
14 | 进入 `PHPMyAdmin` 也是非常简单的,只需要进入 `宝塔 Web 面板-> 数据库-> PHPMyAdmin` 即可
15 | 之后,我们再选择对应的数据表,即可看到上一节迁移的结构.
16 | 如果你运行命令再刷新表,此时结构就已经回滚.
17 |
18 | ~~~~ shell
19 | /* 回滚 */
20 | php think migrate:rollback
21 |
22 | /* 迁移 */
23 | php think migrate:run
24 | ~~~~
--------------------------------------------------------------------------------
/5.4模型文件.md:
--------------------------------------------------------------------------------
1 | # 模型
2 |
3 | >模型(Model) - 程序员编写程序应有的功能(实现算法等等)、数据库专家进行数据管理和数据库设计(可以实现具体的功能).
4 |
5 | 在 `MVC` 组件的互动中,
6 | `模型(Model)` 用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。`Model` 有对数据直接访问的权力,例如对数据库的访问。 `Model` 不依赖 `View` 和 `Controller`,也就是说, `Model` 不关心它会被如何显示或是如何被操作. 但是 `Model` 中数据的变化一般会通过一种刷新机制被公布。为了实现这种机制,那些用于监视此 `Model` 的 `View` 必须事先在此 `Model` 上注册,从而,View 可以了解在数据 `Model` 上发生的改变。 (比较:观察者模式 (软件设计模式))
7 |
8 | 在本书中,主要使用 `Think-ORM` 与数据库进行交互.
9 |
10 | ## 创建 模型文件
11 |
12 | 键入命令:
13 |
14 | ~~~~ shell
15 | /* make:model 创建 模型文件 */
16 | php think make:model user/User
17 | ~~~~
18 |
19 | 完成后,打开新建的 模型文件 `application/user/model/User.php`:
20 | 可以看到默认生成的 模型文件 已经为我们创建好了 命令空间、继承 等操作.
21 |
22 | ## 约定成俗的 表名
23 |
24 | 在实际的模型处理当中,`Think-ORM` 会根据 模型文件名 自动找到 表名 进行操作.
25 | 默认情况下,会使用类的「下划线命名法」与「复数形式名称」来作为数据表的名称生成规则。如:
26 |
27 | * User 对应 users 表
28 | * BlogList 对应 blog_list 表
29 |
30 | 因此 `Think-ORM` 将会假设模型储存在对应的表中,如果你需要手动指定数据表,可以通过 `$table` 来指定:
31 |
32 | ~~~~ php
33 | /* 指定 auths 表 */
34 | protected $table = 'auths';
35 | ~~~~
36 |
37 | ## 约定编程
38 |
39 | >约定编程(convention over configuration),是一种软件设计范式,旨在减少软件开发人员需做决定的数量,获得简单的好处,而又不失灵活性.
40 |
41 | 本质是说,开发人员仅需规定应用中不符约定的部分。例如,如果模型中有个名为 `Sale` 的类,那么数据库中对应的表就会默认命名为 `sales`,只有在偏离这一约定时,例如将该表命名为 `products_sold`, 才需写有关这个名字的配置.
42 | 如果您所用工具的约定与你的期待相符,便可省去配置;反之,你可以配置来达到你所期待的方式.
--------------------------------------------------------------------------------
/5.5小结.md:
--------------------------------------------------------------------------------
1 | # 小结
2 |
3 | 通过本章,我们学习到:
4 |
5 | * 模型的创建与 「约定成俗」 的软件设计模式
6 | * 数据库迁移的创建、数据表生成、数据表回滚
7 |
8 | ## 同步代码
9 |
10 | 别忘了 `Git` 这个工具,按下 `Ctrl+Shift+G`,键入更新的消息之后点击提交,并在多选栏中选择 推送到,进入 `GitHub` 查看线上代码是否同步.
--------------------------------------------------------------------------------
/6.1章节说明.md:
--------------------------------------------------------------------------------
1 | # 章节说明
2 |
3 | >请使用 VScode 打开 第五章 创建的应用,本章的内容基于上一章节
4 |
5 | 本章开始,我们进入了真正的 M 层操作,我们将通过 表单提交,数据验证,数据保存 来学习到一个完整的表单及数据库操作的流程.
--------------------------------------------------------------------------------
/6.2注册表单.md:
--------------------------------------------------------------------------------
1 | # 表单构建
2 |
3 | 更改之前创建好的注册页面 `resources/views/user/auth/create.blade.php`:
4 |
5 | ~~~~ html
6 | @extends('_layout.default')
7 | @section('title', '注册')
8 | @section('content')
9 |
10 |
11 |
12 |
注册
13 |
14 |
60 |
61 |
62 | @stop
63 | ~~~~
64 |
65 | 修改控制器代码 `application/user/controller/Auth.php`:
66 |
67 | ~~~~ php
68 | public function create()
69 | {
70 | $token = $this->request->token('__token__', 'sha1');
71 | $this->assign('token', $token);
72 | return $this->fetch();
73 | }
74 | ~~~~
75 |
76 | 这一步的目的是将自定义 CSRF Token 传入模板当中.
77 |
78 | ## CSRF 防御
79 |
80 | > 跨站请求伪造(英语:Cross-site request forgery),也被称为one-click attack 或者session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的 Web 应用程序上执行非本意的操作的攻击方法. https://zh.wikipedia.org/zh/%E8%B7%A8%E7%AB%99%E8%AF%B7%E6%B1%82%E4%BC%AA%E9%80%A0
81 | > 假如一家银行用以运行转账操作的URL地址如下: `http://www.examplebank.com/withdraw?account=AccoutName&amount=1000&for=PayeeName`
82 | 那么,一个恶意攻击者可以在另一个网站上放置如下代码: `
`
83 | 如果有账户名为Alice的用户访问了恶意站点,而她之前刚访问过银行不久,登录信息尚未过期,那么她就会损失1000资金.
84 | 这种恶意的网址可以有很多种形式,藏身于网页中的许多地方.此外,攻击者也不需要控制放置恶意网址的网站.例如他可以将这种地址藏在论坛,博客等任何用户生成内容的网站中.这意味着如果服务端没有合适的防御措施的话,用户即使访问熟悉的可信网站也有受攻击的危险.
85 |
86 | ## 防御措施
87 |
88 | * 添加校验token
89 |
90 | > 由于 `CSRF` 的本质在于攻击者欺骗用户去访问自己设置的地址,所以如果要求在访问敏感数据请求时,要求用户浏览器提供不保存在 `cookie` 中,并且攻击者无法伪造的数据作为校验,那么攻击者就无法再运行 `CSRF` 攻击.这种数据通常是窗体中的一个数据项.服务器将其生成并附加在窗体中,其内容是一个伪随机数.当客户端通过窗体提交请求时,这个伪随机数也一并提交上去以供校验.正常的访问时,客户端浏览器能够正确得到并传回这个伪随机数,而通过CSRF传来的欺骗性攻击中,攻击者无从事先得知这个伪随机数的值,服务端就会因为校验 `token` 的值为空或者错误,拒绝这个可疑请求.
91 |
92 | * 检查 Referer 字段
93 |
94 | > `HTTP` 头中有一个 `Referer` 字段,这个字段用以标明请求来源于哪个地址.在处理敏感数据请求时,通常来说,`Referer` 字段应和请求的地址位于同一域名下.以上文银行操作为例,`Referer` 字段地址通常应该是转账按钮所在的网页地址,应该也位于 `www.examplebank.com` 之下.而如果是 `CSRF` 攻击传来的请求,`Referer` 字段会是包含恶意网址的地址,不会位于 `www.examplebank.com` 之下,这时候服务器就能识别出恶意的访问.
95 | 这种办法简单易行,工作量低,仅需要在关键访问处增加一步校验.但这种办法也有其局限性,因其完全依赖浏览器发送正确的 `Referer` 字段.虽然 `http` 协议对此字段的内容有明确的规定,但并无法保证来访的浏览器的具体实现,亦无法保证浏览器没有安全漏洞影响到此字段.并且也存在攻击者攻击某些浏览器,篡改其 `Referer` 字段的可能.
96 |
97 | 上面这段代码中的 `{:token()}` 是通过添加校验 `token` 来防止 `CSRF` 攻击.
--------------------------------------------------------------------------------
/6.3用户数据验证.md:
--------------------------------------------------------------------------------
1 | # 使用资源路由及控制器
2 |
3 | 修改路由路径 `route\route.php`:
4 |
5 | ~~~~ php
6 | ~Route::get('/signup', 'user/auth/create');~
7 | Route::resource('auth', 'user/auth');
8 | ~~~~
9 |
10 | 在 ThinkPHP 的资源路由解析中,以上语句表示注册了一个名称为 `auth` 的资源路由到 `user` 模块的 `auth` 控制器,实际注册的路径就是 `application\user\controller\Auth.php`.
11 |
12 | 打开 `Auth` 控制器 `application\user\controller\Auth.php`,在之前的章节中我们已经使用 `Think` 命令行来创建了一个资源控制器,可以看到系统为我们自动生成了 7个 模块,其中包括:
13 |
14 | 标识 | 请求类型 | 生成路由规则 | 对应操作方法(默认)
15 | ------------ | ------------- | ------------- | -------------
16 | index | GET | auth | index
17 | create | GET | auth/create | create
18 | save | POST | auth | save
19 | read | GET | auth/:id | read
20 | edit | GET | auth/:id/edit | edit
21 | update | PUT | auth/:id | update
22 | delete | DELETE | auth/:id | delete
23 |
24 | 可以看到,我们在表单注册页面的 `URL`路径是 `http://thinkphp.test/user/auth/create.html`.
25 | 在 6.2 章节中我们写入的 HTML 代码 `
174 | @endif
175 | ...
176 | ~~~
177 |
178 | 这时候重新注册一个没有管理员权限的账号,访问 http://thinkphp.test/user/auth/index 就不会看到有任何的删除按钮了,下面来编写删除功能。
179 | `application\user\controller\Auth.php`
180 |
181 | ~~~php
182 | ...
183 | public function delete($id)
184 | {
185 | User::where('id', $id)->where('god', false)->delete();
186 | return redirect('user/auth/index');
187 | }
188 | ...
189 | ~~~
190 |
191 | 请注意,我们在删除语句中添加了一句 `where('god', false)`,这是因为管理员不能够删除自己。
192 | 刷新页面,点击删除按钮,却被提示 `非法操作`,这是因为在 `UserPolicy` 的策略中,我们判断当前登入用户必须要和传入用户一致才能够进行下一步操作,现在来修改中间件。
193 | `application\http\middleware\UserAuthorize.php`
194 |
195 | ~~~php
196 | id);
213 | return
214 | $result
215 | ? $next($request)
216 | : $this->redirect();
217 | }
218 |
219 | private function redirect()
220 | {
221 | return redirect('user/session/create')->with('validate', '非法操作');
222 | }
223 | }
224 | ~~~
225 |
226 | 上述代码中,当我们判断到当前登入用户是管理员时,即可直接返回下一步,即管理员拥有超级权限。
227 | 再刷新页面并点击删除按钮,现在如愿以偿的工作了。
--------------------------------------------------------------------------------
/8.7访客模式.md:
--------------------------------------------------------------------------------
1 | # 访客模式
2 |
3 | 在前面几节的中间件策略中,我们始终没有放开 `Auth/@index` 的访客访问,在未登录的情况下,直接访问将会跳转到登录页面,并且已登录用户无法浏览其他用户的页面,接下来的步骤将会解决这个问题。
4 |
5 | ## 放开权限
6 |
7 | 由于在控制器中多个方法都被中间件拦截,现在重新编辑
8 | `application\user\controller\Auth.php`
9 |
10 | ~~~php
11 | ...
12 | protected $middleware = [
13 | 'UserAuthorize' => [
14 | 'except' => [
15 | 'create',
16 | 'save',
17 | 'index',
18 | 'read'
19 | ]
20 | ],
21 | ...
22 | ~~~
23 |
24 | 退出登录后再次访问 http://thinkphp.test/user/auth/index ,即可看到所有用户的列表,然后我们随意点击一个用户的名字,发现页面中出现 `欢迎您` 的字样和 `编辑资料` 按钮,这是访客模式不可见的,现在我们需要一一解决。
25 |
26 | ## 判断访客
27 |
28 | 访客分为两种:
29 | 1. 未登录用户
30 | 2. 已登录用户访问其他用户页面
31 |
32 | 非常简单的,虽然拥有两种状态,但是我们只需要在控制器中传入 `Session` 即可判断。
33 | `application\user\controller\Auth.php`
34 |
35 | ~~~php
36 | public function read($id)
37 | {
38 | $user = User::find($id);
39 | $this->assign([
40 | 'user' => $user,
41 | 'session' => Session::get('user')
42 | ]);
43 | return $this->fetch();
44 | }
45 | ~~~
46 |
47 | 再编辑前端页面
48 | `resources\views\user\auth\read.blade.php`
49 |
50 | ~~~html
51 | @extends('_layout.default')
52 | @section('title', $user->name)
53 | @section('content')
54 |
55 |
56 |
57 |
58 | @if(!is_null($session) && $session->id === $user->id)
59 |
60 | 编辑资料
61 |
62 | 欢迎您
63 | @else
64 | 您正在查看
65 | @endif
66 | {{ $user->name }}
67 |
68 |
69 |
70 |
71 | @stop
72 | ~~~
73 |
74 | 现在用不登录和登录状态随意访问其他用户的页面,可以看到以上问题均解决了。
75 | 在上一节添加删除按钮的时候,我们删除逻辑中排除了管理员自己删除自己,现在需要在前端页面中移除这个按钮。
76 | `resources\views\user\auth\index.blade.php`
77 |
78 | ~~~html
79 | @if ($god && !$user->god)
80 |
85 | @endif
86 | ~~~
87 |
88 | 非常简单的,只需要判断循环列表的用户 `god` 属性就行。
89 | 使用管理员登录并访问所有用户页面,可以看到所有是管理员的删除按钮全部消失了。
--------------------------------------------------------------------------------
/8.8优化前端.md:
--------------------------------------------------------------------------------
1 | # 优化前端
2 |
3 | 本章的后端逻辑代码到这里就结束了,现在的前端页面不难看,但是也不好看,由于我们是要打造一款类似微博功能的网站,恰好今日看到 twitter 更新了 UI,布局简洁值得模仿,由下图为例,我们尽可能的还原 twitter。
4 |
5 | 
6 |
7 | ## 整体布局
8 |
9 | 由于上图中的布局呈 左-中-右 的形式,所以我们需要把默认布局更改为三栏。
10 | `resources\views\_layout\default.blade.php`
11 |
12 | ~~~html
13 | ...
14 |
15 |
16 |
17 |
18 | @include('_layout.header')
19 |
20 |
21 |
22 | -
23 |
24 | «
25 |
26 | @yield('title')
27 |
28 | -
29 | @yield('content')
30 |
31 |
32 |
33 |
34 | @include('_layout.footer')
35 |
36 |
37 |
38 | ...
39 | ~~~
40 |
41 | 修改侧栏布局
42 | `resources\views\_layout\header.blade.php`
43 |
44 | ~~~html
45 |
89 | ~~~
90 |
91 | 创建样式表文件
92 | `public\static\css\app.css`
93 |
94 | ~~~css
95 | .pagination li:first-child {
96 | margin-left: 0;
97 | border-top-left-radius: 0.25rem;
98 | border-bottom-left-radius: 0.25rem;
99 | }
100 |
101 | .pagination li {
102 | position: relative;
103 | display: block;
104 | padding: 0.5rem 0.75rem;
105 | margin-left: -1px;
106 | line-height: 1.25;
107 | color: #007bff;
108 | background-color: #fff;
109 | border: 1px solid #dee2e6;
110 | }
111 | ~~~
112 |
113 | 全部保存后,刷新页面,可以看到整体的布局已经非常接近了,细节方面存在瑕疵,我们将会在后面的章节中持续优化。
--------------------------------------------------------------------------------
/8.9小结.md:
--------------------------------------------------------------------------------
1 | # 小结
2 |
3 | 通过本章,我们学习到:
4 |
5 | * 游客与管理员权限控制
6 | * 基本的增删查改
7 | * 更好看的前端页面
8 |
9 | ## 同步代码
10 |
11 | 别忘了 `Git` 这个工具,按下 `Ctrl+Shift+G`,键入更新的消息之后点击提交,并在多选栏中选择 推送到,进入 `GitHub` 查看线上代码是否同步.
--------------------------------------------------------------------------------
/9.1章节说明.md:
--------------------------------------------------------------------------------
1 | # 章节说明
2 |
3 | >请使用 VScode 打开 第八章 创建的应用,本章的内容基于上一章节
4 |
5 | 本章将正式进入关系流模型的操作,主要实现微博模型的多对多增删查改等功能。
--------------------------------------------------------------------------------
/9.2微博模型.md:
--------------------------------------------------------------------------------
1 | # 微博模型
2 |
3 | 和之前创建 User 模型的步骤一致,我们需要
4 | 1. 创建数据表 Posts
5 | 2. 建立微博模型 PostModel
6 |
7 | ## 创建数据表
8 |
9 | 打开命令行,键入命令并打开
10 | `php think migrate:create Posts`
11 |
12 | `database\migrations\20190728094237_posts.php`
13 |
14 | ~~~php
15 | table('posts');
28 | $table->addColumn('content', 'text')
29 | ->addColumn('user_id', 'integer')
30 | ->addTimestamps('created_at', 'updated_at')
31 | ->create();
32 | }
33 | /**
34 | * Migrate Down.
35 | */
36 | public function down()
37 | {
38 | $this->dropTable('posts');
39 | }
40 | }
41 | ~~~
42 |
43 | 运行命令 `php think migrate:run`
44 | 其中,`user_id` 是为了和 `User` 表中的 `id` 字段关联,当我们创建关系模型时,只用一个 `id` 即可读取该用户发送过的所有推文。
45 |
46 | ## 创建微博模型
47 |
48 | 和之前一致,只用在控制台中键入命令
49 | `php think make:model User/Post`
50 | 创建完成后并打开文件
51 | `application\user\model\Post.php`
52 |
53 | ~~~php
54 | hasMany('Post', 'user_id');
98 | }
99 | ...
100 | ~~~
101 |
102 | 定义反向关联
103 | `application\user\model\Post.php`
104 |
105 | ~~~php
106 | belongsTo('User');
114 | }
115 | ...
116 | ~~~
117 |
118 | 非常简单的,两个关联操作已经定义,下一节将展示出关联数据。
--------------------------------------------------------------------------------
/9.3显示微博.md:
--------------------------------------------------------------------------------
1 | # 显示微博
2 |
3 | 本节将为每个人显示自己发布的微博。
4 |
5 | ## 关联查询
6 |
7 | 在上一节中,我们定义了
8 |
9 | ~~~php
10 | // 正向关联 Post 模型
11 | public function posts()
12 | {
13 | return $this->hasMany('Post', 'user_id');
14 | }
15 | ~~~
16 |
17 | 非常简单的,在控制器中只需要多加一句 `with('posts')` 即可展示该用户的所有微博
18 | `application\user\controller\Auth.php`
19 |
20 | ~~~php
21 | public function read($id)
22 | {
23 | $user = User::with('posts')->find($id);
24 | return $user;
25 | }
26 | ~~~
27 |
28 | 接着,访问 http://thinkphp.test/user/auth/read/id/1.html ,可以看到一行 `"posts":[]`
29 | 这是因为现在 `posts` 表中还未有数据,我们需要为用户填充一些假数据。
30 |
31 | 命令行键入 `php think seed:create Posts`
32 | `database\seeds\Posts.php`
33 |
34 | ~~~php
35 | $faker->text,
50 | 'user_id' => $user_id,
51 | ];
52 | }
53 |
54 | $this->table('posts')->insert($data)->save();
55 | }
56 | }
57 | ~~~
58 |
59 | 上面代码中,`$i % 2` 表示能否被 2 整除。
60 | 创建完毕后运行 `php think seed:run` 再次访问 http://thinkphp.test/user/auth/read/id/1.html 就可以看到刚刚装填好的假数据了。
61 |
62 | ## 前端显示
63 |
64 | 现在数据库中已经有填充好的假数据,我们只需要在前端中输出即可。
65 | `application\user\controller\Auth.php`
66 |
67 | ~~~php
68 | public function read($id)
69 | {
70 | $user = User::with(['posts' => function ($query) {
71 | $query->limit(8);
72 | $query->order('created_at', 'desc');
73 | }])->find($id);
74 | $this->assign([
75 | 'user' => $user,
76 | 'session' => Session::get('user')
77 | ]);
78 | return $this->fetch();
79 | }
80 | ~~~
81 |
82 | 注意,`with(['posts' => function ($query)` 是一个闭包操作,下面的 `limit` 等语句都是针对关联模型 `posts` 操作而不是 `User`
83 |
84 | 切换到前端页面
85 | `resources\views\user\auth\read.blade.php`
86 |
87 | ~~~html
88 | @extends('_layout.default')
89 | @section('title', $user->name)
90 | @section('content')
91 |
92 |
93 |
94 | @if(!is_null($session) && $session->id === $user->id)
95 |
96 | 编辑资料
97 |
98 | 欢迎您
99 | @else
100 | 您正在查看
101 | @endif
102 | {{ $user->name }}
103 |
104 |
105 | @foreach ($user->posts as $post)
106 |
107 |
108 | {{ $post->content }}
109 |
110 | {{ $post->created_at }}
111 |
112 | @endforeach
113 |
114 | @stop
115 | ~~~
116 |
117 | 再次访问 http://thinkphp.test/user/auth/read/id/1.html 即可看到前端内容完整的被渲染出来了。
--------------------------------------------------------------------------------
/9.4发布微博.md:
--------------------------------------------------------------------------------
1 | # 发布微博
2 |
3 | 微博的创建与删除原理和用户的相关操作是一样的,只不过把对象换成了微博而已
4 |
5 | ## 微博控制器
6 |
7 | 现在来创建一个微博相关的控制器。
8 | 打开命令行并键入: `php think make:controller user/Post --plain`
9 | `--plain` 表示生成一个空控制器。
10 | `application\user\controller\Post.php`
11 |
12 | ~~~php
13 | [
25 | 'only' => [
26 | 'save',
27 | ]
28 | ]
29 | ];
30 |
31 | public function save(Request $request)
32 | {
33 | PostModel::create([
34 | 'content' => $request->content,
35 | 'user_id' => session('user.id')
36 | ]);
37 | return redirect('/');
38 | }
39 | }
40 | ~~~
41 |
42 | 虽然我们还未创建前端页面,但是能够从基本的发布流程中来编写后端逻辑,现在来编辑页面。
43 | `resources\views\welcome\index\home.blade.php`
44 |
45 | ~~~html
46 | @extends('_layout.default')
47 | @section('title', '主页')
48 | @section('content')
49 |
50 |
61 |
62 | @stop
63 | ~~~
64 |
65 | 现在访问主页:http://thinkphp.test ,即可看到输入框,可是现在路由还未绑定,编辑路由。
66 | `route\route.php`
67 |
68 | ~~~php
69 | ...
70 | Route::resource('post', 'user/post')->only(['save']);
71 | ...
72 | ~~~
73 |
74 | 需要注意的是,后面的 `->only` 表示只通过控制器的某一个方法。
75 | 再次访问:http://thinkphp.test 并在输入框内输入一些内容点击发布,正常跳转。
76 | 访问个人资料页面:http://thinkphp.test/user/auth/read/id/1.html 就能够看到刚刚发布的内容了。
--------------------------------------------------------------------------------
/9.5微博数据流.md:
--------------------------------------------------------------------------------
1 | # 微博数据流
2 |
3 | 上一节中,我们虽然创建了发布微博的功能,可是发布之后并不能实时的看到自己发布的内容,也无法在首页看到大家发布的内容,所以本节将会在首页添加微博动态的功能。
4 |
5 | ## 读取微博表
6 |
7 | 要获取整个微博的内容,非常简单的,我们只需要读取微博表并倒序即可。
8 | `application\welcome\controller\Index.php`
9 |
10 | ~~~php
11 | assign([
23 | 'posts' => Post::with('user')->order('created_at', 'desc')->paginate(20)
24 | ]);
25 | return $this->fetch();
26 | }
27 | ...
28 | }
29 | ~~~
30 |
31 | 编辑前端页面
32 | `resources\views\welcome\index\home.blade.php`
33 |
34 | ~~~html
35 | ...
36 |
37 |
38 | @foreach ($posts as $post)
39 |
40 |
41 | {{ $post->user->name }} -- {{ $post->created_at }}
42 |
43 |
44 | {{ $post->content }}
45 |
46 |
47 | @endforeach
48 |
49 |
50 | {!! $posts !!}
51 |
52 | @stop
53 | ...
54 | ~~~
55 |
56 | 再次访问首页,即可看到所有微博已经呈现出来。
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 介绍
2 |
3 | > 本书籍在看云及其他平台完全停止更新,最新内容请前往 https://heroui.net/ 查看
4 | > 本书籍源码请前往
5 | > https://github.com/AGDholo/hero
6 | > https://github.com/AGDholo/hero/tree/master/docs/thinkphp5.1
7 | 本书将教你使用现代工具流构建一个类似微博的应用。
8 |
9 | 通过本书,你将会学到如 HTML、CSS、JavaScript、PHP、ThinkPHP 等 Web 开发的相关基础知识。
10 |
11 | 除此之外,编辑器使用、开发环境搭建、Git、Composer、Bootstrap 前端框架在本书中也会使用, 本书代码严格 PSR 规范编写,使用这些知识将会为你以后的 Web 开发生涯奠定结实的基础,无论在大型项目或是个人练手作品都能有一个好的开发习惯和规范。
12 |
13 | ## 浏览须知
14 |
15 | 这是 ThinkPHP 5.1 教程 - Web 入门开发实战 书籍内容
16 | > 本书籍在看云及其他平台完全停止更新,最新内容请前往 https://heroui.net/ 查看
17 | > 本书籍源码请前往
18 | > https://github.com/AGDholo/hero
19 | > https://github.com/AGDholo/hero/tree/master/docs/thinkphp5.1
20 |
21 | ## 安全提示
22 | PHP 7.1 在 2020-01-01 将正式停止维护,请开发时不要使用老版本的 PHP.
23 | 请运行命令 composer update 将 ThinkPHP 框架更新至最新版本.
24 |
25 | ## 赞助项目
26 |
27 | ThinkPHP 5.1 教程 - Web 入门开发实战 是一个为了解决大多数新手开发者入门难,编写不规范等问题的入门教程书籍, 由 EpicLearn 发起. 如果您有兴趣支持此项目,请考虑成为赞助人.
28 |
29 | ## 感谢
30 |
31 | 文档样式基于 Markdown.Lite: https://www.kancloud.cn/epiclearn/markdown 进行构建
32 |
33 | ## 社区支持
34 |
35 | 在 [EpicLearn QQ 群](https://jq.qq.com/?_wv=1027&k=5T19zAw) 进行讨论反馈
36 |
37 | ## 贡献
38 |
39 | 本书内容托管地址: [ThinkPHP5.1-Web-Actual-combat](https://github.com/EpicLearn/ThinkPHP5.1-Web-Actual-combat)
40 |
41 | 本书源码托管地址: [ThinkPHP5.1-Web-Actual-combat-code](https://github.com/EpicLearn/ThinkPHP5.1-Web-Actual-combat-code)
42 | ### License
43 |
44 | 
本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。
45 |
--------------------------------------------------------------------------------
/SUMMARY.md:
--------------------------------------------------------------------------------
1 | * [第一章. 基础信息](第一章.基础信息.md)
2 | * [1.1 序言](1.1序言.md)
3 | * [1.2 关于作者](1.2关于作者.md)
4 | * [1.3 本书源码](1.3本书源码.md)
5 | * [1.4 反馈纠错](1.4反馈纠错.md)
6 | * [1.5 安全指南](1.5安全指南.md)
7 | * [1.6 捐助作者](1.6捐助作者.md)
8 | * [第二章. 开发环境布置](第二章.开发环境布置.md)
9 | * [2.1 编辑器选用](2.1编辑器选用.md)
10 | * [2.2 命令行工具](2.2命令行工具.md)
11 | * [2.3 开发环境搭建](2.3开发环境搭建.md)
12 | * [2.4 浏览器选择](2.4浏览器选择.md)
13 | * [2.5 第一个应用](2.5第一个应用.md)
14 | * [2.6 Git 工作流](2.6Git工作流.md)
15 | * [第三章. 构建页面](第三章.构建页面.md)
16 | * [3.1 章节说明](3.1章节说明.md)
17 | * [3.2 静态页面](3.2静态页面.md)
18 | * [3.3 Think 命令](3.3Think命令.md)
19 | * [3.4 小结](3.4小结.md)
20 | * [第四章. 优化页面](第四章.优化页面.md)
21 | * [4.1 章节说明](4.1章节说明.md)
22 | * [4.2 样式美化](4.2样式美化.md)
23 | * [4.3 局部视图](4.3局部视图.md)
24 | * [4.4 路由链接](4.4路由链接.md)
25 | * [4.5 用户注册页面](4.5用户注册页面.md)
26 | * [4.6 集中视图](4.6集中视图.md)
27 | * [4.7 小结](4.7小结.md)
28 | * [第五章. 用户模型](第五章.用户模型.md)
29 | * [5.1 章节说明](5.1章节说明.md)
30 | * [5.2 数据库迁移](5.2数据库迁移.md)
31 | * [5.3 查看数据表](5.3查看数据表.md)
32 | * [5.4 模型文件](5.4模型文件.md)
33 | * [5.5 小结](5.5小结.md)
34 | * [第六章. 用户注册](第六章.用户注册.md)
35 | * [6.1 章节说明](6.1章节说明.md)
36 | * [6.2 注册表单](6.2注册表单.md)
37 | * [6.3 用户数据验证](6.3用户数据验证.md)
38 | * [6.4 注册失败错误信息](6.4注册失败错误信息.md)
39 | * [6.5 注册成功](6.5注册成功.md)
40 | * [6.6 小结](6.6小结.md)
41 | * [第七章. 会话管理](第七章.会话管理.md)
42 | * [7.1 章节说明](7.1章节说明.md)
43 | * [7.2 会话](7.2会话.md)
44 | * [7.3 用户登录](7.3用户登录.md)
45 | * [7.4 退出](7.4退出.md)
46 | * [7.5 小结](7.5小结.md)
47 | * [第八章. 用户 CRUD](第八章.用户CRUD.md)
48 | * [8.1 章节说明](8.1章节说明.md)
49 | * [8.2 重构代码](8.2重构代码.md)
50 | * [8.3 更新用户](8.3更新用户.md)
51 | * [8.4 权限系统](8.4权限系统.md)
52 | * [8.5 列出所有用户](8.5列出所有用户.md)
53 | * [8.6 删除用户](8.6删除用户.md)
54 | * [8.7 访客模式](8.7访客模式.md)
55 | * [8.8 优化前端](8.8优化前端.md)
56 | * [8.9 小结](8.9小结.md)
57 | * [第九章. 微博 CRUD](第九章.微博CRUD.md)
58 | * [9.1 章节说明](9.1章节说明.md)
59 | * [9.2 微博模型](9.2微博模型.md)
60 | * [9.3 显示微博](9.3显示微博.md)
61 | * [9.4 发布微博](9.4发布微博.md)
62 | * [9.5 微博数据流](9.5微博数据流.md)
63 | * [9.6 删除微博](9.6删除微博.md)
64 | * [9.7 小结](9.7小结.md)
--------------------------------------------------------------------------------
/book.json:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | "highlight",
4 | "navigation",
5 | "comment",
6 | "copy-code",
7 | "image-zoom"
8 | ]
9 | }
--------------------------------------------------------------------------------
/cover.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AGDholo/ThinkPHP5.1-Web-Actual-combat/45f6b0d02d7785d44581daa01a3d9d84aa1acd70/cover.jpg
--------------------------------------------------------------------------------
/images/1516383654686.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AGDholo/ThinkPHP5.1-Web-Actual-combat/45f6b0d02d7785d44581daa01a3d9d84aa1acd70/images/1516383654686.jpg
--------------------------------------------------------------------------------
/images/GIF.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AGDholo/ThinkPHP5.1-Web-Actual-combat/45f6b0d02d7785d44581daa01a3d9d84aa1acd70/images/GIF.gif
--------------------------------------------------------------------------------
/images/Router-MVC-DB.svg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AGDholo/ThinkPHP5.1-Web-Actual-combat/45f6b0d02d7785d44581daa01a3d9d84aa1acd70/images/Router-MVC-DB.svg.png
--------------------------------------------------------------------------------
/images/TIM截图20180121181857.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AGDholo/ThinkPHP5.1-Web-Actual-combat/45f6b0d02d7785d44581daa01a3d9d84aa1acd70/images/TIM截图20180121181857.png
--------------------------------------------------------------------------------
/images/TIM截图20180129165617.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AGDholo/ThinkPHP5.1-Web-Actual-combat/45f6b0d02d7785d44581daa01a3d9d84aa1acd70/images/TIM截图20180129165617.png
--------------------------------------------------------------------------------
/images/screenshot_1516529870045.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AGDholo/ThinkPHP5.1-Web-Actual-combat/45f6b0d02d7785d44581daa01a3d9d84aa1acd70/images/screenshot_1516529870045.png
--------------------------------------------------------------------------------
/style/website.css:
--------------------------------------------------------------------------------
1 | h1,
2 | h2,
3 | h3,
4 | h4,
5 | h5,
6 | h6 {
7 | font-weight: 600;
8 | line-height: 1.25;
9 | border-left: 2px #5b3cc4;
10 | -webkit-box-shadow: 0 20px 40px -15px rgba(0, 0, 0, 0.05);
11 | box-shadow: 0 20px 40px -15px rgba(0, 0, 0, 0.05);
12 | -webkit-transition: all 0.25s ease;
13 | transition: all 0.25s ease;
14 | border-bottom: 1px solid #f0f0f0;
15 | }
16 |
17 | h1 {
18 | padding: 15px 0;
19 | color: #5b3cc4;
20 | border-radius: 0;
21 | font-size: 3rem !important;
22 | font-weight: 400 !important;
23 | line-height: 3.125rem !important;
24 | letter-spacing: normal !important;
25 | }
26 |
27 | h1 a {
28 | margin-left: 10px;
29 | }
30 |
31 | h2,
32 | h3,
33 | h4,
34 | h5,
35 | h6 {
36 | padding: 10px 0;
37 | width: calc(100% - 10px);
38 | border-bottom: 0 !important;
39 | font-size: 2.125rem !important;
40 | font-weight: 400 !important;
41 | line-height: 2.5rem !important;
42 | letter-spacing: 0.0073529412em !important;
43 | }
44 |
45 | h1:hover,
46 | h2:hover,
47 | h3:hover,
48 | h4:hover,
49 | h5:hover,
50 | h6:hover {
51 | padding-left: 10px;
52 | }
53 |
54 | h1 > a::before,
55 | h2 > a::before,
56 | h3 > a::before,
57 | h4 > a::before,
58 | h5 > a::before,
59 | h6 > a::before {
60 | content: "#" !important;
61 | }
62 |
63 | h1 > a,
64 | h2 > a,
65 | h3 > a,
66 | h4 > a,
67 | h5 > a,
68 | h6 > a {
69 | font-size: 0.85em;
70 | float: left;
71 | margin-left: -0.87em;
72 | padding-right: 0.23em;
73 | margin-top: 0.125em;
74 | opacity: 0;
75 | -webkit-transform: translate(-10px);
76 | transform: translate(-10px);
77 | -webkit-transition: all 0.3s ease !important;
78 | transition: all 0.3s ease !important;
79 | }
80 |
81 | p {
82 | width: 100%;
83 | padding: 3px 0px;
84 | background: transparent !important;
85 | margin-top: 0;
86 | border-radius: 10px;
87 | }
88 |
89 | pre {
90 | background-color: #f5f7fb !important;
91 | border-radius: 6px;
92 | white-space: pre-wrap;
93 | word-break: break-word;
94 | overflow: auto;
95 | position: relative;
96 | margin: 0;
97 | background: transparent;
98 | font-family: "Inconsolata", monospace;
99 | font-weight: 300;
100 | font-size: 15px;
101 | line-height: 1.55;
102 | }
103 |
104 | pre code {
105 | color: rgba(0, 0, 0, 0.65) !important;
106 | padding: 0;
107 | background-color: transparent;
108 | border-radius: 0;
109 | margin: 0;
110 | font-size: 0.85em;
111 | }
112 |
113 | table {
114 | padding: 10px;
115 | margin-top: 10px;
116 | background: #fbfbfb;
117 | border-radius: 5px;
118 | -webkit-box-shadow: 0 20px 40px -15px rgba(0, 0, 0, 0.05);
119 | box-shadow: 0 20px 40px -15px rgba(0, 0, 0, 0.05);
120 | }
121 |
122 | table th {
123 | border: none;
124 | }
125 |
126 | tbody tr {
127 | background: #fff;
128 | border-radius: 5px;
129 | transition: all 0.3s ease;
130 | width: calc(100% - 10px);
131 | margin-left: 5px;
132 | z-index: 100;
133 | margin-top: 5px;
134 | margin-bottom: 5px;
135 | border-radius: 5px;
136 | background: #fff;
137 | padding: 6px 0;
138 | position: relative;
139 | -webkit-transition: all 0.25s ease;
140 | transition: all 0.3s ease;
141 | }
142 |
143 | tbody tr:hover {
144 | border-radius: 5px;
145 | -webkit-transform: translateY(-4px);
146 | transform: translateY(-4px);
147 | }
148 | tbody tr td {
149 | padding: 10px;
150 | border: 0;
151 | }
152 |
153 | ul {
154 | border-radius: 6px;
155 | width: 100%;
156 | margin-top: 10px;
157 | padding: 10px 0;
158 | }
159 |
160 | ul li {
161 | border-bottom: 1px solid rgba(0, 0, 0, 0.12);
162 | padding: 5px 0;
163 | list-style-type: none;
164 | }
165 |
166 | ul:first-child li {
167 | border: none;
168 | padding: 0;
169 | }
170 |
171 | blockquote {
172 | border-left: #5b3cc4 solid 4px;
173 | border-top-left-radius: inherit;
174 | border-bottom-left-radius: inherit;
175 | left: 0;
176 | content: "";
177 | border-radius: 4px;
178 | }
179 |
--------------------------------------------------------------------------------
/第一章.基础信息.md:
--------------------------------------------------------------------------------
1 | * [第一章. 基础信息](第一章.基础信息.md)
2 | * [1.1 序言](1.1序言.md)
3 | * [1.2 关于作者](1.2关于作者.md)
4 | * [1.3 本书源码](1.3本书源码.md)
5 | * [1.4 反馈纠错](1.4反馈纠错.md)
6 | * [1.5 安全指南](1.5安全指南.md)
7 | * [1.6 捐助作者](1.6捐助作者.md)
--------------------------------------------------------------------------------
/第七章.会话管理.md:
--------------------------------------------------------------------------------
1 | * [第七章. 会话管理](第七章.会话管理.md)
2 | * [7.1 章节说明](7.1章节说明.md)
3 | * [7.2 会话](7.2会话.md)
4 | * [7.3 用户登录](7.3用户登录.md)
5 | * [7.4 退出](7.4退出.md)
6 | * [7.5 小结](7.5小结.md)
--------------------------------------------------------------------------------
/第三章.构建页面.md:
--------------------------------------------------------------------------------
1 | * [第三章. 构建页面](第三章.构建页面.md)
2 | * [3.1 章节说明](3.1章节说明.md)
3 | * [3.2 静态页面](3.2静态页面.md)
4 | * [3.3 Think 命令](3.3Think命令.md)
5 | * [3.4 小结](3.4小结.md)
--------------------------------------------------------------------------------
/第九章.微博CRUD.md:
--------------------------------------------------------------------------------
1 | * [第九章. 微博 CRUD](第九章.微博CRUD.md)
2 | * [9.1 章节说明](9.1章节说明.md)
3 | * [9.2 微博模型](9.2微博模型.md)
4 | * [9.3 显示微博](9.3显示微博.md)
5 | * [9.4 微博相关的操作](9.4微博相关的操作.md)
6 | * [9.5 小结](9.5小结.md)
--------------------------------------------------------------------------------
/第二章.开发环境布置.md:
--------------------------------------------------------------------------------
1 | * [第二章. 开发环境布置](第二章.开发环境布置.md)
2 | * [2.1 编辑器选用](2.1编辑器选用.md)
3 | * [2.2 命令行工具](2.2命令行工具.md)
4 | * [2.3 开发环境搭建](2.3开发环境搭建.md)
5 | * [2.4 浏览器选择](2.4浏览器选择.md)
6 | * [2.5 第一个应用](2.5第一个应用.md)
7 | * [2.6 Git 工作流](2.6Git工作流.md)
--------------------------------------------------------------------------------
/第五章.用户模型.md:
--------------------------------------------------------------------------------
1 | * [第五章. 用户模型](第五章.用户模型.md)
2 | * [5.1 章节说明](5.1章节说明.md)
3 | * [5.2 数据库迁移](5.2数据库迁移.md)
4 | * [5.3 查看数据表](5.3查看数据表.md)
5 | * [5.4 模型文件](5.4模型文件.md)
6 | * [5.5 小结](5.5小结.md)
--------------------------------------------------------------------------------
/第八章.用户CRUD.md:
--------------------------------------------------------------------------------
1 | * [第八章. 用户 CRUD](第八章.用户CRUD.md)
2 | * [8.1 章节说明](8.1章节说明.md)
3 | * [8.2 重构代码](8.2重构代码.md)
4 | * [8.3 更新用户](8.3更新用户.md)
5 | * [8.4 权限系统](8.4权限系统.md)
6 | * [8.5 列出所有用户](8.5列出所有用户.md)
7 | * [8.6 删除用户](8.6删除用户.md)
8 | * [8.7 小结](8.7小结.md)
--------------------------------------------------------------------------------
/第六章.用户注册.md:
--------------------------------------------------------------------------------
1 | * [第六章. 用户注册](第六章.用户注册.md)
2 | * [6.1 章节说明](6.1章节说明.md)
3 | * [6.2 注册表单](6.2注册表单.md)
4 | * [6.3 用户数据验证](6.3用户数据验证.md)
5 | * [6.4 注册失败错误信息](6.4注册失败错误信息.md)
6 | * [6.5 注册成功](6.5注册成功.md)
7 | * [6.6 小结](6.6小结.md)
--------------------------------------------------------------------------------
/第四章.优化页面.md:
--------------------------------------------------------------------------------
1 | * [第四章. 优化页面](第四章.优化页面.md)
2 | * [4.1 章节说明](4.1章节说明.md)
3 | * [4.2 样式美化](4.2样式美化.md)
4 | * [4.3 局部视图](4.3局部视图.md)
5 | * [4.4 路由链接](4.4路由链接.md)
6 | * [4.5 用户注册页面](4.5用户注册页面.md)
7 | * [4.6 集中视图](4.6集中视图.md)
8 | * [4.7 小结](4.7小结.md)
--------------------------------------------------------------------------------