├── LICENSE ├── README.md ├── git ├── advanced-git-commands.md └── git.md ├── laravel_cms ├── 01.md ├── 02.md ├── 03.md ├── 04.md └── 05.md ├── mysql └── basic.md └── php ├── 30_seconds_of_knowledge_php.md ├── interview.md ├── interview_2.md └── randomLuckyRedPacket.php /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 笔记文摘 2 | ======= 3 | 4 | 用 `markdown` 书写的笔记(部分来源于互联网),共享出来给大家! 5 | 6 | 7 | ### 面试题系列: 8 | 9 | - [PHP面试题汇总](php/interview.md) [#1](https://github.com/ycrao/mynotes/issues/1) 10 | - [PHP面试题汇总二](php/interview_2.md) [#4](https://github.com/ycrao/mynotes/issues/4) 11 | 12 | ### 代码片段: 13 | 14 | - [实现QQ/微信拼手气红包算法](php/randomLuckyRedPacket.php):这里仅考虑红包分配自身,不考虑并发、超时退回等逻辑。 15 | - 来自 [30 seconds of knowledge](https://github.com/30-seconds/30_seconds_of_knowledge/tree/master/src/assets/snippets/php) 相关 [PHP代码片段](php/30_seconds_of_knowledge_php.md) [#5](https://github.com/ycrao/mynotes/issues/5) 。 16 | 17 | ### Laravel 入门教程: 18 | 19 | 本人 `2017` 年写的 `Laravel` 系列教程,使用的4版,内容可能有些过时或错漏。博客连载地址为:http://douyasi.com/category/startlaravel/ 20 | 21 | 目录 22 | 23 | 1. [准备性工作](laravel_cms/01.md) 24 | 2. [建立数据库](laravel_cms/02.md) 25 | 3. [页面显示与路由控制(一)](laravel_cms/03.md) 26 | 4. [页面显示与路由控制(二)](laravel_cms/04.md) 27 | 5. [RESTFUL路由与控制器](laravel_cms/05.md) 28 | ... 29 | 30 | ### Git 相关: 31 | 32 | - [Git设置与使用帮助](git/git.md) [#2](https://github.com/ycrao/mynotes/issues/2) 33 | - [直接拿来用!10段超有用的Git命令行代码](git/advanced-git-commands.md) [#3](https://github.com/ycrao/mynotes/issues/3) 34 | 35 | ### MySQL 相关: 36 | 37 | [MySQL基础命令](mysql/basic.md) 38 | 39 | ### Rust 相关: 40 | 41 | Rust 学习笔记及示例代码: [Learning Rust](https://github.com/ycrao/learning_rust) 。 42 | 43 | ### Bash 相关: 44 | 45 | 本人翻译的 [Bash 中文指南](https://github.com/ycrao/bash-guide) ,不错的 `linux bash` 命令入门材料。 46 | 47 | ### Vue 相关: 48 | 49 | Vue.js 学习示例及笔记:[Learning Vue](https://github.com/ycrao/learning_vue) 。 50 | 51 | ### JAVA 相关: 52 | 53 | - 学习 Java 示例及笔记:[Learning Java](https://github.com/ycrao/learning_java) 54 | - Simple restful API service Demo: [simple-api-service](https://github.com/douyasi/simple-api-service) 55 | - Spring 集成大全: [spring-tutorials](https://github.com/ycrao/spring-tutorials) 56 | 57 | ### RabbitMQ 相关: 58 | 59 | - RabbitMQ 多运行模式简介:[rabbitmq-examples](https://github.com/ycrao/rabbitmq-examples) 60 | - PHP 运行时下 RabbitMQ 消费端常驻解决办法:[rabbitmq-consumer](https://github.com/ycrao/rabbitmq-consumer) 61 | 62 | ### Golang 相关: 63 | 64 | - 学习 `golang` 过程中,编写的一些代码及软件:[learning_golang](https://github.com/ycrao/learning_golang) 65 | 66 | ### Docker 相关: 67 | 68 | - 基于 `alpine` 底包原始构建[基础运行时镜像](https://github.com/ycrao/base-runtime-images),镜像文件较小,且生产可用,目前主要是 `php-fpm` 运行时相关的镜像,后期会编写一些其它语言与服务的镜像。 69 | 70 | ### 大前端相关: 71 | 72 | - 最新的 `Vue3` 架手架模版:[ycrao/topop-vue](https://github.com/ycrao/topop-vue) 。 73 | - 前端 `Excel` 导出解决方案:[ycrao/frontend-excel-export](https://github.com/ycrao/frontend-excel-export) 74 | - 云端研学代码:[stackblitz.com/@ycrao](https://stackblitz.com/@ycrao/collections/learning-typescript) 75 | 76 | ### 杂项: 77 | 78 | - 和谐:[ycrao/harmony](https://github.com/ycrao/harmony) 79 | - 如意:[ycrao/ruyi](https://github.com/ycrao/ruyi) -------------------------------------------------------------------------------- /git/advanced-git-commands.md: -------------------------------------------------------------------------------- 1 | # 直接拿来用!10段超有用的Git命令行代码 2 | 3 | 4 | > 迄今,我已经使用Git很长一段时间了,考虑分享一些不管你是团队开发还是个人项目,都受用的高级git命令。 5 | 6 | ## 1. 输出最后一次提交的改变 7 | 这个命令,我经常使用它 来发送其他没有使用git的人来检查或者集成所修改的。它会输出最近提交的修改内容到一个zip文件中。 8 | 9 | ```bash 10 | git archive -o ../updated.zip HEAD $(git diff --name-only HEAD^) 11 | ``` 12 | 13 | ## 2. 输出两个提交间的改变 14 | 类似的,如果你需要输出某两个提交间的改变时,你可以使用这个。 15 | 16 | ``` 17 | git archive -o ../latest.zip NEW_COMMIT_ID_HERE $(git diff --name-only OLD_COMMIT_ID_HERE NEW_COMMIT_ID_HERE) 18 | ``` 19 | 20 | ## 3. 克隆 指定的远程分支 21 | 如果你渴望只克隆远程仓库的一个指定分支,而不是整个仓库分支,这对你帮助很大。 22 | 23 | ```bash 24 | git init 25 | git remote add -t BRANCH_NAME_HERE -f origin REMOTE_REPO_URL_PATH_HERE 26 | git checkout BRANCH_NAME_HERE 27 | ``` 28 | 29 | ## 4. 应用 从不相关的本地仓库来的补丁 30 | 如果你需要其它一些不相关的本地仓库作为你现在仓库的补丁,这里就是通往那里的捷径。 31 | 32 | ```bash 33 | git --git-dir=PATH_TO_OTHER_REPOSITORY_HERE/.git format-patch -k -1 --stdout COMMIT_HASH_ID_HERE| git am -3 -k 34 | ``` 35 | 36 | ## 5. 检测 你的分支的改变是否为其它分支的一部分 37 | cherry命令让我们检测你的分支的改变是否出现在其它一些分支中。它通过+或者-符号来显示从当前分支与所给的分支之间的改变:是否合并了(merged)。.+ 指示没有出现在所给分支中,反之,-就表示出现在了所给的分支中了。这里就是如何去检测: 38 | 39 | ```bash 40 | git cherry -v OTHER_BRANCH_NAME_HERE 41 | #For example: to check with master branch 42 | git cherry -v master
43 | ``` 44 | 45 | ## 6. 开始一个无历史的新分支 46 | 有时,你需要开始一个新分支,但是又不想把很长很长的历史记录带进来,例如,你想在公众区域(开源)放置你的代码,但是又不想别人知道它的历史记录。 47 | 48 | ```bash 49 | git checkout --orphan NEW_BRANCH_NAME_HERE 50 | ``` 51 | 52 | ## 7. 无切换分支的从其它分支Checkout文件 53 | 不想切换分支,但是又想从其它分支中获得你需要的文件: 54 | 55 | ```bash 56 | git checkout BRANCH_NAME_HERE -- PATH_TO_FILE_IN_BRANCH_HERE 57 | ``` 58 | 59 | ## 8. 忽略已追踪文件的变动 60 | 61 | 如果您正在一个团队中工作,而且大家都在同一条branch上面工作,那么您很有可能会经常用到fetch和merge。但是有时候这样会重置您的环境配置文件,如此的话,您就得在每次merge后修改它。使用这一命令,您就能要求git忽视指定文件的变动。这样,下回你再merge的话,这个文件就不会被修改了。 62 | 63 | ```bash 64 | git update-index --assume-unchanged PATH_TO_FILE_HERE 65 | ``` 66 | 67 | ## 9. 检查提交的变动是否是release的一部分 68 | 69 | name-rev命令能告诉您一个commit相对于最近一次release的位置。使用这条命令,您就可以检查您所做出的改动是否是release的一部分了。 70 | 71 | ```bash 72 | git name-rev --name-only COMMIT_HASH_HERE 73 | ``` 74 | 75 | ## 10. 使用rebase推送而非merge 76 | 77 | 如果您正在团队中工作并且整个团队都在同一条branch上面工作,那么您就得经常地进行fetch/merge或者pull。Git中,分支的合并以所提交的merge来记录,以此表明一条feature分支何时与主分支合并。但是在多团队成员共同工作于一条branch的情形中,常规的merge会导致log中出现多条消息,从而产生混淆。因此,您可以在pull的时候使用rebase,以此来减少无用的merge消息,从而保持历史记录的清晰。 78 | 79 | ```bash 80 | git pull --rebase 81 | ``` 82 | 83 | 您也可以将某条branch配置为总是使用rebase推送: 84 | 85 | ```bash 86 | git config branch.BRANCH_NAME_HERE.rebase true 87 | ``` 88 | 89 | 英文出自: [Webdeveloperplus](http://webdeveloperplus.com/general/10-useful-advanced-git-commands/) 90 | 91 | 中文译文来自:[OSChina](http://www.oschina.net/translate/10-useful-advanced-git-commands) 92 | -------------------------------------------------------------------------------- /git/git.md: -------------------------------------------------------------------------------- 1 | # Git设置与使用帮助 2 | 3 | 4 | > 参考网站: 5 | http://rogerdudler.github.io/git-guide/index.zh.html 6 | http://git.oschina.net/progit/ 7 | 8 | ### 1. 检查是否已经有SSH Key 9 | 10 | ```bash 11 | cd ~/.ssh 12 | ``` 13 | 14 | ### 2. 生成一个新的SSH Key 15 | 16 | ```bash 17 | ssh-keygen -t rsa -C "admin@example.com" 18 | ``` 19 | 请自行替换 `admin@example.com` 为自己的电邮地址。之后直接回车,不用填写东西。之后会让你输入密码短语(`passphrase`)。然后就生成一个目录 `.ssh` ,里面有两个文件: `id_rsa` 和 `id_rsa.pub` 。 20 | 21 | ### 3. Git配置 22 | 23 | **1. 配置用户信息** 24 | 25 | ```bash 26 | git config --global user.name "John Doe" 27 | git config --global user.email "johndoe@example.com" 28 | ``` 29 | 30 | 请自行替换 `John Doe` 为自己常用的英文网络`ID` , `johndeo@exaple.com` 为自己常用的 `Email` 。 31 | 32 | **2. 获取帮助** 33 | 34 | 想了解 `Git` 的各式工具该怎么用,可以阅读它们的使用帮助,方法有三: 35 | 36 | ```bash 37 | git help 38 | git --help 39 | man git- 40 | ``` 41 | 42 | 比如,要学习 `config` 命令可以怎么用,运行: 43 | 44 | ```bash 45 | git help config 46 | ``` 47 | 48 | ### 4. Git相关操作命令 49 | 50 | 51 | **1. 创建新仓库** 52 | 53 | 创建新文件夹,打开,然后执行: 54 | 55 | ```bash 56 | git init 57 | ``` 58 | 59 | 以创建新的 git 仓库。 60 | 61 | **2. 检出仓库** 62 | 63 | 执行如下命令以创建一个本地仓库的克隆版本: 64 | 65 | ```bash 66 | git clone /path/to/repository 67 | ``` 68 | 69 | 如果是远端服务器上的仓库,你的命令会是这个样子: 70 | 71 | ```bash 72 | git clone username@host:/path/to/repository 73 | ``` 74 | 75 | **3. 工作流** 76 | 77 | 你的本地仓库由 `git` 维护的三棵“树”组成。第一个是你的 工作目录,它持有实际文件;第二个是 缓存区(`Index`),它像个缓存区域,临时保存你的改动;最后是 `HEAD`,指向你最近一次提交后的结果。 78 | 79 | **4. 添加与提交** 80 | 81 | 你可以计划改动(把它们添加到缓存区),使用如下命令: 82 | 83 | ```bash 84 | git add 85 | git add * 86 | ``` 87 | 88 | 这是 git 基本工作流程的第一步;使用如下命令以实际提交改动: 89 | 90 | ```bash 91 | git commit -m "代码提交信息" 92 | ``` 93 | 94 | 现在,你的改动已经提交到了 `HEAD`,但是还没到你的远端仓库。 95 | 96 | **5. 推送改动** 97 | 98 | 你的改动现在已经在本地仓库的 HEAD 中了。执行如下命令以将这些改动提交到远端仓库: 99 | 100 | ```bash 101 | git push origin master 102 | ``` 103 | 104 | 可以把 `master` 换成你想要推送的任何分支。 105 | 106 | 如果你还没有克隆现有仓库,并欲将你的仓库连接到某个远程服务器,你可以使用如下命令添加: 107 | 108 | ```bash 109 | git remote add origin 110 | ``` 111 | 112 | 如此你就能够将你的改动推送到所添加的服务器上去了。 113 | 114 | **6. 分支** 115 | 116 | 分支是用来将特性开发绝缘开来的。在你创建仓库的时候,`master` 是“默认的”。在其他分支上进行开发,完成后再将它们合并到主分支上。 117 | 118 | 创建一个叫做 `feature_x` 的分支,并切换过去: 119 | 120 | ```bash 121 | git checkout -b feature_x 122 | ``` 123 | 124 | 切换回主分支: 125 | 126 | ```bash 127 | git checkout master 128 | ``` 129 | 130 | 再把新建的分支删掉: 131 | 132 | ```bash 133 | git branch -d feature_x 134 | ``` 135 | 136 | 除非你将分支推送到远端仓库,不然该分支就是 不为他人所见的: 137 | 138 | ```bash 139 | git push origin 140 | ``` 141 | 142 | **7. 更新与合并** 143 | 144 | 要更新你的本地仓库至最新改动,执行: 145 | 146 | ```bash 147 | git pull 148 | ``` 149 | 150 | 以在你的工作目录中 获取(`fetch`) 并 合并(`merge`) 远端的改动。 151 | 要合并其他分支到你的当前分支(例如 `master`),执行: 152 | 153 | ```bash 154 | git merge 155 | ``` 156 | 157 | 两种情况下,`git` 都会尝试去自动合并改动。不幸的是,自动合并并非次次都能成功,并可能导致 冲突(`conflicts`)。 这时候就需要你修改这些文件来人肉合并这些 冲突(`conflicts`) 了。改完之后,你需要执行如下命令以将它们标记为合并成功: 158 | 159 | ```bash 160 | git add 161 | ``` 162 | 在合并改动之前,也可以使用如下命令查看: 163 | 164 | ```bash 165 | git diff 166 | ``` 167 | 168 | **8. 标签** 169 | 170 | 在软件发布时创建标签,是被推荐的。这是个旧有概念,在 `SVN` 中也有。可以执行如下命令以创建一个叫做 `1.0.0` 的标签: 171 | 172 | ```bash 173 | git tag 1.0.0 1b2e1d63ff 174 | ``` 175 | 176 | `1b2e1d63ff` 是你想要标记的提交 `ID` 的前 10 位字符。使用如下命令获取提交 `ID`: 177 | 178 | ```bash 179 | git log 180 | ``` 181 | 你也可以用该提交 `ID` 的少一些的前几位,只要它是唯一的。 182 | 183 | **9. 替换本地改动** 184 | 185 | 假如你做错事(自然,这是不可能的),你可以使用如下命令替换掉本地改动: 186 | 187 | ```bash 188 | git checkout -- 189 | ``` 190 | 191 | 此命令会使用 `HEAD` 中的最新内容替换掉你的工作目录中的文件。已添加到缓存区的改动,以及新文件,都不受影响。 192 | 193 | 假如你想要丢弃你所有的本地改动与提交,可以到服务器上获取最新的版本并将你本地主分支指向到它: 194 | 195 | ```bash 196 | git fetch origin 197 | git reset --hard origin/master 198 | ``` 199 | 200 | **10.在命令行中创建并提交Git仓库** 201 | 202 | ```bash 203 | mkdir example 204 | cd example 205 | git init 206 | echo "# example" >> README.md 207 | git add README.md 208 | git commit -m "first commit" 209 | git remote add origin git@github.com:ycrao/example.git 210 | git push -u origin master 211 | ``` 212 | 213 | **11. 在命令行提交已有项目** 214 | 215 | ```bash 216 | cd existing_git_repo 217 | git remote add origin git@github.com:ycrao/existing_git_repo.git 218 | git push -u origin master 219 | ``` 220 | 221 | 注意:第10、11条示例中 `git@github.com:ycrao/example.git` 或 `git@github.com:ycrao/existing_git_repo.git` 是仓库 `SSH` 方式地址,一般源码托管服务商(如 `GitHub` 和 `Coding` )会在仓库页面中告知你,请根据实际情况与操作自行替换。 -------------------------------------------------------------------------------- /laravel_cms/01.md: -------------------------------------------------------------------------------- 1 | # Laravel入门教程——一个简单cms的实现(01) 2 | 3 | > 作者: douyasi 4 | > 网站:http://douyasi.com/category/startlaravel/ 5 | > 备注:本教程是在当前最新Laravel稳定版v4.2.X下实现的,其它相异版本如果有问题请自行排除。 6 | > 本文为作者原创记录,转载请保留署名与来源。 7 | 8 | ## 准备性工作 9 | 10 | ### 说明 11 | 12 | 这里准备性工作是指“实现这个cms项目之前必须完成的事务”,比如: 13 | **需求的明确**,**前端页面的设计与实现**,**框架初始化环境的搭建**,**数据库模型的设计**等。 14 | 15 | 这里我就不多列举出来啊,这些准备性的工作有时也会耗费不少精力,尤其是在我自己一个人独立完成的情况下。 16 | 17 | ### 系统目标与需求 18 | 下面简单的说下,这个简单cms最主要实现的目标和需求吧: 19 | 20 | 21 | 22 | ``` 23 | 1.前台文章展示: 24 | 文章有分类、标签; 25 | 文章类型分单页、普通文章,后期会扩展一些其它模型,比如图片、软件等。 26 | 2.后台文章管理: 27 | 实现增删改查文章,文章可以使用Markdown来编辑 28 | 3.用户管理: 29 | 实现对后台用户的管理,包含登录模块 30 | 4.系统设置管理: 31 | 实现对系统一些常变量的设置、配置等 32 | ``` 33 | 34 | 使用的前后台页面都是本人自行设计与代码实现的,本cms的设计与实现一定程度上地受到 [typecho](http://typecho.org/) 的启发,感想 [typecho](http://typecho.org/)。 35 | 36 | ### 安装Laravel框架 37 | 38 | 如果对安装 `Laravel` 框架还有疑惑或困难的,建议多看下 `Laravel` 帮助手册。 39 | 40 | ### 初始配置Laravel框架 41 | 42 | 参照官方帮助,我们需要修改一些配置文件。 43 | 44 | > 修改 `/app/config/app.php` 文件,开启debug: 45 | 46 | ```php 47 | 'debug' => true, 48 | ``` 49 | 50 | > 使用 `php artisan` 来生成32应用程序的key,在命令行终端里输入以下命令: 51 | 52 | ```bash 53 | php artisan key:generate 54 | ``` 55 | 56 | > 会在 `/app/config/app.php` 文件里生成类似于下面的32位字符串配置项: 57 | 58 | ``` 59 | 'key' => 'RDFRcyFo3CulrDUMHmUDDm7CnVlQzIXb', 60 | ``` 61 | 62 | > 根据自己数据库实际,修改 `/app/config/database.php` 里面数据库相关配置项: 63 | 64 | ```php 65 | 'mysql' => array( 66 | 'driver' => 'mysql', 67 | 'host' => 'localhost', 68 | 'database' => 'laravel_cmf', 69 | 'username' => 'root', 70 | 'password' => 'root', 71 | 'charset' => 'utf8', 72 | 'collation' => 'utf8_unicode_ci', 73 | 'prefix' => 'yascms_', 74 | ), 75 | ``` 76 | 77 | 准备性工作已经完成了,下一节,我们将开始使用Artisan和Migrations工具进行建立数据库操作。 -------------------------------------------------------------------------------- /laravel_cms/02.md: -------------------------------------------------------------------------------- 1 | # Laravel入门教程——一个简单cms的实现(02) 2 | 3 | > 作者: douyasi 4 | > 网站:http://douyasi.com/category/startlaravel/ 5 | > 备注:本教程是在当前最新Laravel稳定版v4.2.X下实现的,其它相异版本如果有问题请自行排除。 6 | > 本文为作者原创记录,转载请保留署名与来源。 7 | 8 | ## 建立数据库 9 | 10 | `Laravel` 框架自带数据库建立与迁移工具,使用 `php artisan` 可以很方便建立或迁移数据库。 11 | 12 | 下面简单说下本cms数据库结构。 13 | 14 | ### 数据库表结构 15 | 16 | 实现本cms需要用到多张表,为了加快教程,我们先把最主要的2张表(某些扩展或关联字段也有可能被省去)——管理用户表 `admin` 和文章表`article` 拿出来操作。 17 | 18 | 其它表,诸如文章分类表,文章标签表,系统设置配置表等一律略去。 19 | 20 | `admin`表: 21 | 22 | 字段名 | 类型 | 备注说明 23 | ----- | ----- | ----- 24 | id | int | 管理用户ID(自增) 25 | username | varchar | 管理用户名,用于登录 26 | password | varchar | 管理用户密码 27 | 28 | 29 | `article`表: 30 | 31 | 字段名 | 类型 | 备注说明 32 | ----- | ----- | ----- 33 | id | int | 文章ID(自增) 34 | title | varchar | 文章标题 35 | content | text | 文章内容 36 | slug | varchar | 文章缩略名 37 | 38 | 39 | 40 | ### 使用Artisan和Migrations建立数据库 41 | 42 | > 命令行终端里输入以下命令: 43 | ```bash 44 | php artisan migrate:install 45 | ``` 46 | 47 | 执行之后,会发现目标数据库里多出了 `{prefix}_migrations` 的表, `{prefix}` 对应你数据库设置的表前缀。 48 | 49 | > 接着我们执行下面语句: 50 | ```bash 51 | php artisan migrate:make create_admin_table 52 | php artisan migrate:make create_article_table 53 | ``` 54 | 55 | > 执行之后,我们发现在 `/app/database/migrations`下多出带日期时间前缀的`create_admin_table.php` 和 `create_article_table.php` 文件。 56 | 57 | > 先打开`create_admin_table.php`文件,添加以下代码: 58 | ```php 59 | public function up() 60 | { 61 | Schema::create('admin', function(Blueprint $table) 62 | { 63 | $table->increments('id'); 64 | $table->string('username',20)->index(); 65 | $table->string('password',60); 66 | $table->softDeletes(); //软删除 67 | /*使用softDeletes,表中会多出timestamp类型 68 | 的'deleted_at'字段*/ 69 | $table->timestamps(); //时间戳 70 | /*使用timestamps,表中会多出timestamp类型 71 | 的'created_at'和'updated_at'字段*/ 72 | }); 73 | } 74 | public function down() 75 | { 76 | Schema::drop('admin'); 77 | } 78 | ``` 79 | 80 | > 再打开`create_article_table.php`文件,添加以下代码: 81 | ```php 82 | public function up() 83 | { 84 | Schema::create('article', function(Blueprint $table) 85 | { 86 | $table->increments('id'); 87 | $table->string('title',120)->index(); 88 | $table->text('content'); 89 | $table->string('slug',60)->nullable(); 90 | $table->softDeletes(); 91 | $table->timestamps(); 92 | }); 93 | } 94 | public function down() 95 | { 96 | Schema::drop('article'); 97 | } 98 | ``` 99 | 100 | > 保存完毕之后我们继续运行命令: 101 | ```bash 102 | php artisan migrate 103 | ``` 104 | 105 | > 会提示你是否执行此命令,输入y回车,之后如果看到下文就说明数据库建立成功了。 106 | ```bash 107 | ************************************** 108 | * Application In Production! * 109 | ************************************** 110 | Do you really wish to run this command? y 111 | Migrated: 2014_10_11_060945_create_admin_table 112 | Migrated: 2014_10_11_061004_create_article_table 113 | ``` 114 | 115 | ### 使用seed数据库填充 116 | 117 | `Laravel` 可以简单的使用 `seed` 类填充测试数据到数据库。所有的 `seed` 类放在 `app/database/seeds` 目录下。可以使用任何您想要的类名称,但是应该遵守某些大小写规范,如 `UserTableSeeder` 之类。默认已经有一个 `DatabaseSeeder` 类。 118 | 119 | 当然你也可以使用Laravel第三方包或插件(比如 [`way/generators`](https://packagist.org/packages/way/generators) 、 [`fzaninotto/faker`](https://packagist.org/packages/fzaninotto/faker) )来管理和填充填充数据。我也推荐大家使用 `generators` 和 `faker` 来进行数据库填充,这里连载文章定位于 `Laravel` 入门教程,以贴近官方帮助手册为准,故不再赘述,可具体参考下[这篇博文教程](http://lvwenhan.com/laravel/398.html)。 120 | 121 | 我们手动在`seed`目录下建立2个`seeder`文件,位于 `/app/database/seeds/AdminTableSeeder.php` 文件代码: 122 | 123 | ```php 124 | delete(); 129 | Admin::create( 130 | array( 131 | 'username' => 'admin', 132 | 'password' => Hash::make('123456'), 133 | 'created_at' => date('Y-m-d H:i:s'), 134 | 'updated_at' => date('Y-m-d H:i:s'), 135 | //'created_at' => Carbon::now()->toDateTimeString(), 136 | //'updated_at' => Carbon::now()->toDateTimeString(), 137 | /*使用Carbon需在app/config/app.php下注册ClassAliases*/ 138 | )); 139 | } 140 | } 141 | ``` 142 | 143 | > 注:使用时间处理的`Carbon`扩展包需要在`/app/config/app.php`配置Class Aliases,不然无法识别。 144 | ```php 145 | 'aliases' => array( 146 | 'App' => 'Illuminate\Support\Facades\App', 147 | 'Artisan' => 'Illuminate\Support\Facades\Artisan', 148 | 'Auth' => 'Illuminate\Support\Facades\Auth', 149 | 'Blade' => 'Illuminate\Support\Facades\Blade', 150 | ......, 151 | 'Carbon' => 'Carbon\Carbon', 152 | ......, 153 | ) 154 | ``` 155 | 156 | 位于 `/app/database/seeds/AdminTableSeeder.php` 文件代码: 157 | 158 | ```php 159 | class ArticleTableSeeder extends Seeder { 160 | 161 | public function run() 162 | { 163 | DB::table('article')->delete(); 164 | Article::create( 165 | array( 166 | 'title' => 'Test', 167 | 'content' => 'Test Content', 168 | 'slug' => 'test', 169 | 'created_at' => date('Y-m-d H:i:s'), 170 | 'updated_at' => date('Y-m-d H:i:s'), 171 | )); 172 | } 173 | } 174 | ``` 175 | 176 | 位于 `/app/database/seeds/AdminTableSeeder.php` 文件代码: 177 | 178 | ```php 179 | call('UserTableSeeder'); 185 | $this->call('AdminTableSeeder'); 186 | $this->command->info('Admin table seeded!'); 187 | $this->call('ArticleTableSeeder'); 188 | $this->command->info('Article table seeded!'); 189 | } 190 | } 191 | ``` 192 | 193 | 好,下面我们在命令行终端运行以下命令: 194 | 195 | ```bash 196 | php artisan db:seed 197 | ``` 198 | 199 | 结果我们发现命令行终端报错,很好,很多时候,照本宣科地按着我们教程来,也会出现一些意外,错误提示一大串,最主要原因是: `Class 'Admin' not found`。我们需要解决这个问题,那原因是啥呢?`Laravel` 使用 `Eloquent ORM`,而我们没有创建对应的 `Admin` 和 `Article` 这2个 `Eloquent` 模型。 200 | 下面我们在 `/app/models/` 目录下,参考 `Laravel` 本身的 `User.php`,来定义 `Admin` 和`Article` 的 `Eloquent` 模型。 201 | 202 | `/app/models/Admin.php`代码如下: 203 | 204 | ```php 205 | 作者: douyasi 4 | > 网站:http://douyasi.com/category/startlaravel/ 5 | > 备注:本教程是在当前最新Laravel稳定版v4.2.X下实现的,其它相异版本如果有问题请自行排除。 6 | > 本文为作者原创记录,转载请保留署名与来源。 7 | 8 | ## 页面显示与路由控制 9 | 10 | ### 建立静态首页 11 | 12 | 实际上,由于目前数据很少,复杂的首页页面对我们来说是种干扰,不如先写一个简单的首页。 13 | 14 | 为了方便快捷起见,我们把控制器,视图,模型文件都放在`app`对应目录下,位于顶级命名空间下,当然你也可以使用或建立 `workbench` 来管理的你的代码。 15 | 16 | 好,在 `/app/views/` 下新建一个 `index.blade.php`,写下代码: 17 | 18 | ```html 19 | 20 | 21 | 22 | 23 | 首页 24 | 25 | 26 |

这是首页

27 | 28 | 29 | ``` 30 | 31 | 现在,我们需要实现访问网站域名首页就能展示“这是首页”内容。 32 | 33 | 下面,我们修改下路由,文件位于 `/app/route.app` : 34 | 35 | ```php 36 | Route::get('/',function() 37 | { 38 | returnView::make('index'); 39 | }); 40 | ``` 41 | 42 | 随后,我们访问下网站首页,就能看到“这是首页”4个字。 43 | 44 | 45 | 46 | ### 展示登录页面 47 | 首页我们已经显示出来,下面,我们开始实现登录页面。 48 | `Laravel` 的 `Blade` 模版对于某些新接触的人来说,很不习惯,实际上我也不习惯,当然你也可以不使用它的一些语法,直接使用原生的`HTML/PHP` 标签。 49 | 50 | 我们先把登录页面给套出来,登录页面看起来像下图: 51 | 52 | ![20141012211031.jpg][1] 53 | 54 | > 设计不好,不喜勿喷啊。 55 | 56 | 我们先把 `js`、`img`、`css` 等资源按一定的规范放在网站根目录 `/public/assets` 文件夹下。 `assets` 文件夹下包括所有静态资源,目录结构大概如下: 57 | 58 | ``` 59 | /public/ 60 | |__ css/ 61 | |_ style.css 62 | |_ ... 63 | |__ img/ 64 | |_ favicon.ico 65 | |_ ... 66 | |__ js/ 67 | |_ script.js 68 | |_ ... 69 | |__ lib/ 70 | |__ font-awesome/ 71 | |__ fonts/ 72 | |__ ... 73 | |__ ... 74 | ``` 75 | 76 | 既然使用 `Laravel`,还是要必要学习下它的 `blade` 模版语法,以及其相关表单和HTML标签。 77 | 78 | 本人比较喜欢那种头中尾切分的那种 `layout` 布局,我们可以把 `layout` 模版按头中尾切分细一点。由于登录页面布局跟后台布局没有多大统一地方(估计就只有 `HTML meta` 声明部分有些一样),故我按以下来设置 `layout` 和 `blade` 代码。 79 | 80 | 文件位置:`/app/view/layout/base.blade.php` 81 | 82 | ```html 83 | 84 | 85 | 86 | 87 | @section('title') YASCMF - YASCMF @show{{-- 页面标题 --}} 88 | 89 | 90 | 91 | {{-- 360浏览器使用webkit内核渲染页面 --}} 92 | {{-- IE(内核)浏览器优先使用高版本内核 --}} 93 | {{-- 移动端页面缩放 --}} 94 | 95 | {{-- favicon --}} 96 | 97 | @section('head_css') 98 | @show{{-- head区域css样式表 --}} 99 | 100 | @section('head_js') 101 | @show{{-- head区域javscript脚本 --}} 102 | 103 | @section('beforeStyle') 104 | @show{{-- 在内联样式之前填充一些东西 --}} 105 | 106 | @section('head_style') 107 | @show{{-- head区域内联css样式表 --}} 108 | 109 | @section('afterStyle') 110 | @show{{-- 在内联样式之后填充一些东西 --}} 111 | 112 | 113 | @section('beforeBody') 114 | @show{{--在正文之后填充一些东西 --}} 115 | 116 | @section('body') 117 | @show{{-- 正文部分 --}} 118 | 119 | @section('afterBody') 120 | @show{{-- 在正文之后填充一些东西,比如统计代码之类的东东 --}} 121 | 122 | 123 | 124 | ``` 125 | 126 | 我们先来学习下一些blade语法: 127 | 128 | `@section('title')` 为区块,以便后续模版继承与修改。 129 | 130 | `{{{ isset($description) ? $description : 'YASCMF' }}}` 输出 `$description` 之前先检查该变量是否存在,如果存在则输出,否则给默认值 `YASCMF` 。 131 | 132 | 三个连大括号(`{}`)表示对变量中的特殊字符串进行自动转义。 133 | 134 | `{{-- 这是注释内容 --}}` 表示注释。 135 | 136 | 我们已经写好了一个基础的 `layout`,下面我们开始写下针对登录页面的 `blade` 模版页面。 137 | 138 | 文件位置:`/app/view/authority/login.blade.php` 139 | 140 | ```php 141 | @extends('layout.base') 142 | 143 | @section('title') 登录 - YASCMF @stop 144 | 145 | @section('head_style') 146 | 163 | @parent 164 | @stop 165 | 166 | @section('body') 167 |
168 |
169 |
170 |
- 芽丝CMF
171 |
172 |
173 | {{ Form::open(array('route' => 'login','id' => 'login_form', 'method' => 'post')) }} 174 | 175 | {{ Form::text('username',null,array('placeholder'=>'请输入用户名', 'class' => 'input_text', 'id' =>'username', 'maxlength'=>20, 'onFocus' => "this.value=(this.value=='UserName')? '' : this.value;")) }} 176 | {{ Form::password('password', array('placeholder'=>'请输入用户密码', 'class' => 'input_text', 'id' =>'password', 'maxlength'=>20, 'onFocus' => "this.value=(this.value=='PassWord')? '' : this.value;")) }} 177 | {{ Form::submit('登录',array('id' => 'sf_submit')) }} 178 | {{ Form::close() }} 179 |
180 |
181 |

Copyright © 2011 - 2014 All by raoyc

182 |
183 |
184 |
185 | @stop 186 | ``` 187 | 188 | 我们接着学习 `blade` 标签和一些生成 `Form` 表单方法: 189 | 190 | 上段代码里,我们看到了`@extends('layout.base')`,这个表示继承我们最上面的`base.blade.php`,继承以后,我们需要根据当前登录页面实际,修改自己特定的`section`,比如标题 `@section('title')` 、head内联样式 `@section('head_style')` 、正文body `@section('body')` 。 191 | 192 | 我们发现一些 `Form::xxx` 之类的代码,这些是 `Laravel` 内置的一些生成 `Form` 表单元素的方法,具体请查阅官方帮助手册,如果你觉得很麻烦,也可以使用原生的HTML代码。 193 | 194 | 模版页面我们都弄好了,现在通过修改路由与控制器,访问前台登录页面看看。 195 | 196 | 修改路由,文件位置:`/app/routes.php` ,这里我们使用到路由群组和路由筛选器(关于路由筛选器 `filter`,后文再谈),以便后期维护方便。 197 | 198 | ```php 199 | /*路由群组*/ 200 | Route::group(array('prefix' => 'auth'), function () { 201 | $Authority = 'AuthorityController@'; 202 | Route::group(array('before' => 'guest'), function () use ($Authority) { 203 | # 登录 204 | Route::get('login', array('as' => 'login', 'uses' => $Authority.'getLogin')); 205 | Route::post('login', $Authority.'postLogin'); 206 | }); 207 | }); 208 | ``` 209 | 210 | 上面路由代码,把对 `auth/login` 的 `get` 访问映射到 `AuthorityController` 的 `getLogin` 方法,`post` 访问映射到`AuthorityController` 的 `postLogin` 方法。 211 | 212 | 下面我们开始书写AuthorityController,文件位置:`/app/controllers/AuthorityController.php` 。 213 | 214 | ```php 215 | Input::get('username'), 'password'=>Input::get('password')); //认证凭证 247 | if (Auth::attempt($credentials)) 248 | { 249 | return Redirect::intended(); 250 | } 251 | else { 252 | // 登录失败,跳回 253 | return Redirect::back() 254 | ->withInput() 255 | ->withErrors(array('attempt' => '“用户名”或“密码”错误,请重新登录!')); 256 | } 257 | } 258 | ``` 259 | 260 | 这里我们使用到 `Laravel` 自带的 `Auth` 认证与安全类方法,默认情况下,`Laravel` 是对数据库 `users` 表进行相关身份认证的,而我们这里操作的是 `admin` 表用户,所以我们需要修改 `model` 里面 `Admin.php`,给其继承 `Auth` 相关 `Traits` 和 `Interface`,否则会报错。 261 | 262 | 文件`/apps/models/Admin.php`的代码: 263 | 264 | ```php 265 | 'Admin', 282 | 'table' => 'admin', 283 | ``` 284 | 285 | 上面控制器 `postLogin()`方法在登录校验失败时,会传递一个错误信息到 `login` 视图里,我们需要简单修改下 `login.blade.php`。 286 | 287 | ```php 288 | ...... 289 | {{ Form::close() }} 290 |

{{ $errors->first('attempt') }}

291 | 292 |
293 |

Copyright © 2011 - 2014 All by raoyc

294 |
295 | ...... 296 | ``` 297 | 298 | 好的,现在我们尝试下登录看看。 299 | 在用户名和密码错误的情况下,会出现下图: 300 | 301 | ![20141013173908.jpg][3] 302 | 303 | 在用户名和密码正确的情况下,会跳回首页。 304 | 305 | 好了,这一节就讲到这里,下一节我们继续深入。 306 | 307 | 308 | [1]: http://douyasi.com/usr/uploads/2014/10/3667231108.jpg 309 | [2]: http://douyasi.com/usr/uploads/2014/10/197222214.jpg 310 | [3]: http://douyasi.com/usr/uploads/2014/10/1532786503.jpg -------------------------------------------------------------------------------- /laravel_cms/04.md: -------------------------------------------------------------------------------- 1 | # Laravel入门教程——一个简单cms的实现(04) 2 | 3 | > 作者: douyasi 4 | > 网站:http://douyasi.com/category/startlaravel/ 5 | > 备注:本教程是在当前最新Laravel稳定版v4.2.X下实现的,其它相异版本如果有问题请自行排除。 6 | > 本文为作者原创记录,转载请保留署名与来源。 7 | 8 | ## 页面显示与路由控制(二) 9 | 10 | ### Auth继续深入使用 11 | 12 | 上一节我们只是简单地使用了下 `Auth`,这一节打算继续深入使用 `Auth`。在使用 `Auth` 时我们可能会(反正我觉得是一定会)遇到诸多问题,这是因为 `Laravel` 作者的一些认证构思与你我想象的认证构思不同。 13 | 14 | `Auth` 默认使用 `email` 作为认证验证的一个条件,还提供了诸如“记住我”快捷认证功能和找回登录密码凭证的方法。 15 | 16 | 使用 `Auth::logout()` 退出用户时,我发现框架报了一个错误,错误界面在此: 17 | 18 | ![logout_error][1] 19 | 20 | 错误原因是 `admin` 数据表中没有 `remember_token` 字段。在数据库设计时我就没考虑过这个字段,但 `Auth` 认证时有使用到,审查下 `Laravel Auth` 相关代码,我们可以发现,`logout`调用了 `refreshRememberToken` 方法。 21 | 22 | 为此,我们需要修改`admin`数据表相关字段。 23 | 24 | 为`admin`添加`remember_token`字段,也添加上`email`字段,以配合`Auth`使用。 25 | 26 | 27 | 28 | 我们为首页加上登录和退出链接,修改`index.blade.php`模版: 29 | 30 | ```php 31 | 32 | 33 | 34 | 35 | 首页 36 | 37 | 38 | @if(Auth::check()) 39 |

[ {{ Auth::user()->username }} ] 退出

40 | @else 41 |

登录

42 | @endif 43 |

这是首页

44 | 45 | 46 | ``` 47 | 48 | 修改路由`route.php`,添加一条退出路由: 49 | 50 | ```php 51 | Route::get('logout', array('as' => 'logout', 'uses' => $Authority.'getLogout')); 52 | ``` 53 | 54 | 修改控制器`AuthorityController`,添加`getLogout`退出登录方法。 55 | 56 | ```php 57 | public function getLogout() 58 | { 59 | Auth::logout(); 60 | return Redirect::to('/'); 61 | } 62 | ``` 63 | 64 | 访问首页,在未登录状态下,会出现登录链接;在已登录状态下,会出现用户名和退出链接。 65 | 66 | ![login_status][2] 67 | 68 | ### 展示后台页面 69 | 70 | 登录页面我们套取完毕了,我们现在开始管理员登录之后的后台页面。 71 | 72 | 跟前面套登录页面很类似,我们需要制作后台页面对应的 `blade` 模版。具体对应代码可以查看我本项目源码。 73 | 74 | 大致说下后台模版页面结构,后台模版放置在`/app/view/admin`目录下。 75 | 76 | 在`/app/view/layout`目录下,会定义一个通用的后台`layout`,文件位置`/app/views/layout/backend.blade.php`,代码为: 77 | 78 | ```php 79 | @extends('layout.base') 80 | 81 | @section('title') 后台 - YASCMF @stop 82 | 83 | @section('head_css') 84 | 85 | 86 | {{-- 可以到此查看fontawesome图标字体:http://fontawesome.io/icons/ --}} 87 | @parent 88 | @stop 89 | 90 | @section('head_js') 91 | 92 | 93 | 94 | @parent 95 | @stop 96 | 97 | @section('body') 98 | 99 | @include('widgets.topHeadNav'){{-- 头部导航区域 --}} 100 | 101 | 102 |
103 |
104 | 105 | @include('widgets.leftSidebar'){{-- 左侧导航栏 --}} 106 | 107 | 108 |
109 | 110 |
111 | @section('main_content') 112 | @show{{-- 页面主体内容 --}} 113 |
114 | 115 | 118 | 119 |
120 | 121 |
122 | 123 |
124 | 125 | @include('scripts.endCommonScript') 126 | 127 | @section('endMainCon') 128 | @show{{-- main container之后添加一些应用JS --}} 129 | 130 | @stop 131 | 132 | ``` 133 | 134 | 这里我们使用`@include`标签引如几个外挂型的布局文件, 135 | 136 | ```php 137 | @include('widgets.topHeadNav'){{-- 头部导航区域 --}} 138 | @include('widgets.leftSidebar'){{-- 左侧导航栏 --}} 139 | ``` 140 | 141 | 他们位于目录 `/app/views/wigets/` 下,负责显示头部导航与左侧导航。更多模版细节请查看后续公开的项目源码。 142 | 143 | 最后我们展示出了后台页面看起来像下面这样的: 144 | 145 | ![backend][3] 146 | 147 | 对应的后台路由代码如下: 148 | 149 | ```php 150 | Route::group(array('prefix' => 'admin', 'before' => 'auth'), function () { 151 | $Admin = 'AdminController@'; 152 | # 后台首页 153 | Route::get('/', array('as' => 'admin', 'uses' => $Admin.'getIndex')); 154 | Route::get('/index',array('as' => 'admin.index', 'uses' => $Admin.'getIndex')); 155 | } 156 | ``` 157 | 158 | 对应的控制器代码如下,文件位于`/app/controllers/AdminController.php`: 159 | 160 | ```php 161 | 184 | 187 | 188 | 189 | 190 |
191 |
192 |

这是后台概要内容区域。

193 |
194 |
195 | 196 | @stop 197 | ``` 198 | 199 | 这一节我们继续讲解了 `Auth` 的使用,写了一些路由和控制器方法来展示简单后台页面,下一节开始,我们将设计 `RESTFUL` 路由,实现对文章资源的增删改。 200 | 201 | 202 | [1]: http://douyasi.com/usr/uploads/2014/10/469140762.jpg 203 | [2]: http://douyasi.com/usr/uploads/2014/10/3413491079.jpg 204 | [3]: http://douyasi.com/usr/uploads/2014/10/1543185316.jpg -------------------------------------------------------------------------------- /laravel_cms/05.md: -------------------------------------------------------------------------------- 1 | # Laravel入门教程——一个简单cms的实现(05) 2 | 3 | > 作者: douyasi 4 | > 网站:http://douyasi.com/category/startlaravel/ 5 | > 备注:本教程是在当前最新Laravel稳定版v4.2.X下实现的,其它相异版本如果有问题请自行排除。 6 | > 本文为作者原创记录,转载请保留署名与来源。 7 | 8 | ## RESTFUL路由与控制器 9 | 10 | ### RESTFUL详解 11 | 12 | 资源控制器可以简单的建立跟资源相关的 `RESTful` 控制器。下面,我们开始演示操作文章资源。 13 | 14 | 命令行执行以下命令建立控制器: 15 | 16 | ```bash 17 | php artisan controller:make ArticleController 18 | ``` 19 | 20 | 然后我们可以注册一个资源化路由至控制器上: 21 | 22 | ```php 23 | Route::resource('article', 'ArticleController'); 24 | ``` 25 | 26 | 打开 `/app/controllers/` 目录,我们可以看见框架已经自动地给我们生成 `ArticleController.php` 文件,打开我们看看,大致可以看到以下结构: 27 | 28 | 29 | 30 | ```php 31 | with('arts',$arts); 148 | } 149 | ``` 150 | 151 | 访问 `http://{locdomain}/article` 展示出来的页面如下图: 152 | 153 | ![article_index][1] 154 | 155 | #### `create`方法 156 | 157 | `create` 方法用于显示创建新资源页面,我们先把这个页面模版(位于`/apps/views/article/create.blade.php`)给套出来,完善下 `create` 方法。 158 | 159 | ```php 160 | public function create() 161 | { 162 | return View::make('article.create'); 163 | } 164 | ``` 165 | 166 | 访问`http://{locdomain}/article/create`展示出来的页面如下图: 167 | 168 | ![article_create][2] 169 | 170 | #### `store`方法 171 | 172 | `store` 方法用于接受 `post` 过来的数据,将接受过来的经过数据验证,验证通过之后,写入到数据库中。 完善下 `store` 方法,这里我们略去数据校验那一块东西,直接假定它合法存入数据库中。 173 | 174 | ```php 175 | public function store() 176 | { 177 | $art = new Article; 178 | $art->title = Input::get('title'); 179 | $art->content = Input::get('text_editor'); 180 | $art->slug = Input::get('slug'); 181 | $art->created_at = $art->updated_at = date('Y-m-d H:i:s'); 182 | $art->save(); 183 | } 184 | ``` 185 | 186 | 存储数据使用到 `Eloquent ORM`。 187 | 188 | #### `show`方法 189 | 190 | `show` 方法用于显示某个特定 `id` 的资源,这里没啥好说的,由于文章的显示主要是在前台,这里我们简单的打印输出下变量。 191 | 192 | ```php 193 | public function show($id) 194 | { 195 | $art = Article::find($id); 196 | var_dump($art); 197 | } 198 | ``` 199 | 200 | #### `edit`方法 201 | 202 | `edit` 方法用于修改特定 `id` 资源的页面,我们先把这个页面模版(位于`/apps/views/article/edit.blade.php`)给套出来。 203 | 204 | 这里简单说下,由于 `edit` 页面要使用 `PUT` 或 `PATCH` 方法向服务器传输修改请求的数据,我们需要对表单进行改造,由于某些低版本的浏览器对`PUT/PATCH/DELETE`请求方法支持的不是很好,所以,Laravel本身提供了一个很好的倒退兼容解决方法: 205 | 206 | > 仍然使用 `POST` 方法,但在表单中提供一个 `name` 为 `_method`, `value` 为 `PUT` 或 `PATCH` 的隐藏域,以便`Laravel` 能够很好地处理 `PUT/PATCH` 过来的数据。 207 | 208 | 只要在模版表单中使用以下标签即可: 209 | 210 | ```php 211 | {{ Form::open( array('url' => 'article/'.$art->id, 'method' => 'put') ) }} 212 | ...... 213 | {{ Form::close() }} 214 | ``` 215 | 216 | 或者 217 | 218 | ```php 219 |
220 | 221 | ...... 222 |
223 | ``` 224 | 225 | 节奏我们完善下 `edit` 方法: 226 | 227 | ```php 228 | public function edit($id) 229 | { 230 | $art = Article::find($id); 231 | return View::make('article.edit')->with('art',$art); 232 | } 233 | ``` 234 | 235 | 访问 `http://{locdomain}/article/2/edit` 展示出来的页面如下图: 236 | 237 | ![article_edit][3] 238 | 239 | `edit` 页面需要把原始的数据 `value` 传入模版中。 240 | 241 | #### `update` 方法 242 | 243 | `update` 方法接受 `edit` 页面 `PUT` 或 `PATCH` 过来的数据,理应也对数据进行校验,校验通过之后,写入数据库。这里,我们仍然略去了校验一步,`update` 方法代码如下: 244 | 245 | ```php 246 | public function update($id) 247 | { 248 | // 249 | $art = Article::find($id); 250 | $art->title = Input::get('title'); 251 | $art->content = Input::get('text_editor'); 252 | $art->slug = Input::get('slug'); 253 | $art->updated_at = date('Y-m-d H:i:s'); 254 | $art->save(); 255 | } 256 | ``` 257 | 258 | #### `destroy`方法 259 | 260 | `destroy` 方法,使用 `DELETE` 方式来删除特定 `id` 资源。类似于 `PUT/PATCH` 方式,Laravel也提供了一个倒退兼容解决方案。 261 | 262 | > 仍然使用 `POST` 方法,但在表单中提供一个 `name` 为 `_method` , `value` 为 `DELETE` 的隐藏域,以便 `Laravel` 能够很好地通过 `DELETE` 方式删除特定资源数据。 263 | 264 | 只要在模版表单中使用以下标签即可: 265 | 266 | ```php 267 | {{ Form::open( array('url' => 'article/'.$art->id, 'method' => 'delete') ) }} 268 | ...... 269 | {{ Form::close() }} 270 | ``` 271 | 272 | 或者 273 | 274 | ```php 275 |
276 | 277 | ...... 278 |
279 | ``` 280 | 281 | 如果我们使用 `jQuery` 来实现删除某个特定的资源,可以使用它常规的 `POST Ajax` 方式。这里有个相关演示 `jQuery` 代码: 282 | 283 | ```php 284 | $('.delete_item').click(function(){ 285 | var id = $(this).data('id'); 286 | $.ajax({ 287 | type: "POST", 288 | url: "{{ url('article') }}" + '/' + id, 289 | data: "_method=DELETE&_token={{{ csrf_token() }}}>", 290 | success: function(msg){ 291 | if(msg == 1) 292 | { 293 | alert( "删除:成功" ); 294 | } 295 | else{ 296 | alert( "删除:失败" ); 297 | } 298 | } 299 | }); 300 | }); 301 | ``` 302 | 303 | 注意到 `data` 那一行,我们将 `_method=DELETE` 和 `_token={{{ csrf_token() }}}` 两个隐藏域值通过常规的 `POST` 方式传递过去了。后面的 `_token` 是为了抵制 `CSRF`(跨站请求伪造)的令牌值。 304 | 305 | 好了到此,这一节我们完整讲解了 `RESTFUL` 的路由及其控制器。下一节,我们开始铺垫下数据校验与前台文章页面的显示等内容。 306 | 307 | 308 | [1]: http://douyasi.com/usr/uploads/2014/10/4102585041.jpg 309 | [2]: http://douyasi.com/usr/uploads/2014/10/3258134266.jpg 310 | [3]: http://douyasi.com/usr/uploads/2014/10/1898640204.jpg -------------------------------------------------------------------------------- /mysql/basic.md: -------------------------------------------------------------------------------- 1 | # MySQL基础命令 2 | 3 | 4 | > 本文来源于网络,可能存在错漏之处,仅供参考。 5 | 6 | ### 1. 连接MySQL: `mysql -h host_address -u user_name -p user_password` 7 | 8 | ```bash 9 | mysql -h110.110.110.110 -u root -p 123; 10 | ``` 11 | 12 | ### 2. 修改密码:`mysqladmin -u user_name -p old_password password new_password` 13 | 14 | ```bash 15 | mysqladmin -u root -p abc123 password def456; 16 | ``` 17 | 18 | ### 3. 增加新用户:`grant select on db_name.* to user_name@login_host identified by 'user_password'` 19 | 20 | ```bash 21 | /* mysql grant命令添加用户常用的三种模式 */ 22 | grant all PRIVILEGES on *.* to 'test'@'localhost' identified by '123'; 23 | grant all PRIVILEGES on *.* to 'test'@'%' identified by '123'; 24 | grant all PRIVILEGES on *.* to 'test'@'10.22.225.18' identified by '123'; 25 | ``` 26 | 27 | > 说明: 28 | 第一条命令添加一个本地用户 'test' ,一般用于web服务器和数据库服务器在一起的情况; 29 | 第二条命令添加一个用户 'test' ,只要能连接数据库服务器的机器都可以使用,这个比较危险,一般不用; 30 | 最后条命令在数据库服务器上给 '10.22.225.18' 机器添加一个用户'test',一般用于web服务器和数据库服务器分离的情况。 31 | 32 | 33 | > 注意: 34 | 真正使用的时候不会用 `grant all PRIVILEGES on *.*` ,而是根据实际需要设定相关的权限。 35 | 比如 `grant select,insert,delete,update on test.* to 'test'@'localhost' identified by '123';` 36 | 37 | 38 | ### 4. 创建数据库: `create database db_name` 39 | 40 | ``` 41 | create database news; 42 | ``` 43 | 44 | ### 5. 显示数据库: `show databases` 45 | 46 | ### 6. 删除数据库: `drop database db_name` 47 | 48 | ```mysql 49 | drop database news; 50 | ``` 51 | 52 | ### 7. 连接数据库:`use db_name` 53 | 54 | ```mysql 55 | use news; 56 | ``` 57 | 58 | `use` 语句可以通告MySQL把 `db_name` 数据库作为默认(当前)数据库使用,用于后续语句。该数据库保持为默认数据库,直到语段的结尾,或者直到发布一个不同的 `USE` 语句: 59 | 60 | ``` 61 | mysql> USE db1; 62 | mysql> SELECT COUNT(*) FROM mytable; # selects from db1.mytable 63 | mysql> USE db2; 64 | mysql> SELECT COUNT(*) FROM mytable; # selects from db2.mytable 65 | ``` 66 | 67 | ### 8. 选择的数据库:`select method()` 68 | 69 | MySQL中 `SELECT` 命令类似于其他编程语言里的 `print` 或者 `write`,你可以用它来显示一个字符串、数字、数学表达式的结果等等。如何使用 `MySQL` 中 `SELECT` 命令的特殊功能? 70 | 71 | ① 显示MYSQL的版本 72 | 73 | ```mysql 74 | mysql> select version(); 75 | +-----------------------+ 76 | | version() | 77 | +-----------------------+ 78 | | 6.0.4-alpha-community | 79 | +-----------------------+ 80 | 1 row in set (0.02 sec) 81 | ``` 82 | 83 | ② 显示当前时间 84 | 85 | ```mysql 86 | mysql> select now(); 87 | +---------------------+ 88 | | now() | 89 | +---------------------+ 90 | | 2009-09-15 22:35:32 | 91 | +---------------------+ 92 | 1 row in set (0.04 sec) 93 | ``` 94 | 95 | ③ 显示年月日 96 | 97 | ```mysql 98 | SELECT DAYOFMONTH(CURRENT_DATE); 99 | +--------------------------+ 100 | | DAYOFMONTH(CURRENT_DATE) | 101 | +--------------------------+ 102 | | 15 | 103 | +--------------------------+ 104 | 1 row in set (0.01 sec) 105 | 106 | SELECT MONTH(CURRENT_DATE); 107 | +---------------------+ 108 | | MONTH(CURRENT_DATE) | 109 | +---------------------+ 110 | | 9 | 111 | +---------------------+ 112 | 1 row in set (0.00 sec) 113 | 114 | SELECT YEAR(CURRENT_DATE); 115 | +--------------------+ 116 | | YEAR(CURRENT_DATE) | 117 | +--------------------+ 118 | | 2009 | 119 | +--------------------+ 120 | 1 row in set (0.00 sec) 121 | ``` 122 | 123 | ④ 显示字符串 124 | 125 | ```mysql 126 | mysql> SELECT "welecome to my blog!"; 127 | +----------------------+ 128 | | welecome to my blog! | 129 | +----------------------+ 130 | | welecome to my blog! | 131 | +----------------------+ 132 | 1 row in set (0.00 sec) 133 | ``` 134 | 135 | ⑤ 当计算器用 136 | 137 | ```mysql 138 | select ((4 * 4) / 10 ) + 25; 139 | +----------------------+ 140 | | ((4 * 4) / 10 ) + 25 | 141 | +----------------------+ 142 | | 26.60 | 143 | +----------------------+ 144 | 1 row in set (0.00 sec) 145 | ``` 146 | 147 | ⑥ 串接字符串 148 | 149 | ```mysql 150 | select CONCAT(f_name, " ", l_name) 151 | AS Name 152 | from employee_data 153 | where title = 'Marketing Executive'; 154 | +---------------+ 155 | | Name | 156 | +---------------+ 157 | | Monica Sehgal | 158 | | Hal Simlai | 159 | | Joseph Irvine | 160 | +---------------+ 161 | 3 rows in set (0.00 sec) 162 | ``` 163 | 164 | > 注意:这里用到 `CONCAT()` 函数,用来把字符串串接起来。另外,我们还用到以前学到的 `AS` 给结果列 `'CONCAT(f_name, " ", l_name)'` 起了个假名。 165 | 166 | ### 9. 创建数据表:`create table table_name (field_1_name field_1_type [ ,... field_n_name field_n_type ])` 167 | 168 | 169 | ```mysql 170 | CREATE TABLE IF NOT EXISTS `user` ( 171 | `uid` int(10) unsigned NOT NULL AUTO_INCREMENT, 172 | `user_name` varchar(20) DEFAULT NULL, 173 | `user_password` varchar(32) DEFAULT NULL, 174 | `user_email` varchar(40) DEFAULT NULL, 175 | PRIMARY KEY (`uid`), 176 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; 177 | ``` 178 | 179 | ### 10. 获取表结构:`desc table_name` 或者 `show columns from table_name` 180 | 181 | > 使用MySQL数据库desc 表名时,我们看到Key那一栏,可能会有4种值,即 `' '` , `'PRI'` , `'UNI'` , `'MUL'` 。 182 | 183 | ① 如果 `Key` 是空的, 那么该列值的可以重复, 表示该列没有索引, 或者是一个非唯一的复合索引的非前导列; 184 | 185 | ② 如果 `Key` 是 `PRI` , 那么该列是主键的组成部分; 186 | 187 | ③ 如果 `Key` 是 `UNI` , 那么该列是一个唯一值索引的第一列(前导列),并别不能含有空值(`NULL`); 188 | 189 | ④ 如果 `Key` 是 `MUL` , 那么该列的值可以重复, 该列是一个非唯一索引的前导列(第一列)或者是一个唯一性索引的组成部分但是可以含有空值 `NULL`。 190 | 如果对于一个列的定义,同时满足上述4种情况的多种,比如一个列既是 `PRI` ,又是`UNI` ,那么 `desc table_name` 的时候,显示的`Key` 值按照优先级来显示 `PRI->UNI->MUL` 。那么此时,显示 `PRI` 。 191 | 一个唯一性索引列可以显示为 `PRI` ,并且该列不能含有空值,同时该表没有主键。 192 | 一个唯一性索引列可以显示为 `MUL` ,如果多列构成了一个唯一性复合索引,因为虽然索引的多列组合是唯一的,比如 `ID+NAME` 是唯一的,但是没一个单独的列依然可以有重复的值,只要 `ID+NAME` 是唯一的即可。 193 | 194 | ### 11. 删除表:`drop table table_name` 195 | 196 | `DROP TABLE` 用于取消一个或多个表。您必须有每个表的 `DROP`权限。所有的表数据和表定义会被取消,所以使用本语句要小心! 197 | 198 | ### 12. 表插入数据:`insert into table_name ( field_1_name [ ,... field_n_name ]) values ( value_1 [,... value_n ] )` 199 | 200 | ```mysql 201 | INSERT INTO user (`uid`, `user_name`, `user_password`, `user_email`) VALUES (1, 'admin', 'admin', 'admin@example.com'); 202 | ``` 203 | `insert into` 每次只能向表中插入一条记录。 204 | 205 | ### 13. 查询表数据:`select field_1_name [,... field_n_name ] from table_name where sql_expression` 206 | 207 | ① 查询所有行: 208 | 209 | 查看表 `user` 中所有数据 210 | `select * from user;` 211 | 212 | ② 查询前几行数据: 213 | 214 | 查看表 user 中前2行数据 215 | `select * from user order by id limit 0,2;` 216 | > 注:`select` 一般配合 `where` 使用,以查询更精确更复杂的数据。 217 | 218 | ### 14. 删除表中数据:`delete from table_name where sql_expression` 219 | 220 | 删除表 user 中编号为1 的记录 221 | `delete from user where uid=1;` 222 | 223 | ### 15. 修改表中数据:`update table_name set field_name = new_value [ ,…] where sql_expression` 224 | 225 | 如更新 `id` 为 `1` 的 `user`,设置 `user_name`字段值为 `Mary`。 226 | 227 | ```mysql 228 | update user set user_name='Mary' where id=1; 229 | ``` 230 | 231 | ① 单表的MySQL UPDATE语句: 232 | 233 | `UPDATE [LOW_PRIORITY] [IGNORE] tbl_name SET col_name1=expr1 [, col_name2=expr2 ...] [WHERE where_definition] [ORDER BY ...] [LIMIT row_count]` 234 | 235 | ② 多表的UPDATE语句: 236 | 237 | `UPDATE [LOW_PRIORITY] [IGNORE] table_references SET col_name1=expr1 [, col_name2=expr2 ...] [WHERE where_definition]` 238 | 239 | `UPDATE` 语法可以用新值更新原有表行中的各列。`SET` 子句指示要修改哪些列和要给予哪些值。`WHERE` 子句指定应更新哪些行。如果没有 `WHERE` 子句,则更新所有的行。如果指定了 `ORDER BY` 子句,则按照被指定的顺序对行进行更新。 `LIMIT` 子句用于给定一个限值,限制可以被更新的行的数目。 240 | 241 | ### 16. 增加字段:`alter table table_name [ add field_name field_type / other_sql_expression ]` 242 | 243 | 在表 `user` 中添加了一个字段 `user_pic` ,类型为 `varchar(40)`,默认值为 `NULL` 244 | `alter table user add user_pic varchar(40) default NULL;` 245 | 246 | 加索引 247 | `alter table employee add index emp_name (name);` 248 | 249 | 加主关键字的索引 250 | `alter table employee add primary key(id);` 251 | 252 | 加唯一限制条件的索引 253 | `alter table employee add unique emp_name2(cardnumber);` 254 | 255 | 删除某个索引 256 | `alter table employee drop index emp_name;` 257 | 258 | 增加字段 259 | `alter table user add user_pic varchar(40) default NULL;` 260 | 261 | 修改原字段名称及类型 262 | `ALTER TABLE table_name CHANGE old_field_name new_field_name field_type;` 263 | 264 | 删除字段 265 | `ALTER TABLE table_name DROP field_name;` 266 | 267 | ### 17. 修改表名:`rename table old_table_name to new_table_name` 268 | 269 | 当你执行 `RENAME` 时,你不能有任何锁定的表或活动的事务。你同样也必须有对原初表的 `ALTER` 和 `DROP` 权限,以及对新表的 `CREATE` 和 `INSERT` 权限。 270 | 如果在多表更名中,`MySQL` 遭遇到任何错误,它将对所有被更名的表进行倒退更名,将每件事物退回到最初状态。 271 | 272 | ### 18.备份数据库: 273 | 274 | ① 导出整个数据库,导出文件默认是存在mysql\bin目录下 275 | `mysqldump -u user_name -p user_password db_name > new_db_name.sql` 276 | 277 | ② 导出一个表 278 | `mysqldump -u user_name -p user_password database_name table_name > outfile_name.sql` 279 | 280 | ③ 导出一个数据库结构 281 | `mysqldump -u user_name -puser_password -d -add-drop-table database_name > outfile_name.sql` 282 | `-d` 没有数据 `-add-drop-table` 在每个 `create` 语句之前增加一个 `drop table` 283 | 284 | ④带语言参数导出 285 | `mysqldump -u user_name -p user_password -default-character-set=latin1 -set-charset=gbk -skip-opt database_name > outfile_name.sql` 286 | 287 | ### 19. 建库建表示例: 288 | 289 | ```mysql 290 | drop database if exists school; //如果存在SCHOOL则删除 291 | create database school; //建立库SCHOOL 292 | use school; //打开库SCHOOL 293 | create table teacher //建立表TEACHER 294 | ( 295 | id int(3) auto_increment not null primary key, 296 | name char(10) not null, 297 | address varchar(50) default ‘深圳’, 298 | year date 299 | ); //建表结束 300 | 301 | //以下为插入字段 302 | insert into teacher values(”,’allen’,'大连一中’,'1976-10-10′); 303 | insert into teacher values(”,’jack’,'大连二中’,'1975-12-23′); 304 | ``` 305 | 306 | 如果你在 `mysql` 提示符键入上面的命令也可以,但不方便调试。 307 | 308 | ① 你可以将以上命令原样写入一个文本文件中,假设为 `school.sql` ,然后复制到 `c:\` 下,并在 `DOS` 状态进入目录 `mysql\bin` ,然后键入以下命令: 309 | `mysql -u user_name -p user_password < c:\school.sql` 310 | 311 | 如果成功,空出一行无任何显示;如有错误,会有提示。(以上命令已经调试,你只要将//的注释去掉即可使用)。 312 | 313 | ② 或者进入命令行后使用 `mysql> source c:\school.sql; ` 也可以将 `school.sql` 文件导入数据库中。 314 | -------------------------------------------------------------------------------- /php/30_seconds_of_knowledge_php.md: -------------------------------------------------------------------------------- 1 | # 来自 30 seconds of knowledge 相关PHP代码片段 2 | 3 | ### 部分片段展示 4 | 5 | > 这里只列出部分代码片段,完整的请查阅:https://github.com/30-seconds/30_seconds_of_knowledge/blob/master/src/assets/snippets/php/ 。 6 | 7 | 8 |
9 | `average` - 求平均数 10 | 11 | ```php 12 | function average(...$items) { 13 | $count = count($items); 14 | return $count === 0 ? 0 : array_sum($items) / $count; 15 | } 16 | average(1, 2, 3); // 2 17 | ``` 18 |
19 | 20 |
21 | `deepFlatten` - 混维数组平展成一维数组 22 | 23 | ```php 24 | function deepFlatten($items) { 25 | $result = []; 26 | foreach ($items as $item) { 27 | if (!is_array($item)) { 28 | $result[] = $item; 29 | } else { 30 | $result = array_merge($result, deepFlatten($item)); 31 | } 32 | } 33 | return $result; 34 | } 35 | deepFlatten([1, [2], [[3], 4], 5]); // [1, 2, 3, 4, 5] 36 | ``` 37 |
38 | 39 |
40 | `endsWith` - 是否以某个特定词结尾 41 | 42 | ```php 43 | function endsWith($haystack, $needle) { 44 | return strrpos($haystack, $needle) === (strlen($haystack) - strlen($needle)); 45 | } 46 | endsWith('Hi, this is me', 'me'); // true 47 | ``` 48 |
49 | 50 |
51 | `factorial` - 阶乘计算 52 | 53 | ```php 54 | function factorial($n) { 55 | if ($n <= 1) { 56 | return 1; 57 | } 58 | return $n * factorial($n - 1); 59 | } 60 | factorial(6); // 720 61 | ``` 62 |
63 | 64 |
65 | `fibonacci` - 斐波那契数列 66 | 67 | ```php 68 | function fibonacci($n) { 69 | $sequence = [0, 1]; 70 | for ($i = 2; $i < $n; $i++) { 71 | $sequence[$i] = $sequence[$i-1] + $sequence[$i-2]; 72 | } 73 | return $sequence; 74 | } 75 | fibonacci(6); // [0, 1, 1, 2, 3, 5] 76 | ``` 77 |
78 | 79 |
80 | `gcd` - 最大公约数计算 81 | 82 | ```php 83 | function gcd(...$numbers) { 84 | if (count($numbers) > 2) { 85 | return array_reduce($numbers, 'gcd'); 86 | } 87 | $r = $numbers[0] % $numbers[1]; 88 | return $r === 0 ? abs($numbers[1]) : gcd($numbers[1], $r); 89 | } 90 | gcd(8, 36); // 4 91 | gcd(12, 8, 32); // 4 92 | ``` 93 |
94 | 95 |
96 | `head` - 取得首元素 97 | 98 | ```php 99 | function head($items) { 100 | return reset($items); 101 | } 102 | head([1, 2, 3]); // 1 103 | ``` 104 |
105 | 106 |
107 | `isPrime` - 质数判定 108 | 109 | ```php 110 | function isPrime($number) { 111 | $boundary = floor(sqrt($number)); 112 | for ($i = 2; $i <= $boundary; $i++) { 113 | if ($number % $i === 0) { 114 | return false; 115 | } 116 | } 117 | return $number >= 2; 118 | } 119 | isPrime(3); // true 120 | ``` 121 |
122 | 123 |
124 | `last` - 取得尾元素 125 | 126 | ```php 127 | function last($items) { 128 | return end($items); 129 | } 130 | last([1, 2, 3]); // 3 131 | ``` 132 |
133 | 134 |
135 | `lcm` - 最小公倍数计算 136 | 137 | ```php 138 | function lcm(...$numbers) { 139 | $ans = $numbers[0]; 140 | for ($i = 1, $max = count($numbers); $i < $max; $i++) { 141 | $ans = (($numbers[$i] * $ans) / gcd($numbers[$i], $ans)); 142 | } 143 | return $ans; 144 | } 145 | lcm(12, 7); // 84 146 | lcm(1, 3, 4, 5); // 60 147 | ``` 148 |
149 | 150 |
151 | `palindrome` - 回文判断 152 | 153 | ```php 154 | function palindrome($string) { 155 | return strrev($string) === (string) $string; 156 | } 157 | palindrome('racecar'); // true 158 | palindrome(2221222); // true 159 | ``` 160 |
161 | 162 |
163 | `startsWith` - 是否以某个特定词开始 164 | 165 | ```php 166 | function startsWith($haystack, $needle) { 167 | return strpos($haystack, $needle) === 0; 168 | } 169 | startsWith('Hi, this is me', 'Hi'); // true 170 | ``` 171 |
-------------------------------------------------------------------------------- /php/interview.md: -------------------------------------------------------------------------------- 1 | # PHP面试题汇总 2 | 3 | > 部分题目收集自网络,里面可能会穿插一些MySQL与HTML相关问题。 4 | 5 | ## 1. echo(),print(),print_r()的区别? 6 | 7 | **echo** 和 **print** 不是一个函数,是一个语言结构; 8 | `print(string $arg)` 只有一个参数; 9 | `echo arg1,arg2` 可以输出多个参数,返回 `void` ; 10 | `echo` 和 `print` 只能打印出string,不能打印出结构; 11 | `print_r`能打印出结构。比如: 12 | 13 | ```php 14 | $arr = array("key"=>"value"); 15 | print_r($arr); 16 | ``` 17 | 18 | ## 2. 语句include和require的区别是什么? 19 | 20 | 在失败的时候: 21 | `include` 产生一个 `warning` ,而 `require` 直接产生错误中断; 22 | `require` 在运行前载入; 23 | `include` 在运行时载入; 24 | `require_once` 和 `include_once` 可以避免重复包含同一文件。 25 | 26 | ## 3. php中传值与传引用有啥区别? 27 | 28 | &表示传引用; 29 | 函数中参数传引用会将参数进行改变; 30 | 一般在输出参数有多个的时候可以考虑使用引用。 31 | 32 | ```php 33 | $num = 10 34 | function multiply($num){ 35 | $num = $num * 10; 36 | } 37 | multiply($num); 38 | echo $num; 39 | ``` 40 | 41 | ## 4. 下面哪项没有将john添加到users数组中? 42 | 43 | ``` 44 | (a) $users[] = 'john'; 45 | (b) array_add($users,'john'); 46 | (c) array_push($users,'john'); 47 | (d) $users ||= 'john'; 48 | ``` 49 | 答案为bd,php 里面无 `array_add` 函数,d项为语法错误的表达。 50 | 51 | ## 5. HTTP协议中几个状态码的含义。 52 | 53 | ``` 54 | 200 : 请求成功,请求的数据随之返回。 55 | 301 : 永久性重定向。 56 | 302 : 暂时行重定向。 57 | 401 : 当前请求需要用户验证。 58 | 403 : 服务器拒绝执行请求,即没有权限。 59 | 404 : 请求失败,请求的数据在服务器上未发现。 60 | 500 : 服务器错误。一般服务器端程序执行错误。 61 | 503 : 服务器临时维护或过载。这个状态时临时性的。 62 | ``` 63 | ## 6. 写出一些php魔术方法。 64 | 65 | ``` 66 | __construct() 实例化类时自动调用。 67 | __destruct() 类对象使用结束时自动调用。 68 | __set() 在给未定义的属性赋值的时候调用。 69 | __get() 调用未定义的属性时候调用。 70 | __isset() 使用isset()或empty()函数时候会调用。 71 | __unset() 使用unset()时候会调用。 72 | __sleep() 使用serialize序列化时候调用。 73 | __wakeup() 使用unserialize反序列化的时候调用。 74 | __call() 调用一个不存在的方法的时候调用。 75 | __callStatic()调用一个不存在的静态方法是调用。 76 | __toString() 把对象转换成字符串的时候会调用。比如 echo。 77 | __invoke() 当尝试把对象当方法调用时调用。 78 | __set_state() 当使用var_export()函数时候调用。接受一个数组参数。 79 | __clone() 当使用clone复制一个对象时候调用。 80 | ``` 81 | 82 | ## 7. MySQL存储引擎 MyISAM 和 InnoDB 的区别。 83 | 84 | ``` 85 | a. MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持. 86 | b. MyISAM类型的表强调的是性能,其执行数度比InnoDB类型更快. 87 | c. InnoDB不支持FULLTEXT类型的索引. 88 | d. InnoDB中不保存表的具体行数,也就是说,执行select count(*) from table时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可. 89 | e. 对于AUTO_INCREMENT类型的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中,可以和其他字段一起建立联合索引。 90 | f. DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的删除。 91 | g. LOAD TABLE FROM MASTER操作对InnoDB是不起作用的,解决方法是首先把InnoDB表改成MyISAM表,导入数据后再改成InnoDB表,但是对于使用的额外的InnoDB特性(例如外键)的表不适用. 92 | h. MyISAM支持表锁,InnoDB支持行锁。 93 | ``` 94 | 95 | ## 8. 说出一些MySQL优化方法? 96 | 97 | ``` 98 | a. 设计良好的数据库结构,允许部分数据冗余,尽量避免join查询,提高效率。 99 | b. 选择合适的表字段数据类型和存储引擎,适当的添加索引。 100 | c. mysql库主从读写分离。 101 | d. 找规律分表,减少单表中的数据量提高查询速度。 102 | e. 添加缓存机制,比如memcached,apc等。 103 | f. 不经常改动的页面,生成静态页面。 104 | g. 书写高效率的SQL。比如 SELECT * FROM TABEL 改为 SELECT field_1, field_2, field_3 FROM TABLE. 105 | ``` 106 | 107 | ## 9. 下面$a的结果是: 108 | ```php 109 | 112 | ``` 113 | A true 114 | B false 115 | 116 | 答案为B 117 | 118 | ## 10. 说下php中empty()和isset()的区别。 119 | 120 | `isset` 用于检测变量是否被设置,使用 `isset()` 测试一个被设置成 NULL 的变量,将返回 `FALSE` 。 121 | `empty` 如果 `var` 是非空或非零的值,则 `empty()` 返回 `FALSE`。换句话说,`""、0、"0"、NULL、FALSE、array()、var $var;` 以及没有任何属性的对象都将被认为是空的,如果 `var` 为空,则返回 `TRUE` 。 122 | 123 | 如果变量为 `0` ,则`empty()`会返回`TRUE`,`isset()`会返回`TRUE`; 124 | 如果变量为空字符串,则`empty()`会返回TRUE,`isset()`会返回`TRUE`; 125 | 如果变量未定义,则`empty()`会返回`TRUE`,`isset()`会返回`FLASE`。 126 | 127 | 注意:`isset()` 只能用于变量,因为传递任何其它参数都将造成解析错误。若想检测常量是否已设置,可使用 `defined()` 函数。 128 | 当要 判断一个变量是否已经声明的时候 可以使用 `isset` 函数; 129 | 当要 判断一个变量是否已经赋予数据且不为空 可以用 `empty `函数; 130 | 当要 判断 一个变量 存在且不为空 先 `isset` 函数 再用 `empty` 函数; 131 | 132 | -------------------------------------------------------------------------------- /php/interview_2.md: -------------------------------------------------------------------------------- 1 | # PHP面试题汇总 (二) 2 | 3 | 大部分面试题来自网络,由于多重转载,已不知原始出处,链接就不一一列出。欢迎大家在 `issue` 页面留言讨论问题。 4 | 5 | 问题来源: 6 | 7 | http://tieba.baidu.com/p/3612369052 8 | http://blog.csdn.net/hyr352114576/article/details/49638345 9 | https://my.oschina.net/u/574366/blog/64814 10 | 11 | 12 | ## 自我表述型问题 13 | 14 | > 没有固定/参考答案,结合问题和自身实际予以表述即可。 15 | 16 | ### 简单做一下自我介绍,? 然后谈一下近三年来你的得意之作? 17 | 18 | 点评: 19 | A、此问题考察你的描述同简历的相符之处; 20 | B、从描述中,发现可以追问的点,追问细节,你是不是真参与了,参与了多少; 21 | C、从项目的周期、职责、复杂程序对你的能力进行定位和评估。 22 | 23 | ### 面试官看过你的简历,会问一些你做的项目的用户量、PV、吞吐量、相关难点和解决方法等。 24 | 25 | 点评: 26 | 同上。 27 | 28 | ### 假如你现在是12306火车订票的设计师,你该如何设计满足全国人民订票? 29 | 30 | 参考答案:https://www.zhihu.com/question/20017917 31 | 32 | ### 假如有1亿用户的访问量,你的服务器架构是怎样的? 用户信息的存储方案如何设计? 33 | 34 | 点评: 35 | A、此问答也比较泛,考察的是对解决一个问题的分析思路; 36 | B、从哪些方面,哪些层面对问题进行考察; 37 | C、对于想到的方面和层面,再细致挖掘考虑是否严谨; 38 | D、用户信息存储考察面试者对用户信息业务本身的了解、存储方式及其特点的了解。 39 | 40 | ### 如果你是技术组长,所带团队任务进度无法完成你该如何解决?如果在进度排满的前提下插入任务,你该如何保证总进度不延期?如果有的工程师今天预定任务没有完成,你该如何解决? 41 | 42 | 点评: 43 | A、考察带队能力; 44 | B、注意不是所有的问题都有非常肯定和完美的答案,思考和解决问题的方式,比回答问题本身更为重要。 45 | 46 | ### 从你的经验方面谈一下如何构建高性能web站点? 需要哪些环节? 步骤? 每个步骤需要注意什么如何优化等? 47 | 48 | 参考提示点:带宽、DNS、CDN、gzip、负载均衡以及数据库等。 49 | 50 | ## 技术型问题 51 | 52 | ### for与foreach哪个更快? 53 | 54 | 参考答案:http://www.cnblogs.com/niniwzw/archive/2008/06/03/1212535.html 55 | 56 | `foreach` 的效率要比 `for` 高很多,也许有很大的一个原因是 `for` 要进行很多次条件判断。所以以后能用 `foreach` 的地方就用 `foreach` ,可以提高1倍的效率。 57 | 58 | 如果循环内要调用函数,用 `array_walk` 最好,它的效率要比 `for` 高出1倍,要比 `foreach` 高出43%的效率。 59 | 60 | ### PECL 和 PEAR 有什么区别? 61 | 62 | 参考答案:http://jingyan.baidu.com/article/e9fb46e1a3eb277521f76619.html 63 | 64 | `PECL (PHP Extension Community Library)` 可以看作 `PEAR (PHP Extension and Application Repository)` 的一个组成部分,提供了与 `PEAR` 类似的功能。不同的是 `PEAR` 的所有扩展都是用纯粹的 `PHP` 代码编写的,用户在下载到 `PEAR` 扩展以后可以直接使用将扩展的代码包含到自己的 `PHP` 文件中使用。而 `PECL` 是使用 `C` 语言开发的,通常用于补充一些用 `PHP` 难以完成的底层功能,往往需要重新编译或者在配置文件中设置后才能在用户自己的代码中使用。 65 | 66 | 最直接的表述:`PEAR` 是 `PHP` 的上层扩展,`PECL` 是 `PHP` 的底层扩展。它们都是为特定的应用提供现成的函数或者类。 67 | 68 | ### 如何处理多服务器共享 Session ? 69 | 70 | 参考答案:http://www.toutiao.com/a6294758409293086977/ 71 | 72 | 大致上有三种方式可以处理: 73 | 74 | - 数据库/文件同步 `session` 75 | - `cookie` 同步 `session` 76 | - 缓存 (如 `memcache` )同步 `session` 77 | 78 | 推荐使用最后缓存同步方案。 79 | 80 | ### 什么是跨站脚本?SQL注入? 81 | 82 | 跨站脚本( `XSS` )是一种计算机安全漏洞,是代码注入的一种,通常出现在web应用程序上。它允许恶意用户将代码注入到网页上,其他用户观看网页时就会收到影响。这种攻击通常包含了html以及客户端脚本语言。 `SQL` 注入是发生于应用程序数据库层的安全漏洞。是在输入的字符中注入 `SQL` 指令,在设计不良的程序中忽略了检查,那么这些注入的指令会被数据库误认为是正常的 `SQL` 指令而运行,因此遭到破坏。 83 | 84 | ### 描述一下大流量高并发量网站的解决方案 85 | 86 | - 确认服务器硬件是否足够支持当前的流量。 87 | - 使用 `memcache` 缓存技术,将动态数据缓存到文件中,动态网页直接调用这些文件,而不必在访问数据库。 88 | - 禁止外部的盗链。外部网站的图片或者文件盗链往往会带来大量的负载压力,因此应该严格限制外部对自身图片或者文件盗链,可以通过apache的URL重定向来防止盗链。 89 | - 控制大文件的下载。大文件的下载会占用很大的流量,对于非SCSI硬盘来说会消耗,使得网站响应能力下降。 90 | - 使用不同的主机分流主要流量。 91 | - 使用流量统计软件。在网站上安装一个流量统计软件,可以即时知道哪些地方耗费了大量流量,哪些页面需要再进行优化。 92 | 93 | ### PHP内存管理机制与垃圾回收机制 94 | 95 | 参考答案:http://www.cnblogs.com/zk0533/p/5667122.html 96 | 97 | `php` 的内存管理机制是:预先给出一块空间,用来存储变量,当空间不够时,再申请一块新的空间。 98 | 1. 存储变量名,存在符号表。 99 | 2. 变量值存储在内存空间。 100 | 3. 在删除变量的时候,会将变量值存储的空间释放,而变量名所在的符号表不会减小。 101 | 102 | `php` 垃圾回收机制是: 103 | 104 | 1. 在5.2版本或之前版本,PHP会根据 引用计数 ( `refcount` )值来判断是不是垃圾,如果refcount值为0,PHP会当做垃圾释放掉,这种回收机制有缺陷,对于环状引用的变量无法回收。 105 | 106 | 2. 在5.3之后版本改进了垃圾回收机制。具体如下: 107 | 108 | 如果发现一个 `zval` 容器中的 `refcount` 在增加,说明不是垃圾; 109 | 如果发现一个 `zval` 容器中的 `refcount` 在减少,如果减到了0,直接当做垃圾回收; 110 | 如果发现一个 `zval` 容器中的 `refcount` 在减少,并没有减到0,`PHP` 会把该值放到缓冲区,当做有可能是垃圾的怀疑对象; 111 | 当缓冲区达到了临界值,`PHP` 会自动调用一个方法去遍历每一个值,如果发现是垃圾就清理。 112 | 113 | ### 为什么要对数据库进行主从分离? 114 | 115 | 参考答案:https://my.oschina.net/candiesyangyang/blog/203425 116 | 117 | 118 | ### 多线程和多进程的区别为? 119 | 120 | 参考答案:http://www.cnblogs.com/kaituorensheng/p/3603057.html 121 | 122 | 进程是程序在计算机上的一次执行活动。当你运行一个程序,你就启动了一个进程。显然,程序是死的(静态的),进程是活的(动态的)。进程可以分为系统进程和用户进程。凡是用于完成操作系统的各种功能的进程就是系统进程,它们就是处于运行状态下的操作系统本身;所有由你启动的进程都是用户进程。进程是操作系统进行资源分配的单位。在 `Windows` 下,进程又被细化为线程,也就是一个进程下有多个能独立运行的更小的单位。 123 | 124 | ### TCP/IP 网络协议,OSI 7 层指是什么? 125 | 126 | 127 | 参考答案:http://blog.csdn.net/jenminzhang/article/details/47017741 128 | 129 | `TCP/IP` 5层 指的是: 130 | 131 | ``` 132 | 应用层 133 | HTTP、FTP、SMTP、DNS、DSP、Telnet、Gopher、WAIS…… 134 | 传输层 135 | TCP、UDP、DVP…… 136 | 网络层 137 | IP、ICMP、AKP、RARP、UUCP…… 138 | 接口层 139 | Ethernet、Arpanet、PDN…… 140 | 物理层 141 | 只要能传输IP数据报(Datagram),允许任何协议…… 142 | ``` 143 | 144 | `OSI` 7层指的是: 145 | 146 | ``` 147 | 应用层 文件传输,电子邮件,文件服务,虚拟终端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 148 | 表示层 数据格式化,代码转换,数据加密 没有协议 149 | 会话层 解除或建立与别的接点的联系 没有协议 150 | 传输层 提供端对端的接口 TCP,UDP 151 | 网络层 为数据包选择路由 IP,ICMP,RIP,OSPF,BGP,IGMP 152 | 数据链路层 传输有地址的帧以及错误检测功能 SLIP,CSLIP,PPP,ARP,RARP,MTU 153 | 物理层 以二进制数据形式在物理媒体上传输数据 ISO2110,IEEE802,IEEE802.2 154 | ``` 155 | 156 | -------------------------------------------------------------------------------- /php/randomLuckyRedPacket.php: -------------------------------------------------------------------------------- 1 | 6 | * @param int $bonusSize 红包份数 7 | * @return array 8 | */ 9 | function randBonus($totalBonus, $bonusSize) { 10 | if ($totalBonus < 1) { 11 | die('红包总金额不得少于1分钱').PHP_EOL; 12 | } 13 | if ($bonusSize < 1) { 14 | die('红包份数不得少于1份').PHP_EOL; 15 | } 16 | if ($totalBonus < $bonusSize) { 17 | die('红包金额不足,不满足拼手气红包要求!').PHP_EOL; 18 | } 19 | $remainBonus = $totalBonus; // 剩余可分配的红包金额 20 | $iCount = 0; 21 | $divisions = []; 22 | $min = 1; // 随机最小值使用 1 23 | while ($iCount < $bonusSize) { 24 | if ($iCount < $bonusSize - 1) { 25 | $restSize = $bonusSize - $iCount; 26 | $max = bcdiv($remainBonus, $restSize)*2; // 随机最大值使用 未分配金额的平均值的2倍 27 | $randCent = $min; 28 | if (($remainBonus > $restSize*$min) && $max > $min ) { 29 | $randCent = mt_rand($min, $max); // 随机金额范围 30 | while ($randCent == $remainBonus) { 31 | $randCent = mt_rand($min, $max); 32 | } 33 | } 34 | $divisions[] = $randCent; 35 | $remainBonus -= $randCent; 36 | echo 'max:'.$max.',iCount:'.$iCount.',randCent:'.$randCent.',remainBonus:'.$remainBonus.PHP_EOL; 37 | } else { 38 | $divisions[] = $remainBonus; 39 | echo 'max:null,iCount:'.$iCount.',randCent:'.$remainBonus.',remainBonus:0'.PHP_EOL; 40 | } 41 | $iCount ++; 42 | } 43 | return $divisions; 44 | } 45 | $totalBonus = 16; 46 | $bonusSize = 10; 47 | // 0.16 元 10 人份 48 | $ret = randBonus($totalBonus, $bonusSize); 49 | $total = array_sum($ret); 50 | echo '红包总金额:'.$total.' 分,'.'红包总份数:'.$bonusSize.' 份'.PHP_EOL; 51 | echo '拼手气红包领取明细:'.implode(',', $ret).PHP_EOL; 52 | --------------------------------------------------------------------------------