├── _config.yml ├── CHANGELOG.md ├── Select-license.md ├── iOS └── app.sqlite ├── Docs └── Images │ ├── MVC.png │ ├── man-cn.png │ ├── Vim-molokai.png │ ├── Select-license.jpg │ └── the-relationship-between-design-patterns.jpg ├── iOS.md ├── Vue ├── vue-base-demo │ ├── images │ │ └── icon_fada.png │ ├── detail.html │ └── list.html └── demo.html ├── .github ├── FUNDING.yml └── workflows │ └── lint-md.yml ├── Rust ├── hello-world.rs └── Rust.md ├── Go ├── hello-world.go ├── Go.md └── golang.go ├── .gitmodules ├── .lintmdrc ├── .editorconfig ├── .minttyrc.md ├── .all-contributorsrc ├── Frontend ├── JSON.md ├── XML.md ├── HTML.md ├── jQuery.md ├── YAML.md ├── CSS.md ├── Less.md └── Sass.md ├── mac-man-cn.md ├── Vscode.md ├── MySQL ├── 数据类型.md ├── MySQL常用函数汇总.md └── 语法.md ├── PHP ├── PHP常量.md ├── PHP学习路线图.md ├── PHP的SPL-Exception.md ├── PHP工具包.md └── php.php ├── README.md ├── 设计模式的七大原则.md ├── MongoDB └── SQL到Mongo的对应表.md ├── 《代码整洁之道》.md ├── Linux ├── Vim.md └── bash.md ├── 应用代码分层.md ├── Git ├── git-commit-message-change-log.md ├── 常用Git命令清单.md └── Git.md ├── 正则表达式不要背.md ├── .vimrc.md ├── macOS.md ├── Chrome.md ├── Redis └── Redis.md ├── Python └── Python.md ├── PhpStorm.md └── Lua └── Lua.md /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 1.0.0 (2018-11-12) 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Select-license.md: -------------------------------------------------------------------------------- 1 | # 如何选择开源协议 2 | 3 | ![](./Docs/Images/Select-license.jpg) 4 | -------------------------------------------------------------------------------- /iOS/app.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanguans/notes/HEAD/iOS/app.sqlite -------------------------------------------------------------------------------- /Docs/Images/MVC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanguans/notes/HEAD/Docs/Images/MVC.png -------------------------------------------------------------------------------- /Docs/Images/man-cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanguans/notes/HEAD/Docs/Images/man-cn.png -------------------------------------------------------------------------------- /iOS.md: -------------------------------------------------------------------------------- 1 | # iOS 2 | 3 | ## [使我的 iOS 体验更加惊人的应用程序和工具列表](https://github.com/nikitavoloboev/my-ios) 4 | -------------------------------------------------------------------------------- /Docs/Images/Vim-molokai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanguans/notes/HEAD/Docs/Images/Vim-molokai.png -------------------------------------------------------------------------------- /Docs/Images/Select-license.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanguans/notes/HEAD/Docs/Images/Select-license.jpg -------------------------------------------------------------------------------- /Vue/vue-base-demo/images/icon_fada.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanguans/notes/HEAD/Vue/vue-base-demo/images/icon_fada.png -------------------------------------------------------------------------------- /Docs/Images/the-relationship-between-design-patterns.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanguans/notes/HEAD/Docs/Images/the-relationship-between-design-patterns.jpg -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | patreon: guanguans # Replace with a single Patreon username 4 | custom: # Replace with a single custom sponsorship URL 5 | -------------------------------------------------------------------------------- /Rust/hello-world.rs: -------------------------------------------------------------------------------- 1 | /**.----------------------------------------------- 2 | * | Author: guanguans 3 | * | Date: 2019-02-22 10:22 4 | * '---------------------------------------------*/ 5 | 6 | fn main() { 7 | println!("Hello World!"); 8 | } 9 | -------------------------------------------------------------------------------- /Go/hello-world.go: -------------------------------------------------------------------------------- 1 | /**.----------------------------------------------- 2 | * | Author: guanguans 3 | * '---------------------------------------------*/ 4 | 5 | package main 6 | 7 | import "fmt" 8 | 9 | func main() { 10 | fmt.Println("Hello World") 11 | } 12 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "design-patterns-for-humans-cn"] 2 | path = design-patterns-for-humans-cn 3 | url = https://github.com/guanguans/design-patterns-for-humans-cn.git 4 | [submodule "awesome-mongodb-cn"] 5 | path = awesome-mongodb-cn 6 | url = https://github.com/guanguans/awesome-mongodb-cn.git 7 | -------------------------------------------------------------------------------- /.lintmdrc: -------------------------------------------------------------------------------- 1 | { 2 | "excludeFiles": [ 3 | "src/", 4 | "tests/", 5 | "vendor/" 6 | ], 7 | "rules": { 8 | "no-empty-code": 1, 9 | "no-long-code": [ 10 | 2, 11 | { 12 | "length": 256, 13 | "exclude": [ 14 | "dot" 15 | ] 16 | } 17 | ] 18 | } 19 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = false 10 | 11 | [*.{vue,js,scss}] 12 | charset = utf-8 13 | indent_style = space 14 | indent_size = 2 15 | end_of_line = lf 16 | insert_final_newline = true 17 | trim_trailing_whitespace = true 18 | 19 | [*.md] 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /.github/workflows/lint-md.yml: -------------------------------------------------------------------------------- 1 | name: lint markdown 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | lint-markdown: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout 10 | uses: actions/checkout@v2 11 | 12 | - name: lint-md-github-action 13 | uses: lint-md/github-action@v0.1.1 14 | with: 15 | configFile: .lintmdrc 16 | failOnWarnings: false 17 | files: ./ ./*/ 18 | -------------------------------------------------------------------------------- /.minttyrc.md: -------------------------------------------------------------------------------- 1 | # .minttyrc 2 | 3 | ## 配置 4 | 5 | ``` bash 6 | Black=39,40,34 7 | BoldBlack=117,113,94 8 | Red=249,38,114 9 | BoldRed=253,151,31 10 | Green=166,226,46 11 | BoldGreen=56,56,48 12 | Yellow=244,191,117 13 | BoldYellow=73,72,62 14 | Blue=102,217,239 15 | BoldBlue=165,159,133 16 | Magenta=174,129,255 17 | BoldMagenta=245,244,241 18 | Cyan=161,239,228 19 | BoldCyan=204,102,51 20 | White=248,248,242 21 | BoldWhite=249,248,245 22 | ``` 23 | 24 | ## 相关链接 25 | 26 | * [https://github.com/oumu/mintty-color-schemes](https://github.com/oumu/mintty-color-schemes) 27 | -------------------------------------------------------------------------------- /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "contributors": [ 8 | { 9 | "login": "gaoyongfu", 10 | "name": "渊虹", 11 | "avatar_url": "https://avatars2.githubusercontent.com/u/32188852?v=4", 12 | "profile": "https://github.com/gaoyongfu", 13 | "contributions": [ 14 | "doc" 15 | ] 16 | } 17 | ], 18 | "contributorsPerLine": 7, 19 | "projectName": "notes", 20 | "projectOwner": "guanguans", 21 | "repoType": "github", 22 | "repoHost": "https://github.com" 23 | } 24 | -------------------------------------------------------------------------------- /Go/Go.md: -------------------------------------------------------------------------------- 1 | # Go 2 | 3 | ## 最佳实践和建议 4 | 5 | * 尽可能的使用:=去初始化声明一个变量(在函数内部) 6 | * 尽可能的使用字符代替字符串 7 | * 尽可能的使用切片代替数组 8 | * 尽可能的使用数组和切片代替映射 9 | * 如果只想获取切片中某项值,不需要值的索引,尽可能的使用 for range 去遍历切片,这比必须查询切片中的每个元素要快一些 10 | * 当数组元素是稀疏的(例如有很多 0 值或者空值 nil),使用映射会降低内存消耗 11 | * 初始化映射时指定其容量 12 | * 当定义一个方法时,使用指针类型作为方法的接受者 13 | * 在代码中使用常量或者标志提取常量的值 14 | * 尽可能在需要分配大量内存时使用缓存 15 | * 使用缓存模板 16 | 17 | ## 常见的陷阱与错误 18 | 19 | * 永远不要使用形如 `var p*a` 声明变量,这会混淆指针声明和乘法运算 20 | * 永远不要在`for`循环自身中改变计数器变量 21 | * 永远不要在`for-range`循环中使用一个值去改变自身的值 22 | * 永远不要将`goto`和前置标签一起使用 23 | * 永远不要忘记在函数名后加括号 (),尤其调用一个对象的方法或者使用匿名函数启动一个协程时 24 | * 永远不要使用`new()`一个 map,一直使用 make 25 | * 当为一个类型定义一个 String() 方法时,不要使用`fmt.Print`或者类似的代码 26 | * 永远不要忘记当终止缓存写入时,使用`Flush`函数 27 | * 永远不要忽略错误提示,忽略错误会导致程序奔溃 28 | * 不要使用全局变量或者共享内存,这会使并发执行的代码变得不安全 29 | * `println`函数仅仅是用于调试的目的 30 | -------------------------------------------------------------------------------- /Frontend/JSON.md: -------------------------------------------------------------------------------- 1 | # JSON 2 | 3 | 因为 JSON 是一个极其简单的数据交换格式,本教程最有可能成为有史以来最简单的 4 | Learn X in Y Minutes。 5 | 6 | 纯正的 JSON 实际上没有注释,但是大多数解析器都 7 | 接受 C-风格(//, /\* \*/)的注释。为了兼容性,最好不要在其中写这样形式的注释。 8 | 9 | 因此,本教程的一切都会是 100%有效的 JSON。幸亏,它的表达能力很丰富。 10 | 11 | 支持的数据类型: 12 | 13 | - 字符串: "hello", "\"A quote.\"", "\u0abe", "Newline.\n" 14 | - 数字: 23, 0.11, 12e10, 3.141e-10, 1.23e+4 15 | - 对象: { "key": "value" } 16 | - 数组: ["Values"] 17 | - 其他: true, false, null 18 | 19 | ```json 20 | { 21 | "numbers": 0, 22 | "strings": "Hellø, wørld. All unicode is allowed, along with \"escaping\".", 23 | "has bools?": true, 24 | "nothingness": null, 25 | 26 | "big number": 1.2e+100, 27 | 28 | "objects": { 29 | "comment": "Most of your structure will come from objects.", 30 | 31 | "array": [0, 1, 2, 3, "Arrays can have anything in them.", 5], 32 | 33 | "another object": { 34 | "comment": "These things can be nested, very useful." 35 | } 36 | }, 37 | 38 | "silliness": [ 39 | { 40 | "sources of potassium": ["bananas"] 41 | }, 42 | [ 43 | [1, 0, 0, 0], 44 | [0, 1, 0, 0], 45 | [0, 0, 1, "neo"], 46 | [0, 0, 0, 1] 47 | ] 48 | ], 49 | 50 | "that was short": "And, you're done. You now know everything JSON has to offer." 51 | } 52 | ``` 53 | -------------------------------------------------------------------------------- /mac-man-cn.md: -------------------------------------------------------------------------------- 1 | # Mac 安装中文版 man 帮助命令 2 | 3 | ![](./Docs/Images/man-cn.png) 4 | 5 | ## [linux 环境安装](https://github.com/man-pages-zh/manpages-zh/blob/master/README.md) 6 | 7 | ## macOS 环境安装 8 | 9 | ### 编译工具安装 10 | 11 | 因为需要编译安装,所以你电脑上需要有编译工具,运行下面两个命令安装 12 | 13 | ``` bash 14 | $ brew install automake 15 | $ brew install opencc 16 | ``` 17 | 18 | ### 安装 19 | 20 | ``` bash 21 | # 进入下载目录 22 | $ cd ~/Downloads/ 23 | # 下载最新版本的源码包 24 | $ wget https://github.com/man-pages-zh/manpages-zh/archive/v1.6.3.3.tar.gz 25 | # 解压源码包(atool命令,推荐安装这个工具,统一所有压缩文档的命令) 26 | $ atool -x v1.6.3.3.tar.gz 27 | # 或者使用这个命令解压 28 | $ tar zxvf v1.6.3.3.tar.gz 29 | # 进入源码包文件夹 30 | $ cd manpages-zh-1.6.3.3/ 31 | # 编译安装 1 32 | $ autoreconf --install --force 33 | # 编译安装 2 34 | $ ./configure 35 | # 编译安装 3 36 | $ sudo make 37 | # 编译安装 4 38 | $ sudo make install 39 | # 配置别名(如果是 zsh 对应处理即可) 40 | $ echo "alias cman='man -M /usr/local/share/man/zh_CN'" >> ~/.bash_profile 41 | # 使别名生效 42 | $ source ~/.bash_profile 43 | # 我们就安装上了中文版本的 man 工具了,但是运行命令会发现乱码。 44 | cman ls 45 | ``` 46 | 47 | ### 安装 groff 新版本解决中文乱码的问题 48 | 49 | ``` bash 50 | # 进入下载目录 51 | $ cd ~/Downloads/ 52 | # 下载1.22版本的源码包 53 | $ wget http://git.savannah.gnu.org/cgit/groff.git/snapshot/groff-1.22.tar.gz 54 | # 解压 55 | $ atool -x groff-1.22.tar.gz 56 | # 进入目录 57 | $ cd groff-1.22 58 | # 编译安装 59 | $ ./configure 60 | $ sudo make 61 | $ sudo make install 62 | # 打开配置文件 63 | $ sudo vim /etc/man.conf 64 | # 进入编辑器之后,在文件末尾添加 65 | `NROFF preconv -e UTF8 | /usr/local/bin/nroff -Tutf8 -mandoc -c` 66 | # 保存退出 67 | # 运行命令,完美解决乱码问题 68 | cman ls 69 | ``` 70 | -------------------------------------------------------------------------------- /Vscode.md: -------------------------------------------------------------------------------- 1 | # Vscode.md 2 | 3 | ## Users Settings 4 | 5 | ``` json 6 | { 7 | "workbench.colorTheme": "Monokai", 8 | "terminal.integrated.shell.windows": "D:\\Git\\bin\\bash.exe", // 终端在 Windows 上使用的 Shell 的路径。 9 | "files.trimTrailingWhitespace": true, 10 | "files.insertFinalNewline": true, 11 | "files.trimFinalNewlines": true, 12 | "workbench.iconTheme": "material-icon-theme", 13 | "trailing-spaces.trimOnSave": true, 14 | "files.autoSave": "afterDelay", 15 | "files.autoSaveDelay": 3000, 16 | "workbench.statusBar.feedback.visible": false, 17 | "phpfmt.enable_auto_align": true 18 | } 19 | ``` 20 | 21 | ## XDebug 配置 22 | 23 | ``` json 24 | { 25 | // 使用 IntelliSense 了解相关属性。 26 | // 悬停以查看现有属性的描述。 27 | // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 28 | "version": "0.2.0", 29 | "configurations": [ 30 | { 31 | "name": "Listen for XDebug", 32 | "type": "php", 33 | "request": "launch", 34 | "log": true, 35 | "localSourceRoot": "${workspaceRoot}", 36 | "serverSourceRoot": "/var/www/laravel", 37 | // "pathMappings": { 38 | // "/var/www/laravel": "${workspaceRoot}" 39 | // }, 40 | "port": 9000 41 | }, 42 | { 43 | "name": "Launch currently open script", 44 | "type": "php", 45 | "request": "launch", 46 | "program": "${file}", 47 | "cwd": "${fileDirname}", 48 | "port": 9000 49 | } 50 | ] 51 | } 52 | ``` 53 | -------------------------------------------------------------------------------- /MySQL/数据类型.md: -------------------------------------------------------------------------------- 1 | # MySQL 数据类型 2 | 3 | ## 串数据类型 4 | 5 | |数据类型 |说明| 6 | |:---------|:--| 7 | |CHAR |1~255 个字符的定长串。它的长度必须在创建时指定,否则 MySQL 假定为 CHAR(1)| 8 | |ENUM |接受最多 64 K 个串组成的一个预定义集合的某个串| 9 | |LONGTEXT |与 TEXT 相同,但最大长度为 4GB| 10 | |MEDIUMTEXT|与 TEXT 相同,但最大长度为 16K| 11 | |SET |接受最多 64 个串组成的一个预定义集合的零个或多个串| 12 | |TEXT |最大长度为 64K 的变长文本| 13 | |TINYTEXT |与 TEXT 相同,但最大长度为 255 字节| 14 | |VARCHAR |长度可变,最多不超过 255 字节。如果在创建时指定为 VARCHAR(n),则可存储 0 到 n 个字符的变长串(其中 n≤255)| 15 | 16 | ## 数值数据类型 17 | 18 | |数据类型 |说明| 19 | |:---------------|:---| 20 | |BIT |位字段,1~64 位。(在 MySQL 5 之前,BIT 在功能上等价于 TINYINT| 21 | |BIGINT |整数值,支持9223372036854775808~9223372036854775807(如果是 UNSIGNED,为 0~18446744073709551615)的数| 22 | |BOOLEAN(或 BOOL)|布尔标志,或者为 0 或者为 1,主要用于开/关(on/off)标志| 23 | |DECIMAL(或 DEC) |精度可变的浮点值| 24 | |DOUBLE |双精度浮点值| 25 | |FLOAT |单精度浮点值| 26 | |INT(或 INTEGER)|整数值,支持2147483648~2147483647(如果是 UNSIGNED,为 0~4294967295)的数| 27 | |MEDIUMINT |整数值,支持8388608~8388607(如果是 UNSIGNED,为 0~16777215)的数| 28 | |REAL|4 字节的浮点值| 29 | |SMALLINT |整数值,支持32768~32767(如果是 UNSIGNED,为 0~65535)的数| 30 | |TINYINT |整数值,支持128~127(如果为 UNSIGNED,为 0~255)的数| 31 | 32 | ## 日期和时间数据类型 33 | 34 | |数据类型 |说明| 35 | |:--------|:---| 36 | |DATE |表示 1000-01-01~9999-12-31 的日期,格式为 YYYY-MM-DD| 37 | |DATETIME |DATE 和 TIME 的组合| 38 | |TIMESTAMP|功能和 DATETIME 相同(但范围较小)| 39 | |TIME |格式为 HH:MM:SS| 40 | |YEAR |用 2 位数字表示,范围是 70(1970 年)~69(2069 年),用 4 位数字表示,范围是 1901 年~2155 年| 41 | 42 | ## 二进制数据类型 43 | 44 | |数据类型 |说明| 45 | |:---------|:---| 46 | |BLOB |Blob 最大长度为 64KB| 47 | |MEDIUMBLOB|Blob 最大长度为 16MB| 48 | |LONGBLOB |Blob 最大长度为 4GB| 49 | |TINYBLOB |Blob 最大长度为 255 字节| -------------------------------------------------------------------------------- /PHP/PHP常量.md: -------------------------------------------------------------------------------- 1 | # PHP 常量 2 | 3 | ## [](#自定义常量 "自定义常量")自定义常量 4 | 5 | | 比较项 | define | const | 6 | | --- | --- | --- | 7 | | 版本 | php 4.0 + | php 5.3.0 + | 8 | | 定义位置 | 任意 | 作用域的最顶端,不能在函数内、循环内以及 `if` 语句之内 | 9 | | 是否支持表达式 | 是 | 否 | 10 | | 是否支持大小写不敏感 | 是, 第三个参数为 `true` , 表示不敏感 | 否 | 11 | | 常量数组支持的版本 | php 7 + | php 5.6 + | 12 | 13 | 详细说明, 参考 [PHP 中 const 和 define() 定义常量的细节区别](http://blog.csdn.net/cscrazybing/article/details/46989749) 14 | 15 | ## [](#预定义常量 "预定义常量")预定义常量 16 | 17 | 是在 `PHP` 的内核中就定义好了的常量。区分大小写。这些变量包括了以下这些东西:从外部变量到内置的环境变量,从最新的错误信息到最新收到的 `header`。 18 | 19 | 常用的预定义常量有: 20 | 21 | | 名称 | 说明 | 22 | | --- | --- | 23 | | PHP_VERSION | 当前 `php` 的版本 | 24 | | PHP_OS | 当前所使用的操作系统类型 | 25 | | PHP_SAPI | `web` 服务器与 `php` 之间的接口 | 26 | | DEFAULT_INCLUDE_PATH | `php` 默认的包含路径 | 27 | | PHP_BINDIR | `php` 的执行路径 | 28 | | PHP_LIBDIR | `php` 扩展模块的路径 | 29 | | PEAR_INSTALL_DIR | `pear` 的安装路径 | 30 | | PEAR_EXTENSION_DIR | `pear` 的扩展路径 | 31 | | E_ERROR | 指向最近的错误处 | 32 | | E_WARNING | 指向最近的警告处 | 33 | | E_NOTICE | 指向最近的注意处 | 34 | | PHP_INT_MAX | 最大的整型数 | 35 | | M_E | 自然对数 `e`值 | 36 | | M_PI | 数学上的圆周率的值 | 37 | | TRUE | 逻辑真值 | 38 | | FALSE | 逻辑假值 | 39 | 40 | ## [](#魔术常量 "魔术常量")魔术常量 41 | 42 | | 名称 | 说明 | 43 | | --- | --- | 44 | | `__DIR__` | 文件所在的目录。如果用在被包括文件中,则返回被包括的文件所在的目录。 45 | 它等价于 `dirname(__FILE__)`。除非是根目录,否则目录中名不包括末尾的斜杠。 【PHP 5.3.0+】 | 46 | | `__FILE__` | 文件的完整路径和文件名。如果用在被包含文件中,则返回被包含的文件名。 47 | 自 `PHP 4.0.2` 起,`__FILE__` 总是包含一个绝对路径(如果是符号连接,则是解析后的绝对路径),而在此之前的版本有时会包含一个相对路径。 | 48 | | `__LINE__` | 文件中的当前行号。 | 49 | | `__NAMESPACE__` | 当前命名空间的名称(区分大小写)。此常量是在编译时定义的。 【PHP 5.3.0+】 | 50 | | `__FUNCTION__` | 函数名称。【PHP 4.3.0+】 | 51 | | `__TRAIT__` | `Trait` 的名字,包括其被声明的作用区域(例如 `Foo\Bar`) 52 | 【PHP 5.4.0+】 | 53 | | `__CLASS__` | 类的名称。【PHP 4.3.0+】 | 54 | | `__METHOD__` | 类的方法名。返回该方法被定义时的名字(区分大小写)。 55 | 【PHP 5.0.0+】 | 56 | -------------------------------------------------------------------------------- /PHP/PHP学习路线图.md: -------------------------------------------------------------------------------- 1 | # PHP 学习路线图 2 | 3 | PHP 学习的关键是:多看代码,多写代码,多总结。 4 | 5 | ## HTML5 和 CSS 6 | 7 | > 推荐书籍《HTML5+CSS3 从入门到精通》·李东博 8 | 9 | * HTML 标签 10 | * CSS 样式 11 | * Javascript 脚本 12 | 13 | ## PHP 基础 14 | 15 | > 推荐书籍《PHP 编程》·Kevin Tatroe,Peter MacIntyre,Rasmus Lerdorf 16 | 17 | * 变量 18 | * 数组 19 | * 循环控制 20 | * 函数 21 | * Cookie 和 Session 22 | * JSON 和 XML 23 | * AJAX 24 | * 文件读写 25 | * 上传和下载 26 | * 图片处理 27 | * RESTful 28 | 29 | ## WEB 服务器 30 | 31 | > 推荐书籍《鸟哥的 Linux 私房菜基础篇》·鸟哥 32 | 33 | * Linux 基础 34 | * LNMP 安装 35 | * PHP-FPM 配置 36 | 37 | ## PHP MySQL 操作 38 | 39 | > 推荐书籍《PHP 和 MySQL Web 开发》·Luke Welling 40 | 41 | * 增查改删操作 42 | * 表单处理 43 | * MySQLi 和 PDO 扩展 44 | 45 | ## PHP 面向对象和设计模式 46 | 47 | > 推荐书籍《深入 PHP:面向对象、模式与实践》·Matt Zandstra 48 | 49 | * 类和对象的关系 50 | * 继承、封装、多态 51 | * 性状 52 | * 面向对象设计原则 53 | * 类 UML 关系 54 | * 设计模式 55 | 56 | ## 代码编写和规范 57 | 58 | > 推荐书籍《代码整洁之道》·Robert C. Martin 59 | 60 | * PHP-FIG PSR1~4 规范 61 | * phpStorm 集成开发环境 62 | * Git 版本控制 63 | * Github 代码仓库 64 | 65 | ## MVC 框架 66 | 67 | * 单一入口 68 | * MVC 职责划分 69 | * PHP 框架 ThinkPHP5+Yii2+Laravel 70 | 71 | ## 组件 72 | 73 | * Composer 74 | * 组件 75 | 76 | ## Nginx 77 | 78 | > 推荐书籍《Nginx 高性能 Web 服务器详解》·苗泽,《大型网站技术架构 核心原理与案例分析》·李智慧 79 | 80 | * Nginx 配置优化 81 | * 负载均衡 82 | * 反向代理 83 | * 集群 84 | * CDN 85 | 86 | ## 数据库 87 | 88 | > 推荐书籍《高性能 MySQL》·Baron Schwartz,Peter Zaitsev,Vadim Tkachenko 89 | 90 | * ORM 91 | * 索引和全文索引 92 | * 锁机制 93 | * 分表 94 | * 集群 95 | * Redis 缓存 96 | 97 | ## PHP 高级 98 | 99 | > 推荐书籍《Modern PHP》·Josh Lockhart 100 | 101 | * Opcache 102 | * xDebug 调试和分析 103 | * Xhprof + Xhgui 性能分析 104 | * PHPUnit 单元测试 105 | * Docker LNMP 环境部署 106 | * 持续集成 107 | 108 | ## 原文连接 109 | 110 | * [phproad](https://github.com/yeszao/phproad/blob/master/README.md), by yeszao -------------------------------------------------------------------------------- /PHP/PHP的SPL-Exception.md: -------------------------------------------------------------------------------- 1 | # PHP 的 SPL-Exception 2 | 3 | PHP 的 SPL 里自带了 13 种 Exception,很多看起来意思也都差不多,那么到底它们应该在什么时候使用?各自的意义又有什么不同? 4 | 5 | SPL 的 Exception,只有两个是直接继承自 \Exception 的。一个是 RuntimeException,一个是 LogicException。另外 11 个 Exceptions 都是又继承自它们。所以只要搞清楚它们两兄弟的区别,整个 SPL Exception 也就搞清楚一大半了。 6 | 7 | RuntimeException 顾名思义,是运行时的异常。相对应的,LogicException 则是编译时的异常。说到这里,可能有的小伙伴就会问了,PHP 不是解释性脚本语言吗,怎么还分编译时和运行时呢?小伙伴的话说得很对(当然 PHP 也是有代码 => opcode 这个过程的,可以看作编译),但这个概念不能直接套用在 Exception 上。我们看看 PHP 官方文档对这两种 Exception 的阐述: 8 | 9 | > RuntimeException: Exception thrown if an error which can only be found on runtime occurs. 10 | > LogicException: Exception that represents error in the program logic. This kind of exceptions should directly lead to a fix in your code. 11 | 12 | 也就是说,RuntimeException 这种意外,往往是用户造成,是代码调用者无法通过写更多逻辑代码来避免的。比如封装一个 ORM,在找不到数据的时候返回 NotFoundException(继承自 RuntimeException),ORM 调用者也无法避免此意外的产生,只能根据 NotFoundException 来作出意外处理,比如再抛出 Http404Exception 什么的。 13 | 14 | 而 LogicException 呢,则是相关代码创作人可以避免的,按照上面引用官方的说法,这类 Exception 都是应该被直接修复掉的。比如说你调用一个作除法的函数,抛出一个除数为 0 的 LogicException,函数使用者就应该对代码除数先作检查,避免用户输入 0 的时候还去调用此函数。 15 | 16 | 由此可见相对于 RuntimeException 而言,LogicException 更像是跟调用者说:你的调用方式不对,请检查您的代码! 17 | 18 | 说完 Logic/Runtime Exception 的区别,我们在看看其他 SPL 提供的 Exception 的意义: 19 | 20 | 1. Bad(Method/Function)CallException: Method 本身继承自 Function,都是调用时出错,这肯定是 LogicException,一定是方法调用者又没有好好看文档了。 21 | 2. DomianException: 官方文档的第一个评论就是一个很好的栗子:说好了是处理图片的方法,其他类型的文件就请先过滤掉吧。Domain 是域的意思,这个例子即是在表达文件类型必须属于图片类型这个域的意思。 22 | 3. InvalidArgumentException: 第一个评论同样提供了很好的栗子。其实在 PHP 的世界,因为没有基础类型的 type hint,所以往往都使用 InvalidArgumentException 来作为非法参数类型的错误。 23 | 4. LengthException: 官方文档里没有很明确的说明,从名称上看应该是说对期望数组变量的长度的一种判断,如果长度不在期望范围之内应该抛出此异常。 24 | 5. OutOfBoundsException: 看官方说法也应该是针对数组的:如果 key 不合法,那么抛出此异常。此异常属于 Runtime 异常。 25 | 6. OutOfRangeException: 跟 OutOfBoundsException 完全一样,只是此异常是 Logic 类型。所以,如果你能非常确定某个数组有哪些 key,就用 OutOfRangeException;如果你也不知道某个数组有哪些 key(可能又来自数据库什么的),就只能使用 OutOfBoundsException 26 | 7. OverflowException: 如果一个容器已经满了,调用者还往里塞东西,就抛出此异常。容器什么时候满肯定是代码创调用者自己无法预知的,所以此 Exception 属于 RuntimeException 27 | 8. RangeException: Runtime 版本的 DomainException 28 | 9. UnderflowException: 这个一定是针对空容器的。比如从空容器里删除一个元素,就可以抛出此异常 29 | 10. UnexpectedValueException: 这是官方文档说得最详细的 SPL Exception 了,我就原话翻译一下:如果变量不在某一组期待值里,抛出此异常。主要用于一个函数调用另外一个函数时返回值不是期待的类型或者值,也没有算法或者缓冲问题出现的时候。 30 | -------------------------------------------------------------------------------- /MySQL/MySQL常用函数汇总.md: -------------------------------------------------------------------------------- 1 | # MySQL 常用函数汇总 2 | 3 | 字符串函数 4 | ===== 5 | 6 | | 函数 | 功能 | 7 | | --- | --- | 8 | | CONCAT(s1,s2,……) | 字符串连接 | 9 | | INSERT(str,x,y,instr) | 将指定开始标记到结束的字符串替换为指定字符串 | 10 | | LOWER(str) | 将字符串所有字符转为小写 | 11 | | UPPER(str) | 将字符串所有字符串转为大写 | 12 | | LEFT(str,x) | 返回字符串 str 最左边的 x 个字符 | 13 | | RIGHT(str,x) | 返回字符串 str 最右边的 x 个字符 | 14 | | LPAD(str,n,pad) | 在 str 最左边填充 n 个 pad | 15 | | RPAD(str,n,pad) | 在 str 最右边填充 n 个 pad | 16 | | LTRIM(str) | 去掉字符串 str 左侧的空格 | 17 | | RTRIM(str) | 去掉字符串 str 右侧的空格 | 18 | | REPEAT(str,x) | 返回 str 重复 x 次的结果 | 19 | | STRCMP(s1,s2) | 比较字符串 s1 和 s2 | 20 | | REPLACE(str,a,b) | 用字符串 b 替换字符串 str 中所有出现的字符串 a | 21 | | TRIM(str) | 去掉字符串行尾和行头的空格 | 22 | | SUBSTRING(str,x,y) | 返回从字符串 str x 位置起 y 个字符长度的字串 | 23 | 24 | 数学函数 25 | ==== 26 | 27 | | 函数 | 功能 | 28 | | --- | --- | 29 | | ABS(x) | 返回 x 的绝对值 | 30 | | CEIL(x) | 返回大于 x 的最小整数值 | 31 | | FLOOR(x) | 返回小于 x 的最大整数值 | 32 | | MOD(x,y) | 返回 x/y 的模 | 33 | | RAND() | 返回 0~1 内的随机值 | 34 | | ROUND(x,y) | 返回参数 x 的四舍五入的有 y 位小数的值 | 35 | | TRUNCATE(x,y) | 返回数字 x 截断位 y 位小数的结果 | 36 | 37 | 日期和时间函数 38 | ======= 39 | 40 | | 函数 | 功能 | 41 | | --- | --- | 42 | | CURDATE() | 返回当前日期 | 43 | | CURTIME() | 返回当前时间 | 44 | | NOW() | 返回当前的日期和时间 | 45 | | UNIX_TIMESTAMP(date) | 返回日期 date 的 UNIX 时间戳 | 46 | | FROM_UNIXTIME | 返回 UNIX 时间戳的日期值 | 47 | | WEEK(date) | 返回日期 date 为一年中的第几周 | 48 | | YEAR(date) | 返回日期 date 的年份 | 49 | | HOUR(time) | 返回 time 的小时值 | 50 | | MINUTE(time) | 返回 time 的分钟值 | 51 | | MONTHNAME(date) | 返回 date 的月份名 | 52 | | DATE_FORMAT(date,fmt) | 返回按字符串 fmt 格式日期 date 值 | 53 | | DATE_ADD(date,interval expr type) | 返回一个日期或时间值加上一个时间间隔的时间值 | 54 | | DATEDIFF(expr,expr2) | 返回起始时间 expr 和结束时间 expr2 之间的天数 | 55 | 56 | 流程函数 57 | ==== 58 | 59 | | 函数 | 功能 | 60 | | --- | --- | 61 | | IF(value,t f) | 如果 value 是真,返回 t;否则返回 f | 62 | | IFNULL(value1,value2) | 如果 value1 不为空,返回 value1,否则返回 value2 | 63 | | CASE WHEN [value1] THEN[result1]...ELSE[default]END | 如果 value1 是真,返回 result1,否则返回 result | 64 | | CASE[expr] WHEN [value1]THEN[result1]...ELSE[default]END | 如果 expr 等于 value1,返回 result1,否则返回 default | 65 | 66 | 其他常用函数 67 | ====== 68 | 69 | | 函数 | 功能 | 70 | | --- | --- | 71 | | DATEBASE() | 返回当前数据库名 | 72 | | VERSION() | 返回当前数据库版本 | 73 | | USER() | 返回当前登录用户名 | 74 | | INET_ATON(ip) | 返回 ip 地址的数字表示 | 75 | | INET_NTOA(num) | 返回数字代表的 ip 地址 | 76 | | PASSWORD(str) | 返回字符串 str 的加密版本 | 77 | | MD5() | 返回字符串 str 的 md5 值 | 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # notes 2 | 3 | [![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors) 4 | 5 | 学习笔记 6 | 7 | ## Linux 8 | 9 | * [命令行的艺术](Linux/the-art-of-command-line.md) 10 | 11 | ## PHP 12 | 13 | * [PHP 学习路线图](PHP/PHP学习路线图.md) 14 | * [PHP7.0 至 PHP7.3 的新特性](PHP/PHP7.0至PHP7.3的新特性.md) 15 | * [php.php](PHP/php.php) 16 | * [PHP 常用函数](PHP/PHP常用函数.md) 17 | * [PHP 常量](PHP/PHP常量.md) 18 | * [PHP 工具包](PHP/PHP工具包.md) 19 | * [PHPUnit](PHP/PHPUnit.md) 20 | * [PHP 的 SPL Exception](PHP/PHP的SPL-Exception.md) 21 | 22 | ## Redis 23 | 24 | * [Redis](Redis/Redis.md) 25 | 26 | ## Go 27 | 28 | * [Go](Go/Go.md) 29 | * [golang.go](Go/golang.go) 30 | 31 | ## MySQL 32 | 33 | * [MySQL 语法](MySQL/语法.md) 34 | * [MySQL 数据类型](MySQL/数据类型.md) 35 | * [MySQL 数据库开发的三十六条军规](MySQL/MySQL数据库开发的三十六条军规.md) 36 | * [MySQL 数据库设计规范](MySQL/MySQL数据库设计规范.md) 37 | * [MySQL 常用函数汇总](MySQL/MySQL常用函数汇总.md) 38 | 39 | ## MongoDB 40 | 41 | * [SQL 到 Mongo 的对应表](MongoDB/SQL到Mongo的对应表.md) 42 | 43 | ## Git 44 | 45 | * [常用 Git 命令清单](Git/常用Git命令清单.md) 46 | * [git commit message 和 Change log](Git/git-commit-message-change-log.md) 47 | 48 | ## 其他 49 | 50 | * [应用代码分层](应用代码分层.md) 51 | * [有哪些鲜为人知,但是很有意思的网站?](Useful-website.md) 52 | * [《代码整洁之道》](《代码整洁之道》.md) 53 | * [设计模式(45 种)](设计模式(45种).md) 54 | * [设计模式的七大原则](设计模式的七大原则.md) 55 | * [Mac 安装中文版 man 帮助命令](mac-man-cn.md) 56 | * [PhpStorm](PhpStorm.md) 57 | * [Sublime](Sublime.md) 58 | * [Chrome](Chrome.md) 59 | * [Select-license](Select-license.md) 60 | * [.minttyrc](.minttyrc.md) 61 | * [.vimrc](.vimrc.md) 62 | * [macOS](macOS.md) 63 | * [iOS](iOS.md) 64 | * [Shell](Shell.md) 65 | * [Vscode](Vscode.md) 66 | 67 | ## Contributors ✨ 68 | 69 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 |
渊虹
渊虹

📖
78 | 79 | 80 | 81 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! 82 | 83 | ## License 84 | 85 | [Apache License 2.0](./LICENSE) 86 | -------------------------------------------------------------------------------- /Vue/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | vue-demo 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 |

{{ title }}

21 | 30 |
31 | 32 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /设计模式的七大原则.md: -------------------------------------------------------------------------------- 1 | # 设计模式的七大原则 2 | 3 | ## 开闭原则( Open Close Principle ) 4 | 5 | > 在对程序进行更新迭代的过程中,应当合理的避免修改类或方法的内部代码,而是优先选择通过继承、扩展等方式来实现。简而言之,就是:对扩展开放,对修改关闭。 6 | 7 | ## 里氏替换原则( Liskov Substitution Principle ) 8 | 9 | > 在实现子类的定义时,应该让它完全拥有替代父类进行工作的能力。简而言之,就是:子类对外要具与父类一致的方法或接口。 10 | 11 | ## 依赖倒置原则( Dependence Inversion Principle ) 12 | 13 | > 在对象或类的依赖关系定义上,父类或者其他上层实现不应该依赖于子类或者其他下层实现,通过这样,来避免依赖关系的耦合。 14 | 15 | ## 单一职责原则( Single Responsibility Principle ) 16 | 17 | > 在程序结构和依赖关系的定义上,要将类的功能职责充分理清,尽力减少类之间的耦合。避免对某个类进行修改时,牵一发动全身的连锁反应。 18 | 19 | ## 接口隔离原则( Interface Segregation Principle ) 20 | 21 | > 在对外接口的定义上,要避免庞大而臃肿的接口,而是进行责任细化的区分,避免冗余的代码实现。这对于提高内聚,提升系统灵活度是非常有效果的。 22 | 23 | ## 最少知识原则( Least Knowledge Principle ) 24 | 25 | > 在分配类的职责和建立依赖关系时,应该只关注于自身的功能实现和周围与之接触类的交互方式。避免类去考虑整个系统结构和处理流程,让类的职责清晰化,让系统的耦合度降低。 26 | 27 | ## 合成复用原则( Composite Reuse Principle ) 28 | 29 | > 在扩展功能的时候,要优先考虑水平形式的新增类或方法,而不是通过继承去实现。也就是通过功能的组合实现类,而不是通过基础去实现新的功能。这样可以提高类的可扩展性,减少系统的层次。 30 | 31 | ## 设计模式 32 | 33 | ### 面向对象的设计原则 34 | 35 | * 对接口编程,不要对实现编程 36 | * 使用对象之间的组合,减少对继承的使用 37 | * 抽象用于不同的事物,而接口用于事物的行为 38 | 39 | ### 设计模式的设计原则 40 | 41 | * 开闭原则:对扩展开放,对修改封闭 42 | * mean: 实例的内部不可修改,但可以增加新功能 43 | * 依赖倒转:对接口编程,依赖于抽象而不依赖于具体 44 | * mean: 就是把公共的拿出来,定义成抽象类、接口、抽象方法,然后大家再去实现这个抽 45 | 象,实现的方法各有不同,各个实体相互独立没有依赖,各个实体离开谁都能活 46 | * 接口隔离:使用多个接口,而不是对一个接口编程,去依赖降低耦合 47 | * mean: 就是抽象再抽象 48 | * 最少知道:减少内部依赖,尽可能的独立 49 | * mean: 实现依赖注入容器,把依赖的实体注入到一个实例(所谓容器) 50 | * 合成复用:多个独立的实体合成聚合,而不是使用继承 51 | * mean:尽可能不用继承,使用以上三种方式构成代码结构 52 | * 里氏代换:超类(父类)出现的地方,派生类(子类)都可以出现 53 | * mean:能用父类实现的子类也能实现 54 | 55 | ### 简单设计原则 56 | 57 | * 通过所有测试:及需求为上 58 | * 尽可能的消除重复:高内聚低耦合 59 | * 尽可能的清晰表达:可读性 60 | * 更少代码元素:常量,变量,函数,类,包 …… 都属于代码元素,降低复杂性 61 | * 以上四个原则的重要程度依次降低 62 | 63 | > 核心:高内聚松耦合(单一职责),外部依赖,实体对抽象编程,抽象就是分层 64 | 65 | --- 66 | 67 | ## 依赖倒置原则(Dependence Inversion Principle, DIP) 68 | 69 | > DIP 是一种软件设计的指导思想。传统软件设计中,上层代码依赖于下层代码,当下层出现变动时, 上层代码也要相应变化,维护成本较高。而 DIP 的核心思想是上层定义接口,下层实现这个接口, 从而使得下层依赖于上层,降低耦合度,提高整个系统的弹性。这是一种经实践证明的有效策略。 70 | 71 | ## 控制反转(Inversion of Control, IoC) 72 | 73 | > IoC 就是 DIP 的一种具体思路,DIP 只是一种理念、思想,而 IoC 是一种实现 DIP 的方法。 IoC 的核心是将类(上层)所依赖的单元(下层)的实例化过程交由第三方来实现。 一个简单的特征,就是类中不对所依赖的单元有诸如 `$component = new yii\component\SomeClass()`的实例化语句。 74 | 75 | ## 依赖注入(Dependence Injection, DI) 76 | 77 | > DI 是 IoC 的一种设计模式,是一种套路,按照 DI 的套路,就可以实现 IoC,就能符合 DIP 原则。 DI 的核心是把类所依赖的单元的实例化过程,放到类的外面去实现。 78 | 79 | ## 控制反转容器(IoC Container) 80 | 81 | > 当项目比较大时,依赖关系可能会很复杂。 而 IoC Container 提供了动态地创建、注入依赖单元,映射依赖关系等功能,减少了许多代码量。 Yii 设计了一个 yii\di\Container 来实现了 DI Container。 82 | 83 | ## 服务定位器(Service Locator) 84 | 85 | > Service Locator 是 IoC 的另一种实现方式, 其核心是把所有可能用到的依赖单元交由 Service Locator 进行实例化和创建、配置, 把类对依赖单元的依赖,转换成类对 Service Locator 的依赖。 DI 与 Service Locator 并不冲突,两者可以结合使用。 目前,Yii2.0 把这 DI 和 Service Locator 这两个东西结合起来使用,或者说通过 DI 容器,实现了 Service Locator。 86 | -------------------------------------------------------------------------------- /Frontend/XML.md: -------------------------------------------------------------------------------- 1 | # XML 2 | 3 | XML 是一种标记语言,被设计用来存储数据和传输数据。 4 | 5 | 不像 HTML, XML 不指定怎样显示或格式化数据,只是携带它。 6 | 7 | * XML 语法 8 | 9 | ```xml 10 | 11 | 12 | 13 | 14 | 15 | Everyday Italian 16 | Giada De Laurentiis 17 | 2005 18 | 30.00 19 | 20 | 21 | Harry Potter 22 | J K. Rowling 23 | 2005 24 | 29.99 25 | 26 | 27 | Learning XML 28 | Erik T. Ray 29 | 2003 30 | 39.95 31 | 32 | 33 | 34 | 41 | 42 | 43 | 44 | 51 | 52 | 53 | 54 | computer.gif 55 | 56 | 57 | ``` 58 | 59 | * 良好格式的文件 x 验证 60 | 61 | 一个 XML 文件是良好格式的如果它是语法正确的。 62 | 但是, 使用文件定义,比如 DTD 和 XML 概要,在文件中插入更多的限制是可能的。 63 | 64 | 一个遵守一个文件定义的 XML 文件被叫做有效的,对于那个文件来说。 65 | 66 | 有了这个工具,你能够在应用逻辑之外检查 XML 数据。 67 | 68 | ```xml 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | Everyday Italian 77 | 30.00 78 | 79 | 80 | 81 | 82 | 83 | 86 | 87 | 88 | 89 | 90 | ]> 91 | 92 | 93 | 98 | 99 | 100 | 101 | 102 | 103 | 106 | 107 | 108 | 109 | 110 | ]> 111 | 112 | 113 | 114 | Everyday Italian 115 | 30.00 116 | 117 | 118 | ``` 119 | -------------------------------------------------------------------------------- /Frontend/HTML.md: -------------------------------------------------------------------------------- 1 | # HTML 2 | 3 | HTML 是超文本标记语言的缩写。 4 | 这门语言可以让我们为万维网创造页面。 5 | 这是一门标记语言,它允许我们用代码来指示网页上文字和数据应该如何显示。 6 | 实际上 html 文件是简单的文本文件。 7 | 什么是标记?标记是通过使用开始和结束标签包围数据的方法,来组织管理页面上的数据。 8 | 这些标记对它们环绕的文本有重要的意义。 9 | 和其它计算机语言意义,HTML 有很多版本。这里我们将讨论 HTML5。 10 | 11 | **注意:** 你可以在类似[codepen](http://codepen.io/pen/)的网站上的教程中,尝试不同的标签和元素带来的效果,理解它们如何起效,并且逐渐熟悉这门语言。 12 | 本文主要关注 HTML 的语法和一些有用的小窍门。 13 | 14 | ```html 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 我的网站 25 | 26 | 27 |

Hello, world!

28 | 来看看这里有什么 29 |

这是一个段落。

30 |

这是另外一个段落。

31 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 我的网站 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 |

Hello, world!

65 | 66 | 来看看这里有什么 67 |

这是一个段落。

68 |

这是另外一个段落。

69 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 |
第一个表头 第二个表头
第一行第一列 第一行第二列
第二行第一列第二行第二列
101 | 102 | ``` 103 | 104 | ## 使用 105 | 106 | HTML 文件使用`.html`后缀。 107 | 108 | ## 扩展阅读 109 | 110 | * [维基百科](https://en.wikipedia.org/wiki/HTML) 111 | * [HTML tutorial](https://developer.mozilla.org/en-US/docs/Web/HTML) 112 | * [W3School](http://www.w3schools.com/html/html_intro.asp) 113 | -------------------------------------------------------------------------------- /MongoDB/SQL到Mongo的对应表.md: -------------------------------------------------------------------------------- 1 | # SQL 到 Mongo 的对应表 2 | 3 | 这个列表是 PHP 版本的 [» SQL to Mongo](http://www.mongoing.com/docs/reference/sql-comparison.html) 对应表(在 MongoDB 官方手册中有更加通用的版本)。 4 | 5 | | SQL 查询语句 | Mongo 查询语句 | 6 | | --- | --- | 7 | |CREATE TABLE USERS (a Number, b Number) | 隐式的创建,或 [MongoDB::createCollection()](mongodb.createcollection.php). | 8 | |INSERT INTO USERS VALUES(1,1) |$db->users->insert(array("a" => 1, "b" => 1)); | 9 | |SELECT a,b FROM users |$db->users->find(array(), array("a" => 1, "b" => 1)); | 10 | |SELECT * FROM users WHERE age=33 |$db->users->find(array("age" => 33)); | 11 | |SELECT a,b FROM users WHERE age=33 |$db->users->find(array("age" => 33), array("a" => 1, "b" => 1)); | 12 | |SELECT a,b FROM users WHERE age=33 ORDER BY name |$db->users->find(array("age" => 33), array("a" => 1, "b" => 1))->sort(array("name" => 1)); | 13 | |SELECT * FROM users WHERE age>33 |$db->users->find(array("age" => array('$gt' => 33))); | 14 | |SELECT * FROM users WHERE age<33 |$db->users->find(array("age" => array('$lt' => 33))); | 15 | |SELECT * FROM users WHERE name LIKE "%Joe%" |$db->users->find(array("name" => new MongoRegex("/Joe/"))); | 16 | |SELECT * FROM users WHERE name LIKE "Joe%" |$db->users->find(array("name" => new MongoRegex("/^Joe/"))); | 17 | |SELECT * FROM users WHERE age>33 AND age<=40 |$db->users->find(array("age" => array('$gt' => 33, '$lte' => 40))); | 18 | |SELECT * FROM users ORDER BY name DESC |$db->users->find()->sort(array("name" => -1)); | 19 | |CREATE INDEX myindexname ON users(name) |$db->users->ensureIndex(array("name" => 1)); | 20 | |CREATE INDEX myindexname ON users(name,ts DESC) |$db->users->ensureIndex(array("name" => 1, "ts" => -1)); | 21 | |SELECT * FROM users WHERE a=1 and b='q' |$db->users->find(array("a" => 1, "b" => "q")); | 22 | |SELECT * FROM users LIMIT 20, 10 |$db->users->find()->limit(10)->skip(20); | 23 | |SELECT * FROM users WHERE a=1 or b=2 |$db->users->find(array('$or' => array(array("a" => 1), array("b" => 2)))); | 24 | |SELECT * FROM users LIMIT 1 |$db->users->find()->limit(1); | 25 | |EXPLAIN SELECT * FROM users WHERE z=3 |$db->users->find(array("z" => 3))->explain() | 26 | |SELECT DISTINCT last_name FROM users |$db->command(array("distinct" => "users", "key" => "last_name")); | 27 | |SELECT COUNT(*y) FROM users |$db->users->count(); | 28 | |SELECT COUNT(*y) FROM users where AGE > 30 |$db->users->find(array("age" => array('$gt' => 30)))->count(); | 29 | |SELECT COUNT(AGE) from users |$db->users->find(array("age" => array('$exists' => true)))->count(); | 30 | |UPDATE users SET a=1 WHERE b='q' |$db->users->update(array("b" => "q"), array('$set' => array("a" => 1))); | 31 | |UPDATE users SET a=a+2 WHERE b='q' |$db->users->update(array("b" => "q"), array('$inc' => array("a" => 2))); | 32 | |DELETE FROM users WHERE z="abc" |$db->users->remove(array("z" => "abc")); | 33 | 34 | 35 | ## 内嵌、引用选择 36 | 37 | | 更适合内嵌 | 更适合引用 | 38 | | --- | --- | 39 | | 子文档较小 | 子文档较大 | 40 | | 数据不会定期改变 | 数据经常改变 | 41 | | 最终数据一致即可 | 中间阶段的数据必须一致 | 42 | | 文档数据小幅增加 | 文档数据大幅增加 | 43 | | 数据通常需要执行二次查询才能获得 | 数据通常不包含在结果中 | 44 | | 快速读取 | 快速写入 | 45 | -------------------------------------------------------------------------------- /Frontend/jQuery.md: -------------------------------------------------------------------------------- 1 | # jQuery 2 | 3 | jQuery 是 JavaScript 的一个函数库,它可以帮你“写更少,做更多”。它集成了很多常见的 JavaScript 任务并且很容易调用。jQuery 被世界各地的很多的大公司和开发者使用。它包括了 AJAX,事件处理,文档操作以及很多其它功能,并且更加简单和快速。 4 | 5 | 正因为 jQuery 是 JavaScript 的一个函数库,所以你需要[首先学习 JavaScript](https://learnxinyminutes.com/docs/javascript/) 6 | 7 | ```js 8 | 9 | 10 | /////////////////////////////////// 11 | // 1. 选择器 12 | 13 | // jQuery中的选择器被用来选择一个元素 14 | var page = $(window); // 选择整个视窗 15 | 16 | // 选择器可以作为CSS选择器使用 17 | var paragraph = $('p'); // 选择所有段落元素 18 | var table1 = $('#table1'); // 选择id为table1的元素 19 | var squares = $('.square'); // 选择所有类是square的元素 20 | var square_p = $('p.square') // 选择具有square类的所有段落 21 | 22 | 23 | /////////////////////////////////// 24 | // 2. 事件和效果 25 | // jQuery非常善于处理当事件触发的时候应该做什么 26 | // 一个非常常见的事件就是文档的就绪事件 27 | // 你可以用ready方法,在所有元素完成加载的时候执行 28 | $(document).ready(function(){ 29 | // 只有文档加载完成以后代码才会执行 30 | }); 31 | // 你也可以用定义了的函数 32 | function onAction() { 33 | // 本函数在事件触发的时候被执行 34 | } 35 | $('#btn').click(onAction); // 当点击的时候调用onAction函数 36 | 37 | // 其它常见的事件: 38 | $('#btn').dblclick(onAction); // 双击 39 | $('#btn').hover(onAction); // 划过 40 | $('#btn').focus(onAction); // 聚焦 41 | $('#btn').blur(onAction); // 失焦 42 | $('#btn').submit(onAction); // 提交 43 | $('#btn').select(onAction); // 当元素被选中 44 | $('#btn').keydown(onAction); // 当一个按键被按下 45 | $('#btn').keyup(onAction); // 当一个按键被抬起 46 | $('#btn').keypress(onAction); // 当一个按键被按住 47 | $('#btn').mousemove(onAction); // 当鼠标在移动 48 | $('#btn').mouseenter(onAction); // 鼠标移入元素 49 | $('#btn').mouseleave(onAction); // 鼠标离开元素 50 | 51 | 52 | // 如果不提供任何参数的话,那么这些方法可以触发事件 53 | // 而不是定义处理事件的方法 54 | $('#btn').dblclick(); // 触发元素上的双击 55 | 56 | // 你可以只用选择器一次而处理多个事件 57 | $('#btn').on( 58 | {dblclick: myFunction1} // 双击的时候触发 59 | {blur: myFunction1} // 失焦的时候触发 60 | ); 61 | 62 | // 你可以用一些效果函数来移动或隐藏元素 63 | $('.table').hide(); // 隐藏元素 64 | 65 | // 注意:在这些方法中调用函数会仍然隐藏元素 66 | $('.table').hide(function(){ 67 | // 元素先隐藏然后函数被执行 68 | }); 69 | 70 | // 你可以在变量中储存选择器 71 | var tables = $('.table'); 72 | 73 | // 一些基本的文档操作方法有: 74 | tables.hide(); // 隐藏元素 75 | tables.show(); // 显示元素 76 | tables.toggle(); // 对被选元素进行隐藏和显示的切换 77 | tables.fadeOut(); // 淡出 78 | tables.fadeIn(); // 淡入 79 | tables.fadeToggle(); // 对被选元素进行淡入和淡出显示的切换 80 | tables.fadeTo(0.5); // 把被选元素逐渐改变至给定的不透明度(0和1之间) 81 | tables.slideUp(); // 通过调整高度来滑动隐藏被选元素 82 | tables.slideDown(); // 对被选元素进行滑动隐藏和滑动显示的切换 83 | tables.slideToggle(); // 对被选元素进行滑动隐藏和滑动显示的切换 84 | 85 | // 上面所有的方法接受速度参数(毫秒)和一个回调函数 86 | tables.hide(1000, myFunction); // 持续一秒的隐藏动画然后执行函数 87 | 88 | // fadeTo要求提供透明度参数作为第二个参数 89 | tables.fadeTo(2000, 0.1, myFunction); // 通过2秒钟将透明度变为0.1然后执行函数 90 | 91 | // 你可以用animate方法实现一些略微高级的效果 92 | tables.animate({margin-top:"+=50", height: "100px"}, 500, myFunction); 93 | // animate方法接受一个包含CSS和值的对象作为目标, 94 | // 其次是可选的速度参数, 95 | // 以及最后的回调函数 96 | 97 | /////////////////////////////////// 98 | // 3. 操作 99 | 100 | // 这些类似效果函数但是可以做更多 101 | $('div').addClass('taming-slim-20'); // 给所有div添加类taming-slim-20 102 | 103 | // 常见操作方法 104 | $('p').append('Hello world'); // 添加到元素末尾 105 | $('p').attr('class'); // 获取属性 106 | $('p').attr('class', 'content'); // 设置属性 107 | $('p').hasClass('taming-slim-20'); // 如果有类则为真 108 | $('p').height(); // 获取和设置元素的高度 109 | 110 | 111 | // 对于很多的操作函数来说,获取元素的信息 112 | // 仅仅是第一个符合元素的 113 | $('p').height(); // 仅仅获取第一个p标签的高度 114 | 115 | // 你可以用each来迭代所有元素 116 | var heights = []; 117 | $('p').each(function() { 118 | heights.push($(this).height()); // 把所有p标签的高度加入数组 119 | }); 120 | 121 | 122 | ``` 123 | -------------------------------------------------------------------------------- /MySQL/语法.md: -------------------------------------------------------------------------------- 1 | # MySQL 语法 2 | 3 | ## 在阅读语句语法时,应该记住以下约定 4 | 5 | * | 符号用来指出几个选择中的一个,因此, NULL|NOT NULL 表示或者给出 NULL 或者给出 NOT NULL 。 6 | * 包含在方括号中的关键字或子句(如[like this])是可选的。 7 | * 既没有列出所有的 MySQL 语句,也没有列出每一条子句和选项。 8 | 9 | ## SQL 执行顺序 10 | 11 | ``` sql 12 | (8)SELECT (9)DISTINCT (11) 24 | 25 | 26 | 27 | 28 | 29 |
30 |
31 |
32 |
33 |
34 | 列表 35 |
36 |
37 |
38 | {{ ci.rhythmic }} 39 |
40 |
41 | 作者:{{ ci.author }} 42 |
43 |
44 |

45 | {{ ci.paragraphs }} 46 |

47 |
48 |
49 | 50 | 51 |
52 |
53 |
54 |
55 |
56 |
57 | 58 | 61 | 62 | 63 | 64 | 65 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /Frontend/YAML.md: -------------------------------------------------------------------------------- 1 | # YAML 2 | 3 | YAML 是一个数据序列化语言,被设计成人类直接可写可读的。 4 | 5 | 它是 JSON 的严格超集,增加了语法显著换行符和缩进,就像 Python。但和 Python 不一样, 6 | YAML 根本不容许文字制表符。 7 | 8 | ```yaml 9 | # YAML 中的注解看起来像这样。 10 | 11 | ################ 12 | # 标量类型 # 13 | ################ 14 | 15 | # 我们的根对象 (它们在整个文件里延续) 将会是一个映射, 16 | # 它等价于在别的语言里的一个字典,哈西表或对象。 17 | key: value 18 | another_key: Another value goes here. 19 | a_number_value: 100 20 | # 如果你想将数字 1 作为值,你必须要将它括在引号中。 21 | # 不然 YAML 解析器会假定它是一个布尔值 true。 22 | scientific_notation: 1e+12 23 | boolean: true 24 | null_value: null 25 | key with spaces: value 26 | # 注意到字符串不需要被括在引号中。但是,它们可以被括起来。 27 | "Keys can be quoted too.": "Useful if you want to put a ':' in your key." 28 | 29 | # 多行字符串既可以写成像一个'文字块'(使用 |), 30 | # 或像一个'折叠块'(使用 '>')。 31 | literal_block: | 32 | This entire block of text will be the value of the 'literal_block' key, 33 | with line breaks being preserved. 34 | 35 | The literal continues until de-dented, and the leading indentation is 36 | stripped. 37 | 38 | Any lines that are 'more-indented' keep the rest of their indentation - 39 | these lines will be indented by 4 spaces. 40 | folded_style: > 41 | This entire block of text will be the value of 'folded_style', but this 42 | time, all newlines will be replaced with a single space. 43 | 44 | Blank lines, like above, are converted to a newline character. 45 | 46 | 'More-indented' lines keep their newlines, too - 47 | this text will appear over two lines. 48 | 49 | #################### 50 | # 集合类型 # 51 | #################### 52 | 53 | # 嵌套是通过缩进完成的。 54 | a_nested_map: 55 | key: value 56 | another_key: Another Value 57 | another_nested_map: 58 | hello: hello 59 | 60 | # 映射的键值不必是字符串。 61 | 0.25: a float key 62 | 63 | # 键值也可以是复合型的,比如多行对象 64 | # 我们用 ? 后跟一个空格来表示一个复合键的开始。 65 | ? | 66 | This is a key 67 | that has multiple lines 68 | : and this is its value 69 | 70 | # YAML 也允许使用复杂键语法表示序列间的映射关系。 71 | # 但有些语言的解析器可能会不支持。 72 | # 一个例子: 73 | ? - Manchester United 74 | - Real Madrid 75 | : [ 2001-01-01, 2002-02-02 ] 76 | 77 | # 序列 (等价于列表或数组) 看起来像这样: 78 | a_sequence: 79 | - Item 1 80 | - Item 2 81 | - 0.5 # 序列可以包含不同类型。 82 | - Item 4 83 | - key: value 84 | another_key: another_value 85 | - 86 | - This is a sequence 87 | - inside another sequence 88 | 89 | # 因为 YAML 是 JSON 的超集,你也可以写 JSON 风格的映射和序列: 90 | json_map: {"key": "value"} 91 | json_seq: [3, 2, 1, "takeoff"] 92 | 93 | ####################### 94 | # 其余的 YAML 特性 # 95 | ####################### 96 | 97 | # YAML 还有一个方便的特性叫 '锚',它能让你很容易在文档中进行文本复用。 98 | # 如下两个键会有相同的值: 99 | anchored_content: &anchor_name This string will appear as the value of two keys. 100 | other_anchor: *anchor_name 101 | 102 | # 锚也可被用来复制/继承属性 103 | base: &base 104 | name: Everyone has same name 105 | 106 | foo: &foo 107 | <<: *base 108 | age: 10 109 | 110 | bar: &bar 111 | <<: *base 112 | age: 20 113 | 114 | # foo 和 bar 将都含有 name: Everyone has same name 115 | 116 | # YAML 还有标签,你可以用它显示地声明类型。 117 | explicit_string: !!str 0.5 118 | # 一些解析器实现特定语言的标签,就像这个针对 Python 的复数类型。 119 | python_complex_number: !!python/complex 1+2j 120 | 121 | # 我们也可以在 YAML 的复合键中使用特定语言的标签 122 | ? !!python/tuple [5, 7] 123 | : Fifty Seven 124 | # 将会是 Python 中的 {(5, 7): 'Fifty Seven'} 125 | 126 | #################### 127 | # 其余的 YAML 类型 # 128 | #################### 129 | 130 | # 除了字符串和数字,YAML 还能理解其它标量。 131 | # ISO 格式的日期和日期时间文本也可以被解析。 132 | datetime: 2001-12-15T02:59:43.1Z 133 | datetime_with_spaces: 2001-12-14 21:59:43.10 -5 134 | date: 2002-12-14 135 | 136 | # 这个 !!binary 标签表明这个字符串实际上 137 | # 是一个用 base64 编码表示的二进制 blob。 138 | gif_file: !!binary | 139 | R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5 140 | OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+ 141 | +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC 142 | AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= 143 | 144 | # YAML 还有一个集合类型,它看起来像这样: 145 | set: 146 | ? item1 147 | ? item2 148 | ? item3 149 | 150 | # 像 Python 一样,集合仅是值为 null 的映射;上面的集合等价于: 151 | set2: 152 | item1: null 153 | item2: null 154 | item3: null 155 | ``` 156 | 157 | ### 更多资源 158 | 159 | + [YAML official website](http://yaml.org/) 160 | + [Online YAML Validator](http://codebeautify.org/yaml-validator) 161 | -------------------------------------------------------------------------------- /Frontend/CSS.md: -------------------------------------------------------------------------------- 1 | # CSS 2 | 3 | 早期的 web 没有样式,只是单纯的文本。通过 CSS,可以实现网页样式和内容的分离。 4 | 5 | 简单来说,CSS 可以指定 HTML 页面上的元素所使用的样式。 6 | 7 | 和其他语言一样,CSS 有很多版本。最新的版本是 CSS 3. CSS 2.0 兼容性最好。 8 | 9 | 你可以使用[dabblet](http://dabblet.com/)来在线测试 CSS 的效果。 10 | 11 | ``` css 12 | /* 注释 */ 13 | 14 | /* #################### 15 | ## 选择器 16 | ####################*/ 17 | 18 | /* 一般而言,CSS的声明语句非常简单。 */ 19 | 选择器 { 属性: 值; /* 更多属性...*/ } 20 | 21 | /* 选择器用于指定页面上的元素。 22 | 23 | 针对页面上的所有元素。 */ 24 | * { color:red; } 25 | 26 | /* 27 | 假定页面上有这样一个元素 28 | 29 |
30 | */ 31 | 32 | /* 你可以通过类名来指定它 */ 33 | .some-class { } 34 | 35 | /* 给出所有类名 */ 36 | .some-class.class2 { } 37 | 38 | /* 标签名 */ 39 | div { } 40 | 41 | /* id */ 42 | #someId { } 43 | 44 | /* 由于元素包含attr属性,因此也可以通过这个来指定 */ 45 | [attr] { font-size:smaller; } 46 | 47 | /* 以及有特定值的属性 */ 48 | [attr='value'] { font-size:smaller; } 49 | 50 | /* 通过属性的值的开头指定 */ 51 | [attr^='val'] { font-size:smaller; } 52 | 53 | /* 通过属性的值的结尾来指定 */ 54 | [attr$='ue'] { font-size:smaller; } 55 | 56 | /* 通过属性的值的部分来指定 */ 57 | [attr~='lu'] { font-size:smaller; } 58 | 59 | 60 | /* 你可以把这些全部结合起来,注意不同部分间不应该有空格,否则会改变语义 */ 61 | div.some-class[attr$='ue'] { } 62 | 63 | /* 你也可以通过父元素来指定。*/ 64 | 65 | /* 某个元素是另一个元素的直接子元素 */ 66 | div.some-parent > .class-name {} 67 | 68 | /* 或者通过该元素的祖先元素 */ 69 | div.some-parent .class-name {} 70 | 71 | /* 注意,去掉空格后语义就不同了。 72 | 你能说出哪里不同么? */ 73 | div.some-parent.class-name {} 74 | 75 | /* 你可以选择某元素前的相邻元素 */ 76 | .i-am-before + .this-element { } 77 | 78 | /* 某元素之前的同级元素(相邻或不相邻) */ 79 | .i-am-any-before ~ .this-element {} 80 | 81 | /* 伪类允许你基于页面的行为指定元素(而不是基于页面结构) */ 82 | 83 | /* 例如,当鼠标悬停在某个元素上时 */ 84 | :hover {} 85 | 86 | /* 已访问过的链接*/ 87 | :visited {} 88 | 89 | /* 未访问过的链接*/ 90 | :link {} 91 | 92 | /* 当前焦点的input元素 */ 93 | :focus {} 94 | 95 | 96 | /* #################### 97 | ## 属性 98 | ####################*/ 99 | 100 | 选择器 { 101 | 102 | /* 单位 */ 103 | width: 50%; /* 百分比 */ 104 | font-size: 2em; /* 当前字体大小的两倍 */ 105 | width: 200px; /* 像素 */ 106 | font-size: 20pt; /* 点 */ 107 | width: 5cm; /* 厘米 */ 108 | width: 50mm; /* 毫米 */ 109 | width: 5in; /* 英尺 */ 110 | 111 | /* 颜色 */ 112 | background-color: #F6E; /* 短16位 */ 113 | background-color: #F262E2; /* 长16位 */ 114 | background-color: tomato; /* 颜色名称 */ 115 | background-color: rgb(255, 255, 255); /* rgb */ 116 | background-color: rgb(10%, 20%, 50%); /* rgb 百分比 */ 117 | background-color: rgba(255, 0, 0, 0.3); /* rgb 加透明度 */ 118 | 119 | /* 图片 */ 120 | background-image: url(/path-to-image/image.jpg); 121 | 122 | /* 字体 */ 123 | font-family: Arial; 124 | font-family: "Courier New"; /* 使用双引号包裹含空格的字体名称 */ 125 | font-family: "Courier New", Trebuchet, Arial; /* 如果第一个 126 | 字体没找到,浏览器会使用第二个字体,一次类推 */ 127 | } 128 | 129 | ``` 130 | 131 | ## 使用 132 | 133 | CSS 文件使用 `.css` 后缀。 134 | 135 | ```xml 136 | 137 | 138 | 139 | 140 | 143 | 144 | 146 |
147 |
148 | 149 | ``` 150 | 151 | ## 优先级 152 | 153 | 同一个元素可能被多个不同的选择器指定,因此可能会有冲突。 154 | 155 | 假定 CSS 是这样的: 156 | 157 | ```css 158 | /*A*/ 159 | p.class1[attr='value'] 160 | 161 | /*B*/ 162 | p.class1 {} 163 | 164 | /*C*/ 165 | p.class2 {} 166 | 167 | /*D*/ 168 | p {} 169 | 170 | /*E*/ 171 | p { property: value !important; } 172 | 173 | ``` 174 | 175 | 然后标记语言为: 176 | 177 | ```xml 178 |

179 |

180 | ``` 181 | 182 | 那么将会按照下面的顺序应用风格: 183 | 184 | 185 | * `E` 优先级最高,因为它使用了 `!important`,除非很有必要,尽量避免使用这个。 186 | * `F` 其次,因为它是嵌入的风格。 187 | * `A` 其次,因为它比其他指令更具体。 188 | * `C` 其次,虽然它的具体程度和`B`一样,但是它在`B`之后。 189 | * 接下来是 `B`。 190 | * 最后是 `D`。 191 | 192 | ## 兼容性 193 | 194 | CSS2 的绝大部分特性兼容各种浏览器和设备。现在 CSS3 的兼容性也越来越好了。 195 | 但是兼容性问题仍然是需要留意的一个问题。 196 | 197 | [QuirksMode CSS](http://www.quirksmode.org/css/)是关于这方面最好的资源。 198 | 199 | ## 扩展阅读 200 | 201 | * [理解 CSS 的风格优先级: 特定性, 继承和层叠](http://www.vanseodesign.com/css/css-specificity-inheritance-cascaade/) 202 | * [QuirksMode CSS](http://www.quirksmode.org/css/) 203 | * [Z-Index - The stacking context](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context) 204 | -------------------------------------------------------------------------------- /Vue/vue-base-demo/list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 新闻列表 8 | 9 | 10 | 11 | 12 | 13 |
14 | 29 |
30 |
31 |
32 |
33 |
34 | 列表 35 |
36 |
37 |
    38 |
  • 39 |
    40 | {{ item.author }} 41 |
    42 |
    43 | 46 |
    47 | 50 |
    51 |
    52 |
  • 53 | 54 |
55 |
56 |
57 | 71 |
72 |
73 |
74 |
75 |
76 | 79 |
80 | 81 | 82 | 83 | 84 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /《代码整洁之道》.md: -------------------------------------------------------------------------------- 1 | # 《代码整洁之道》 2 | 3 | ## 第一章 整洁代码 4 | 5 | ### 1、赶上期限的唯一方法:始终尽可能保持代码整洁 6 | 7 | ### 2、整洁的代码只做好一件事 8 | 9 | ### 3、整本书的主旨,不要重复代码,只做一件事,表达力,小规模抽象 10 | 11 | ### 4、要想干得快,要想快点做完,要想轻松写代码,先让代码易读吧 12 | 13 | ### 5、让每次签入时,代码都比签出时干净 14 | 15 | ## 第二章 有意义的命名 16 | 17 | ### 1、名副其实 18 | 19 | > 如果名称需要注释来补充,那就不算是名副其实。 20 | 21 | ### 2、避免误导 22 | 23 | > 别用 xxxList 来指称一组账号,除非它真的是 List 类型。(用 xxxGroup/bunchOfxxx/xxxs 代替更好) 24 | 25 | ### 3、做有意义的区分 26 | 27 | > 不要使用数字区分变量 / 函数命名。如 a1,a2... 28 | > 不要添加废话区分命名。如:ProductInfo 和 ProductData 29 | 30 | ### 4、使用读得出来的名称 31 | 32 | > 比如日期:用 generationTimestamp,而不要使用 genymdhms。 33 | 34 | ### 5、使用可搜索的名称 35 | 36 | > 单字母和数字常量很难搜出。使用宏或者变量命名这类数据。 37 | 38 | ### 6、避免使用编码 39 | 40 | > 不必用前缀表示成员变量。 41 | 42 | ### 7、避免思维映射 43 | 44 | ### 8、类名 45 | 46 | > 类名和对象应该是名词或名词短语。 47 | 48 | ### 9、方法名 49 | 50 | > 方法名应该是动词或动词短语。 51 | 52 | ### 10、别扮可爱 53 | 54 | ### 11、每个概念对应一个词 55 | 56 | ### 12、别用双关语 57 | 58 | > 避免将同一个单词用于不同目的。 59 | 60 | ### 13、使用解决方案领域名称 61 | 62 | > 尽可能使用 IT 类术语 63 | 64 | ### 14、使用源自所涉问题领域的名称 65 | 66 | ### 15、使用有意义的语境 67 | 68 | > 如:使用 addrState 代替 state 69 | 70 | ### 16、不要添加没用的语境 71 | 72 | > 如:不要用 GSD 代替 GasStationDeluxe 这样类似的短语。 73 | 74 | ## 第三章 函数 75 | 76 | ### 1、函数的第一规则是要短小,第二规则是还要更短小 77 | 78 | ### 2、函数的缩进层数不该多于一层或两层 79 | 80 | ### 3、函数应该做一件事,做好这件事,只做这一件事 81 | 82 | ### 4、要判断函数是否不止做了一件事,看是否能再拆出一个函数,该函数不仅是单纯地重新诠释其实现 83 | 84 | ### 5、函数参数,最理想的参数是 0, 其次是 1, 再次是 2\. 尽量避免 3 个。有足够特殊的理由才能用 3 个以上函数 85 | 86 | ### 6、如果函数看起来需要两个,三个或三个以上参数,就说明其中一些参数应该封装成类了 87 | 88 | ### 7、函数不应有副作用,如,检查密码的函数不应该有初始化 Session 的步骤 89 | 90 | ### 8、把指令和询问分隔开来 91 | 92 | ### 9、别重复自己 93 | 94 | ### 10、如何做到:先想些什么就写什么,然后再打磨它 95 | 96 | ## 第四章 注释 97 | 98 | ### 1、注释的恰当用法是弥补我们在用代码表达意图时遭遇的失败 99 | 100 | ### 2、注释会撒谎,因为修改代码后并不会让注释随之变动 101 | 102 | ### 3、注释不会美化糟糕的代码 103 | 104 | ### 4、与其花时间美化代码,不如花时间清洁代码 105 | 106 | ### 好注释 107 | 108 | * 法律信息 109 | * 提供信息的注释 110 | * 对意图的注释 111 | * 阐释 112 | * 警示 113 | * TODO 114 | * 放大:放大某种看起来不合理之物的重要性 115 | * 公共 API 中的 javadoc 116 | 117 | ### 坏注释 118 | 119 | * 喃喃自语 120 | * 多余的注释 121 | * 误导性注释 122 | * 循规式注释 123 | * 日志式注释 124 | * 废话注释 125 | * 可怕的废话 126 | * 能用函数或变量时就别用注释 127 | * 位置标记 128 | * 括号后面的注释 129 | * 归属和署名 130 | * 注释掉的代码(别这么干) 131 | * html 注释 132 | * 非本地信息 133 | * 信息过多 134 | * 不明显的联系 135 | * 函数头 136 | * 非公共代码中的 javadoc 137 | 138 | ## 第五章 格式 139 | 140 | ### 1、代码格式很重要,关乎沟通 141 | 142 | ### 2、实体变量应该在类的顶部声明 143 | 144 | ### 3、相关函数。若某个函数调用了另一个,就应该把它们放到一起。而且调用着应该尽可能放在被调用着上面 145 | 146 | ### 4、四则运算时,运算级较高的符号可以不用空格隔开 147 | 148 | ### 5、每个程序员都有自己喜欢的格式规则,但如果在一个团队中工作,就是团队说了算 149 | 150 | ## 第六章 对象和数据结构 151 | 152 | ### 1、隐藏实现并非只是变量之间放上一个函数层那么简单。隐藏实现关乎抽象。类并不简单地用取值器和赋值器将变量推向外间,而是暴露抽象接口,以便用户无需了解数据的实现便能操作数据本体 153 | 154 | ### 2、要以最好的方式呈现某个对象包含的数据,需要做严肃的思考 155 | 156 | ### 3、过程式代码便于在不改动既有函数的前提下添加新类 157 | 158 | ### 4、得墨耳律:模块不应了解它所操作对象的内部情形 159 | 160 | ### 例如:类 C 的 f 方法只应调用以下对象的方法 161 | 162 | > C 由 f 创建的对象 163 | > 由 C 的实体变量持有的对象 164 | > 即:方法不应调用由任何函数返回的对象的方法。 165 | 166 | ## 第七章 错误处理 167 | 168 | ### 1、使用异常而非返回码。 先写 try、catch、finally 语句 169 | 170 | ### 2、使用不可控异常 171 | 172 | ### 3、给出异常发生的环境说明 173 | 174 | > 应创建信息充分的错误信息,并和异常一起传递出去。在消息中,包括失败的操作和失败的类型。如果你的应用程序由日志系统,传递足够的信息给 catch 块,并记录下来。 175 | 176 | ### 4、依调用者需要定义异常类 177 | 178 | ### 5、定义常规流程 179 | 180 | ### 6、别返回 null 值 181 | 182 | ### 7、别传递 null 值 183 | 184 | ## 第九章 单元测试 185 | 186 | ### 1、TDD 三定律 187 | 188 | 1. 在编写不能通过的单元测试前,不可编写生产代码。 189 | 2. 只可编写刚好无法通过的单元测试,不能编译也不算通过。 190 | 3. 只可编写刚好足以通过当前失败测试的生产代码。 191 | 192 | ### 2、保持测试整洁 193 | 194 | ### 3、脏测试等同于没测试 195 | 196 | ### 4、测试代码和生产代码一样重要 197 | 198 | ### 5、整洁的测试三要素:可读性,可读性和可读性 199 | 200 | ### 6、每个测试一个断言 201 | 202 | ### 7、每个测试只测试一个概念 203 | 204 | ### 8、F.I.R.S.T 205 | 206 | > Fast(快速)、Independent(独立)、Repeatable(可重复)、Self-Validating(自足验证)、Timely(及时) 207 | 208 | ## 第十章 类 209 | 210 | ### 1、类应该短小 211 | 212 | ### 2、用权责衡量类的大小 213 | 214 | ### 3、如果无法为某个类命以精确的名称,这个类大概太长了 215 | 216 | ### 4、SRP,单一权责原则,类或模块应有且只有一条加以修改的理由 217 | 218 | ### 5、系统应该有许多短小的类而不是少量巨大的类组成。每个小雷封装一个权责,只有一个修改的原因,并与少数其他类一起协同达成期望的系统行为 219 | 220 | ### 6、内聚:如果一个类中的每个变量都被每个方法所使用,则该类具有最大的内聚性 221 | 222 | ## 第十一章 系统 223 | 224 | ### 1、将构造与使用分开的方法之一是将全部构造过程搬迁到 main 或被称之为 main 的模块中,设计系统的其他部分时,假设所有对象都已正确构造和设置 225 | 226 | ### 2、使用工厂方法,让程序负责确定何时创建对象 227 | 228 | ### 3、AOP 切面编程 229 | 230 | ## 第十二章 迭进 231 | 232 | ### 1、简单设计四条规则 233 | 234 | 1. 运行所有测试; 235 | 2. 不可重复; 236 | 3. 表达了程序员的意图; 237 | 4. 尽可能减少类和方法的数量。 238 | 239 | ### 2、极其雷同的代码就是重复 240 | 241 | ### 3、要想实现大规模复用,必须理解如何实现小规模复用 242 | 243 | ### 4、模板方法模式是一种移除高层级重复的通用技巧 244 | 245 | ## 第十三章 并发编程 246 | 247 | ### 1、对象是过程的抽象,线程是调度的抽象 248 | 249 | ### 2、并发是一种解耦策略,帮助我们把做什么(目的)和何时(时间)做分解开 250 | 251 | ### 3、并发会在性能和编写额外代码上增加一些开销 252 | 253 | ### 4、正确的并发是复杂的,即便对于简单的问题也是如此 254 | 255 | ### 5、并发缺陷并非总能重现,所以常被看做偶发事件而忽略,未被当作真的缺陷对待 256 | 257 | ### 6、并发常常需要对设计策略的根本性修改 258 | 259 | ### 7、并发防御原则 260 | 261 | * SRP,分离并发相关代码和其他代码。 262 | * 推论:限制数据作用域。 263 | * 推论:使用数据复本,避免共享数据的好方法之一就是一开始就避免共享数据。 264 | * 推论:线程应尽可能独立。尝试将数据分解到可独立线程(可能在不同处理器上)操作的独立子集。 265 | 266 | ### 8、并发执行模型 267 | 268 | * 生产者-消费者 269 | * 读者-作者 270 | * 宴席哲学家 271 | 272 | ### 9、学习这些基础算法,理解其解决方案 273 | 274 | ### 10、在你认为自己完成某个函数之前,确认自己理解了它是怎么工作的。通过全部测试还不够好。你必须知道解决方案是正确的。获得这种知识和理解的最好途径,往往是重构函数,得到某种整洁而足具表达力、清楚呈示如何工作的东西 275 | 276 | ### 11、用多态替代 If/Else 或 Switch/Case 277 | -------------------------------------------------------------------------------- /Linux/Vim.md: -------------------------------------------------------------------------------- 1 | # Vim 2 | 3 | [Vim](http://www.vim.org) 4 | (Vi IMproved) 是 Unix 上的流行编辑器 vi 的克隆版本。这个文本编辑器 5 | 是为性能和提升效率而设计的,并且在大多数基于 unix 的系统上普遍存在。 6 | 它有大量的快捷键可用来快速导航到文件的特定位置,以便进行快速编辑。 7 | 8 | ## Vim 导航基础 9 | 10 | ``` bash 11 | vim # 在 Vim 中打开 12 | :q # 退出 Vim 13 | :w # 保存当前文件 14 | :wq # 保存文件并退出 Vim 15 | :q! # 退出 Vim 并且不保存文件 16 | # ! *强制* 执行 :q, 因此没有保存就退出 Vim 17 | :x # 保存文件并且退出 Vim, 是 :wq 的简写版本 18 | 19 | u # 撤销 20 | CTRL+R # 重做 21 | 22 | h # 左移一个字符 23 | j # 下移一行 24 | k # 上移一行 25 | l # 右移一个字符 26 | 27 | # 在行内移动 28 | 29 | 0 # 移到行首 30 | $ # 移到行尾 31 | ^ # 移到行内的第一个非空白字符处 32 | 33 | # 在文本中查找 34 | 35 | /word # 光标之后的所有该词都高亮显示 36 | ?word # 光标之前的所有该词都高亮显示 37 | n # 查找后将光标移到该词的下一个出现位置 38 | N # 光标移到该词的上一个出现位置 39 | 40 | :%s/foo/bar/g # 将文件每一行上的所有 'foo' 都改成 'bar' 41 | :s/foo/bar/g # 将当前行上的所有 'foo' 都改成 'bar' 42 | 43 | # 跳到字符处 44 | 45 | f<字符> # 向前跳移到 <字符> 上 46 | t<字符> # 向前跳移到 <字符> 的左侧 47 | 48 | # 例如, 49 |    f<               # 向前跳移到 < 上 50 | t< # 向前跳移到 < 的左侧 51 | 52 | # 按词移动 53 | # 默认一个单词由字母,数字和下划线组成 54 | 55 |    w               # 移动到下一个词首 56 |    b               # 移动到前一个词首 57 |    e               # 移动到下一个词尾 58 | 59 | 60 | # 移动的其它命令 61 | 62 | gg # 移到文件顶部 63 | G # 移到文件末尾 64 | :NUM # 移到第 NUM 行 (NUM 是任意数字) 65 | H # 移到屏幕顶部 66 | M # 移到屏幕中间位置 67 | L # 移到屏幕末尾 68 | ``` 69 | 70 | ## 模式 71 | 72 | Vim 基于 **模式** 这个概念。 73 | 74 | 命令模式 - Vim 启动后就处于这个模式,用于导航和操作命令 75 | 插入模式 - 用于在你的文件中进行修改 76 | 可视模式 - 用于高亮文本并对它们进行操作 77 | Ex 模式 - 用于跳到底部的 ':' 提示行上输入命令 78 | 79 | ``` bash 80 | i # 在光标位置前,将 Vim 切换到插入模式 81 | a # 在光标位置后,将 Vim 切换到插入模式 82 | v # 将 Vim 切换到可视模式 83 | : # 将 Vim 切换到 ex 模式 84 | # 无论你当前处于什么模式,都返回到命令模式 85 | 86 | # 复制和粘贴文本 87 | 88 | y # 复制所选的内容 89 | yy # 复制当前行 90 | d # 删除所选的内容 91 | dd # 删除当前行 92 | p # 在当前光标位置后粘贴复制的文本 93 | P # 在当前光标位置前粘贴复制的文本 94 | x # 删除当前光标位置处的字符 95 | ``` 96 | 97 | ## Vim 的 '语法' 98 | 99 | Vim 可以被认为是按 '动词-修饰词-名词' 格式编排的一组命令: 100 | 101 | 动词 - 你的动作 102 | 修饰词 - 你如何执行你的动作 103 | 名词 - 你的动作所作用于的对象 104 | 105 | 关于 '动词','修饰词',和 '名词' 的几个重要例子: 106 | 107 | ``` bash 108 | # '动词' 109 | 110 | d # 删除 111 | c # 修改 112 | y # 复制 113 | v # 可视化选择 114 | 115 | # '修饰词' 116 | 117 | i # 内部的 118 | a # 周围的 119 | NUM # 数字 (NUM 是任意数字) 120 | f # 查找文本并位于其上 121 | t # 查找文本并停于其前面 122 | / # 从光标处开始查找字符串 123 | ? # 在光标前查找字符串 124 | 125 | # '名词' 126 | 127 | w # 词 128 | s # 句子 129 | p # 段落 130 | b # 块 131 | 132 | # 示例 '语句' 或命令 133 | 134 | d2w # 删除 2 个词 135 | cis # 修改段落内的内容 136 | yip # 复制段落内的内容 (复制你所在的段落) 137 | ct< # 修改直到括号开启处 138 | # 对你的当前位置直到下个括号开启处的内容进行修改 139 | d$ # 删除直到行尾 140 | ``` 141 | 142 | ## 一些快捷键和技巧 143 | 144 | ``` bash 145 | > # 将所选内容缩进一级 146 | < # 将所选内容取消缩进一级 147 | :earlier 15m # 将文档还原到 15 分钟前的状态 148 | :later 15m # 逆转上述命令 149 | ddp # 相邻行交换位置,先 dd 再 p 150 | . # 重复之前动作 151 | ``` 152 | 153 | ## 宏 154 | 155 | 宏基本上来说就是可录制的动作。 156 | 当你开始录制宏时,它会记录你使用的 **每个** 动作和命令, 157 | 直到你停止录制。当调用宏时,它会将这个完全相同的动作和命令序列 158 | 再次应用于所选文本之上。 159 | 160 | ``` bash 161 | qa # 开始录制一个叫 'a' 的宏 162 | q # 停止录制 163 | @a # 重播宏 164 | ``` 165 | 166 | ### 配置 ~/.vimrc 167 | 168 | .vimrc 可用于在启动时对 Vim 进行配置。 169 | 170 | 这里是一个示例 ~/.vimrc 文件: 171 | 172 | ``` bash 173 | " 示例 ~/.vimrc 174 | " 2015.10 175 | 176 | " 需要 Vim iMproved 版本 177 | set nocompatible 178 | 179 | " 根据文件名检测文件类型,以便能进行智能自动缩进等操作。 180 | filetype indent plugin on 181 | 182 | " 开启语法高亮 183 | syntax on 184 | 185 | " 更好的命令行补全 186 | set wildmenu 187 | 188 | " 除了当使用大写字母时使用大小写无关查找 189 | set ignorecase 190 | set smartcase 191 | 192 | " 当新开一行时,如果没有开启文件特定的缩进规则, 193 | " 则缩进保持与你当前行一致 194 | set autoindent 195 | 196 | " 在左侧显示行号 197 | set number 198 | 199 | " 缩进选项,根据个人偏好进行修改 200 | 201 | " 每个 TAB 的可视空格数 202 | set tabstop=4 203 | 204 | " 编辑时 TAB 对应的空格数 205 | set softtabstop=4 206 | 207 | " 当使用缩进操作 (>> 和 <<) 时缩进的空格数 208 | set shiftwidth=4 209 | 210 | " 将 TAB 转换成空格 211 | set expandtab 212 | 213 | " 为缩进和对齐开启智能化的 TAB 和空格切换功能 214 | set smarttab 215 | ``` 216 | 217 | ### 参考 218 | 219 | [Vim | Home](http://www.vim.org/index.php) 220 | 221 | `$ vimtutor` 222 | 223 | [A vim Tutorial and Primer](https://danielmiessler.com/study/vim/) 224 | 225 | [What are the dark corners of Vim your mom never told you about? (Stack Overflow thread)](http://stackoverflow.com/questions/726894/what-are-the-dark-corners-of-vim-your-mom-never-told-you-about) 226 | 227 | [Arch Linux Wiki](https://wiki.archlinux.org/index.php/Vim) 228 | -------------------------------------------------------------------------------- /应用代码分层.md: -------------------------------------------------------------------------------- 1 | # 应用代码分层 2 | 3 | 我们在写应用里的代码时根据代码负责的不同任务讲其分为五大块`Controller`, `Repository`, `Service`, `Model`, `View`。 4 | 5 | - `Model` 数据模型, 数据模型面向的是数据层,在这里我们只关心数据表的问题,在 Model 中应该只定义数据与对象映射相关的属性和方法如:表名、主键名、是否让 laravel 管理时间字段等属性,以及模型关联、查询作用域等方法。其他与数据表无关的业务逻辑都不应出现在这里。 6 | - `Repository` 数据逻辑访问层,由它来对接 Model 层,理论上有一个 Model 就会有一个相应的`Repository`,除了做最基础的数据访问外与数据相关的逻辑也放在这里,如果一个相对复杂的数据应用到了`Repository`对应的`Model`外其他`Model`的数据,不要直接去访问相关`Model`,应该由`Repository`调用相关`Model`的`Repository`。`Repository`是具体`interface`的实现,比如做订单相关的业务,应该有`OrderRepositoryInterface`定义`Order`数据交互流程中必须要实现的方法然后由`OrderRepository`去具体实现,之后将`OrderRepositoryInterface`和`OrderRepository`注册到服务容器中,解析时直接使用`OrderRepositoryInterface`解析出具体实现,这样消费层既不需要关心数据来自哪里是`Mysql`还是`MongoDB`,也给项目提供了足够的灵活性。当数据来源从`Mysql`更改为`MongoDB`后,我们只需要重新写一个实现类`OrderMongoRepository`然后将服务容器里`OrderRepositoryInterface`的实现切换成`OrderMongoRepository`就好,消费层完全不需要改动。 7 | (Repository 是我之前一直觉得在程序设计中特别多余而现在觉得特别重要的一个 Layer,之前在 Service 中揉进去了 Repository 的职能,后续会把相关的 Example 也做一下修改) 8 | - `Service` 项目中除了数据的 CRUD 还会有图片上传、请求外部 API 获取数据、发送邮件等等其他这些功能,这些功能应该定义在`Service`层。 9 | - `Controller` 控制器,面向的对象是一个完整的页面或者是接口,其主要职责是作为接收请求和发送响应的中控程序,通过调度项目中的 Service、 Repository 等来完成请求、组合响应数据,并通过页面响应或者接口数据的形式将响应返回给客户端。 10 | - `View` 视图, 负责渲染 HTML 响应,使用 Laravel 自带的 blade 模版引擎,并且应该尽量减少 PHP 代码。 11 | 12 | 总结:所以如果一个请求对应的业务逻辑相当复杂,我们可以通过 Controller 方法调用多个 Service 方法(单一逻辑)来完成这个复杂的逻辑,在 Service 方法中我们通过多个 Model 操作来实现更新、获取数据。通过这种原则来对复杂逻辑进行解耦。 13 | 14 | 我们通过看两个例子来更好的理解代码如何分层: 15 | 16 | ## 代码示例 17 | 18 | ### Example 1: 应该在哪里写 SQL 操作 19 | 20 | 如果一个查询在项目中只会用到一次,那么我们直接在 Controller 方法里写这个查询就很好, 举例来说你想查出所有的管理员用户: 21 | 22 | ``` php 23 | $admins = User::where('type', 'admin')->get(); 24 | ``` 25 | 26 | 现在假设你需要在不止一个 Controller 方法中用到这个查询, 你可以在`UserRepository`类里包装对`User`模型的访问: 27 | 28 | ``` php 29 | class UserRepository 30 | { 31 | public function getAlladmins() 32 | { 33 | return User::where('type', 'admin')->get(); 34 | } 35 | } 36 | ``` 37 | 38 | 现在你可以在用到`UserRepository`的`Controller`中通过依赖注入`UserRepository`, 然后通过这个 UserRepository 方法获取所有管理员用户: 39 | 40 | ``` php 41 | //Controller 42 | public function __construct(UserRepository $UserRepository) 43 | { 44 | $this->UserRepository = $UserRepository; 45 | } 46 | //Controller action 47 | public function index() 48 | { 49 | $admins = $this->UserRepository->getAllAdmins(); 50 | } 51 | ``` 52 | 53 | 最后,假设你还需要一个查询来计算管理员的数量, 可以在把这个查询封装到 UserService 的一个方法里: 54 | 55 | ``` php 56 | public function getAdminNum() 57 | { 58 | return User::where('type', 'admin')->count(); 59 | } 60 | ``` 61 | 62 | 这样写是 OK 的,但是你可能已经注意到了`User::where('type', 'admin')`这个片段在`getAllAdmins`这个查询里也有用到,所以我们可以用查询作用域来改进它(查询作用域也会让你的代码可读性变得更高): 63 | 64 | ``` php 65 | //UserModel 66 | public function scopeAdmins($query) 67 | { 68 | return $query->where('type', 'admin'); 69 | } 70 | ``` 71 | 72 | 然后在 UserRepository 里我们可以向下面这样重写它的查询: 73 | 74 | ``` php 75 | //UserRepository 76 | public function getAllAdmins() 77 | { 78 | return User:admins()->get(); 79 | } 80 | 81 | public function getAdminNum() 82 | { 83 | return User::admins()->count(); 84 | } 85 | ``` 86 | 87 | 就像上面说的那样在 Model 中我们应该撇开业务逻辑,面向数据表进行抽象,只定义表相关的属性、模型关联和查询作用域, 具体怎么应用 Model 中定义的这些内容, 那是 Controller 层和 Service 层要关心的事情。 88 | 89 | ### Example2: 通过 Service 类提高代码复用率 90 | 91 | 我们在做 CMS 系统管理内容时, 通常都会涉及到文章的上下线,置顶等操作。假设在系统中我们会用两个数据表分别存储文章和置顶, 在项目中对应两个 Model: Article 和 TopArticle。 92 | 93 | 假设我们需要实现下线文章的功能,如果文章是置顶文章,还要把文章取消置顶,我们在 ArticleService 里包装这个操作: 94 | 95 | ``` php 96 | public function setArticleOffline(Article $article) 97 | { 98 | if ($article->is_top == 1) {//如果是置顶文章需要将文章取消置顶 99 | $this->cancelTopArticle($article); 100 | } 101 | $article->status = Article::STATUS_OFFLINE; 102 | $article->offline_time = date('Y-m-d H:i:s'); 103 | $article->save(); 104 | 105 | return true; 106 | } 107 | 108 | /** 109 | * 取消文章的置顶 110 | * @param \App\Models\Article $article 111 | */ 112 | public function cancelTopArticle($article) 113 | { 114 | if (TopArticle::specificArticle($article->id)->count()) { 115 | //删除置顶表里的记录(待上线的置顶文章上线后置顶表中才能有相应的记录) 116 | TopArticle::specificArticle($article->id)->delete(); 117 | } 118 | //将文章的is_top字段置为0 119 | $article->is_top = 0; 120 | $article->save(); 121 | 122 | return true; 123 | } 124 | ``` 125 | 126 | 在 Controller 的 Action 里我们只需要负责验证接收来的参数,查询文章对象传递给 Service 来做下线操作, 这里之所以把取消置顶也单独提取出来是因为通常 CMS 系统里还有单独的文章取消置顶功能。 127 | 128 | ``` php 129 | //ArticleController 130 | public function setArticleOff(Request $request, ArticleService $artService) 131 | { 132 | ...//表单验证 133 | 134 | $article = Article::find($request->get('article_id')); 135 | $this->articleService->setArticleOffline($article); 136 | 137 | ... 138 | } 139 | ``` 140 | 141 | 除了上面讲到的主动下线文章的功能, 一般的文章系统里还会有定时上下线文章的功能, 因为我们在 ArticleService 里包装了下线文章的功能, 所以在设置定时任务时就可以再次调用 setArticleOffline 方法来完成文章下线的功能: 142 | 143 | ``` php 144 | //App\Console\Commands\ArticleCommand 145 | public function __construct(ArticleService $articleService) 146 | { 147 | $this->articleService = $articleService; 148 | parent::__construct(); 149 | } 150 | 151 | public function handle() 152 | { 153 | $operation = $this->argument('operation'); 154 | switch ($operation) { 155 | case 'offline': 156 | $this->setOffline(); 157 | break; 158 | default: 159 | break; 160 | } 161 | 162 | public function setOffline() 163 | { 164 | ......//前置条件查出要下线的文章 165 | $this>articleService>setArticleOffline($article); 166 | ...... 167 | } 168 | ``` 169 | 170 | 上面两个例子简单说明了我们把代码分层后每个层里应该写什么类型的程序,以及代码分层后在可读性、耦合性、维护成本等方面带来的收益。 171 | 172 | ## 原文链接 173 | 174 | * [https://github.com/kevinyan815/laravel_best_practices_cn/blob/master/src/CodeConvention/CodeLayer.md](https://github.com/kevinyan815/laravel_best_practices_cn/blob/master/src/CodeConvention/CodeLayer.md) 175 | -------------------------------------------------------------------------------- /Git/git-commit-message-change-log.md: -------------------------------------------------------------------------------- 1 | # git commit message 和 Change log 2 | 3 | ## Commit message 的格式 4 | 5 | 每次提交,Commit message 都包括三个部分:Header,Body 和 Footer。 6 | 7 | ```plain 8 | (): 9 | // 空一行 10 | 11 | // 空一行 12 |