├── Docker安装和基本使用.md
├── Gogs安装配置.md
├── Homestead.md
├── LNMP安装.md
├── Laravel优化配置.md
├── Memcache.md
├── MogonDB笔记.md
├── Mongodb.md
├── MySQL定时备份.md
├── PHP实现一致性哈希算法.php
├── PHP常用代码样例
└── README.md
├── PHP常用工具类封装
└── regexTool.class.php
├── PHP技能评测
└── README.md
├── PHP珍贵资源
├── CODE-OF-CONDUCT.md
├── COLLABORATING.md
├── CONTRIBUTING.md
├── LICENSE.md
└── README.md
├── README.md
├── Redis.md
├── Windows下搭建wnmp环境.md
├── docker+nginx负载均衡.md
├── images
├── images.jpg
├── nginx.png
├── ps.png
├── test.png
└── tree.png
├── mysql防注入.php
├── nginx详解
├── README1.md
└── README2.md
├── php常用函数.php
├── regex.php
├── samba安装与配置.md
├── 其他资源
└── readme.MD
└── 十个非常有用的PHP片段.php
/Docker安装和基本使用.md:
--------------------------------------------------------------------------------
1 | # Docker安装
2 | ### 1、使用下面的shell命令安装Docker
3 | ```
4 | $ curl -sSL https://get.docker.com/ | sh
5 | 或者 yum -y install docker
6 | ```
7 | ### 2、启动docker服务
8 | ```
9 | service docker start
10 | ```
11 | ### 3、使用Docker创建一个nginx的容器:(用国内网易云镜像,提高下载速度)
12 | ```
13 | docker run -d --name=web -p 80:80 hub.c.163.com/library/nginx:latest
14 | (创建一个名称为web的容器,并把容器内部的80端口与宿主机上的80端口做映射,使得通过宿主机80端口的流量转发到容器内部的80端口 上。其中 -d 为守护进程在后台启动,-p 端口映射)
15 | ```
16 | ### 4、docker ps 列出正在运行的容器,现在访问宿主机地址的80端口,看到nginx的欢迎页面。
17 | ```
18 | docker images 能看到目前的镜像
19 | ```
20 | ### 5、进入刚才创建的容器内部
21 | ```
22 | docker exec -i -t web bash
23 | 退出:exit
24 | (-t:在新容器内指定一个伪终端或终端。-i:允许你对容器内的标准输入 (STDIN) 进行交互。)
25 | ```
26 | ### 6、查看容器的更多详细信息
27 | ```
28 | docker inspect web
29 | 在networks部分可以看到容器的网络环境信息:
30 | 可以看到这个容器的IP地址为172.17.0.2,网关地址为172.17.0.1。
31 | ```
32 | ### 7、宿主和容器间的通信
33 | ```
34 | docker在启动的时候会在宿主机上创建一块名为docker0的网卡,可以用ifconfig查看ip地址也是172.17.0.1.
35 | docker容器就是通过这张名为docker0的网卡进行通信
36 |
37 | 真正实现端口转发的魔法的是nat规则。如果容器使用-p指定映射的端口时,docker会通过iptables创建一条nat规则,把宿主机打到 映射端口的数据包通过转发到docker0的网关,docker0再通过广播找到对应ip的目标容器,把数据包转发到容器的端口上。反过来,如 果docker要跟外部的网络进行通信,也是通过docker0和iptables的nat进行转发,再由宿主机的物理网卡进行处理,使得外部可以不知 道容器的存在。
38 |
39 | 使用iptables -t nat命令可以看到添加的nat规则:
40 | 可以观察到流量转发到了172.17.0.2的80端口上,这个地址就是刚才创建容器使用的IP地址。
41 |
42 | 提示:容器具有隔离性优势,更好地控制环境和版本的隔离
43 | ```
44 | ### 8、下面新建一个应用ping,作用是统计该应用的访问次数,每次访问页面将次数累加1,返回响应次数给前端页面,并把访问次数存到数据库中。
45 | ```
46 | 使用redis作为ping的数据库,与之前类似,拉取redis的镜像,运行容器。
47 | docker pull redis
48 | docker run -d --name=redis -p 6379 redis
49 | ```
50 |
51 |
52 |
53 | # 注意:
54 | ```
55 | 启动docker web服务时 虚拟机端口转发 外部无法访问(WARNING: IPv4 forwarding is disabled. Networking will not work.)
56 | 或者宿主机可以访问,但外部无法访问
57 | # vi /etc/sysctl.conf
58 | 或者
59 | # vi /usr/lib/sysctl.d/00-system.conf
60 | 添加如下代码:
61 | net.ipv4.ip_forward=1
62 | ```
63 | ### 重启network服务
64 | ```
65 | # systemctl restart network
66 | ```
67 | ### 查看是否修改成功
68 | ```
69 | # sysctl net.ipv4.ip_forward
70 |
71 | 如果返回为“net.ipv4.ip_forward = 1”则表示成功了
72 | ```
73 |
74 |
75 | # 安装 Docker-Compose
76 | curl -L https://github.com/docker/compose/releases/download/1.13.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
77 |
78 | chmod +x /usr/local/bin/docker-compose
--------------------------------------------------------------------------------
/Gogs安装配置.md:
--------------------------------------------------------------------------------
1 | ## 安装nginx
2 | `sudo yum -y install nginx`
3 |
4 | ## 安装git
5 | `sudo yum -y install git`
6 |
7 | ## 安装MySQL
8 | `sudo yum -y install mysql-server`
9 |
10 | ## 创建gogs数据库
11 | ```
12 | set global storage_engine = 'InnoDB';
13 | create database gogs default character set utf8mb4 collate utf8mb4_unicode_ci;
14 | create user 'gogs'@'localhost' identified by '你的密码';
15 | grant all privileges on gogs.* to 'gogs'@'localhost';
16 | flush privileges;
17 | exit;
18 | ```
19 |
20 | ## 为gogs创建用户
21 | `sudo adduser git`
22 |
23 | ## 下载并解压gogs
24 | ```
25 | su git
26 | cd ~
27 | wget https://dl.gogs.io/0.11.34/linux_amd64.tar.gz
28 | sudo tar zxvf linux_amd64.tar.gz -C /usr/local
29 | ```
30 | ## 自定义配置文件
31 | Gogs的配置要自己创建文件,在Gogs根目录下创建自定义配置文件(文件目录以及名称是固定的):
32 |
33 | `mkdir -p custom/conf`
34 |
35 | `vim custom/conf/app.ini`
36 |
37 | ```
38 | APP_NAME = Go Git Service
39 | RUN_USER = git
40 | RUN_MODE = prod
41 |
42 | [database]
43 | DB_TYPE = mysql
44 | HOST = 127.0.0.1:3306
45 | NAME = gogs
46 | USER = gogs
47 | PASSWD = gogs
48 | SSL_MODE = disable
49 | PATH = data/gogs.db
50 |
51 | [repository]
52 | ROOT = /home/git/gogs-repositories
53 |
54 | [server]
55 | DOMAIN = 127.0.0.1
56 | HTTP_PORT = 3000
57 | ROOT_URL = http://127.0.0.1:3000/
58 | DISABLE_SSH = false
59 | SSH_PORT = 22
60 | OFFLINE_MODE = false
61 |
62 | [mailer]
63 | ENABLED = false
64 |
65 | [service]
66 | REGISTER_EMAIL_CONFIRM = false
67 | ENABLE_NOTIFY_MAIL = false
68 | DISABLE_REGISTRATION = false
69 | ENABLE_CAPTCHA = true
70 | REQUIRE_SIGNIN_VIEW = false
71 |
72 | [picture]
73 | DISABLE_GRAVATAR = false
74 |
75 | [session]
76 | PROVIDER = file
77 |
78 | [log]
79 | MODE = file
80 | LEVEL = Info
81 | ROOT_PATH = /usr/local/gogs/log
82 |
83 | [security]
84 | INSTALL_LOCK = true
85 | SECRET_KEY = i4B7R55aRaFdw8j
86 | ```
87 |
88 | ### 启动gogs
89 | /usr/local/gogs/gogs web
90 |
91 | ### 后台启动方案一
92 | `nohup /usr/local/gogs/gogs web &`
93 |
94 | `tail -f nohup.out`
95 |
96 | 然后访问http://服务器IP:3000/install
97 |
98 | ### 后台运行方案二 (加入系统服务)
99 | ```
100 | 复制并修改脚本文件
101 | #sudo vim /usr/local/gogs/scripts/init/centos/gogs(修改对应的地址和用户)
102 | #sudo cp /usr/local/gogs/scripts/init/centos/gogs /etc/init.d/
103 | #sudo chmod +x /etc/init.d/gogs
104 |
105 | sudo cp /usr/local/gogs/scripts/systemd/gogs.service /etc/systemd/system/
106 | sudo vim /etc/systemd/system/gogs.service (修改对应的地址和用户)
107 |
108 | sudo systemctl daemon-reload
109 | sudo service gogs start(返回ok,但查看status还是失败状态且无法访问,则还是因为地址用户修改不正确)
110 | sudo chkconfig --add gogs (开机自启)
111 | ```
112 | ## nginx 反向代理
113 | ```
114 | server {
115 | server_name 二级域名或IP;
116 | listen 80; # 或者 443,如果你使用 HTTPS 的话
117 | # ssl on; 是否启用加密连接
118 | # 如果你使用 HTTPS,还需要填写 ssl_certificate 和 ssl_certificate_key
119 |
120 | location / { # 如果你希望通过子路径访问,此处修改为子路径,注意以 / 开头并以 / 结束
121 | proxy_pass http://127.0.0.1:3000/;
122 | }
123 | }
124 | ```
--------------------------------------------------------------------------------
/Homestead.md:
--------------------------------------------------------------------------------
1 | ## 基本介绍
2 | > Homestead 可以运行在 Windows 、 Mac 或 Linux 系统上,并且里面包含了 Nginx Web 服务器、 PHP 7.1 、 MySQL 、 Postgres 、 Redis 、 Memcached 、 Node等以及所有利于你开发 laravel 应用的其他程序。
3 |
4 | ## 内置软件
5 | + Ubuntu 16.04
6 | + Git
7 | + PHP 7.1、7.0、5.6
8 | + Nginx
9 | + MySQL
10 | + MariaDB
11 | + Sqlite3
12 | + Postgres
13 | + Composer
14 | + Node (With Yarn, Bower, Grunt, and Gulp)
15 | + Redis
16 | + Memcached
17 | + Beanstalkd
18 | + Mailhog
19 | + ngrok
20 |
21 | ## 安装与配置(windows用户自行安装git方便操作以下命令)
22 | ### 安装vagrant
23 | [vagrant-win](https://releases.hashicorp.com/vagrant/1.9.7/vagrant_1.9.7_x86_64.msi?_ga=2.103239433.86842748.1500269595-159348511.1499308757)
24 | [vagrant-linux](https://releases.hashicorp.com/vagrant/1.9.7/vagrant_1.9.7_x86_64.rpm?_ga=2.103239433.86842748.1500269595-159348511.1499308757)
25 | ### 安装Virtualbox
26 | [virtualbox-win](http://download.virtualbox.org/virtualbox/5.1.22/VirtualBox-5.1.22-115126-Win.exe)
27 | [virtualbox-linux](https://www.virtualbox.org/wiki/Linux_Downloads)
28 | ### 导入box
29 | ```
30 | vagrant box add laravel/homestead
31 | ```
32 | 由于众所周知的原因,上述方法可能需要下载个几天,所以推荐直接用迅雷下载virtualbox版的box文件
33 |
34 | - [box文件下载](https://atlas.hashicorp.com/laravel/boxes/homestead/versions/2.2.0/providers/virtualbox.box)
35 |
36 | 接下来我新建了一个文件夹名为homestead,然后我将下好的box重命名为homestead.box放入,然后在此文件夹内运行如下命令
37 | ```
38 | vagrant box add laravel/homestead E:\homestead\homestead.box
39 | vagrant box list
40 | ```
41 | 会反馈一条信息:`laravel/homestead (virtualbox, 0)` 这说明box已经添加进来了
42 |
43 | ### 下载官方homestead配置
44 | ```
45 | git clone https://github.com/laravel/homestead.git Homestead
46 | ```
47 | 克隆的文件夹内有init.sh和init.bat文件,运行如下命令进行初始化生成homestead.yml配置文件
48 | ```
49 | bash init.sh
50 | ```
51 | 或者直接双击init.bat
52 |
53 | ### 配置Homestead.yaml
54 | ##### 设置 IP及Provider
55 | Homestead.yaml文件中的provider键表示使用哪个 Vagrant 提供者:virtualbox、vmware_fushion或者vmware_workstation
56 | ```
57 | ip: "192.168.10.10"
58 | provider: virtualbox
59 | ```
60 | ##### 配置共享文件夹
61 | Homestead.yaml文件中的folders属性列出了所有主机和 Homestead 虚拟机共享的文件夹,一旦这些目录中的文件有了修改,将会在本地和 Homestead 虚拟机之间保持同步,如果有需要的话,你可以配置多个共享文件夹(一般一个就够了),如果要开启 NFS,只需简单添加一个标识到同步文件夹配置
62 | ```
63 | folders:
64 | - map: D:/homestead/code #(这是我本地的文件夹)
65 | to: /home/vagrant/Code
66 | type: "nfs"
67 | ```
68 |
69 | ##### 配置 Nginx 站点
70 | 通过sites属性可以方便地将域名映射到 Homestead 虚拟机的指定目录,Homestead.yaml中默认已经配置了一个示 例站点。和共享文件夹一样,可以配置多个站点:
71 | ```
72 | sites:
73 | - map: homestead.app
74 | to: /home/vagrant/Code/Laravel/public
75 | - map: yii2.app
76 | to: /home/vagrant/Code/yii2/basic/web
77 | ```
78 |
79 | ##### 修改Hosts文件
80 | 把 Nginx 站点配置中的域名添加到本地机器上的hosts文件中,该文件会将对本地域名的请求重定向到 Homestead 虚拟机
81 | ```
82 | 192.168.10.10 homestead.app
83 | 192.168.10.10 www.yii2.com
84 | ```
85 |
86 | ### 修改homestead.rb文件
87 | 如果这时候你直接在Homestead目录下启动homestead虚拟机,肯定会得到反复叫你下载virtualbox的提示,猜测这是由于手动添加的virtualbox没有保存版本信息的缘故(可以使用命令vagrant box list来查看)。所以可以通过修改Homestead/scripts/homestead.rb来解决这一个问题,找到
88 |
89 | `config.vm.box_version = settings["version"] ||= ">= 2.0.0"`这一行,将其修改为`config.vm.box_version = settings["version"] ||= ">= 0"`即可
90 |
91 | ### 启动虚拟机
92 | 进入Homestead目录(git clone下来里面的那个目录),使用命令`vagrant up`命令启动虚拟机,可使用`vagrant ssh`登陆虚拟机。顺便一提,虚拟机数据库的root用户密码为secret,远程连接是用户homestead 密码 secret
93 | > 若提示ssh的key没有生成则执行:`ssh-keygen`
94 | >
95 | > 更换composer中国镜像:`composer config -g repo.packagist composer https://packagist.phpcomposer.com`
96 | >
97 | >若访问网站出现文件未找到(No input file specified.)则需要执行:vagrant provision
98 |
99 |
100 | ## 命令操作
101 | - Homestead 目录下
102 |
103 | 开机: vagrant up
104 | 关机: vagrant halt
105 | 更改homestead.yml后使用:vagrant provision
106 | 盒子列表:vagrant box list
107 | 重新加载配置:vagrant --reload
108 | 从vagrant中去除添加的盒子:vagrant box remove '盒子名称'
109 | 销毁虚拟机: vagrant destroy --force
110 | 登录: vagrant ssh
111 |
112 | - 访问网站
113 |
114 | 绑定hosts 192.168.10.10 homestead.app
115 | 访问 http://homestead.app
116 |
117 | - SSH登录
118 |
119 | 通过ssh登录 ssh vagrant@127.0.0.1 -p 2222 或者创建别名 alias vm="ssh vagrant@127.0.0.1 -p 2222",使用vm登录
120 | 通过在Homestead 目录使用 vagrant ssh 命令
121 |
122 | - 连接虚拟机内Mysql
123 |
124 | mysql -h 127.0.0.1:33060 -u homestead -p secret
125 |
126 | - 端口映射
127 |
128 | SSH: 2222 → Forwards To 22
129 | HTTP: 8000 → Forwards To 80
130 | HTTPS: 44300 → Forwards To 443
131 | MySQL: 33060 → Forwards To 3306
132 | Postgres: 54320 → Forwards To 5432
133 |
134 | - 增加额外端口
135 |
136 | ports:
137 | - send: 93000
138 | to: 9300
139 | - send: 7777
140 | to: 777
141 | protocol: udp
142 |
143 | - 增加站点
144 |
145 | 方式一 Homestead.yaml 文件中增加站点
146 | Homestead 目录中执行 vagrant provision
147 | 会破坏以后数据库
148 |
149 | 方式二 Homestead环境中的 serve 命令
150 | SSH 进入 Homestead 环境中
151 | 执行下列命令`serve domain.app /home/vagrant/Code/path/to/public/directory 80`
152 |
153 |
154 | ## License
155 |
156 | [MIT](http://opensource.org/licenses/MIT)
157 |
158 | Copyright (c) 2016-present, Voocel
159 |
--------------------------------------------------------------------------------
/LNMP安装.md:
--------------------------------------------------------------------------------
1 | >经过自己反复多次安装验证总结出来的,以便今后查阅
2 |
3 | ## 一、更新系统软件
4 | ```
5 | yum update
6 | ```
7 | ## 二、安装编译工具:
8 | ```
9 | yum install gcc automake autoconf libtool gcc-c++
10 | ```
11 | ## 三、安装nginx
12 | ### 方法一:
13 |
14 | ##### 1. 安装nginx源:
15 | ```
16 | yum localinstall http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
17 | ```
18 | ##### 2. 安装nginx:
19 | ```
20 | yum install nginx
21 | ```
22 | ##### 3. 启动nginx:
23 | ```
24 | service nginx start
25 | 成功显示:Redirecting to /bin/systemctl start nginx.service
26 | 查看状态:systemctl status nginx 或者 service nginx status
27 | ```
28 | ##### 4. 访问http://你的ip/
29 | 如果成功安装会出来nginx默认的欢迎界面
30 | 括号内为设置开机自启
31 | (systemctl enable nginx
32 | ln -s '/usr/lib/systemd/system/nginx.service' '/etc/systemd/system/multi-user.target.wants/nginx.service')
33 |
34 | ### 方法二:
35 |
36 | ##### 1、安装编译软件
37 | ```
38 | yum -y install gcc gcc-c++ wget
39 | ```
40 | ##### 2、安装依赖
41 | ```
42 | yum -y install gcc wget automake autoconf libtool libxml2-devel libxslt-devel perl-devel perl-ExtUtils-Embed pcre-devel openssl-devel
43 | ```
44 | ##### 3、进入目录
45 | ```
46 | cd /usr/local/src/
47 | ```
48 | ##### 4、下载源码
49 | ```
50 | wget http://nginx.org/download/nginx-1.12.0.tar.gz
51 | ```
52 | ##### 5、解压
53 | ```
54 | tar zxvf nginx-1.12.0.tar.gz
55 | ```
56 | ##### 6、进入目录
57 | ```
58 | cd nginx-1.12.0/
59 | ```
60 | ##### 7、创建缓存目录
61 | ```
62 | mkdir -p /var/cache/nginx
63 | ```
64 | ##### 8、configure
65 | ```
66 | ./configure \
67 | --prefix=/usr/local/nginx \
68 | --sbin-path=/usr/sbin/nginx \
69 | --conf-path=/etc/nginx/nginx.conf \
70 | --error-log-path=/var/log/nginx/error.log \
71 | --http-log-path=/var/log/nginx/access.log \
72 | --pid-path=/var/run/nginx.pid \
73 | --lock-path=/var/run/nginx.lock \
74 | --http-client-body-temp-path=/var/cache/nginx/client_temp \
75 | --http-proxy-temp-path=/var/cache/nginx/proxy_temp \
76 | --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
77 | --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
78 | --http-scgi-temp-path=/var/cache/nginx/scgi_temp \
79 | --user=nobody \
80 | --group=nobody \
81 | --with-pcre \
82 | --with-http_v2_module \
83 | --with-http_ssl_module \
84 | --with-http_realip_module \
85 | --with-http_addition_module \
86 | --with-http_sub_module \
87 | --with-http_dav_module \
88 | --with-http_flv_module \
89 | --with-http_mp4_module \
90 | --with-http_gunzip_module \
91 | --with-http_gzip_static_module \
92 | --with-http_random_index_module \
93 | --with-http_secure_link_module \
94 | --with-http_stub_status_module \
95 | --with-http_auth_request_module \
96 | --with-mail \
97 | --with-mail_ssl_module \
98 | --with-file-aio \
99 | --with-http_v2_module \
100 | --with-threads \
101 | --with-stream \
102 | --with-stream_ssl_module
103 | ```
104 | ##### 9、编译安装
105 | ```
106 | make && make install
107 | ```
108 | ##### 10、然后配置服务:vim /usr/lib/systemd/system/nginx.service
109 | ```
110 | [Unit]
111 | Description=nginx - high performance web server
112 | Documentation=http://nginx.org/en/docs/
113 | After=network.target remote-fs.target nss-lookup.target
114 |
115 | [Service]
116 | Type=forking
117 | PIDFile=/var/run/nginx.pid
118 | ExecStartPre=/usr/sbin/nginx -t -c /etc/nginx/nginx.conf
119 | ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
120 | ExecReload=/bin/kill -s HUP $MAINPID
121 | ExecStop=/bin/kill -s QUIT $MAINPID
122 | PrivateTmp=true
123 |
124 | [Install]
125 | WantedBy=multi-user.target
126 | ```
127 | ##### 11、开启开机启动:
128 | ```
129 | systemctl enable nginx.service
130 | ```
131 | ##### 12、启动:
132 | ```
133 | systemctl start nginx.service
134 | ```
135 |
136 | pkill -9 nginx(强制关闭Nginx)firewall-cmd --zone=public --add-port=80/tcp --permanent(开放80端口)
137 | systemctl restart firewalld.service(重启防火墙)
138 | ps aux |grep nginx(查看nginx进程) netstat -tunpl |grep :80(查看80端口)
139 |
140 | ## 四、安装MySQL5.7.*
141 | #### 1. 安装mysql源:
142 | ```
143 | yum localinstall http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm
144 | ```
145 | #### 2. 安装mysql:
146 | ```
147 | yum -y install mysql-community-server
148 | ```
149 | 确认一下mysql的版本,有时可能会提示mysql5.6
150 | #### 3. 安装mysql的开发包,以后会有用
151 | ```
152 | yum -y install mysql-community-devel
153 | ```
154 | #### 4. 启动mysql
155 | ```
156 | service mysqld start
157 | ```
158 | 成功返回Redirecting to /bin/systemctl start mysqld.service
159 | #### 5. 查看mysql启动状态
160 | ```
161 | service mysqld status
162 | ```
163 | 出现pid证明启动成功
164 | #### 6. 获取mysql默认生成的密码
165 | ```
166 | grep 'temporary password' /var/log/mysqld.log
167 | 2017-02-10T14:59:42.328736Z 1 [Note] A temporary password is generated for root@localhost: s/giN9Vo>L9h
168 | ```
169 | 冒号后面的都是密码(没有空格) 复制就好
170 | #### 7. 换成自己的密码
171 | ```
172 | mysql -uroot -p
173 | Enter password:输入上面复制的密码
174 | ```
175 | #### 8. 更换密码:
176 | ```
177 | mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'MyNewPass4!';
178 | ```
179 | 这个密码一定要足够复杂,不然会不让你改,提示密码不合法(ERROR 1819 (HY000): Your password does not satisfy the current policy requirements)
180 | 如果不想设置那么复杂的密码可以通过修改validate_password_policy参数的值
181 | ```
182 | mysql> set global validate_password_policy=0;
183 | ```
184 | 这样,判断密码的标准就基于密码的长度了。这个由validate_password_length参数来决定。
185 | #### 9. 退出mysql:
186 | ```
187 | mysql> quit;
188 | ```
189 | #### 10. 用新密码再登录,试一下新密码
190 | ```
191 | mysql -uroot -p
192 | Enter password:输入你的新密码
193 | ```
194 | #### 11. 确认密码正确后,退出mysql;
195 | ```
196 | mysql> quit;
197 | ```
198 | ## 五、编译安装php7.0.0 (创建用户作为用于启动nginx进程的用户 groupadd nginx useradd -r -g nginx nginx)
199 |
200 | #### 1. 下载php7源码包
201 | ```
202 | cd /root & wget -O php7.tar.gz http://cn2.php.net/get/php-7.0.1.tar.gz/from/this/mirror
203 | ```
204 | #### 2. 解压源码包
205 | 源码包的位置可以使用 find / -name php7 查找 并进入所在文件夹
206 | ```
207 | tar -xvf php7.tar.gz
208 | ```
209 | #### 3. 打开解压好的包
210 | ```
211 | cd php-7.0.1
212 | ```
213 | #### 4. 安装php依赖包:(若yum源没有libmcrypt则:yum -y install epel-release //扩展包更新包yum update //更新yum源
214 | ```
215 | yum -y install libmcrypt libmcrypt-devel mcrypt mhash 就ok了)
216 | yum -y install libxml2 libxml2-devel openssl openssl-devel bzip2 bzip2-devel libcurl libcurl-devel
217 | libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel gmp gmp-devel libmcrypt
218 | libmcrypt-devel readline readline-devel libxslt libxslt-devel
219 | ```
220 |
221 |
222 | #### 5. 编译配置:(如果以前编译安装过php可通过php -i | grep configure | sed -e "s/Configure Command => //; s/'//g")获得
223 | ```
224 | ./configure \
225 | --prefix=/usr/local/php \
226 | --with-config-file-path=/etc \
227 | --enable-fpm \
228 | --with-fpm-user=nginx \
229 | --with-fpm-group=nginx \
230 | --enable-inline-optimization \
231 | --disable-debug \
232 | --disable-rpath \
233 | --enable-shared \
234 | --enable-pcntl \
235 | --enable-soap \
236 | --with-libxml-dir \
237 | --with-xmlrpc \
238 | --with-openssl \
239 | --with-mcrypt \
240 | --with-mhash \
241 | --with-pcre-regex \
242 | --with-sqlite3 \
243 | --with-zlib \
244 | --enable-bcmath \
245 | --with-iconv \
246 | --with-bz2 \
247 | --enable-calendar \
248 | --with-curl \
249 | --with-cdb \
250 | --enable-dom \
251 | --enable-exif \
252 | --enable-fileinfo \
253 | --enable-filter \
254 | --with-pcre-dir \
255 | --enable-ftp \
256 | --with-gd \
257 | --with-openssl-dir \
258 | --with-jpeg-dir \
259 | --with-png-dir \
260 | --with-zlib-dir \
261 | --with-freetype-dir \
262 | --enable-gd-native-ttf \
263 | --enable-gd-jis-conv \
264 | --with-gettext \
265 | --with-gmp \
266 | --with-mhash \
267 | --enable-json \
268 | --enable-mbstring \
269 | --enable-mbregex \
270 | --enable-mbregex-backtrack \
271 | --with-libmbfl \
272 | --with-onig \
273 | --enable-pdo \
274 | --with-mysqli=mysqlnd \
275 | --with-pdo-mysql=mysqlnd \
276 | --with-zlib-dir \
277 | --with-pdo-sqlite \
278 | --with-readline \
279 | --enable-session \
280 | --enable-shmop \
281 | --enable-simplexml \
282 | --enable-sockets \
283 | --enable-sysvmsg \
284 | --enable-sysvsem \
285 | --enable-sysvshm \
286 | --enable-wddx \
287 | --with-libxml-dir \
288 | --with-xsl \
289 | --enable-zip \
290 | --enable-mysqlnd-compression-support \
291 | --with-pear \
292 | --enable-opcache
293 | ```
294 | #### 6.正式安装:
295 | ```
296 | make && make install
297 | ```
298 | #### 7.配置环境变量:
299 | ```
300 | vi /etc/profile
301 | ```
302 | 在末尾追加(全局)
303 | ```
304 | PATH=$PATH:/usr/local/php/bin
305 | export PATH
306 | ```
307 | 执行命令使得改动立即生效
308 | ```
309 | source /etc/profile
310 | ```
311 | #### 8.配置php-fpm
312 | ```
313 | cp php.ini-production /etc/php.ini
314 | cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf
315 | cp /usr/local/php/etc/php-fpm.d/www.conf.default /usr/local/php/etc/php-fpm.d/www.conf
316 | cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
317 | cp sapi/fpm/php-fpm.service /usr/lib/systemd/system/ (配置 php-fpm 启动服务脚本,使用service启动,编辑本文件 若有${prefix},则用具体安装地址替换,再重启systemctl daemon-reload)
318 | chmod +x /etc/init.d/php-fpm
319 | ```
320 | #### 9.启动php-fpm
321 | ```
322 | /etc/init.d/php-fpm start
323 | 括号内为设置开机自启
324 | (systemctl enable php-fpm
325 | ln -s '/usr/lib/systemd/system/php-fpm.service' '/etc/systemd/system/multi-user.target.wants/php-fpm.service')
326 |
327 | ```
328 | ## composer安装:
329 | ```
330 | //下载安装脚本composer-setup.php到当前目录
331 | php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');"
332 | //执行安装过程。
333 | php composer-setup.php
334 | //删除安装脚本
335 | php -r "unlink('composer-setup.php');"
336 | mv composer.phar /usr/local/bin/composer
337 | //更换Packagist中国全量镜像,修改 composer 的全局配置文件
338 | composer config -g repo.packagist composer https://packagist.phpcomposer.com
339 | ```
340 | **推荐使用docker来部署环境,更加简单高效 [点击查看](https://github.com/voocel/docker-lnmp)**
341 |
342 | ## 附录(创建用户)
343 | 1.创建一个用户名为:voocel
344 | ```
345 | adduser voocel
346 | ```
347 |
348 | 2.为这个用户初始化密码,Linux会判断密码复杂度,不过可以强行忽略
349 | ```
350 | passwd voocel
351 | ```
352 |
353 | 3.授权
354 | 先添加w权限:
355 | ```
356 | chmod -v u+w /etc/sudoers
357 | vim /etc/sudoers
358 | voocel ALL=(ALL) NOPASSWD: ALL #加入这行
359 | ```
360 | 保存退出,并将写权限收回:
361 | ```
362 | chmod -v u-w /etc/sudoers
363 | ```
--------------------------------------------------------------------------------
/Laravel优化配置.md:
--------------------------------------------------------------------------------
1 | #
Laravel 网站优化
2 | ## 关闭debug
3 | 打开.env文件,把debug设置为false
4 | ```
5 | APP_ENV=local
6 | APP_DEBUG=false
7 | APP_KEY=base64:6ouIfKdFXfaIGZrH9qBCKAWupg4kVwuRsRGpeQnCRh4=
8 | ```
9 |
10 | ## 缓存路由和配置
11 | ```
12 | php artisan route:cache
13 |
14 | php artisan config:cache
15 | ```
16 |
17 | ## composer优化
18 | ```
19 | sudo composer dump-autoload --optimize
20 | ```
21 |
22 | ## Laravel优化命令
23 | ```
24 | php artisan optimize
25 | ```
26 |
27 | ## 使用Laravel缓存
28 | 使用Laravel的Cache方法缓存内容,有文件缓存,数据库缓存,redis缓存。
29 | ```php
30 | $lists = Cache::remember('travel.destination.lists', 20, function () {
31 | return $this->destination->getList();
32 | });
33 | ```
34 |
35 | ## 使用CDN
36 | 如七牛、网易、百度、阿里等CDN,不过收费
37 |
38 | ## 使用PHP7并开启OPcache
39 | ```
40 | apt-get install php70-php-opcache.x86_64
41 | ```
42 | 然后使用service php70-php-fpm restart命令重启php-fpm。
43 |
44 | 注:不同的系统和环境根据自己的情况安装和开启opache,通过phpinfo()查看是否安装
45 |
46 | ## nginx开启gzip压缩
47 | >在服务器Nginx开启gzip压缩是优化网站性能的方法之一,可以有效减少服务器带宽的消耗,缺点是会增大CPU的占用率,但是很多时候CPU往往是空闲最多的。
48 |
49 | **在Nginx开启gzip压缩**
50 |
51 | 打开nginx.conf文件,添加如下:
52 | ```
53 | gzip on;
54 | gzip_min_length 1k;
55 | gzip_buffers 16 64k;
56 | gzip_http_version 1.1;
57 | gzip_comp_level 9;
58 | gzip_types text/plain application/x-javascript application/javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png font/ttf font/otf image/svg+xml;
59 | gzip_vary on;
60 | ```
61 | **gzip参数的一些介绍**
62 |
63 | `GZIP ON|OFF`
64 |
65 | 开启或者关闭gzip模块
66 |
67 | ``GZIP_MIN_LENGTH 1000``
68 |
69 | 设置允许压缩的页面最小字节数,页面字节数从header头中的Content-Length中进行获取。默认值是0,不管页面多大都压缩。建议设置成大于1k的字节数,小于1k可能会越压越大。 即: gzip_min_length 1024
70 |
71 | ```GZIP_PROXIED EXPIRED NO-CACHE NO-STORE PRIVATE AUTH;```
72 |
73 | Nginx作为反向代理的时候启用,开启或者关闭后端服务器返回的结果,匹配的前提是后端服务器必须要返回包含”Via”的 header头。
74 |
75 | `GZIP_TYPES TEXT/PLAIN APPLICATION/XML;`
76 |
77 | 匹配MIME类型进行压缩,(无论是否指定)”text/html”类型总是会被压缩的。
78 |
79 | **通过浏览器判断是否开启gzip压缩**
80 | 查看控制台http响应 Content-Encoding字段是gzip,表示该网页是经过gzip压缩的
--------------------------------------------------------------------------------
/Memcache.md:
--------------------------------------------------------------------------------
1 | wget https://github.com/websupport-sk/pecl-memcache/archive/php7.zip
2 | unzip php7.zip
3 | cd pecl-memcache-php7
4 | ./configure --with-php-config=/usr/local/php/bin/php-config
5 | make && make install
6 |
7 | 在php.ini的最下面添加
8 |
9 | [memcache]
10 | extension_dir = "/usr/local/php/lib/php/extensions/no-debug-non-zts-20160306/"
11 | extension = "memcache.so"
12 |
13 | 配置Memcached的步骤
14 | 首先安装Libevent事件触发管理器。
15 |
16 | # wget https://github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz
17 | tar vxf libevent-2.0.21-stable.tar.gz
18 | cd libevent-2.0.21-stable
19 | ./configure -prefix=/usr/local/libevent
20 | # make && make install
21 | # yum install libevent-devel
22 |
23 | 编译安装Memcache
24 |
25 | wget http://memcached.org/files/memcached-1.4.25.tar.gz
26 | tar vxf memcached-1.4.25.tar.gz
27 | cd memcached-1.4.25
28 | ./configure -with-libevent=/usr/local/libevent # ./configure
29 | # make && make install
30 |
31 | 启动Memcache
32 |
33 | # /usr/local/bin/memcached -d -m 128 -l 127.0.0.1 -p 11211 -u root # (128为内存, 11211为端口,root为用户组)
34 |
35 | 重启php-fpm ,重新加载nginx
36 |
37 | 浏览器访问test.php,文件内容,检测是否整合php
38 |
39 | connect('localhost', 11211);
42 | $mem->set('key', 'cbam_liangshu!');
43 | $val = $mem->get('key');
44 | echo $val;
45 | ?>
--------------------------------------------------------------------------------
/MogonDB笔记.md:
--------------------------------------------------------------------------------
1 |
2 | ## 名词解释
3 | * Schema: 一种以文件形式存储的数据库模型骨架,不具备数据库的操作能力
4 | * Model: 由Schema编译而成的假想(fancy)构造器,具有抽象属性和行为。Model的每一个实例(instance)就是一个document。document可以保存到数据库和从数据库返回。
5 | * Instance: 由Model创建的实例。
6 | ## 概念解析
7 | | SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
8 | | ------------- |:-------------:| :-----|
9 | | rdatabase | database | - |
10 | | table | collection | 数据库表/集合 |
11 | | row | document | 数据记录行/文档 |
12 | | column | index | 数据记录行/文档 |
13 | | table joins | - | 表连接,MongoDB不支持 |
14 | | primary key | primary key 主键 | MongoDB自动将_id字段设置为主键 |
15 | ## 定义Schema
16 | mongoose中任何任何事物都是从Schema开始的。每一个Schema对应MongoDB中的一个集合(collection)。Schema中定义了集合中文档(document)的样式。
17 | ```
18 | var mongoose = require('mongoose');
19 | var Schema = mongoose.Schema;
20 | var blogSchema = new Schema({
21 | title: String,
22 | author: String,
23 | body: String,
24 | comments: [{ body: String, date: Date }],
25 | date: { type: Date, default: Date.now },
26 | hidden: Boolean,
27 | meta: { votes: Number, favs: Number }
28 | });
29 | ```
30 | 如果之后想要在Schema中添加键,可以使用Schema#add方法。
31 | ## 创造一个model
32 | 为了使用schema定义,我们需要转换blogSchema为一个Model。使用
33 | ```
34 | mongoose.model(modelName, schema)
35 | var BlogModel = mongoose.model('Blog', blogSchema);// 开始吧!
36 | ```
37 | ## 实例方法
38 | Model的实例是document。实例有很多内置的方法,我们也可以给实例自定义方法。
39 | ```
40 | var animalSchema = new Schema({
41 | name: String, type: String
42 | });
43 | animalSchema.methods.findSimilarTypes = function (cb) {
44 | return this.model('Animal').find({ type: this.type }, cb);
45 | }
46 | ```
47 | 现在所有的动物实例有findSimilarTypes方法。
48 | ```
49 | var AnimalModel = mongoose.model('Animal', animalSechema);
50 | var dog = new AnimalModel({ type: 'dog' });
51 | dog.findSimilarTypes(function (err, dogs) {
52 | console.log(dogs); // woof
53 | });
54 | ```
55 | 重写一个默认的实例方法可能会导致不期待的结果。
56 | ## Statics方法
57 | 给Model添加一个静态方法也是简单的。
58 | ```
59 | animalSchema.statics.findByName = function (name, cb) {
60 | this.find({ name: new RegExp(name, 'i') }, cb);
61 | }
62 |
63 | var AnimalModel = mongoose.model('Animal', animalSchema);
64 | AnimalModel.findByName('fido', function (err, animals) {
65 | console.log(animals);
66 | });
67 | ```
68 | ### methods和statics的区别
69 | 区别就是一个给Model添加方法(statics),
70 | 一个给实例添加方法(methods)。
71 | ## 索引
72 | MongoDB支持二级索引,定义索引有两种方式
73 |
74 | 路径级别 schema级别
75 | ```
76 | var animalSchema = new Schema({
77 | name: String,
78 | type: String,
79 | tags: { type: [String], index: true } // field level
80 | });
81 |
82 | animalSchema.index({ name: 1, type: -1 }); // schema level, 1是正序,-1是倒序
83 | ```
84 | 如果要建立复合索引的话,在schema级别建立是必要的。
85 |
86 | 索引或者复合索引能让搜索更加高效,默认索引就是主键索引ObjectId,属性名为_id。
87 |
88 | 数据库中主要的就是CRUD操作,建立索引可以提高查询速度。但是过多的索引会降低CUD操作。深度好文如下
89 |
90 | http://www.cnblogs.com/huangxincheng/archive/2012/02/29/2372699.html
91 | ## 虚拟属性
92 | Schema中如果定义了虚拟属性,那么该属性将不写入数据库。写入数据库的还是原来的属性。
93 | ```
94 | // 定义一个schema
95 |
96 | var personSchema = new Schema({
97 | name: { first: String, last: String }
98 | });
99 |
100 | // 编译
101 | var Person = mongoose.model('Person', personSchema);// 创造实例
102 |
103 | var bad = new Person({
104 | name: { first: 'Walter', last: 'White' }
105 | });
106 | ```
107 | 我们将名字分成名字和姓,如果要得到全名,我们需要
108 | ```
109 | console.log(bad.name.first + ' ' + bad.name.last); // Walter White
110 | ```
111 | 这样无疑是麻烦的,我们可以通过虚拟属性的getter来解决这个问题。
112 | ```
113 | personSchema.virtual('name.full').get(function () {
114 | return this.name.first + ' ' + this.name.last;
115 | });
116 | ```
117 | 那么就可以使用bad.name.full直接调用全名了。
118 |
119 | 反之,如果我们知道虚拟属性name.full,通过setter也可以得到组成name.full的每一项。
120 | ```
121 | personSchema.virtual('name.full').set(function (name) {
122 | var split = name.split(' ');
123 | this.name.first = split[0];
124 | this.name.last = split[1];
125 | });
126 |
127 | mad.name.full = 'Breaking Bad';
128 | console.log(mad.name.first); // Breaking
129 | console.log(mad.name.last); // Bad
130 | ```
131 | ## 配置项
132 | schema有一些配置项可以使用,有两种方式:
133 | ```
134 | new Schema({…}, options)
135 |
136 | var schema = new Schema({...});
137 | schema.set(option, value);
138 | ```
139 | 有效的配置有:
140 | 1. autoIndex(默认true)
141 | 2. capped
142 | 3. collection
143 | 4. id _id(默认true)
144 | 5. read safe(默认true)
145 | 6. shardKey strict(默认true)
146 | 7. toJSON
147 | 8. toObject
148 | 9. versionKey
149 | 10. typeKey
150 | 11. validateBeforeSave
151 | 12. skipVersioning
152 | 13. timestamps
153 | 14. useNestedStrict
154 | 15. retainKeyOrder
155 |
156 | ### autoIndex–自动索引
157 | 应用开始的时候,Mongoose对每一个索引发送一个ensureIndex的命令。索引默认(_id)被Mongoose创建。
158 |
159 | 当我们不需要设置索引的时候,就可以通过设置这个选项。
160 | ```
161 | var schema = new Schema({..}, { autoIndex: false });
162 | var Clock = mongoose.model('Clock', schema);
163 | Clock.ensureIndexes(callback);
164 | ```
165 | ### bufferCommands
166 | 似乎是说这个(mongoose buffer)管理在mongoose连接关闭的时候重连,如果取消buffer设置,如下:(存疑)
167 | ```
168 | var schema = new Schema({..}, { bufferCommands: false });
169 | ```
170 | ### capped–上限设置
171 | 如果有数据库的批量操作,该属性能限制一次操作的量,例如:
172 | ```
173 | new Schema({...},{capped:1024}); //一次操作上线1024条数据
174 | ```
175 | 当然该参数也可是对象,包含size、max、autiIndexId属性
176 | ```
177 | new Schema({...},{capped:{size:1024,max:100,autoIndexId:true}});
178 | ```
179 | ### collection–集合名字
180 | 在MongDB中默认使用Model的名字作为集合的名字,如过需要自定义集合的名字,可以通过设置这个选项。
181 | ```
182 | var schema = new Schema({...}, {collection: 'yourName'});
183 | ```
184 | ### id
185 | mongoose分配给每一个schema一个虚拟属性id,它是一个getter。返回的是_id转换为字符串后的值。如果不需要为schema添加这个getter,可以通过id配置修改。
186 | ```
187 | // 默认行为
188 | var pageSchema = new Schema({ name: String });
189 | var pageModel = mongoose.model('Page', pageSchema);
190 | var p = new pageModel({ name: 'mongodb.org' });
191 | console.log(p.id); // '50341373e894ad16347efe01'
192 |
193 | // 禁止id
194 | var pageSchema = new Schema({ name: String }, { id: false } );
195 | var pageModel = mongoose.model('Page', pageSchema);
196 | var p = new pageModel({ name: 'mongodb.org' });
197 | console.log(p.id); // undefined
198 | ```
199 | ### _id
200 | 在一个schema中如果没有定义_id域(field),那么mongoose将会默认分配一个_id域(field)。类型是ObjectId。如果不需要使用这个默认的选择,可以通过设置这个选项。
201 |
202 | 通过在schema中设置这个字段可以阻止生成mongoose获得_id。但是在插入的时候仍然会生成_id。设置这个字段之后,如果再使用Schema.set(’_id’, false)将无效。
203 | ```
204 | // 默认行为
205 | var pageSchema = new Schema({ name: String });
206 | var pageModel = mongoose.model('Page', pageSchema);
207 | var p = new pageModel({ name: 'mongodb.org' });
208 | console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' }
209 |
210 | // 禁用 _id
211 | var pageSchema = new Schema({ name: String }, { _id: false });
212 | // schema构造器设置之后,不要再像下面这样设置
213 | // var schema = new Schema({ name: String });
214 | // schema.set('_id', false);
215 |
216 | var PageModel = mongoose.model('Page', pageSchema);
217 | var p = new pageModel({ name: 'mongodb.org' });
218 | console.log(p); // { name: 'mongodb.org' }
219 | // 当插入的时候,MongoDB将会创建_id
220 | p.save(function (err) {
221 | if (err) return handleError(err);
222 | pageModel.findById(p, function (err, doc) {
223 | if (err) return handleError(err);
224 | console.log(doc);
225 | // { name: 'mongodb.org', _id: '50341373e894ad16347efe12' }
226 | })
227 | })
228 | ```
229 | 为什么不建议使用set
230 | ### read
231 | 允许在schema级别设置query#read,对于所有的查询,提供给我们一种方法应用默认的ReadPreferences。
232 | ### safe
233 | 这个配置会在MongoDB所有的操作中起作用。如果设置成true就是在操作的时候要等待返回的MongoDB返回的结果,比如update,要返回影响的条数,才往后执行,如果safe:false,则表示不用等到结果就向后执行了。
234 | 默认设置为true能保证所有的错误能通过我们写的回调函数。我们也能设置其它的安全等级如:
235 | ```
236 | { j: 1, w: 2, wtimeout: 10000 }
237 | ```
238 | 表示如果10秒内写操作没有完成,将会超时。
239 | 关于j和w,这里有很好的解释。
240 |
241 | http://kyfxbl.iteye.com/blog/1952941
242 | ### shardKey
243 | 需要mongodb做分布式,才会使用该属性。
244 | ### strict
245 | 默认是enabled,如果实例中的域(field)在schema中不存在,那么这个域不会被插入到数据库。
246 | ```
247 | var ThingSchema = new Schema({a:String});
248 | var ThingModel = db.model('Thing',SchemaSchema);
249 | var thing = new Thing({iAmNotInTheThingSchema:true});
250 | thing.save();//iAmNotInTheThingSchema这个属性将无法被存储
251 |
252 | // 通过doc.set()设置也会受到影响。
253 | var thingSchema = new Schema({..})
254 | var Thing = mongoose.model('Thing', thingSchema);
255 | var thing = new Thing;
256 | thing.set('iAmNotInTheSchema', true);
257 | thing.save(); // iAmNotInTheSchema is not saved to the db
258 | ```
259 | 如果取消严格选项,iAmNotInTheThingSchema将会被存入数据库
260 | ```
261 | var thingSchema = new Schema({..}, { strict: false });
262 | var thing = new Thing({ iAmNotInTheSchema: true });
263 | thing.save(); // iAmNotInTheSchema is now saved to the db!!
264 | ```
265 | 该选项也可以在Model级别使用,通过设置第二个参数,例如:
266 | ```
267 | var ThingModel = db.model('Thing');
268 | var thing1 = new ThingModel(doc,true); //启用严格
269 | var thing2 = new ThingModel(doc,false); //禁用严格
270 | ```
271 | strict也可以设置为throw,表示出现问题将会抛出错误而不是抛弃不合适的数据。
272 |
273 | 注意:
274 | * 不要设置为false除非你有充分的理由。
275 |
276 | 在mongoose v2里默认是false。
277 |
278 | 在实例上设置的任何键值对如果再schema中不存在对应的,将会被忽视。
279 | ```
280 | var thingSchema = new Schema({..})
281 | var Thing = mongoose.model('Thing', thingSchema);
282 | var thing = new Thing;
283 | thing.iAmNotInTheSchema = true;
284 | thing.save(); // iAmNotInTheSchema 不会保存到数据库。
285 | ```
286 | ### toJSON
287 | 和toObject类似,选择这个选项为true后,但是只有当实例调用了toJSON方法后,才会起作用。
288 | ```
289 | var schema = new Schema({ name: String });
290 | schema.path('name').get(function (v) {
291 | return v + ' is my name';
292 | });
293 |
294 | schema.set('toJSON', { getters: true, virtuals: false });
295 | var M = mongoose.model('Person', schema);
296 | var m = new M({ name: 'Max Headroom' });
297 | console.log(m.toObject()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom' }
298 | console.log(m.toJSON()); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
299 | console.log(JSON.stringify(m)); // { "_id": "504e0cd7dd992d9be2f20b6f", "name": "Max Headroom is my name" }
300 | ```
301 | 可以看出,配置属性name对toObject没影响,对toJSON有影响。
302 | ### toObject
303 | 选择这个选项为true后,默认对这个schema所有的实例都有作用。不需要实例手动调用。
304 | ```
305 | var schema = new Schema({ name: String });
306 | schema.path('name').get(function (v) {
307 | return v + ' is my name';
308 | });
309 |
310 | schema.set('toObject', { getters: true });
311 | var M = mongoose.model('Person', schema);
312 | var m = new M({ name: 'Max Headroom' });
313 | console.log(m); // { _id: 504e0cd7dd992d9be2f20b6f, name: 'Max Headroom is my name' }
314 | ```
315 | 较上面不同的是,没有virtuals: false这个设置。
316 | ### typeKey
317 | 在mongoose里,如果schema里有个对象,并且这个对象有个type键,mongoose将会将这个作为一种类型声明。
318 | ```
319 | // Mongoose 认为loc字段的类型是一个字符串,而不是有type这个字段
320 | var schema = new Schema({ loc: { type: String, coordinates: [Number] } });
321 | ```
322 | 然而,对于一些应用来说,type字段是必要的。那么可以通过typeKey来设置。
323 | ```
324 | var schema = new Schema({
325 | // Mongoose 这时候认为loc字段有两个键,一个是type,一个是coordinates
326 | loc: { type: String, coordinates: [Number] },
327 | // Mongoose 这时候认为name字段的类型是字符串。
328 | name: { $type: String }
329 | },{ typeKey: '$type' }); // '$type'键意味着这是一个类型宣告,而不是默认的type
330 | ```
331 | ### validateBeforeSave
332 | 默认得,文档被保存到数据库的时候会自动验证,这是为了防止无效的文档。如果想要手动处理验证,并且能保存不通过验证的文档,可以设置这个选项为false。
333 | ```
334 | var schema = new Schema({ name: String });
335 | schema.set('validateBeforeSave', false);
336 | schema.path('name').validate(function (value) {
337 | return v != null;
338 | });
339 | var M = mongoose.model('Person', schema);
340 | var m = new M({ name: null });
341 | m.validate(function(err) {
342 | console.log(err); // 将会告诉你null不被允许
343 | });
344 | m.save(); // 尽管数据无效,但是仍然可以保存。
345 | ```
346 | ### versionKey
347 | 版本锁设置在每一个文档(document)上,由mogoose生成。默认的值是__v,但是可以自定义。
348 | ```
349 | var schema = new Schema({ name: 'string' });
350 | var Thing = mongoose.model('Thing', schema);
351 | var thing = new Thing({ name: 'mongoose v3' });
352 | thing.save(); // { __v: 0, name: 'mongoose v3' }
353 |
354 | // 自定义版本锁
355 | new Schema({..}, { versionKey: '_somethingElse' });
356 | var Thing = mongoose.model('Thing', schema);
357 | var thing = new Thing({ name: 'mongoose v3' });
358 | thing.save(); // { _somethingElse: 0, name: 'mongoose v3' }
359 | ```
360 | 不要将这个选项设置为false除非你知道你在做什么。
361 | ### skipVersioning
362 | http://aaronheckmann.tumblr.com/post/48943525537/mongoose-v3-part-1-
363 |
364 | 按照这里的说法,大致是说,加入在一个博客系统中,一个人所有的评论是一个数组,那么所有的评论是有索引的,比如某一条评论的body,comments.3.body,这里3是索引。假如一个评论者(A)想要修改自己的评论,但是此时另一个评论者(B)删除(或其他操作)了自己的评论,那么对A的索引可能会造成变化,此时对A的操作会发生错误。
365 |
366 | 为了改变这个问题,mongoose v3添加了version key配置。无论什么时候修改一个数组潜在地改变数组元素位置,这个version key(__V)的值会加1。在where条件中也需要添加__v条件,如果能通过(数组索引没改变),就可以修改,例如:
367 | ```
368 | posts.update(
369 | { _id: postId, __v: verionNumber } ,
370 | { $set: { 'comments.3.body': updatedText }}
371 | );
372 | ```
373 | 如果在更新之前删除了评论,那么就会发生错误。
374 | ```
375 | post.save(function (err) {
376 | console.log(err); // Error: No matching document found.
377 | });
378 | ```
379 | ### timestamps
380 | 如果在schema设置这个选项,createdAt和updatedAt域将会被自动添加的文档中。它们默认的类型是Date,默认的名字是createdAt和updatedAt,不过我们可以自己修改。
381 | ```
382 | var thingSchema = new Schema({..}, { timestamps: { createdAt: 'created_at' } });
383 | var Thing = mongoose.model('Thing', thingSchema);
384 | var thing = new Thing();
385 | thing.save(); // created_at & updatedAt将会被包含在文档。
386 | ```
387 | ### useNestedStrict
388 | 在mongoos 4, update()和findOneAndUpdate()方法只检查顶级schema的strict的选项设置。
389 | ```
390 | var childSchema = new Schema({}, { strict: false });// 这里parentSchema是topSchema,而childSchema是subSchema。
391 | var parentSchema = new Schema({ child: childSchema }, { strict: 'throw' });
392 | var Parent = mongoose.model('Parent', parentSchema);
393 | Parent.update({}, { 'child.name': 'Luke Skywalker' }, function(error) {
394 | // 发生错误因为parentSchema设置了strict: 'throw'}
395 | // 即使childSchema设置了{strict: false}
396 | });
397 | var update = { 'child.name': 'Luke Skywalker' };
398 | var opts = { strict: false };
399 | Parent.update({}, update, opts, function(error) {
400 | // 这个可以通过因为重写了parentSchema的strict选项
401 | });
402 | ```
403 | 如果设置了useNestedStrict为true,mogoose在更新时使用childSchema的strict选项。
404 | ```
405 | var childSchema = new Schema({}, { strict: false });
406 | var parentSchema = new Schema({ child: childSchema }, { strict: 'throw', useNestedStrict: true });
407 | var Parent = mongoose.model('Parent', parentSchema);
408 | Parent.update({}, { 'child.name': 'Luke Skywalker' }, function(error) {
409 | // 可以更新
410 | });
411 | ```
412 | ### retainKeyOrder
413 | 默认得,mongoose会转换实体中键的顺序。比如
414 | ```
415 | new Model({ first: 1, second: 2 })
416 | ```
417 | 将会在MongoDB中存储为{ second: 2, first: 1 };这带来了极大的不方便。
418 |
419 | Mongoose v4.6.4 有一个retainKeyOrder选项确保mongoose不会改变键的顺序。
420 | >[原文出处](http://cnodejs.org/topic/58b911997872ea0864fee313)
421 |
422 | >参考
423 |
424 | >http://cnodejs.org/topic/504b4924e2b84515770103dd?utm_source=ourjs.com
425 |
426 | >http://www.nodeclass.com/api/mongoose.html#schema_Schema-add
427 |
428 | >http://mongoosejs.com/docs/guide.html
--------------------------------------------------------------------------------
/Mongodb.md:
--------------------------------------------------------------------------------
1 | ### 1、下载
2 | wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-amazon-3.4.5.tgz
3 | ### 2、解压
4 | tar -zxvf mongodb-linux-x86_64-amazon-3.4.5.tgz
5 | ### 3、将解压包拷贝到指定目录
6 | mv mongodb-linux-x86_64-amazon-3.4.5 /usr/local/mongodb
7 | ### 4、配置环境变量
8 | export PATH=/usr/local/mongodb/bin:$PATH
9 | 或者:PATH=$PATH:/usr/local/mongodb/bin export PATH
10 | source /etc/profile
11 |
12 |
13 | #### 5、创建目录
14 | *MongoDB的数据存储在data目录的db目录下,但是这个目录在安装过程不会自动创建,所以你需要手动创建data目录,并在data目录中创建db目录。
15 | 以下实例中我们将data目录创建于目录(/usr/local/mongodb)。
16 | 注意:/data/db 是 MongoDB 默认的启动的数据库路径(--dbpath)。*
17 |
18 | mkdir -p /usr/local/mongodb/data/db
19 | mkdir -p /usr/local/mongodb/log
20 | touch /usr/local/mongodb/log/mongo.log
21 |
22 | ### 6、启动mongodb服务
23 | ```
24 | 编写配置文件
25 | vim /usr/local/mongodb/bin/mongo.conf
26 | 写入以下内容:
27 | ##数据文件
28 | dbpath=/usr/local/mongodb/data/db
29 | ##日志文件
30 | logpath=/usr/local/mongodb/log/mongo.log
31 | #错误日志采用追加模式,配置这个选项后mongodb的日志会追加到现有的日志文件,而不是从新创建一个新文件
32 | logappend=true
33 | #启用日志文件,默认启用
34 | journal=true
35 | #这个选项可以过滤掉一些无用的日志信息,若需要调试使用请设置为false
36 | quiet=false
37 | #端口号 默认为27017,注意这里端口若是修改后,要用mongo --port=xxxx连接,否则报错。
38 | port=27017
39 | #声明这是一个集群的分片,默认端口27017
40 | #shardsvr=true
41 | #设置每个数据库将被保存在一个单独的目录
42 | #directoryperdb=true
43 | #PID File的完整路径,如果没有设置则没有PID文件
44 | #pidfilepath=/usr/local/mongodb/mongo.pid
45 | #关闭http接口,默认关闭27017端口访问
46 | #nohttpinterface=true
47 | #开启认证
48 | #auth=true
49 | #设置开启简单的rest API,然后打开27017+1000网页端口 MongoDB 提供了简单的 HTTP 用户界面
50 | rest=true
51 |
52 | 启动:mongod --config /usr/local/mongodb/bin/mongo.conf --fork --port 27017 (推荐)
53 |
54 | 也可简单启动:
55 | mongod --dbpath=/usr/local/mongodb/data/db --logpath=/usr/local/mongodb/log/db.log --fork --port 27017 以守护进程的方式启动
56 | ```
57 |
58 | ### 7. 把MongoDB设置为系统服务并且设置开机启动
59 | ```
60 | vim /etc/rc.d/init.d/mongod
61 | 写入一下内容:
62 | ulimit -SHn 655350
63 | #!/bin/sh
64 | # chkconfig: - 64 36
65 | # description:mongod
66 | case $1 in
67 | start)
68 | /usr/local/mongodb/bin/mongod --config /usr/local/mongodb/bin/mongo.conf --fork
69 | ;;
70 |
71 | stop)
72 | /usr/local/mongodb/bin/mongo 127.0.0.1:27017/admin --eval "db.shutdownServer()"
73 | ;;
74 |
75 | status)
76 | /usr/local/mongodb/bin/mongo 127.0.0.1:27017/admin --eval "db.stats()"
77 | ;;
78 | esac
79 |
80 |
81 | chmod +x /etc/rc.d/init.d/mongod
82 | (成功后可通过service mongod start 启动)
83 | ```
84 | ### 8、启动客户端
85 | mongo #进入交互式mongoDB后台后
86 |
87 | MongoDB 提供了简单的 HTTP 用户界面。需要在启动的时候指定参数 --rest或在配置文件mongo.conf中设置rest=true 。
88 | MongoDB 的 Web 界面访问端口比服务的端口多1000。即访问localhost:28017
89 |
--------------------------------------------------------------------------------
/MySQL定时备份.md:
--------------------------------------------------------------------------------
1 | ## 数据库定时备份于日志切割
--------------------------------------------------------------------------------
/PHP实现一致性哈希算法.php:
--------------------------------------------------------------------------------
1 | _node[$node])) return;
27 | for($i = 0; $i < $this->_virtualNode; $i++){
28 | $pos = $this->cHash($node.'_'.$i);
29 | $this->_position[$pos] = $node;
30 | $this->_node[$node][] = $pos;
31 | }
32 | $this->sortPos();
33 | }
34 |
35 | /**
36 | * 查找节点
37 | */
38 | public function lookup($key){
39 | $point = $this->cHash($key);
40 |
41 | //先取环上最小的一个节点
42 | $node = current($this->position);
43 |
44 | //循环获取相近节点
45 | foreach ($this->_position as $key => $value) {
46 | if($point <= $key){
47 | $node = $value;
48 | break;
49 | }
50 | reset($this->_position);
51 | }
52 | return $node;
53 | }
54 |
55 | /**
56 | * 删除节点
57 | */
58 | public function delNode($node){
59 | if(!isset($this->_node[$node])) return;
60 |
61 | //删除虚拟节点
62 | foreach ($this->_node as $key => $value) {
63 | unset($this->_position[$value]);
64 | }
65 |
66 | //删除节点
67 | unset($this->_node[$node]);
68 | }
69 |
70 | /**
71 | * 排序
72 | */
73 | public function sortPos(){
74 | ksort($this->_position,SORT_REGULAR);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/PHP常用代码样例/README.md:
--------------------------------------------------------------------------------
1 | # 33个超级有用必须要收藏的PHP代码样例
2 | 作为一个正常的程序员,会好几种语言是十分正常的,
3 | 相信大部分程序员也都会编写几句PHP程序,如果是WEB程序员,PHP一定是必备的,
4 | 即使你没用开发过大型软件项目,也一定多少了解它的语法。
5 | 在PHP的流行普及中,网上总结出了很多实用的PHP代码片段,这些代码片段在当你遇到类似的问题时,粘贴过去就可以使用,非常的高效,非常的省时省力。将这些程序员前辈总结出的优秀代码放到自己的知识库中,是一个善于学习的程序员的好习惯。
6 | 出处简书
7 | ```php
8 | " . $label . htmlspecialchars($output, ENT_QUOTES) . "";
21 | } else {
22 | $output = $label . print_r($var, true);
23 | }
24 | } else {
25 | ob_start();
26 | var_dump($var);
27 | $output = ob_get_clean();
28 | if (!extension_loaded('xdebug')) {
29 | $output = preg_replace("/\]\=\>\n(\s+)/m", "] => ", $output);
30 | $output = '' . $label . htmlspecialchars($output, ENT_QUOTES) . '
';
31 | }
32 | }
33 | if ($echo) {
34 | echo $output;
35 | return null;
36 | } else
37 | return $output;
38 | }
39 |
40 | /**
41 | * 获取客户端IP地址
42 | */
43 | static public function getClientIP() {
44 | static $ip = NULL;
45 | if ($ip !== NULL)
46 | return $ip;
47 | if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
48 | $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
49 | $pos = array_search('unknown', $arr);
50 | if (false !== $pos)
51 | unset($arr[$pos]);
52 | $ip = trim($arr[0]);
53 | } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
54 | $ip = $_SERVER['HTTP_CLIENT_IP'];
55 | } elseif (isset($_SERVER['REMOTE_ADDR'])) {
56 | $ip = $_SERVER['REMOTE_ADDR'];
57 | }
58 | // IP地址合法验证
59 | $ip = ( false !== ip2long($ip) ) ? $ip : '0.0.0.0';
60 | return $ip;
61 | }
62 |
63 | /**
64 | * 循环创建目录
65 | */
66 | static public function mkdir($dir, $mode = 0777) {
67 | if (is_dir($dir) || @mkdir($dir, $mode))
68 | return true;
69 | if (!mk_dir(dirname($dir), $mode))
70 | return false;
71 | return @mkdir($dir, $mode);
72 | }
73 |
74 | /**
75 | * 格式化单位
76 | */
77 | static public function byteFormat($size, $dec = 2) {
78 | $a = array("B", "KB", "MB", "GB", "TB", "PB");
79 | $pos = 0;
80 | while ($size >= 1024) {
81 | $size /= 1024;
82 | $pos++;
83 | }
84 | return round($size, $dec) . " " . $a[$pos];
85 | }
86 |
87 | /**
88 | * 下拉框,单选按钮 自动选择
89 | *
90 | * @param $string 输入字符
91 | * @param $param 条件
92 | * @param $type 类型
93 | * selected checked
94 | * @return string
95 | */
96 | static public function selected($string, $param = 1, $type = 'select') {
97 |
98 | if (is_array($param)) {
99 | $true = in_array($string, $param);
100 | } elseif ($string == $param) {
101 | $true = true;
102 | }
103 | if ($true)
104 | $return = $type == 'select' ? 'selected="selected"' : 'checked="checked"';
105 |
106 | echo $return;
107 | }
108 |
109 | /**
110 | * 获得来源类型 post get
111 | *
112 | * @return unknown
113 | */
114 | static public function method() {
115 | return strtoupper(isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET' );
116 | }
117 |
118 | /**
119 | * 提示信息
120 | */
121 | static public function message($action = 'success', $content = '', $redirect = 'javascript:history.back(-1);', $timeout = 4) {
122 |
123 | switch ($action) {
124 | case 'success':
125 | $titler = '操作完成';
126 | $class = 'message_success';
127 | $images = 'message_success.png';
128 | break;
129 | case 'error':
130 | $titler = '操作未完成';
131 | $class = 'message_error';
132 | $images = 'message_error.png';
133 | break;
134 | case 'errorBack':
135 | $titler = '操作未完成';
136 | $class = 'message_error';
137 | $images = 'message_error.png';
138 | break;
139 | case 'redirect':
140 | header("Location:$redirect");
141 | break;
142 | case 'script':
143 | if (empty($redirect)) {
144 | exit('');
145 | } else {
146 | exit('');
147 | }
148 | break;
149 | }
150 |
151 | // 信息头部
152 | $header = '
153 |
154 |
155 |
156 | 操作提示
157 |
173 |
174 |
175 | ';
176 | // 信息底部
177 | $footer = '';
178 |
179 | $body = '
192 |
193 |
194 |
->baseUrl . '/static/images/' . $images . ')
195 |
196 |
197 |
198 |
' . $content . '
199 |
系统自动跳转在 ' . $timeout . ' 秒后,如果不想等待,点击这里跳转
200 |
201 |
202 |
';
205 |
206 | exit($header . $body . $footer);
207 | }
208 |
209 | /**
210 | * 查询字符生成
211 | */
212 | static public function buildCondition(array $getArray, array $keys = array()) {
213 | if ($getArray) {
214 | foreach ($getArray as $key => $value) {
215 | if (in_array($key, $keys) && $value) {
216 | $arr[$key] = CHtml::encode(strip_tags($value));
217 | }
218 | }
219 | return $arr;
220 | }
221 | }
222 |
223 | /**
224 | * base64_encode
225 | */
226 | static function b64encode($string) {
227 | $data = base64_encode($string);
228 | $data = str_replace(array('+', '/', '='), array('-', '_', ''), $data);
229 | return $data;
230 | }
231 |
232 | /**
233 | * base64_decode
234 | */
235 | static function b64decode($string) {
236 | $data = str_replace(array('-', '_'), array('+', '/'), $string);
237 | $mod4 = strlen($data) % 4;
238 | if ($mod4) {
239 | $data .= substr('====', $mod4);
240 | }
241 | return base64_decode($data);
242 | }
243 |
244 | /**
245 | * 验证邮箱
246 | */
247 | public static function email($str) {
248 | if (empty($str))
249 | return true;
250 | $chars = "/^([a-z0-9+_]|\\-|\\.)+@(([a-z0-9_]|\\-)+\\.)+[a-z]{2,6}\$/i";
251 | if (strpos($str, '@') !== false && strpos($str, '.') !== false) {
252 | if (preg_match($chars, $str)) {
253 | return true;
254 | } else {
255 | return false;
256 | }
257 | } else {
258 | return false;
259 | }
260 | }
261 |
262 | /**
263 | * 验证手机号码
264 | */
265 | public static function mobile($str) {
266 | if (empty($str)) {
267 | return true;
268 | }
269 |
270 | return preg_match('#^13[\d]{9}$|14^[0-9]\d{8}|^15[0-9]\d{8}$|^18[0-9]\d{8}$#', $str);
271 | }
272 |
273 | /**
274 | * 验证固定电话
275 | */
276 | public static function tel($str) {
277 | if (empty($str)) {
278 | return true;
279 | }
280 | return preg_match('/^((\(\d{2,3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}(\-\d{1,4})?$/', trim($str));
281 | }
282 |
283 | /**
284 | * 验证qq号码
285 | */
286 | public static function qq($str) {
287 | if (empty($str)) {
288 | return true;
289 | }
290 |
291 | return preg_match('/^[1-9]\d{4,12}$/', trim($str));
292 | }
293 |
294 | /**
295 | * 验证邮政编码
296 | */
297 | public static function zipCode($str) {
298 | if (empty($str)) {
299 | return true;
300 | }
301 |
302 | return preg_match('/^[1-9]\d{5}$/', trim($str));
303 | }
304 |
305 | /**
306 | * 验证ip
307 | */
308 | public static function ip($str) {
309 | if (empty($str))
310 | return true;
311 |
312 | if (!preg_match('#^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$#', $str)) {
313 | return false;
314 | }
315 |
316 | $ip_array = explode('.', $str);
317 |
318 | //真实的ip地址每个数字不能大于255(0-255)
319 | return ( $ip_array[0] <= 255 && $ip_array[1] <= 255 && $ip_array[2] <= 255 && $ip_array[3] <= 255 ) ? true : false;
320 | }
321 |
322 | /**
323 | * 验证身份证(中国)
324 | */
325 | public static function idCard($str) {
326 | $str = trim($str);
327 | if (empty($str))
328 | return true;
329 |
330 | if (preg_match("/^([0-9]{15}|[0-9]{17}[0-9a-z])$/i", $str))
331 | return true;
332 | else
333 | return false;
334 | }
335 |
336 | /**
337 | * 验证网址
338 | */
339 | public static function url($str) {
340 | if (empty($str))
341 | return true;
342 |
343 | return preg_match('#(http|https|ftp|ftps)://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?#i', $str) ? true : false;
344 | }
345 |
346 | /**
347 | * 根据ip获取地理位置
348 | * @param $ip
349 | * return :ip,beginip,endip,country,area
350 | */
351 | public static function getlocation($ip = '') {
352 | $ip = new XIp();
353 | $ipArr = $ip->getlocation($ip);
354 | return $ipArr;
355 | }
356 |
357 | /**
358 | * 中文转换为拼音
359 | */
360 | public static function pinyin($str) {
361 | $ip = new XPinyin();
362 | return $ip->output($str);
363 | }
364 |
365 | /**
366 | * 拆分sql
367 | *
368 | * @param $sql
369 | */
370 | public static function splitsql($sql) {
371 | $sql = preg_replace("/TYPE=(InnoDB|MyISAM|MEMORY)( DEFAULT CHARSET=[^; ]+)?/", "ENGINE=\\1 DEFAULT CHARSET=" . Yii::app()->db->charset, $sql);
372 | $sql = str_replace("\r", "\n", $sql);
373 | $ret = array();
374 | $num = 0;
375 | $queriesarray = explode(";\n", trim($sql));
376 | unset($sql);
377 | foreach ($queriesarray as $query) {
378 | $ret[$num] = '';
379 | $queries = explode("\n", trim($query));
380 | $queries = array_filter($queries);
381 | foreach ($queries as $query) {
382 | $str1 = substr($query, 0, 1);
383 | if ($str1 != '#' && $str1 != '-')
384 | $ret[$num] .= $query;
385 | }
386 | $num++;
387 | }
388 | return ($ret);
389 | }
390 |
391 | /**
392 | * 字符截取
393 | *
394 | * @param $string
395 | * @param $length
396 | * @param $dot
397 | */
398 | public static function cutstr($string, $length, $dot = '...', $charset = 'utf-8') {
399 | if (strlen($string) <= $length)
400 | return $string;
401 |
402 | $pre = chr(1);
403 | $end = chr(1);
404 | $string = str_replace(array('&', '"', '<', '>'), array($pre . '&' . $end, $pre . '"' . $end, $pre . '<' . $end, $pre . '>' . $end), $string);
405 |
406 | $strcut = '';
407 | if (strtolower($charset) == 'utf-8') {
408 |
409 | $n = $tn = $noc = 0;
410 | while ($n < strlen($string)) {
411 |
412 | $t = ord($string[$n]);
413 | if ($t == 9 || $t == 10 || ( 32 <= $t && $t <= 126 )) {
414 | $tn = 1;
415 | $n++;
416 | $noc++;
417 | } elseif (194 <= $t && $t <= 223) {
418 | $tn = 2;
419 | $n += 2;
420 | $noc += 2;
421 | } elseif (224 <= $t && $t <= 239) {
422 | $tn = 3;
423 | $n += 3;
424 | $noc += 2;
425 | } elseif (240 <= $t && $t <= 247) {
426 | $tn = 4;
427 | $n += 4;
428 | $noc += 2;
429 | } elseif (248 <= $t && $t <= 251) {
430 | $tn = 5;
431 | $n += 5;
432 | $noc += 2;
433 | } elseif ($t == 252 || $t == 253) {
434 | $tn = 6;
435 | $n += 6;
436 | $noc += 2;
437 | } else {
438 | $n++;
439 | }
440 |
441 | if ($noc >= $length) {
442 | break;
443 | }
444 | }
445 | if ($noc > $length) {
446 | $n -= $tn;
447 | }
448 |
449 | $strcut = substr($string, 0, $n);
450 | } else {
451 | for ($i = 0; $i < $length; $i++) {
452 | $strcut .= ord($string[$i]) > 127 ? $string[$i] . $string[++$i] : $string[$i];
453 | }
454 | }
455 |
456 | $strcut = str_replace(array($pre . '&' . $end, $pre . '"' . $end, $pre . '<' . $end, $pre . '>' . $end), array('&', '"', '<', '>'), $strcut);
457 |
458 | $pos = strrpos($strcut, chr(1));
459 | if ($pos !== false) {
460 | $strcut = substr($strcut, 0, $pos);
461 | }
462 | return $strcut . $dot;
463 | }
464 |
465 | /**
466 | * 描述格式化
467 | * @param $subject
468 | */
469 | public static function clearCutstr($subject, $length = 0, $dot = '...', $charset = 'utf-8') {
470 | if ($length) {
471 | return XUtils::cutstr(strip_tags(str_replace(array("\r\n"), '', $subject)), $length, $dot, $charset);
472 | } else {
473 | return strip_tags(str_replace(array("\r\n"), '', $subject));
474 | }
475 | }
476 |
477 | /**
478 | * 检测是否为英文或英文数字的组合
479 | *
480 | * @return unknown
481 | */
482 | public static function isEnglist($param) {
483 | if (!eregi("^[A-Z0-9]{1,26}$", $param)) {
484 | return false;
485 | } else {
486 | return true;
487 | }
488 | }
489 |
490 | /**
491 | * 将自动判断网址是否加http://
492 | *
493 | * @param $http
494 | * @return string
495 | */
496 | public static function convertHttp($url) {
497 | if ($url == 'http://' || $url == '')
498 | return '';
499 |
500 | if (substr($url, 0, 7) != 'http://' && substr($url, 0, 8) != 'https://')
501 | $str = 'http://' . $url;
502 | else
503 | $str = $url;
504 | return $str;
505 | }
506 |
507 | /*
508 | 标题样式格式化
509 | */
510 |
511 | public static function titleStyle($style) {
512 | $text = '';
513 | if ($style['bold'] == 'Y') {
514 | $text .='font-weight:bold;';
515 | $serialize['bold'] = 'Y';
516 | }
517 |
518 | if ($style['underline'] == 'Y') {
519 | $text .='text-decoration:underline;';
520 | $serialize['underline'] = 'Y';
521 | }
522 |
523 | if (!empty($style['color'])) {
524 | $text .='color:#' . $style['color'] . ';';
525 | $serialize['color'] = $style['color'];
526 | }
527 |
528 | return array('text' => $text, 'serialize' => empty($serialize) ? '' : serialize($serialize));
529 | }
530 |
531 | // 自动转换字符集 支持数组转换
532 | static public function autoCharset($string, $from = 'gbk', $to = 'utf-8') {
533 | $from = strtoupper($from) == 'UTF8' ? 'utf-8' : $from;
534 | $to = strtoupper($to) == 'UTF8' ? 'utf-8' : $to;
535 | if (strtoupper($from) === strtoupper($to) || empty($string) || (is_scalar($string) && !is_string($string))) {
536 | //如果编码相同或者非字符串标量则不转换
537 | return $string;
538 | }
539 | if (is_string($string)) {
540 | if (function_exists('mb_convert_encoding')) {
541 | return mb_convert_encoding($string, $to, $from);
542 | } elseif (function_exists('iconv')) {
543 | return iconv($from, $to, $string);
544 | } else {
545 | return $string;
546 | }
547 | } elseif (is_array($string)) {
548 | foreach ($string as $key => $val) {
549 | $_key = self::autoCharset($key, $from, $to);
550 | $string[$_key] = self::autoCharset($val, $from, $to);
551 | if ($key != $_key)
552 | unset($string[$key]);
553 | }
554 | return $string;
555 | } else {
556 | return $string;
557 | }
558 | }
559 |
560 | /*
561 | 标题样式恢复
562 | */
563 |
564 | public static function titleStyleRestore($serialize, $scope = 'bold') {
565 | $unserialize = unserialize($serialize);
566 | if ($unserialize['bold'] == 'Y' && $scope == 'bold')
567 | return 'Y';
568 | if ($unserialize['underline'] == 'Y' && $scope == 'underline')
569 | return 'Y';
570 | if ($unserialize['color'] && $scope == 'color')
571 | return $unserialize['color'];
572 | }
573 |
574 | /**
575 | * 列出文件夹列表
576 | *
577 | * @param $dirname
578 | * @return unknown
579 | */
580 | public static function getDir($dirname) {
581 | $files = array();
582 | if (is_dir($dirname)) {
583 | $fileHander = opendir($dirname);
584 | while (( $file = readdir($fileHander) ) !== false) {
585 | $filepath = $dirname . '/' . $file;
586 | if (strcmp($file, '.') == 0 || strcmp($file, '..') == 0 || is_file($filepath)) {
587 | continue;
588 | }
589 | $files[] = self::autoCharset($file, 'GBK', 'UTF8');
590 | }
591 | closedir($fileHander);
592 | } else {
593 | $files = false;
594 | }
595 | return $files;
596 | }
597 |
598 | /**
599 | * 列出文件列表
600 | *
601 | * @param $dirname
602 | * @return unknown
603 | */
604 | public static function getFile($dirname) {
605 | $files = array();
606 | if (is_dir($dirname)) {
607 | $fileHander = opendir($dirname);
608 | while (( $file = readdir($fileHander) ) !== false) {
609 | $filepath = $dirname . '/' . $file;
610 |
611 | if (strcmp($file, '.') == 0 || strcmp($file, '..') == 0 || is_dir($filepath)) {
612 | continue;
613 | }
614 | $files[] = self::autoCharset($file, 'GBK', 'UTF8');
615 | ;
616 | }
617 | closedir($fileHander);
618 | } else {
619 | $files = false;
620 | }
621 | return $files;
622 | }
623 |
624 | /**
625 | * [格式化图片列表数据]
626 | *
627 | * @return [type] [description]
628 | */
629 | public static function imageListSerialize($data) {
630 |
631 | foreach ((array) $data['file'] as $key => $row) {
632 | if ($row) {
633 | $var[$key]['fileId'] = $data['fileId'][$key];
634 | $var[$key]['file'] = $row;
635 | }
636 | }
637 | return array('data' => $var, 'dataSerialize' => empty($var) ? '' : serialize($var));
638 | }
639 |
640 | /**
641 | * 反引用一个引用字符串
642 | * @param $string
643 | * @return string
644 | */
645 | static function stripslashes($string) {
646 | if (is_array($string)) {
647 | foreach ($string as $key => $val) {
648 | $string[$key] = self::stripslashes($val);
649 | }
650 | } else {
651 | $string = stripslashes($string);
652 | }
653 | return $string;
654 | }
655 |
656 | /**
657 | * 引用字符串
658 | * @param $string
659 | * @param $force
660 | * @return string
661 | */
662 | static function addslashes($string, $force = 1) {
663 | if (is_array($string)) {
664 | foreach ($string as $key => $val) {
665 | $string[$key] = self::addslashes($val, $force);
666 | }
667 | } else {
668 | $string = addslashes($string);
669 | }
670 | return $string;
671 | }
672 |
673 | /**
674 | * 格式化内容
675 | */
676 | static function formatHtml($content, $options = '') {
677 | $purifier = new CHtmlPurifier();
678 | if ($options != false)
679 | $purifier->options = $options;
680 | return $purifier->purify($content);
681 | }
682 |
683 | }
684 |
685 | ?>
686 | ```
687 |
--------------------------------------------------------------------------------
/PHP常用工具类封装/regexTool.class.php:
--------------------------------------------------------------------------------
1 | '/.+/',
10 | 'email' => '/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/',
11 | 'url' => '/^http(s?):\/\/(?:[A-za-z0-9-]+\.)+[A-za-z]{2,4}(?:[\/\?#][\/=\?%\-&~`@[\]\':+!\.#\w]*)?$/',
12 | 'currency' => '/^\d+(\.\d+)?$/',
13 | 'number' => '/^\d+$/',
14 | 'zip' => '/^\d{6}$/',
15 | 'integer' => '/^[-\+]?\d+$/',
16 | 'double' => '/^[-\+]?\d+(\.\d+)?$/',
17 | 'english' => '/^[A-Za-z]+$/',
18 | 'qq' => '/^\d{5,11}$/',
19 | 'mobile' => '/^1(3|4|5|7|8)\d{9}$/',
20 | );
21 | private $returnMatchResult = false;
22 | private $fixMode = null;
23 | private $matches = array();
24 | private $isMatch = false;
25 |
26 | public function __construct($returnMatchResult = false, $fixMode = null) {
27 | $this->returnMatchResult = $returnMatchResult;
28 | $this->fixMode = $fixMode;
29 | }
30 |
31 | private function regex($pattern, $subject) {
32 | if(array_key_exists(strtolower($pattern), $this->validate))
33 | $pattern = $this->validate[$pattern].$this->fixMode;
34 | $this->returnMatchResult ?
35 | preg_match_all($pattern, $subject, $this->matches) :
36 | $this->isMatch = preg_match($pattern, $subject) === 1;
37 | return $this->getRegexResult();
38 | }
39 |
40 | private function getRegexResult() {
41 | if($this->returnMatchResult) {
42 | return $this->matches;
43 | } else {
44 | return $this->isMatch;
45 | }
46 | }
47 |
48 | public function toggleReturnType($bool = null) {
49 | if(empty($bool)) {
50 | $this->returnMatchResult = !$this->returnMatchResult;
51 | } else {
52 | $this->returnMatchResult = is_bool($bool) ? $bool : (bool)$bool;
53 | }
54 | }
55 |
56 | public function setFixMode($fixMode) {
57 | $this->fixMode = $fixMode;
58 | }
59 |
60 | public function noEmpty($str) {
61 | return $this->regex('require', $str);
62 | }
63 |
64 | public function isEmail($email) {
65 | return $this->regex('email', $email);
66 | }
67 |
68 | public function isMobile($mobile) {
69 | return $this->regex('mobile', $mobile);
70 | }
71 |
72 | public function check($pattern, $subject) {
73 | return $this->regex($pattern, $subject);
74 | }
75 |
76 | //......
77 |
78 | }
--------------------------------------------------------------------------------
/PHP技能评测/README.md:
--------------------------------------------------------------------------------
1 | # PHP技能评测
2 | ### 1. 魔术函数有哪些,分别在什么时候调用?
3 | __construct(),类的构造函数
4 | __destruct(),类的析构函数
5 | __call(),在对象中调用一个不可访问方法时调用
6 | __callStatic(),用静态方式中调用一个不可访问方法时调用
7 | __get(),获得一个类的成员变量时调用
8 | __set(),设置一个类的成员变量时调用
9 | __isset(),当对不可访问属性调用isset()或empty()时调用
10 | __unset(),当对不可访问属性调用unset()时被调用。
11 | __sleep(),执行serialize()时,先会调用这个函数
12 | __wakeup(),执行unserialize()时,先会调用这个函数
13 | __toString(),类被当成字符串时的回应方法
14 | __invoke(),调用函数的方式调用一个对象时的回应方法
15 | __set_state(),调用var_export()导出类时,此静态方法会被调用。
16 | __clone(),当对象复制完成时调用
17 |
18 | ## 2.isset和empty函数有什么区别?
19 | PHP的isset()函数 一般用来检测变量是否设置
20 | 格式:bool isset ( mixed var [, mixed var [, ...]] )
21 |
22 | 功能:检测变量是否设置
23 |
24 | 返回值:
25 |
26 | 若变量不存在则返回 FALSE
27 | 若变量存在且其值为NULL,也返回 FALSE
28 | 若变量存在且值不为NULL,则返回 TURE
29 | 同时检查多个变量时,每个单项都符合上一条要求时才返回 TRUE,否则结果为 FALSE
30 | 版本:PHP 3, PHP 4, PHP 5
31 | 更多说明:
32 | 使用 unset() 释放变量之后,它将不再是 isset()。
33 | PHP函数isset()只能用于变量,传递任何其它参数都将造成解析错误。
34 | 检测常量是否已设置可使用 defined() 函数。
35 |
36 | PHP的empty()函数 判断值为否为空
37 |
38 | 格式:bool empty ( mixed var )
39 |
40 | 功能:检查一个变量是否为空
41 |
42 | 返回值:
43 |
44 | 若变量不存在则返回 TRUE
45 | 若变量存在且其值为""、0、"0"、NULL、、FALSE、array()、var $var; 以及没有任何属性的对象,则返回 TURE
46 | 若变量存在且值不为""、0、"0"、NULL、、FALSE、array()、var $var; 以及没有任何属性的对象,则返回 FALSE
47 | 版本:PHP 3, PHP 4, PHP 5
48 | 更多说明:
49 | empty()的返回值=!(boolean) var,但不会因为变量未定义而产生警告信息。参见转换为布尔值获取更多信息。
50 | empty() 只能用于变量,传递任何其它参数都将造成Paser error而终止运行。
51 | 检测常量是否已设置可使用 defined() 函数。
52 |
53 | ## 3.PHP的与定义变量有哪些,分别是什么?
54 | 超全局变量 — 超全局变量是在全部作用域中始终可用的内置变量
55 | $GLOBALS — 引用全局作用域中可用的全部变量
56 | $_SERVER — 服务器和执行环境信息
57 | $_GET — HTTP GET 变量
58 | $_POST — HTTP POST 变量
59 | $_FILES — HTTP 文件上传变量
60 | $_REQUEST — HTTP Request 变量
61 | $_SESSION — Session 变量
62 | $_ENV — 环境变量
63 | $_COOKIE — HTTP Cookies
64 | $php_errormsg — 前一个错误信息
65 | $HTTP_RAW_POST_DATA — 原生POST数据
66 | $http_response_header — HTTP 响应头
67 | $argc — 传递给脚本的参数数目
68 |
69 | PHP 中的许多预定义变量都是“超全局的”,这意味着它们在一个脚本的全部作用域中都可用。在函数或方法中无需执行 global $variable; 就可以访问它们。
70 |
71 | 这些超全局变量是:
72 |
73 | $GLOBALS
74 | $_SERVER
75 | $_GET
76 | $_POST
77 | $_FILES
78 | $_COOKIE
79 | $_SESSION
80 | $_REQUEST
81 | $_ENV
82 |
83 | ## 4.简述PHP的垃圾回收机制
84 | php 5.3之前使用的垃圾回收机制是单纯的“引用计数”,也就是每个内存对象都分配一个计数器,当内存对象被变量引用时,计数器+1;当变量引用撤掉后,计数器-1;当计数器=0时,表明内存对象没有被使用,该内存对象则进行销毁,垃圾回收完成。
85 |
86 | “引用计数”存在问题,就是当两个或多个对象互相引用形成环状后,内存对象的计数器则不会消减为0;这时候,这一组内存对象已经没用了,但是不能回收,从而导致内存泄露;
87 |
88 | php5.3开始,使用了新的垃圾回收机制,在引用计数基础上,实现了一种复杂的算法,来检测内存对象中引用环的存在,以避免内存泄露。
89 |
90 | php变量存在一个叫"zval"的变量容器中,"zval"变量容器包括含变量的类型和值,还包括额外的两个字节信息,分别是“is_ref”表示变量是否属于引用,“refcount”指向这个zval变量容器的变量个数。
91 |
92 | ## 5.列举PHP的性能优化方法和技巧
93 |
94 | opcache
95 | 通讯缓存
96 | 查询缓存
97 |
98 | ## 6.MySQL存储引擎中,innodb和myisam的区别
99 |
100 | MyISAM 和 InnoDB 讲解
101 |
102 | InnoDB和MyISAM是许多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,视具体应用而定。基本的差别为:MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持。MyISAM类型的表强调的是性能,其执行数度比InnoDB类型更快,但是不提供事务支持,而InnoDB提供事务支持已经外部键等高级数据库功能。
103 |
104 | 以下是一些细节和具体实现的差别:
105 |
106 | ◆1.InnoDB不支持FULLTEXT类型的索引。
107 |
108 | ◆2.InnoDB 中不保存表的具体行数,也就是说,执行select count(*) from table时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count(*)语句包含 where条件时,两种表的操作是一样的。
109 |
110 | ◆3.对于AUTO_INCREMENT类型的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中,可以和其他字段一起建立联合索引。
111 |
112 | ◆4.DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的删除。
113 |
114 | ◆5.LOAD TABLE FROM MASTER操作对InnoDB是不起作用的,解决方法是首先把InnoDB表改成MyISAM表,导入数据后再改成InnoDB表,但是对于使用的额外的InnoDB特性(例如外键)的表不适用。
115 |
116 | 另外,InnoDB表的行锁也不是绝对的,假如在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表,例如update table set num=1 where name like “%aaa%”
117 |
118 | 两种类型最主要的差别就是Innodb 支持事务处理与外键和行级锁.而MyISAM不支持.所以MyISAM往往就容易被人认为只适合在小项目中使用。
119 |
120 | 我作为使用MySQL的用户角度出发,Innodb和MyISAM都是比较喜欢的,但是从我目前运维的数据库平台要达到需求:99.9%的稳定性,方便的扩展性和高可用性来说的话,MyISAM绝对是我的首选。
121 |
122 | 原因如下:
123 |
124 | 1、首先我目前平台上承载的大部分项目是读多写少的项目,而MyISAM的读性能是比Innodb强不少的。
125 |
126 | 2、MyISAM的索引和数据是分开的,并且索引是有压缩的,内存使用率就对应提高了不少。能加载更多索引,而Innodb是索引和数据是紧密捆绑的,没有使用压缩从而会造成Innodb比MyISAM体积庞大不小。
127 |
128 | 3、从平台角度来说,经常隔1,2个月就会发生应用开发人员不小心update一个表where写的范围不对,导致这个表没法正常用了,这个时候MyISAM的优越性就体现出来了,随便从当天拷贝的压缩包取出对应表的文件,随便放到一个数据库目录下,然后dump成sql再导回到主库,并把对应的binlog补上。如果是Innodb,恐怕不可能有这么快速度,别和我说让Innodb定期用导出xxx.sql机制备份,因为我平台上最小的一个数据库实例的数据量基本都是几十G大小。
129 |
130 | 4、从我接触的应用逻辑来说,select count(*) 和order by 是最频繁的,大概能占了整个sql总语句的60%以上的操作,而这种操作Innodb其实也是会锁表的,很多人以为Innodb是行级锁,那个只是where对它主键是有效,非主键的都会锁全表的。
131 |
132 | 5、还有就是经常有很多应用部门需要我给他们定期某些表的数据,MyISAM的话很方便,只要发给他们对应那表的frm.MYD,MYI的文件,让他们自己在对应版本的数据库启动就行,而Innodb就需要导出xxx.sql了,因为光给别人文件,受字典数据文件的影响,对方是无法使用的。
133 |
134 | 6、如果和MyISAM比insert写操作的话,Innodb还达不到MyISAM的写性能,如果是针对基于索引的update操作,虽然MyISAM可能会逊色Innodb,但是那么高并发的写,从库能否追的上也是一个问题,还不如通过多实例分库分表架构来解决。
135 |
136 | 7、如果是用MyISAM的话,merge引擎可以大大加快应用部门的开发速度,他们只要对这个merge表做一些select count(*)操作,非常适合大项目总量约几亿的rows某一类型(如日志,调查统计)的业务表。
137 |
138 | 当然Innodb也不是绝对不用,用事务的项目如模拟炒股项目,我就是用Innodb的,活跃用户20多万时候,也是很轻松应付了,因此我个人也是很喜欢Innodb的,只是如果从数据库平台应用出发,我还是会首选MyISAM。
139 |
140 | 另外,可能有人会说你MyISAM无法抗太多写操作,但是我可以通过架构来弥补,说个我现有用的数据库平台容量:主从数据总量在几百T以上,每天十多亿 pv的动态页面,还有几个大项目是通过数据接口方式调用未算进pv总数,(其中包括一个大项目因为初期memcached没部署,导致单台数据库每天处理 9千万的查询)。而我的整体数据库服务器平均负载都在0.5-1左右。
141 |
142 | ## 7.Mysql的存储类型有哪几种?什么是聚簇索引非聚簇索引?
143 |
144 | 1、B+树索引(O(log(n))):关于B+树索引,可以参考 MySQL索引背后的数据结构及算法原理
145 |
146 | 2、hash索引:
147 | a 仅仅能满足"=","IN"和"<=>"查询,不能使用范围查询
148 | b 其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引
149 | c 只有Memory存储引擎显示支持hash索引
150 |
151 | 3、FULLTEXT索引(现在MyISAM和InnoDB引擎都支持了)
152 |
153 | 4、R-Tree索引(用于对GIS数据类型创建SPATIAL索引)
154 |
155 | 从物理存储角度
156 |
157 | 1、聚集索引(clustered index)
158 |
159 | 2、非聚集索引(non-clustered index)
160 |
161 | 从逻辑角度
162 |
163 | 1、主键索引:主键索引是一种特殊的唯一索引,不允许有空值
164 |
165 | 2、普通索引或者单列索引
166 |
167 | 3、多列索引(复合索引):复合索引指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用复合索引时遵循最左前缀集合
168 |
169 | 4、唯一索引或者非唯一索引
170 |
171 | 5、空间索引:空间索引是对空间数据类型的字段建立的索引,MYSQL中的空间数据类型有4种,分别是GEOMETRY、POINT、LINESTRING、POLYGON。MYSQL使用SPATIAL关键字进行扩展,使得能够用于创建正规索引类型的语法创建空间索引。创建空间索引的列,必须将其声明为NOT NULL,空间索引只能在存储引擎为MYISAM的表中创建
172 |
173 | CREATE TABLE table_name[col_name data type]
174 | [unique|fulltext|spatial][index|key][index_name](col_name[length])[asc|desc]
175 | 1、unique|fulltext|spatial为可选参数,分别表示唯一索引、全文索引和空间索引;
176 |
177 | 2、index和key为同义词,两者作用相同,用来指定创建索引
178 |
179 | 3、col_name为需要创建索引的字段列,该列必须从数据表中该定义的多个列中选择;
180 |
181 | 4、index_name指定索引的名称,为可选参数,如果不指定,MYSQL默认col_name为索引值;
182 |
183 | 5、length为可选参数,表示索引的长度,只有字符串类型的字段才能指定索引长度;
184 |
185 | 6、asc或desc指定升序或降序的索引值存储
186 |
187 | ## 8.Memcache和Redis的过期机制是什么?什么是一致性哈希?
188 |
189 | 数据存储方式:Slab Allocation
190 |
191 | 数据过期方式:Lazy Expiration + LRU
192 |
193 | Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,以完全解决内存碎片问题。
194 |
195 | Slab Allocation的原理相当简单。 将分配的内存分割成各种尺寸的块(chuk),并把尺寸相同的块分成组(chunk的集合)
196 |
197 | Page:分配给Slab的内存空间,默认是1MB。分配给Slab之后根据slab的大小切分成chunk。
198 |
199 | Chunk:用于缓存记录的内存空间。
200 |
201 | Slab Class:特定大小的chunk的组。
202 |
203 | memcached根据收到的数据的大小,选择最适合数据大小的slab。
204 |
205 | memcached中保存着slab内空闲chunk的列表,根据该列表选择chunk,然后将数据缓存于其中。
206 |
207 | Slab Alloction 缺点
208 |
209 | 这个问题就是,由于分配的是特定长度的内存,因此无法有效利用分配的内存。例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了。
210 |
211 | 数据过期方式
212 |
213 | Lazy Expiration
214 |
215 | memcached内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期。这种技术被称为lazy(惰性)expiration。因此,memcached不会在过期监视上耗费CPU时间
216 |
217 | LRU
218 |
219 | memcached会优先使用已超时的记录的空间,但即使如此,也会发生追加新记录时空间不足的情况,此时就要使用名为 Least Recently Used(LRU)机制来分配空间。这是删除“最近最少使用”的记录的机制。因此,当memcached的内存空间不足时(无法从slab class 获取到新的空间时),就从最近未被使用的记录中搜索,并将其空间分配给新的记录
220 |
221 | 大家常常说 memcached命中率低也是LRU策略引起的。大家可能常常遇到当我的内存足够大的时候,为何还会触发LRU那。因为LRU 是针对SLAB 来说的。
222 |
223 | 例如:我存储的数据在100K 左右。内部会选择适合大小的SLAB,这时候他会选择合适他大小的,他会选择上图的SLBA CLASS 2. 如果这时候SLAB CLASS 2 满了或者不足100K。他就会调用LRU机制。会把SLAB CLASS 2 中chunck中最近很少使用的数据清理掉,导致数据被清理掉,即使它没有过期。
224 |
225 | 所以使用memcached 时候 一定要注意数据大小匹配模式和增长因子。
226 |
227 | REDIS 过期时间机制
228 |
229 | 1.volatile-lru:从设置了过期时间的数据集中,选择最近最久未使用的数据释放
230 |
231 | 2.allkeys-lru:从数据集中(包括设置过期时间以及未设置过期时间的数据集中),选择最近最久未使用的数据释放
232 |
233 | 3.volatile-random:从设置了过期时间的数据集中,随机选择一个数据进行释放
234 |
235 | 4.allkeys-random:从数据集中(包括了设置过期时间以及未设置过期时间)随机选择一个数据进行入释放
236 |
237 | 5.volatile-ttl:从设置了过期时间的数据集中,选择马上就要过期的数据进行释放操作
238 |
239 | 6.noeviction:不删除任意数据(但redis还会根据引用计数器进行释放呦~),这时如果内存不够时,会直接返回错误
240 |
241 | 默认的内存策略是noeviction,在Redis中LRU算法是一个近似算法,默认情况下,Redis随机挑选5个键,并且从中选取一个最近最久未使用的key进行淘汰,在配置文件中可以通过maxmemory-samples的值来设置redis需要检查key的个数,但是检查的越多,耗费的时间也就越久,但是结构越精确(也就是Redis从内存中淘汰的对象未使用的时间也就越久~), 设置多少,具体业务权衡吧一般都是按照默认。
242 |
243 | REDIS 还有定期策略,定期删除过期的缓存数据,来节省内存。这种方式还是蛮好的。这种策略优先于LRU。
244 |
245 | 目前对比MEMCACHED 和REDIS 过期时间机制对比。
246 |
247 | REDIS 命中率明显高于MEMCACHED,对于业务适合哪种场景,大家各自匹配吧!目前来说 我认为REDIS 是 MEMCACHED 补充的一款NOSQL 产品。
248 |
249 | 一致性哈希,一种分布式节点key分布算法,可选;
250 |
251 | ## 9.MySQL索引底层数据结构是怎样存储的,为什么使用索引会查询的快?
252 |
253 | 数据结构及算法基础
254 |
255 | 索引的本质
256 |
257 | B-Tree和B+Tree
258 |
259 | 特殊的存储结构,寻道成本低;
260 |
261 | MySQL索引实现
262 |
263 | MyISAM索引实现
264 | 非聚簇索引
265 |
266 | InnoDB索引实现
267 | 聚簇索引
268 |
269 | 第一个重大区别是InnoDB的数据文件本身就是索引文件。
270 |
271 | 第二个与MyISAM索引的不同是InnoDB的辅助索引data域存储相应记录主键的值而不是地址。
272 |
273 | 聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。
274 |
275 | ## 10.优化mysql的方法
276 |
277 | 避免复查查询
278 | 避免模糊查询
279 | 避免数据库内运算
280 | 避免大量吞吐
281 |
282 | 尽可能缩小检索范围
283 | 尽可能使用索引,唯一或者接近唯一的索引
284 | 联查中尽量使用const字段
285 |
286 | ## 11.find 和 grep的区别
287 |
288 | find是查找文件
289 | grep是查找文件内的内容
290 |
291 | ## 12.写出下列的服务的用途和默认端口
292 |
293 | FTP: | 21/tcp | 依照FTP协议提供服务,专门用来传输文件的协议。
294 | SSH: | 22/tcp | 专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。
295 | HTTP: | 80/tcp | 是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。
296 | telnet:| 23/tcp | Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主要方式,它为用户提供了在本地计算机上完成远程主机工作的能力
297 | https:| 443/tcp 443/udp | 是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL
298 |
299 | ## 13.给text.txt文件除所有者之外增加执行权限,最终以数字写出文件权限
300 |
301 | chmod g+x,o+x text.txt
--------------------------------------------------------------------------------
/PHP珍贵资源/CODE-OF-CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Code of Conduct
2 |
3 | As contributors and maintainers of this project, and in the interest of
4 | fostering an open and welcoming community, we pledge to respect all people who
5 | contribute through reporting issues, posting feature requests, updating
6 | documentation, submitting pull requests or patches, and other activities.
7 |
8 | We are committed to making participation in this project a harassment-free
9 | experience for everyone, regardless of level of experience, gender, gender
10 | identity and expression, sexual orientation, disability, personal appearance,
11 | body size, race, ethnicity, age, religion, or nationality.
12 |
13 | Examples of unacceptable behavior by participants include:
14 |
15 | * The use of sexualized language or imagery
16 | * Personal attacks
17 | * Trolling or insulting/derogatory comments
18 | * Public or private harassment
19 | * Publishing other's private information, such as physical or electronic
20 | addresses, without explicit permission
21 | * Other unethical or unprofessional conduct
22 |
23 | Project maintainers have the right and responsibility to remove, edit, or
24 | reject comments, commits, code, wiki edits, issues, and other contributions
25 | that are not aligned to this Code of Conduct, or to ban temporarily or
26 | permanently any contributor for other behaviors that they deem inappropriate,
27 | threatening, offensive, or harmful.
28 |
29 | By adopting this Code of Conduct, project maintainers commit themselves to
30 | fairly and consistently applying these principles to every aspect of managing
31 | this project. Project maintainers who do not follow or enforce the Code of
32 | Conduct may be permanently removed from the project team.
33 |
34 | This Code of Conduct applies both within project spaces and in public spaces
35 | when an individual is representing the project or its community.
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
38 | reported by contacting a project maintainer at awesome-php@josediazgonzalez.com. All
39 | complaints will be reviewed and investigated and will result in a response that
40 | is deemed necessary and appropriate to the circumstances. Maintainers are
41 | obligated to maintain confidentiality with regard to the reporter of an
42 | incident.
43 |
44 |
45 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
46 | version 1.3.0, available at
47 | [http://contributor-covenant.org/version/1/3/0/][version]
48 |
49 | [homepage]: http://contributor-covenant.org
50 | [version]: http://contributor-covenant.org/version/1/3/0/
51 |
--------------------------------------------------------------------------------
/PHP珍贵资源/COLLABORATING.md:
--------------------------------------------------------------------------------
1 | # Collaboration Guidelines
2 | As a collaborator you are representing the Awesome PHP project to the community. Please adhere to the following guidelines to give everyone the best experience possible:
3 |
4 | ## Etiquette
5 | Please adhere to the [CODE-OF-CONDUCT](https://github.com/ziadoz/awesome-php/blob/master/CODE-OF-CONDUCT.md) when reviewing suggestions and participating in discussions on the project's Github account.
6 |
7 | Always be polite and thank people, even if you don’t accept their suggestions.
8 |
9 | You are welcome to suggest projects that you are personally involved with, or those of friends, family or colleagues, but you are not allowed to review or merge them yourself, nor should you request that others do so for you. They must be reviewed by a neutral collaborator in their own time.
10 |
11 | If you provide feedback on a suggested project please be friendly and constructive.
12 |
13 | ## Reviewing
14 | Please work through the following checklist when reviewing a project:
15 |
16 | - Tag pull requests with the most relevant label(s).
17 | - Validate URLs work correctly and don't point to anything malicious.
18 | - Ensure suggestions adhere to [CONTRIBUTING](https://github.com/ziadoz/awesome-php/blob/master/CONTRIBUTING.md).
19 |
20 | ## Enhancements
21 | If you have an idea on how to improve the project, please open a ticket for discussion using the `Enhancement` label. Please don’t make any broad or sweeping changes without consulting other collaborators first and reaching a consensus.
22 |
23 | ## Join
24 | If you want to help out please send an email to my Github username [at] gmail [dot] com with the subject “Awesome PHP Collaborator and a link to your Github account and I’ll get back to you as soon as I can (I'm notoriously slow, sorry).
25 |
26 | Thank you for taking the time to help out with Awesome PHP, your help is appreciated!
27 |
--------------------------------------------------------------------------------
/PHP珍贵资源/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribution Guidelines
2 | Unfortunately, not every library, tool or framework can be considered for inclusion. The aim of Awesome PHP is to be a concise list of noteworthy and interesting software written in modern PHP. Therefore, suggested software should:
3 |
4 | a) Be widely recommended regardless of personal opinion
5 | b) Well known or discussed within the PHP community
6 | c) Be unique in its approach or function
7 | d) Fill a niche gap in the market
8 |
9 | Self-promotion is frowned upon, so please consider seriously whether your project meets the criteria before opening a pull request, otherwise it may be closed without being reviewed.
10 |
11 | Also, please ensure your pull request adheres to the following guidelines:
12 |
13 | * Software that is PHP 5.5+, Composer-installable, PSR compliant, semantically versioned, united tested and well documented in English is preferred.
14 | * Please search previous suggestions before making a new one, as yours may be a duplicate.
15 | * Enter a meaningful pull request description.
16 | * Please make an individual commit for each suggestion in a separate pull request.
17 | * Put a link to each library in your pull request ticket so it's easier to review.
18 | * Use the following format for libraries: \[LIBRARY\]\(LINK\) - DESCRIPTION.
19 | * Prefix duplicate library names with their vendor or namespace followed by a space: Foo\Bar would be Foo Bar.
20 | * New categories, or improvements to the existing categorisation, are always welcome.
21 | * Please keep descriptions short, simple and unbiased. No buzzwords or marketing jargon.
22 | * End all descriptions with a full stop/period.
23 | * Check your spelling and grammar.
24 | * Make sure your text editor is set to remove trailing whitespace.
25 |
26 | Thank you for your suggestions!
27 |
--------------------------------------------------------------------------------
/PHP珍贵资源/LICENSE.md:
--------------------------------------------------------------------------------
1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
2 | Version 2, December 2004
3 |
4 | Copyright (C) 2004 Sam Hocevar
5 |
6 | Everyone is permitted to copy and distribute verbatim or modified
7 | copies of this license document, and changing it is allowed as long
8 | as the name is changed.
9 |
10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12 |
13 | 0. You just DO WHAT THE FUCK YOU WANT TO.
14 |
--------------------------------------------------------------------------------
/PHP珍贵资源/README.md:
--------------------------------------------------------------------------------
1 | # Awesome PHP
2 | 一个PHP资源列表,内容包括:库、框架、模板、安全、代码分析、日志、第三方库、配置工具、Web 工具、书籍、电子书、经典博文等等
3 |
4 | ## 贡献
5 | 详细内容请查看[贡献](https://github.com/ziadoz/awesome-php/blob/master/CONTRIBUTING.md) 和 [代码管理](https://github.com/ziadoz/awesome-php/blob/master/CODE-OF-CONDUCT.md)----[来源](https://github.com/ziadoz/awesome-php).
6 | ## 目录
7 | - [Awesome PHP](#awesome-php)
8 | - [依赖管理 Dependency Management](#依赖管理-dependency-management)
9 | - [其他的依赖管理 Dependency Management Extras](#其他的依赖管理-dependency-management-extras)
10 | - [框架 Frameworks](#框架-frameworks)
11 | - [其他框架 Framework Extras](#其他框架-framework-extras)
12 | - [框架组件 Components](#框架组件-components)
13 | - [微型框架 Micro Frameworks](#微型框架-micro-frameworks)
14 | - [其他微型框架 Micro Framework Extras](#其他微型框架-micro-framework-extras)
15 | - [路由 Routers](#路由-routers)
16 | - [模板 Templating](#模板-templating)
17 | - [静态站点生成器 Static Site Generators](#静态站点生成器-static-site-generators)
18 | - [超文本传输协议 HTTP](#超文本传输协议-http)
19 | - [爬虫 Scraping](#爬虫-scraping)
20 | - [中间件 Middlewares](#中间件-middlewares)
21 | - [网址 URL](#网址-url)
22 | - [电子邮件 Email](#电子邮件-email)
23 | - [文件 Files](#文件-files)
24 | - [流 Streams](#流-streams)
25 | - [依赖注入 Dependency Injection](#依赖注入-dependency-injection)
26 | - [图像 Imagery](#图像-imagery)
27 | - [测试 Testing](#测试-testing)
28 | - [持续集成 Continuous Integration](#持续集成-continuous-integration)
29 | - [文档 Documentation](#文档-documentation)
30 | - [安全 Security](#安全-security)
31 | - [密码 Passwords](#密码-passwords)
32 | - [代码分析 Code Analysis](#代码分析-code-analysis)
33 | - [Architectural Architectural](#architectural-architectural)
34 | - [调试和分析 Debugging and Profiling](#调试和分析-debugging-and-profiling)
35 | - [构建工具 Build Tools](#构建工具-build-tools)
36 | - [任务运行器 Task Runners](#任务运行器-task-runners)
37 | - [导航 Navigation](#导航-navigation)
38 | - [资源管理 Asset Management](#资源管理-asset-management)
39 | - [地理位置 Geolocation](#地理位置-geolocation)
40 | - [日期和时间 Date and Time](#日期和时间-date-and-time)
41 | - [事件 Event](#事件-event)
42 | - [日志 Logging](#日志-logging)
43 | - [电子商务 E-commerce](#电子商务-e-commerce)
44 | - [PDF PDF](#pdf-pdf)
45 | - [Office Office](#office-office)
46 | - [数据库 Database](#数据库-database)
47 | - [迁移 Migrations](#迁移-migrations)
48 | - [NoSQL NoSQL](#nosql-nosql)
49 | - [队列 Queue](#队列-queue)
50 | - [搜索 Search](#搜索-search)
51 | - [命令行 Command Line](#命令行-command-line)
52 | - [身份验证和授权 Authentication and Authorization](#身份验证和授权-authentication-and-authorization)
53 | - [标记 Markup](#标记-markup)
54 | - [字符串 Strings](#字符串-strings)
55 | - [数字 Numbers](#数字-numbers)
56 | - [过滤和验证 Filtering and Validation](#过滤和验证-filtering-and-validation)
57 | - [API API](#api-api)
58 | - [缓存 Caching](#缓存-caching)
59 | - [数据结构和存储 Data Structure and Storage](#数据结构和存储-data-structure-and-storage)
60 | - [通知 Notifications](#通知-notifications)
61 | - [部署 Deployment](#部署-deployment)
62 | - [国际化和本地化 Internationalisation and Localisation](#国际化和本地化-internationalisation-and-localisation)
63 | - [第三方API Third Party APIs](#第三方api-third-party-apis)
64 | - [扩展 Extensions](#扩展-extensions)
65 | - [杂项 Miscellaneous](#杂项-miscellaneous)
66 | - [软件 Software](#软件-software)
67 | - [PHP安装 PHP Installation](#PHP安装-php-installation)
68 | - [开发环境 Development Environment](#开发环境-development-environment)
69 | - [虚拟机 Virtual Machines](#虚拟机-virtual-machines)
70 | - [集成开发环境(IDE) Integrated Development Environment](#集成开发环境ide-integrated-development-environment)
71 | - [Web应用 Web Applications](#web应用-web-applications)
72 | - [基础架构 Infrastructure](#基础架构-infrastructure)
73 | - [资源 Resources](#资源-resources)
74 | - [PHP网站 PHP Websites](#php网站-php-websites)
75 | - [其他网站 Other Websites](#其他网站-other-websites)
76 | - [PHP书籍 PHP Books](#php书籍-php-books)
77 | - [其他书籍 Other Books](#其他书籍-other-books)
78 | - [PHP视频 PHP Videos](#php视频-php-videos)
79 | - [PHP播客 PHP Podcasts](#php播客-php-podcasts)
80 | - [PHP阅读 PHP Reading](#php阅读-php-reading)
81 | - [PHP内核阅读 PHP Internals Reading](#php内核阅读-php-internals-reading)
82 | - [PHP杂志 PHP Magazines](#php杂志-php-magazines)
83 | - [贡献](#贡献)
84 |
85 | ## 依赖管理 Dependency Management
86 | *依赖和包管理库*
87 |
88 | * [Composer Installers](https://github.com/composer/installers) - 一个多框架Composer库安装器
89 | * [Composer](https://getcomposer.org/)/[Packagist](https://packagist.org/) - 一个包和依赖管理器
90 | * [Melody](http://melody.sensiolabs.org/) - 一个用于构建Composer脚本文件的工具
91 | * [Pickle](https://github.com/FriendsOfPHP/pickle) - 一个PHP扩展安装器
92 |
93 | ## 其他的依赖管理 Dependency Management Extras
94 | *其他的相关依赖管理*
95 |
96 | * [Composed](https://github.com/joshdifabio/composed) - 一个在运行时解析你项目Composer环境的库
97 | * [Composer Checker](https://github.com/silpion/composer-checker) - 一个校验Composer配置的工具
98 | * [Composer Merge Plugin](https://github.com/wikimedia/composer-merge-plugin) - 一个用于合并多个composer.json文件的Composer插件
99 | * [Composition](https://github.com/bamarni/composition) - 一个在运行时检查Composer环境的库
100 | * [NameSpacer](https://github.com/ralphschindler/Namespacer) - 一个转化下划线到命名空间的库
101 | * [Patch Installer](https://github.com/goatherd/patch-installer) - 一个使用Composer安装补丁的库
102 | * [Prestissimo](https://github.com/hirak/prestissimo) - 一个开启并行安装进程的Composer插件
103 | * [Satis](https://github.com/composer/satis) - 一个静态Composer存储库的生成器
104 | * [tooly](https://github.com/tommy-muehle/tooly-composer-script) - 一个在项目中使用Composer管理PHAR文件的库
105 | * [Toran Proxy](https://toranproxy.com) - 一个静态Composer存储库和代理
106 |
107 | ## 框架 Frameworks
108 | *Web开发框架*
109 |
110 | * [Aura PHP](http://auraphp.com/) - 一个独立的组件框架
111 | * [CakePHP](https://cakephp.org/) - 一个快速应用程序开发框架 (CP)
112 | * [Laravel 5](https://laravel.com/) - 另一个PHP框架 (L5)
113 | * [Nette](https://nette.org) - 另一个由个体组件组成的框架
114 | * [Phalcon](https://phalconphp.com/en/) - 通过C扩展实现的框架
115 | * [PPI Framework 2](http://www.ppi.io) - 一个互操作性框架
116 | * [Symfony](https://symfony.com/) - 一个独立组件组成的框架 (SF)
117 | * [Yii2](https://github.com/yiisoft/yii2/) - 另一个PHP框架
118 | * [Zend Framework 2](https://framework.zend.com) - 另一个由独立组件组成的框架 (ZF2)
119 | * [Radar](https://github.com/radarphp/Radar.Adr) - 一个基于PHP的Action-Domain-Responder实现
120 | * [Ice](https://www.iceframework.org/) - 另一个通过C扩展实现的简单快速的PHP框架
121 |
122 | ## 其他框架 Framework Extras
123 | *其他Web开发框架*
124 |
125 | * [CakePHP CRUD](https://github.com/friendsofcake/crud) - CakePHP的快速应用程序(RAD)插件
126 | * [Knp RAD Bundle](http://rad.knplabs.com/) - Symfony 2的快速应用程序(RAD)包
127 | * [Symfony CMF](https://github.com/symfony-cmf/symfony-cmf) - 一个创建自定义CMS的内容管理框架
128 |
129 | ## 框架组件 Components
130 | *来自web开发框架的独立组件*
131 |
132 | * [CakePHP Plugins](http://plugins.cakephp.org/) - CakePHP插件的目录
133 | * [Hoa Project](https://hoa-project.net/En/) - 另一个PHP组件包
134 | * [League of Extraordinary Packages](https://thephpleague.com/) - 一个PHP软件开发组
135 | * [Symfony Components](http://symfony.com/doc/master/components/index.html) - Symfony组件
136 | * [Zend Framework 2 Components](https://packages.zendframework.com/) - Zend Framework 2组件
137 |
138 | ## 微型框架 Micro Frameworks
139 | *微型框架和路由*
140 |
141 | * [Bullet PHP](http://bulletphp.com/) - 用于构建REST APIs的微型框架
142 | * [Lumen](https://lumen.laravel.com) - 一个Laravel的微型框架
143 | * [Proton](https://github.com/alexbilbie/Proton) - 一个StackPHP兼容的微型框架
144 | * [Silex](http://silex.sensiolabs.org/) - 基于Symfony2组件的微型框架
145 | * [Slim](https://www.slimframework.com/) - 另一个简单的微型框架
146 |
147 | ## 其他微型框架 Micro Framework Extras
148 | *其他相关的微型框架和路由*
149 |
150 | * [Silex Skeleton](https://github.com/silexphp/Silex-Skeleton) - Silex的项目架构
151 | * [Silex Web Profiler](https://github.com/silexphp/Silex-WebProfiler) - 一个Silex web的调试工具
152 | * [Slim Skeleton](https://github.com/slimphp/Slim-Skeleton) - Slim架构
153 | * [Slim View](https://github.com/slimphp/Slim-Views) - Slim自定义视图的集合
154 |
155 | ## 路由 Routers
156 | *处理应用路由的库*
157 |
158 | * [Fast Route](https://github.com/nikic/FastRoute) - 一个快速路由的库
159 | * [Klein](https://github.com/klein/klein.php) - 一个灵活的路由的库
160 | * [Pux](https://github.com/c9s/Pux) - 另一个快速路由的库
161 | * [Route](https://github.com/thephpleague/route) - 一个基于Fast Route的路由的库
162 |
163 | ## 模板 Templating
164 | *模板化和词法分析的库和工具*
165 |
166 | * [Foil](https://github.com/FoilPHP/Foil) - 另一个原生PHP模板库
167 | * [Lex](https://github.com/pyrocms/lex) - 一个轻量级模板解析器
168 | * [MtHaml](https://github.com/arnaud-lb/MtHaml) - 一个HAML模板语言的PHP实现
169 | * [Mustache](https://github.com/bobthecow/mustache.php) - 一个Mustache模板语言的PHP实现
170 | * [Phly Mustache](https://github.com/phly/phly_mustache) - 另一个Mustache模板语言的PHP实现
171 | * [PHPTAL](http://phptal.org/) - 一个[TAL](https://en.wikipedia.org/wiki/Template_Attribute_Language)模板语言的PHP实现
172 | * [Plates](http://platesphp.com/) - 一个原生PHP模板库
173 | * [Smarty](http://www.smarty.net/) - 一个模板引擎
174 | * [Twig](http://twig.sensiolabs.org/) - 一个全面的模板语言
175 | * [Tale Jade](https://github.com/Talesoft/tale-jade) - Jade模版语言的PHP实现
176 |
177 | ## 静态站点生成器 Static Site Generators
178 | *用来生成web页面的预处理内容的工具*
179 |
180 | * [Couscous](http://couscous.io) - 一个将Markdown转化为漂亮的网站的工具
181 | * [Phrozn](https://github.com/Pawka/phrozn) - 另一个转换Textile,Markdown和Twig为HTML的工具
182 | * [Sculpin](https://sculpin.io) - 转换Markdown和Twig为静态HTML的工具
183 | * [Spress](http://spress.yosymfony.com) - 一个能够将Markdown和Twig转化为HTML的可扩展工具
184 |
185 | ## 超文本传输协议 HTTP
186 | *用于HTTP的库*
187 |
188 | * [Buzz](https://github.com/kriswallsmith/Buzz) - 另一个HTTP客户端
189 | * [Guzzle]( https://github.com/guzzle/guzzle) - 一个全面的HTTP客户端
190 | * [HTTPFul](https://github.com/nategood/httpful) - 一个链式HTTP库
191 | * [PHP VCR](http://php-vcr.github.io/) - 一个录制和重放HTTP请求的库
192 | * [Requests](https://github.com/rmccue/Requests) - 一个简单的HTTP库
193 | * [Retrofit](https://github.com/tebru/retrofit-php) - 一个能轻松创建REST API客户端的库
194 | * [zend-diactoros](https://github.com/zendframework/zend-diactoros) - PSR-7 HTTP消息实现
195 |
196 | ## 爬虫 Scraping
197 | *用于网站爬取的库*
198 |
199 | * [Embed](https://github.com/oscarotero/Embed) - 一个从web服务或网页中提取的信息的工具
200 | * [Goutte](https://github.com/FriendsOfPHP/Goutte) - 一个简单的web爬取器
201 | * [PHP Spider](https://github.com/mvdbos/php-spider) - 一个可配置和可扩展的PHP web爬虫
202 |
203 | ## 中间件 Middlewares
204 | *使用中间件构建应用程序的库*
205 |
206 | * [Expressive](https://zendframework.github.io/zend-expressive/) - 基于PSR-7的Zend中间件
207 | * [PSR7-Middlewares](https://github.com/oscarotero/psr7-middlewares) - 灵感来源于方便的中间件
208 | * [Relay](https://github.com/relayphp/Relay.Relay) - 一个PHP 5.5 PSR-7的中间件调度器
209 | * [Stack](https://github.com/stackphp) - 一个用于Silex/Symfony的可堆叠的中间件的库
210 | * [zend-stratigility](https://github.com/zendframework/zend-stratigility) - 基于PHP PSR-7之上的中间件之上
211 |
212 | ## 网址 URL
213 | *解析URL的库*
214 |
215 | * [PHP Domain Parser](https://github.com/jeremykendall/php-domain-parser) - 一个本地前缀解析库
216 | * [Purl](https://github.com/jwage/purl) - 一个URL处理库
217 | * [sabre/uri](https://github.com/fruux/sabre-uri) - 一个URI操作库
218 | * [Uri](https://github.com/thephpleague/uri) - 另一个URL处理库
219 |
220 | ## 电子邮件 Email
221 | *发送和解析邮件的库*
222 |
223 | * [CssToInlineStyles](https://github.com/tijsverkoyen/CssToInlineStyles) - 一个在邮件模板中的内联CSS库
224 | * [Email Reply Parser](https://github.com/willdurand/EmailReplyParser) - 一个邮件回复解析的库
225 | * [Email Validator](https://github.com/nojacko/email-validator) - 一个较小的电子邮件验证库
226 | * [Fetch](https://github.com/tedious/Fetch) - 一个IMAP库
227 | * [Mautic](https://github.com/mautic/mautic) - 邮件营销自动化
228 | * [PHPMailer](https://github.com/PHPMailer/PHPMailer) - 另一个邮件解决方案
229 | * [Stampie](https://github.com/henrikbjorn/Stampie) - 一个邮件服务库,类似于[SendGrid](http://sendgrid.com),[PostMark](https://postmarkapp.com),[MailGun](http://www.mailgun.com)和[Mandrill](http://www.mandrill.com).
230 | * [SwiftMailer](http://swiftmailer.org/) - 一个邮件解决方案
231 |
232 | ## 文件 Files
233 | *文件处理和MIME类型检测的库*
234 |
235 | * [Apache MIME Types](https://github.com/dflydev/dflydev-apache-mime-types) - 一个解析Apache MIME类型的库
236 | * [Canal](https://github.com/dflydev/dflydev-canal) - 一个检测互联网媒体类型的库
237 | * [CSV](https://github.com/thephpleague/csv) - 一个CSV数据处理库
238 | * [Ferret](https://github.com/versionable/Ferret) - 一个MIME检测库
239 | * [Flysystem](https://github.com/thephpleague/Flysystem) - 另一个文件系统抽象层
240 | * [Gaufrette](https://github.com/KnpLabs/Gaufrette) - 一个文件系统抽象层
241 | * [Hoa Mime](https://github.com/hoaproject/Mime) - 另一个MIME检测库
242 | * [Lurker](https://github.com/henrikbjorn/Lurker) - 一个资源跟踪库
243 | * [PHP FFmpeg](https://github.com/PHP-FFmpeg/PHP-FFmpeg/) - 一个用于[FFmpeg](http://www.ffmpeg.org/)视频包装的库
244 | * [UnifiedArchive](https://github.com/wapmorgan/UnifiedArchive) - 一个统一标准的压缩和解压的库
245 |
246 | ## 流 Streams
247 | *处理流的库*
248 |
249 | * [Streamer](https://github.com/fzaninotto/Streamer) - 一个简单的面向对象的流包装库
250 |
251 | ## 依赖注入 Dependency Injection
252 | *实现依赖注入设计模式的库*
253 |
254 | * [Acclimate](https://github.com/jeremeamia/acclimate-container) - 一个依赖注入容器和服务定位的通用接口
255 | * [Auryn](https://github.com/rdlowrey/Auryn) - 一个递归的依赖注入容器
256 | * [Container](https://github.com/thephpleague/container) - 另一个可伸缩的依赖注入容器
257 | * [PHP-DI](http://php-di.org/) - 一个支持自动装配和PHP配置的依赖注入容器
258 | * [Pimple](http://pimple.sensiolabs.org/) - 一个小的依赖注入容器
259 | * [Symfony DI](https://github.com/symfony/dependency-injection) - 一个依赖注入容器组件 (SF2)
260 |
261 | ## 图像 Imagery
262 | *处理图像的库*
263 |
264 | * [Color Extractor](https://github.com/thephpleague/color-extractor) - 一个从图像中提取颜色的库
265 | * [GIF Creator](https://github.com/Sybio/GifCreator) - 一个通过多张图片创建GIF动画的库
266 | * [GIF Frame Extractor](https://github.com/Sybio/GifFrameExtractor) - 一个提取GIF动画帧信息的库
267 | * [Glide](https://github.com/thephpleague/glide) - 一个按需处理图像的库
268 | * [Image Hash](https://github.com/jenssegers/imagehash) - 一个用于生成图像哈希感知的库
269 | * [Image Optimizer](https://github.com/psliwa/image-optimizer) - 一个优化图像的库
270 | * [Image With Text](https://github.com/nmcteam/image-with-text) - 一个在图像中嵌入文本的库
271 | * [Imagine](http://imagine.readthedocs.io/en/latest/index.html) - 一个图像处理库
272 | * [Intervention Image](https://github.com/Intervention/image) - 另一个图像处理库
273 | * [PHP Image Workshop](https://github.com/Sybio/ImageWorkshop) - 另一个图像处理库
274 |
275 | ## 测试 Testing
276 | *测试代码和生成测试数据的库*
277 |
278 | * [Alice](https://github.com/nelmio/alice) - 富有表现力的一代库
279 | * [AspectMock](https://github.com/Codeception/AspectMock) - 一个PHPUnit/Codeception的模拟框架。
280 | * [Atoum](https://github.com/atoum/atoum) - 一个简单的测试库
281 | * [Behat](http://docs.behat.org/en/v2.5/) - 一个行为驱动开发(BDD)测试框架
282 | * [Codeception](https://github.com/Codeception/Codeception) - 一个全栈测试框架
283 | * [DBUnit](https://github.com/sebastianbergmann/dbunit) - 一个PHPUnit的数据库测试库
284 | * [Faker](https://github.com/fzaninotto/Faker) - 一个伪数据生成库
285 | * [HTTP Mock](https://github.com/InterNations/http-mock) - 一个在单元测试模拟HTTP请求的库
286 | * [Kahlan](https://github.com/kahlan/kahlan) - 全栈Unit/BDD测试框架,内置stub,mock和代码覆盖率的支持
287 | * [Mink](http://mink.behat.org/en/latest/) - Web验收测试
288 | * [Mockery](https://github.com/padraic/mockery) - 一个用于测试的模拟对象的库
289 | * [ParaTest](https://github.com/brianium/paratest) - 一个PHPUnit的并行测试库
290 | * [Peridot](https://github.com/peridot-php/peridot) - 一个事件驱动开发的测试框架
291 | * [Phake](https://github.com/mlively/Phake) - 另一个用于测试的模拟对象的库
292 | * [Pho](https://github.com/danielstjules/pho) - 另一个行为驱动开发测试框架
293 | * [PHP-Mock](https://github.com/php-mock/php-mock) - 一个基于PHP函数的模拟库
294 | * [PHPSpec](https://github.com/phpspec/phpspec) - 一个基于功能点设计的单元测试库
295 | * [PHPT](https://qa.php.net/write-test.php) - 一个使用PHP本身的测试工具
296 | * [PHPUnit](https://github.com/sebastianbergmann/phpunit) - 一个单元测试框架
297 | * [Prophecy](https://github.com/phpspec/prophecy) - 一个可选度很高的模拟框架
298 | * [Samsui](https://github.com/mauris/samsui) - 另一个伪数据生成库
299 | * [VFS Stream](https://github.com/mikey179/vfsStream) - 一个用于测试的虚拟文件系统流的包装器
300 | * [VFS](https://github.com/adlawson/php-vfs) - 另一个用于测试虚拟的文件系统
301 |
302 | ## 持续集成 Continuous Integration
303 | *持续集成的库和应用*
304 |
305 | * [CircleCI](https://circleci.com) - 一个持续集成平台
306 | * [GitlabCi](https://about.gitlab.com/gitlab-ci/) - 使用GitLab CI测试、构建、部署你的代码,像TravisCI
307 | * [Jenkins](https://jenkins.io/index.html) - 一个[PHP支持](http://jenkins-php.org/index.html)的持续集成平台
308 | * [JoliCi](https://github.com/jolicode/JoliCi) - 一个用PHP编写的由Docker支持的持续集成的客户端
309 | * [PHPCI](https://www.phptesting.org/) - 一个PHP的开源的持续集成平台
310 | * [SemaphoreCI](https://semaphoreci.com/) - 一个开放源码和私人项目的持续集成平台
311 | * [Shippable](https://app.shippable.com/) - 一个基于开源和私人项目持续集成平台的docker
312 | * [Sismo](http://sismo.sensiolabs.org/) - 一个持续测试的服务库
313 | * [Travis CI](https://travis-ci.org/) - 一个持续集成平台
314 | * [Wercker](http://www.wercker.com/) - 一个持续集成平台
315 |
316 | ## 文档 Documentation
317 | *生成项目文档的库*
318 |
319 | * [APIGen](https://github.com/apigen/apigen) - 另一个API文档生成器
320 | * [daux.io](https://github.com/justinwalsh/daux.io) - 一个使用Markdown文件的文档生成器
321 | * [PHP Documentor 2](https://github.com/phpDocumentor/phpDocumentor2) - 一个API文档生成器
322 | * [phpDox](http://phpdox.de/) - 一个PHP项目的文档生成器(不限于API文档)
323 | * [Sami](https://github.com/FriendsOfPHP/Sami) - 一个API文档生成器
324 |
325 | ## 安全 Security
326 | *生成安全的随机数,加密数据,扫描漏洞的库*
327 |
328 | * [Halite](https://paragonie.com/project/halite) - 一个简单的使用[libsodium](https://github.com/jedisct1/libsodium)的加密库
329 | * [HTML Purifier](https://github.com/ezyang/htmlpurifier) - 一个兼容标准的HTML过滤器
330 | * [IniScan](https://github.com/psecio/iniscan) - 一个扫描PHP INI文件安全的库
331 | * [Optimus](https://github.com/jenssegers/optimus) - 基于Knuth乘法散列方法的身份混淆工具
332 | * [PHP Encryption](https://github.com/defuse/php-encryption) - 一个安全的PHP加密库
333 | * [PHP IDS](https://github.com/PHPIDS/PHPIDS) - 一个结构化的PHP安全层
334 | * [PHP SSH](https://github.com/Herzult/php-ssh) - 一个试验的面向对象的SSH包装库
335 | * [PHPSecLib](http://phpseclib.sourceforge.net/) - 一个纯PHP安全通信库
336 | * [RandomLib](https://github.com/ircmaxell/RandomLib) - 一个生成随机数和字符串的库
337 | * [SecurityMultiTool](https://github.com/padraic/SecurityMultiTool) - 一个PHP安全库
338 | * [SensioLabs Security Check](https://security.sensiolabs.org/) - 一个为检查Composer依赖提供安全建议的web工具
339 | * [TCrypto](https://github.com/timoh6/TCrypto) - 一个简单的键值加密存储库
340 | * [True Random](https://github.com/pixeloution/true-random) - 使用[www.random.org](https://www.random.org/)生成随机数的库
341 | * [VAddy](https://vaddy.net/) - 一个持续安全的web应用测试平台
342 | * [Zed](https://www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project) - 一个集成的web应用渗透测试工具
343 |
344 | ## 密码 Passwords
345 | *处理和存储密码的库和工具*
346 |
347 | * [GenPhrase](https://github.com/timoh6/GenPhrase) - 一个随机生成安全密码哈希的库
348 | * [Password Compat](https://github.com/ircmaxell/password_compat) - 一个新的PHP5.5密码函数的兼容库
349 | * [Password Policy](https://github.com/ircmaxell/password-policy) - 一个PHP和JavaScript的密码策略库
350 | * [Password Validator](https://github.com/jeremykendall/password-validator) - 一个校验和升级密码哈希的库
351 | * [Password-Generator](https://github.com/hackzilla/password-generator) - 一个生成随机密码的PHP库
352 | * [PHP Password Lib](https://github.com/ircmaxell/PHP-PasswordLib) - 一个生成和校验密码的库
353 | * [phpass](http://www.openwall.com/phpass/) - 一个便携式的密码哈希框架
354 | * [Zxcvbn PHP](https://github.com/bjeavons/zxcvbn-php) - 一个基于Zxcvbn JS的现实的PHP密码强度估计库
355 |
356 | ## 代码分析 Code Analysis
357 | *分析,解析和处理代码库的库和工具*
358 |
359 | * [Athletic](https://github.com/polyfractal/athletic) - 一个基于注释的基准检测库
360 | * [Better Reflection](https://github.com/Roave/BetterReflection) - 基于AST的反射库,允许分析操作代码
361 | * [Code Climate](https://codeclimate.com) - 一个自动代码审查工具
362 | * [Dissect](https://github.com/jakubledl/dissect) - 一个词法和语法分析的工具集合
363 | * [Exakat](https://github.com/exakat/exakat) - 一个PHP的静态分析引擎
364 | * [GrumPHP](https://github.com/phpro/grumphp) - 一个用来保护代码质量的Composer插件
365 | * [Mondrian](https://github.com/Trismegiste/Mondrian) - 使用图论的代码分析工具
366 | * [PHP Analyser](https://github.com/scrutinizer-ci/php-analyzer) - 一个分析PHP代码查找缺陷和错误的库
367 | * [PHP Code Sniffer](https://github.com/squizlabs/PHP_CodeSniffer) - 一个检测PHP、CSS和JS代码标准冲突的库
368 | * [PHP CS Fixer](https://github.com/FriendsOfPHP/PHP-CS-Fixer) - 一个编码标准库
369 | * [PHP Manipulator](https://github.com/schmittjoh/php-manipulator) - 一个分析和修改PHP源代码的库
370 | * [PHP Mess Detector](https://phpmd.org/) - 一个扫描代码缺陷,次优代码,未使用的参数等等的库。
371 | * [PHP Metrics](https://github.com/phpmetrics/PhpMetrics) - 一个静态测量库
372 | * [PHP Migration](https://github.com/monque/PHP-Migration) - 一个PHP版本升级的静态分析库
373 | * [PHP Parser](https://github.com/nikic/PHP-Parser) - 一个PHP编写的PHP解析器
374 | * [PHP Refactoring Browser](https://github.com/QafooLabs/php-refactoring-browser) - 一个重构PHP代码的命令行工具集
375 | * [PHP Semantic Versioning Checker](https://github.com/tomzx/php-semver-checker) - 一个比较两个源集和确定适当的应用语义版本的命令行实用程序
376 | * [phan](https://github.com/etsy/phan) - 一个基于PHP 7+和php-ast扩展的静态分析器
377 | * [PHPCheckstyle](https://github.com/PHPCheckstyle/phpcheckstyle) - 一个帮助遵守特定的编码惯例的工具
378 | * [PHPCPD](https://github.com/sebastianbergmann/phpcpd) - 一个检测复制和粘贴代码的库
379 | * [PhpDependencyAnalysis](https://github.com/mamuz/PhpDependencyAnalysis) - 一个创建可定制依赖图的工具
380 | * [PHPLOC](https://github.com/sebastianbergmann/phploc) - 一个快速测量PHP项目大小的工具
381 | * [PHPQA](https://github.com/EdgedesignCZ/phpqa) - 一个用于运行质量保证工具的工具(phploc, phpcpd, phpcs, pdepend, phpmd, phpmetrics).
382 | * [PHPPHP](https://github.com/ircmaxell/PHPPHP) - 一个PHP实现的PHP虚拟机
383 | * [PHPSandbox](https://github.com/Corveda/PHPSandbox) - 一个PHP沙盒环境
384 | * [PHPStan](https://github.com/phpstan/phpstan) - 一个PHP静态分析工具
385 | * [Qafoo Quality Analyzer](https://github.com/Qafoo/QualityAnalyzer) - 一个可视化指标和源代码的工具
386 | * [Scrutinizer](https://scrutinizer-ci.com/) - 一个审查PHP代码的web工具
387 | * [UBench](https://github.com/devster/ubench) - 一个简单的微型基准检测库
388 |
389 | ## Architectural Architectural
390 | *相关的设计模式库,组织代码编程的方法和途径*
391 |
392 | * [Compose](https://github.com/igorw/compose) - 一个功能组合库
393 | * [Design Patterns PHP](https://github.com/domnikl/DesignPatternsPHP) - 一个使用PHP实现的设计模式存储库
394 | * [Finite](http://yohan.giarel.li/Finite/) - 一个简单的PHP有限状态机
395 | * [Functional PHP](https://github.com/lstrojny/functional-php) - 一个函数式编程库
396 | * [Galapagos](https://github.com/endel/galapagos) - 语言转换进化
397 | * [Iter](https://github.com/nikic/iter) - 一个使用生成器提供迭代原语的库
398 | * [Monad PHP](https://github.com/ircmaxell/monad-php) - 一个简单Monad库
399 | * [Patchwork](http://patchwork2.org/) - 一个重新定义用户的函数库
400 | * [PHP Option](https://github.com/schmittjoh/php-option) - 一个可选的类型库
401 | * [Pipeline](https://github.com/thephpleague/pipeline) - 一个管道模式的实现
402 | * [Ruler](https://github.com/bobthecow/Ruler) - 一个简单的无状态的生产环境规则引擎
403 | * [RulerZ](https://github.com/K-Phoen/rulerz) - 一个强大的规则引擎和规范模式的实现
404 |
405 | ## 调试和分析 Debugging and Profiling
406 | *调试和分析代码的库和工具*
407 |
408 | * [APM](http://pecl.php.net/package/APM) - 一个收集SQLite/MySQL/StatsD错误信息和统计信息的监控扩展
409 | * [Barbushin PHP Console](https://github.com/barbushin/php-console) - 另一个使用Google Chrome的web调试控制台
410 | * [Blackfire.io](https://blackfire.io) - 一个低开销的代码分析器
411 | * [Kint](https://github.com/raveren/kint) - 一个调试和分析工具
412 | * [PHP Console](https://github.com/Seldaek/php-console) - 一个web调试控制台
413 | * [PHP Debug Bar](http://phpdebugbar.com/) - 一个调试工具栏
414 | * [PHPBench](https://github.com/phpbench/phpbench) - 一个基准测试框架
415 | * [PHPDBG](http://phpdbg.com/) - 一个交互的PHP调试器
416 | * [Tideways.io](https://tideways.io/) - Monitoring and profiling tool
417 | * [Tracy](https://github.com/nette/tracy) - A一个简单的错误检测,写日志和时间测量库
418 | * [xDebug](https://github.com/xdebug/xdebug) - 一个调试和分析PHP的工具
419 | * [XHProf](https://github.com/phacility/xhprof) - 一个最初由Facebook开发的分析工具
420 | * [Z-Ray](http://www.zend.com/en/products/server/z-ray) - 一个调试和配置Zend服务器的工具
421 |
422 | ## 构建工具 Build Tools
423 | *项目构建和自动化工具*
424 |
425 | * [Bob](https://github.com/CHH/bob) - 一个简单的项目自动化工具
426 | * [Box](https://github.com/box-project/box2) - 一个构建PHAR文件的工具
427 | * [Construct](https://github.com/jonathantorres/construct) - 一个PHP项目的生成器
428 | * [Phake](https://github.com/jaz303/phake) - 一个PHP克隆库
429 | * [Phing](https://www.phing.info/) - 一个灵感来自于Apache Ant的PHP项目构建系统
430 |
431 | ## 任务运行器 Task Runners
432 | *自动运行任务的库*
433 |
434 | * [Bldr](http://bldr.io/) - 一个构建在Symfony组件上的PHP任务运行器
435 | * [Jobby](https://github.com/jobbyphp/jobby) - 一个没有修改crontab的PHP定时任务管理器
436 | * [Robo](https://github.com/consolidation/Robo) - 一个面向对象配置的PHP任务运行器
437 | * [Task](http://taskphp.github.io/) - 一个灵感来源于Grunt和Gulp的纯PHP任务运行器
438 |
439 | ## 导航 Navigation
440 | *构建导航结构的工具*
441 |
442 | * [Cartographer](https://github.com/tackk/cartographer) - 一个站点地图生成库
443 | * [KnpMenu](https://github.com/KnpLabs/KnpMenu) - 一个菜单库
444 |
445 | ## 资源管理 Asset Management
446 | *管理,压缩和最小化web站点资源的工具*
447 |
448 | * [Assetic](https://github.com/kriswallsmith/assetic) - 一个资源管理的管道库
449 | * [JShrink](https://github.com/tedious/JShrink) - 一个JavaScript的最小化库
450 | * [Munee](https://github.com/meenie/munee) - 一个资源优化库
451 | * [Pipe](https://github.com/CHH/pipe) - 另一个资源管理的管道库
452 | * [Puli](https://github.com/puli/repository) - 一个检测资源绝对路径的库
453 | * [BowerPHP](https://github.com/Bee-Lab/bowerphp) - Bower的一个PHP实现,一个web包管理工具
454 |
455 | ## 地理位置 Geolocation
456 | *地理编码地址和使用纬度经度的库*
457 |
458 | * [GeoCoder](http://geocoder-php.org/) - 一个地理编码库
459 | * [GeoJSON](https://github.com/jmikola/geojson) - 一个GeoJSON的实现
460 | * [GeoTools](https://github.com/thephpleague/geotools) - 一个地理工具相关的库
461 | * [PHPGeo](https://github.com/mjaschen/phpgeo) - 一个简单的地理库
462 |
463 | ## 日期和时间 Date and Time
464 | *处理日期和时间的库*
465 |
466 | * [CalendR](http://yohan.giarel.li/CalendR/) - 一个日历管理库
467 | * [Carbon](https://github.com/briannesbitt/Carbon) - 一个简单的日期时间API扩展
468 | * [Chronos](https://github.com/cakephp/chronos) - 一个支持可变和不可变日期时间的DateTime API扩展
469 | * [ExpressiveDate](https://github.com/jasonlewis/expressive-date) - 另一个日期时间API扩展
470 | * [Moment.php](https://github.com/fightbulc/moment.php) - 灵感来源于Moment.js的PHP DateTime处理库,支持国际化
471 |
472 | ## 事件 Event
473 | *时间驱动或实现非阻塞事件循环的库*
474 |
475 | * [Amp](https://github.com/amphp/amp) - 一个事件驱动的不阻塞的I/O库
476 | * [Broadway](https://github.com/broadway/broadway) - 一个事件源和CQRS(命令查询责任分离)库
477 | * [Cake Event](https://github.com/cakephp/event) - 一个事件调度的库 (CP)
478 | * [Elephant.io](https://github.com/Wisembly/Elephant.io) - 另一个web socket库
479 | * [Evenement](https://github.com/igorw/evenement) - 一个事件调度的库
480 | * [Event](https://github.com/thephpleague/event) - 一个专注于域名事件的库
481 | * [Hoa EventSource](https://github.com/hoaproject/Eventsource) - 一个事件源库
482 | * [Hoa WebSocket](https://github.com/hoaproject/Websocket) - 另一个web socket库
483 | * [Icicle](https://github.com/icicleio/icicle) - 一个支持协同,非阻塞I/O,多线程的异步库
484 | * [Prooph Event Store](https://github.com/prooph/event-store) - 一个持久化事件消息的事件源组件
485 | * [Ratchet](https://github.com/ratchetphp/Ratchet) - 一个web socket库
486 | * [React](https://github.com/reactphp/react) - 一个事件驱动的非阻塞I/O库.
487 | * [Rx.PHP](https://github.com/asm89/Rx.PHP) - 一个reactive扩展库
488 | * [Workerman](https://github.com/walkor/Workerman) - 一个事件驱动的不阻塞的I/O库
489 |
490 | ## 日志 Logging
491 | *生成和处理日志文件的库*
492 |
493 | * [Analog](https://github.com/jbroadway/analog) - 一个基于闭包的微型日志包
494 | * [KLogger](https://github.com/katzgrau/KLogger) - 一个易用的兼容PSR-3的日志类
495 | * [Monolog](https://github.com/Seldaek/monolog) - 一个全面的日志工具
496 |
497 | ## 电子商务 E-commerce
498 | *处理支付和构建在线电子商务商店的库和应用*
499 |
500 | * [Money](https://github.com/moneyphp/money) - 一个Fowler金钱模式的PHP实现
501 | * [OmniPay](https://github.com/thephpleague/omnipay) - 一个框架混合了多网关支付处理的库
502 | * [Payum](https://github.com/payum/payum) - 一个支付抽象库
503 | * [Shopware](https://github.com/shopware/shopware) - 一个可高度定制的电子商务软件
504 | * [Swap](https://github.com/florianv/swap) - 一个汇率库
505 | * [Sylius](http://sylius.org/) - 一个开源的电子商务解决方案
506 |
507 | ## PDF PDF
508 | *处理PDF文件的库和软件*
509 |
510 | * [Dompdf](https://github.com/dompdf/dompdf) - 一个将HTML转换为PDF的工具
511 | * [PHPPdf](https://github.com/psliwa/PHPPdf) - 一个将XML文件转换为PDF和图片的库
512 | * [Snappy](https://github.com/KnpLabs/snappy) - 一个PDF和图像生成器库
513 | * [WKHTMLToPDF](https://github.com/wkhtmltopdf/wkhtmltopdf) - 一个将HTML转换为PDF的工具
514 |
515 | ## Office Office
516 | *Libraries for working with office suite documents.*
517 |
518 | * [ExcelAnt](https://github.com/Wisembly/ExcelAnt) - 一个操作Excel文档的库
519 | * [PHPPowerPoint](https://github.com/PHPOffice/PHPPresentation) - 一个处理PPT文档的库
520 | * [PHPWord](https://github.com/PHPOffice/PHPWord) - 一个处理Word文档的库
521 | * [PHPSpreadsheet](https://github.com/PHPOffice/PhpSpreadsheet) - 一个纯PHP的读写电子表格的库 (successor of PHPExcel)
522 |
523 | ## 数据库 Database
524 | *使用对象关系映射(ORM)或数据映射技术的数据库交互的库*
525 |
526 | * [Baum](https://github.com/etrepat/baum) - 一个Eloquent的嵌套集实现
527 | * [Cake ORM](https://github.com/cakephp/orm) - 对象关系映射工具,利用DataMapper模式实现 (CP)
528 | * [Doctrine Extensions](https://github.com/Atlantic18/DoctrineExtensions) - 一个Doctrine行为扩展的集合
529 | * [Doctrine](http://www.doctrine-project.org/) - 一个全面的DBAL和ORM
530 | * [Eloquent](https://github.com/illuminate/database) - 一个简单的ORM(L5)
531 | * [LazyRecord](https://github.com/corneltek/LazyRecord) - 一个简单、可扩展、高性能的ORM
532 | * [Pomm](https://github.com/chanmix51/Pomm) - 一个PostgreSQL对象模型管理器
533 | * [Propel](http://propelorm.org/) - 一个快速的ORM,迁移库和查询构架器
534 | * [ProxyManager](https://github.com/Ocramius/ProxyManager) - 一个为数据映射生成代理对象的工具集
535 | * [RedBean](http://redbeanphp.com/index.php) - 一个轻量级,低配置的ORM
536 | * [Spot2](https://github.com/vlucas/spot2) - 一个MySQL的ORM映射器
537 |
538 | ## 迁移 Migrations
539 | *帮助管理数据库模式和迁移的库*
540 |
541 | * [Doctrine Migrations](http://docs.doctrine-project.org/projects/doctrine-migrations/en/latest/toc.html) - 一个Doctrine的迁移库
542 | * [Migrations](https://github.com/icomefromthenet/Migrations) - 一个迁移管理库
543 | * [Phinx](https://github.com/robmorgan/phinx) - 另一个数据库迁移的管理库
544 | * [PHPMig](https://github.com/davedevelopment/phpmig) - 另一个迁移管理库
545 | * [Ruckusing](https://github.com/ruckus/ruckusing-migrations) - 基于PHP下ActiveRecord的数据库迁移,支持MySQL, Postgres, SQLite
546 |
547 | ## NoSQL NoSQL
548 | *处理NoSQL后端的库*
549 |
550 | * [Monga](https://github.com/thephpleague/monga) - 一个MongoDB抽象库
551 | * [MongoQB](https://github.com/alexbilbie/MongoQB) - 一个MongoDB查询构建库
552 | * [PHPMongo](https://github.com/sokil/php-mongo) - 一个MongoDB ORM.
553 | * [Predis](https://github.com/nrk/predis) - 一个功能完整的Redis库
554 |
555 | ## 队列 Queue
556 | *处理事件和任务队列的库*
557 |
558 | * [Bernard](https://github.com/bernardphp/bernard) - 一个多后端抽象库
559 | * [BunnyPHP](https://github.com/jakubkulhan/bunny) - 一个高性能的纯PHP AMQP(RabbitMQ)同步和异步(ReactPHP)库
560 | * [Pheanstalk](https://github.com/pda/pheanstalk) - 一个Beanstalkd客户端库
561 | * [PHP AMQP](https://github.com/php-amqplib/php-amqplib) - 一个纯PHP AMQP库
562 | * [Tarantool Queue](https://github.com/tarantool-php/queue) - PHP绑定Tarantool队列
563 | * [Thumper](https://github.com/php-amqplib/Thumper) - 一个RabbitMQ模式库
564 |
565 | ## 搜索 Search
566 | *在数据上索引和执行查询的库和软件*
567 |
568 | * [Elastica](https://github.com/ruflin/Elastica) - ElasticSearch的客户端库
569 | * [ElasticSearch PHP](https://github.com/elastic/elasticsearch-php) - [ElasticSearch](https://www.elastic.co/)的官方客户端库
570 | * [Solarium](http://www.solarium-project.org/) - [Solr](http://lucene.apache.org/solr/)的客户端库
571 | * [Sphinx Search](https://github.com/ripaclub/sphinxsearch) - Sphinx搜索库,提供SphinxQL索引和搜索的功能
572 | * [SphinxQL query builder](http://foolcode.github.io/SphinxQL-Query-Builder/) - [Sphinx](http://sphinxsearch.com/)搜索引擎的的查询库
573 |
574 | ## 命令行 Command Line
575 | *关于命令行工具的库*
576 |
577 | * [Boris](https://github.com/borisrepl/boris) - 一个微型PHP REPL
578 | * [Cilex](https://github.com/Cilex/Cilex) - 一个构建命令行工具的微型框架
579 | * [CLI Menu](https://github.com/php-school/cli-menu) - 一个构建CLI菜单的库
580 | * [CLIFramework](https://github.com/c9s/CLIFramework) - 一个支持完全zsh/bash、子命令和选项约束的命令行框架,这也归功于phpbrew
581 | * [CLImate](https://github.com/thephpleague/climate) - 一个输出带颜色的和特殊格式的命令行库
582 | * [Commando](https://github.com/nategood/commando) - 另一个简单的命令行选择解析器
583 | * [Cron Expression](https://github.com/mtdowling/cron-expression) - 一个计算cron运行日期的库
584 | * [GetOpt](https://github.com/ulrichsg/getopt-php) - 一个命令行选择解析器
585 | * [GetOptionKit](https://github.com/c9s/GetOptionKit) - 另一个命令行选择解析器
586 | * [Hoa Console](https://github.com/hoaproject/Console) - 另一个命令行库
587 | * [OptParse](https://github.com/CHH/optparse) - 另一个命令行选择解析器
588 | * [Pecan](https://github.com/mcrumm/pecan) - 一个事件驱动和非阻塞的shell
589 | * [PsySH](https://github.com/bobthecow/psysh) - 另一个PHP REPL
590 | * [ShellWrap](https://github.com/MrRio/shellwrap) - -一个简单的命令行包装库
591 | * [Shunt](https://github.com/thephpleague/shunt) - 一个在多台远程机器上并行运行命令行的库
592 |
593 | ## 身份验证和授权 Authentication and Authorization
594 | *实现身份验证和授权的库*
595 |
596 | * [Hawk](https://github.com/dflydev/dflydev-hawk) - 一个Hawk HTTP身份认证库
597 | * [HybridAuth](https://github.com/hybridauth/hybridauth) - 一个开源的社交登陆库
598 | * [Json Web Token](https://github.com/lcobucci/jwt) - 使用JSON Tokens进行身份验证和信息传输
599 | * [Lock](https://github.com/BeatSwitch/lock) - 一种实现访问控制列表(ACL)系统的库
600 | * [OAuth 1.0 Client](https://github.com/thephpleague/oauth1-client) - 一个OAuth 1.0客户端的库
601 | * [OAuth 2.0 Client](https://github.com/thephpleague/oauth2-client) - 一个OAuth 2.0客户端的库
602 | * [OAuth2 Server](http://bshaffer.github.io/oauth2-server-php-docs/) - 另一个OAuth2服务器实现
603 | * [OAuth2 Server](http://oauth2.thephpleague.com/) - 另一个OAuth2服务器实现
604 | * [Opauth](https://github.com/opauth/opauth) - 一个多渠道的身份验证框架
605 | * [PHP oAuthLib](https://github.com/Lusitanian/PHPoAuthLib) - 另一个OAuth库
606 | * [Sentinel Social](https://cartalyst.com/manual/sentinel-social/2.0) - 一个社交网络身份验证库
607 | * [Sentinel](https://cartalyst.com/manual/sentinel/2.0) - 一个混合的身份验证和授权的框架库
608 | * [TwitterOAuth](https://github.com/ruudk/twitteroauth) - 一个Twitter OAuth库
609 | * [TwitterSDK](https://github.com/lyrixx/twitter-sdk) - 一个完全测试的Twitter SDK
610 |
611 | ## 标记 Markup
612 | *处理标记的库*
613 |
614 | * [Cebe Markdown](https://github.com/cebe/markdown) - 一个快速的可扩展的Markdown解析器
615 | * [Ciconia](https://github.com/kzykhys/Ciconia) - 另一个支持Github Markdown风格的Markdown解析器
616 | * [CommonMark PHP](https://github.com/thephpleague/commonmark) - 一个对[CommonMark spec](http://spec.commonmark.org/)全支持的Markdown解析器
617 | * [Decoda](https://github.com/milesj/decoda) - 一个轻量级标记解析库
618 | * [Emoji](https://github.com/heyupdate/Emoji) - 一个把Unicode字符和名称转换为表情符号图片的库
619 | * [HTML to Markdown](https://github.com/thephpleague/html-to-markdown) - 将HTML转化为Markdown
620 | * [HTML5 PHP](https://github.com/Masterminds/html5-php) - 一个HTML5解析和序列化库
621 | * [Parsedown](https://github.com/erusev/parsedown) - 另一个Markdown解析器
622 | * [PHP Markdown](https://github.com/michelf/php-markdown) - 一个Markdown解析器
623 |
624 | ## 字符串 Strings
625 | *解析和处理字符串的库*
626 |
627 | * [Agent](https://github.com/jenssegers/agent) - 一个基于Mobiledetect的桌面/手机端user agent解析库
628 | * [ANSI to HTML5](https://github.com/sensiolabs/ansi-to-html) - 一个将ANSI转化为HTML5的库
629 | * [Color Jizz](https://github.com/mikeemoo/ColorJizz-PHP) - 处理和转换颜色的库
630 | * [Device Detector](https://github.com/piwik/device-detector) - 另一个解析user agent字符串的库
631 | * [Hoa String](https://github.com/hoaproject/Ustring) - 另一个UTF-8字符串库
632 | * [Jieba-PHP](https://github.com/fukuball/jieba-php) - Python的jieba的PHP端口,自然语言处理的中文文本分词
633 | * [Mobile-Detect](https://github.com/serbanghita/Mobile-Detect) - 一个用于检测移动设备的轻量级PHP类(包括平板电脑)
634 | * [Patchwork UTF-8](https://github.com/nicolas-grekas/Patchwork-UTF8) - 一个处理UTF-8字符串的便携库
635 | * [Slugify](https://github.com/cocur/slugify) - 转换字符串到slug的库
636 | * [SQL Formatter](https://github.com/jdorn/sql-formatter/) - 一个格式化SQL语句的库
637 | * [Stringy](https://github.com/danielstjules/Stringy) - 一个多字节支持的字符串处理库
638 | * [Text](https://github.com/kzykhys/Text) - 一个文本处理库
639 | * [UA Parser](https://github.com/tobie/ua-parser/tree/master/php) - 一个解析user agent字符串的库
640 | * [URLify](https://github.com/jbroadway/urlify) - 一个Django中URLify.js的PHP版本
641 | * [UUID](https://github.com/ramsey/uuid) - 生成UUIDs的库
642 |
643 | ## 数字 Numbers
644 | *处理数字的库*
645 |
646 | * [ByteUnits](https://github.com/gabrielelana/byte-units) - 一个在二进制和度量系统中解析,格式化和转换字节单元的库
647 | * [LibPhoneNumber for PHP](https://github.com/giggsey/libphonenumber-for-php) - 一个Google电话号码处理的PHP实现库
648 | * [Math](https://github.com/moontoast/math) - 一个处理巨大数字的库
649 | * [Numbers PHP](https://github.com/powder96/numbers.php) - 一个处理数字的库
650 | * [PHP Conversion](https://github.com/Crisu83/php-conversion) - 另一个用于度量单位间转换的库
651 | * [PHP Units of Measure](https://github.com/triplepoint/php-units-of-measure) - 一个计量单位转换的库
652 |
653 | ## 过滤和验证 Filtering and Validation
654 | *过滤和验证数据的库*
655 |
656 | * [Cake Validation](https://github.com/cakephp/validation) - 另一个验证库 (CP)
657 | * [DMS Filter](https://github.com/rdohms/DMS-Filter) - 一个注释过滤库
658 | * [Filterus](https://github.com/ircmaxell/filterus) - 一个简单的PHP过滤库
659 | * [ISO-codes](https://github.com/ronanguilloux/IsoCodes) - 一个验证各种ISO和ZIP编码的库(IBAN, SWIFT/BIC, BBAN, VAT, SSN, UKNIN)
660 | * [MetaYaml](https://github.com/romaricdrigon/MetaYaml) - 一个支持YAML,JSON和XML的模式验证库
661 | * [Respect Validation](https://github.com/Respect/Validation) - 一个简单的验证库
662 | * [Upload](https://github.com/brandonsavage/Upload) - 一个处理文件上传和验证的库
663 | * [Valitron](https://github.com/vlucas/valitron) - 另一个验证库
664 | * [Volan](https://github.com/serkin/Volan) - 另一个简单的验证库
665 |
666 | ## API API
667 | *开发REST-ful API的库和web工具*
668 |
669 | * [API Platform](https://api-platform.com ) - 暴露出REST API的项目,包含JSON-LD, Hydra格式
670 | * [Apigility](https://github.com/zfcampus/zf-apigility-skeleton) - 一个使用Zend Framework 2构建的API构建器
671 | * [Drest](https://github.com/leedavis81/drest) - 一个将Doctrine实体暴露为REST资源节点的库
672 | * [HAL](https://github.com/blongden/hal) - 一个超文本应用语言(HAL)构建库
673 | * [Hateoas](https://github.com/willdurand/Hateoas) - 一个HOATEOAS REST web服务库
674 | * [Negotiation](https://github.com/willdurand/Negotiation) - 一个内容协商库
675 | * [Restler](https://github.com/Luracast/Restler) - 一个将PHP方法暴露为RESTful web API的轻量级框架
676 | * [wsdl2phpgenerator](https://github.com/wsdl2phpgenerator/wsdl2phpgenerator) - 一个从SOAP WSDL文件生成PHP类的工具
677 |
678 | ## 缓存 Caching
679 | *缓存数据的库*
680 |
681 | * [Alternative PHP Cache (APC)](http://php.net/manual/en/book.apc.php) - 打开PHP操作码缓存
682 | * [APIx Cache](https://github.com/frqnck/apix-cache) - 一个轻量级的PSR-6缓存
683 | * [CacheTool](https://github.com/gordalina/cachetool) - 一个使用命令行清除apc/opcode缓存的工具
684 | * [Cake Cache](https://github.com/cakephp/cache) - 一个缓存库 (CP)
685 | * [Doctrine Cache](https://github.com/doctrine/cache) - 一个缓存库
686 | * [Metaphore](https://github.com/sobstel/metaphore) - 一个缓存失效防范的库,使用信号标记阻止dogpile影响
687 | * [Stash](https://github.com/tedious/Stash) - 另一个缓存库
688 | * [Zend Cache](https://github.com/zendframework/zend-cache) - 另一个缓存库 (ZF2)
689 |
690 | ## 数据结构和存储 Data Structure and Storage
691 | *实现数据结构和存储技术的库*
692 |
693 | * [Ardent](https://github.com/morrisonlevi/Ardent) - 一个数据结构库
694 | * [Cake Collection](https://github.com/cakephp/collection) - 一个简单的集合库 (CP)
695 | * [Collections](https://github.com/italolelis/collections) - 一个PHP的集合抽象库
696 | * [Fractal](https://github.com/thephpleague/fractal) - 一个转换复杂数据结构到JSON输出的库
697 | * [Ginq](https://github.com/akanehara/ginq) - 另一个基于.NET实现的PHP的LINQ库
698 | * [JsonMapper](https://github.com/cweiske/jsonmapper) - 一个将内嵌JSON结构映射为PHP类的库
699 | * [Knapsack](https://github.com/DusanKasan/Knapsack) - 一个集合的库,灵感来自Clojure的相关库
700 | * [PHP Collections](https://github.com/schmittjoh/php-collection) - 一个简单的集合库
701 | * [PINQ](https://github.com/TimeToogo/Pinq) - 一个基于.NET实现的PHP的LINQ(Language Integrated Query)库
702 | * [Porter](https://github.com/ScriptFUSION/Porter) - 数据导入的抽象框架
703 | * [Serializer](https://github.com/schmittjoh/serializer) - 一个序列化和反序列化数据的库
704 | * [Totem](https://github.com/Wisembly/Totem) - -一个管理和创建数据交换集的库
705 | * [YaLinqo](https://github.com/Athari/YaLinqo) - 另一个PHP的LINQ库
706 | * [Zend Serializer](https://github.com/zendframework/zend-serializer) - 另一个序列化和反序列化数据的库 (ZF2)
707 |
708 | ## 通知 Notifications
709 | *处理通知软件的库*
710 |
711 | * [JoliNotif](https://github.com/jolicode/JoliNotif) - 一个跨平台的桌面通知库(支持Growl, notify-send, toaster等)
712 | * [Nod](https://github.com/filp/nod) - 一个通知库(Growl等)
713 | * [Notification Pusher](https://github.com/Ph3nol/NotificationPusher) - 一个设备推送通知的独立库
714 | * [Notificato](https://github.com/mac-cain13/notificato) - 一个处理推送通知的库
715 | * [Notificator](https://github.com/namshi/notificator) - 一个轻量级的通知库
716 | * [Php-pushwoosh](https://github.com/gomoob/php-pushwoosh) - 一个使用Pushwoosh REST Web服务轻松推送通知的PHP库
717 |
718 | ## 部署 Deployment
719 | *项目部署库*
720 |
721 | * [Deployer](https://github.com/deployphp/deployer) - 一个部署工具
722 | * [Envoy](https://github.com/laravel/envoy) - 一个用PHP运行SSH任务的工具
723 | * [Plum](https://github.com/aerialls/Plum) - 一个部署库
724 | * [Pomander](https://github.com/tamagokun/pomander) - 一个PHP应用部署工具
725 | * [Rocketeer](https://github.com/rocketeers/rocketeer) - PHP世界里的一个快速简单的部署器
726 |
727 | ## 国际化和本地化 Internationalisation and Localisation
728 | *国际化(I18n)和本地化(L10n)的库*
729 |
730 | * [Cake I18n](https://github.com/cakephp/i18n) - 消息国际化和日期和数字的本地化 (CP)
731 |
732 | ## 第三方API Third Party APIs
733 | *访问第三方API的库*
734 |
735 | * [Amazon Web Service SDK](https://github.com/aws/aws-sdk-php) - PHP AWS SDK官方库
736 | * [Campaign Monitor](http://campaignmonitor.github.io/createsend-php/) - Campaign Monitor官方PHP库
737 | * [Digital Ocean](https://github.com/toin0u/DigitalOcean) - Digital Ocean API接口库
738 | * [Dropbox SDK](https://github.com/dropbox/dropbox-sdk-php) - Dropbox SDK官方PHP库
739 | * [Github](https://github.com/dsyph3r/github-api3-php) - 一个Github API交互库
740 | * [PHP Github API](https://github.com/KnpLabs/php-github-api) - 另一个Github API交互库
741 | * [S3 Stream Wrapper](https://github.com/gwkunze/S3StreamWrapper) - Amazon S3流包装库
742 | * [Stripe](https://github.com/stripe/stripe-php) - Stripe官方PHP库
743 | * [Twilio](https://github.com/twilio/twilio-php) - Twilio官方PHP REST API
744 | * [Twitter OAuth](https://github.com/widop/twitter-oauth) - 一个Twitter OAuth工作流交互库
745 | * [Twitter REST](https://github.com/widop/twitter-rest) - 一个Twitter REST API交互库
746 |
747 | ## 扩展 Extensions
748 | *帮助构建PHP扩展的库*
749 |
750 | * [PHP CPP](http://www.php-cpp.com/) - 一个开发PHP扩展的C++库
751 | * [Zephir](https://github.com/phalcon/zephir) - 用于开发PHP扩展,且介于PHP和C++之间的编译语言
752 |
753 | ## 杂项 Miscellaneous
754 | *创建一个开发环境的软件*
755 |
756 | * [Annotations](https://github.com/doctrine/annotations) - 一个注释库(Doctrine的一部分)
757 | * [Cake Utility](https://github.com/cakephp/utility) - 工具类如Inflector,字符串,哈希,安全和XML (CP)
758 | * [Chief](https://github.com/adamnicholson/Chief) - 一个命令总线库
759 | * [ClassPreloader](https://github.com/ClassPreloader/ClassPreloader) - 一个优化自动加载的库
760 | * [Country List](https://github.com/umpirsky/country-list) - 所有带有名称和ISO 3166-1编码的国家列表
761 | * [Embera](https://github.com/mpratt/Embera) - 一个Oembed消费库
762 | * [Essence](https://github.com/essence/essence) - 一个用于提取网络媒体的库
763 | * [Flux](https://github.com/selvinortiz/flux) - 一个正则表达式构建库
764 | * [Graphviz](https://github.com/alexandresalome/graphviz) - 一个图形库
765 | * [Hprose-PHP](https://github.com/hprose/hprose-php) - 一个很牛的RPC库,现在支持25+种语言
766 | * [JSON Lint](https://github.com/Seldaek/jsonlint) - 一个JSON lint工具
767 | * [JSONPCallbackValidator](https://github.com/willdurand/JsonpCallbackValidator) - 验证JSONP回调的库
768 | * [Jumper](https://github.com/kakawait/Jumper) - 一个远程服务执行库
769 | * [LadyBug](https://github.com/raulfraile/Ladybug) - 一个dumper库
770 | * [Lambda PHP](https://github.com/igorw/lambda-php) - 一个PHP中的Lambda计算解析器
771 | * [LiteCQRS](https://github.com/beberlei/litecqrs-php) - 一个CQRS(命令查询责任分离)库
772 | * [Metrics](https://github.com/beberlei/metrics) - 一个简单的度量API库
773 | * [noCAPTCHA](https://github.com/ARCANEDEV/noCAPTCHA) - 一个帮助使用谷歌noCAPTCHA (reCAPTCHA)的工具
774 | * [Nmap](https://github.com/willdurand/nmap) - 一个[Nmap](https://nmap.org/) PHP包装器
775 | * [Opengraph](https://github.com/euskadi31/Opengraph) - 一个开放图库
776 | * [Pagerfanta](https://github.com/whiteoctober/Pagerfanta) - 一个分页库
777 | * [PHP Expression](https://github.com/Kitano/php-expression) - 一个PHP表达式语言
778 | * [PHP PassBook](https://github.com/eymengunay/php-passbook) - 一个iOS PassBook PHP库
779 | * [PHP-GPIO](https://github.com/ronanguilloux/php-gpio) - 一个用于Raspberry PI的GPIO pin的库
780 | * [PHP-ML](https://github.com/php-ai/php-ml) - 一个机器学习的PHP库
781 | * [PHPCR](https://github.com/phpcr/phpcr) - 一个Java内容存储库(JCR)的PHP实现
782 | * [PHPStack](http://dunkels.com/adam/phpstack/) - 一个PHP编写的TCP/IP栈概念
783 | * [print_o](https://github.com/koriym/print_o) - 一个对象图的可视化器
784 | * [Procrastinator](https://github.com/lstrojny/Procrastinator) - 一个运行耗时任务的库
785 | * [Prooph Service Bus](https://github.com/prooph/service-bus) - 轻量级的消息总线,支持CQRS和微服务
786 | * [RMT](https://github.com/liip/RMT) - 一个编写版本和发布软件的库
787 | * [sabre/vobject](https://github.com/fruux/sabre-vobject) - 一个解析VCard和iCalendar对象的库
788 | * [Slimdump](https://github.com/webfactory/slimdump) - 一个简单的MySQL dumper工具
789 | * [Spork](https://github.com/kriswallsmith/spork) - 一个处理forking的库
790 | * [Sslurp](https://github.com/EvanDotPro/Sslurp) - 一个使得SSL处理减少的库
791 | * [SuperClosure](https://github.com/jeremeamia/super_closure) - 一个允许闭包序列化的库
792 | * [Symfony VarDumper](http://symfony.com/doc/current/components/var_dumper/introduction.html) - 一个dumper库(SF2)
793 | * [Underscore](http://anahkiasen.github.io/underscore-php/) - 一个Undersccore JS库的PHP实现
794 | * [Whoops](https://github.com/filp/whoops) - 一个不错的错误处理库
795 |
796 | ## PHP安装 PHP Installation
797 | *在你的电脑上帮助安装和管理PHP的工具*
798 |
799 | * [HomeBrew PHP](https://github.com/Homebrew/homebrew-php) - 一个HomeBrew的PHP通道
800 | * [HomeBrew](http://brew.sh/) - 一个OSX包管理器
801 | * [PHP Brew](https://github.com/phpbrew/phpbrew) - 一个PHP版本管理和安装器
802 | * [PHP Build](https://github.com/php-build/php-build) - 另一个PHP版本安装器
803 | * [PHP Env](https://github.com/CHH/phpenv) - 另一个PHP版本管理器
804 | * [PHP OSX](https://php-osx.liip.ch/) - 一个OSX下的PHP安装器
805 | * [PHP Switch](https://github.com/jubianchi/phpswitch) - 另一个PHP版本管理器
806 | * [VirtPHP](http://virtphp.org/) - 一个创建和管理独立PHP环境的工具
807 |
808 | ## 开发环境 Development Environment
809 | *创建沙盒开发环境的软件和工具*
810 |
811 | * [Ansible](https://www.ansible.com/) - 一个非常简单的编制框架
812 | * [Phansible](http://phansible.com/) - 一个用Ansible构建PHP开发虚拟机的web工具
813 | * [Protobox](http://getprotobox.com/) - 另一个构建PHP开发虚拟机的web工具
814 | * [PuPHPet](https://puphpet.com/) - 一个构建PHP开发虚拟机的web工具
815 | * [Puppet](https://puppet.com/) - 一个服务器自动化框架和应用
816 | * [Vagrant](https://www.vagrantup.com/) - 一个便携的开发环境工具
817 | * [Docker](https://www.docker.com/) - 一个容器化的平台
818 |
819 | ## 虚拟机 Virtual Machines
820 | *相关的PHP虚拟机*
821 |
822 | * [Hack](http://hacklang.org/) - 一个PHP进行无缝操作的HHVM编程语言
823 | * [HHVM](https://github.com/facebook/hhvm) - Facebook出品的PHP虚拟机,Runtime和JIT
824 | * [HippyVM](https://github.com/hippyvm/hippyvm) - 另一个PHP虚拟机
825 |
826 | ## 集成开发环境(IDE) Integrated Development Environment
827 | *支持PHP的集成开发环境*
828 |
829 | * [Eclipse for PHP Developers](https://www.eclipse.org/downloads/) - 一个基于Eclipse平台的PHP IDE
830 | * [Netbeans](https://netbeans.org) - 一个支持PHP和HTML5的IDE
831 | * [PhpStorm](http://www.jetbrains.com/phpstorm/) - 一个商业PHP IDE
832 |
833 | ## Web应用 Web Applications
834 | *基于Web的应用和工具*
835 |
836 | * [3V4L](https://3v4l.org/) - 一个在线的PHP和HHVM shell
837 | * [DBV](https://dbv.vizuina.com/) - 一个数据库版本控制应用
838 | * [PHP Queue](https://github.com/CoderKungfu/php-queue) - A一个管理后端队列的应用
839 | * [MailCatcher](https://github.com/sj26/mailcatcher) - 一个抓取和查看邮件的web工具
840 | * [Cachet](https://github.com/cachethq/cachet) - 开源状态页面系统
841 | * [phpBeanstalkdAdmin](https://github.com/mnapoli/phpBeanstalkdAdmin) - 一个Beanstalkd的监控管理页面
842 | * [phpRedisAdmin](https://github.com/ErikDubbelboer/phpRedisAdmin) - 一个用于管理[Redis](http://redis.io/)数据库的简单web界面
843 | * [phpPgAdmin](https://github.com/phppgadmin/phppgadmin) - 一个PostgreSQL的web管理工具
844 | * [phpMyAdmin](https://github.com/phpmyadmin/phpmyadmin) - 一个MySQL/MariaDB的web界面
845 | * [Adminer](https://www.adminer.org/) - 一个数据库管理工具
846 | * [Grav](https://github.com/getgrav/grav) - 一个现代的flat-file的CMS
847 |
848 | ## 基础架构 Infrastructure
849 | *提供PHP应用和服务的基础架构*
850 |
851 | * [appserver.io](http://appserver.io/) - 一个用PHP写的多线程的PHP应用服务器
852 | * [php-pm](https://github.com/php-pm/php-pm) - 一个PHP应用的进程管理器、修改器和负载平衡器
853 |
854 | ## PHP网站 PHP Websites
855 | *PHP相关的有用的网站*
856 |
857 | * [Nomad PHP](https://nomadphp.com/) - 一个在线PHP学习资源
858 | * [PHP Best Practices](https://phpbestpractices.org/) - 一个PHP最佳实践指南
859 | * [PHP FIG](http://www.php-fig.org/) - PHP框架交互组
860 | * [PHP Mentoring](https://php-mentoring.org/) - 点对点PHP导师组织
861 | * [PHP School](https://www.phpschool.io/) - 学习PHP的开源资源
862 | * [PHP Security](http://phpsecurity.readthedocs.io/en/latest/index.html) - 一个PHP安全指南
863 | * [PHP The Right Way](http://www.phptherightway.com/) - 一个PHP最佳实践的快速指引手册
864 | * [PHP UG](http://php.ug) - 一个帮助用户定位最近的PHP用户组(UG)的网站
865 | * [PHP Versions](http://phpversions.info/) - 哪些版本的PHP可以用在哪几种流行的Web主机上的列表
866 | * [PHP Weekly](http://www.phpweekly.com/archive.html) - 一个PHP新闻周刊
867 | * [PHPTrends](https://phptrends.com/) - 一个快速增长的PHP类库的概述
868 | * [Securing PHP](http://securingphp.com/) - 一个关于PHP安全和库的建议的简报
869 | * [Seven PHP](http://7php.com/) - 一个PHP社区成员采访的网站
870 |
871 | ## 其他网站 Other Websites
872 | *web开发相关的有用网站*
873 |
874 | * [Atlassian Git Tutorials](https://www.atlassian.com/git/) - 一个Git教程系列
875 | * [Hg Init](http://hginit.com/) - 一个Mercurial教程系列
876 | * [Semantic Versioning](http://semver.org/) - 一个解析语义版本的网站
877 | * [Servers for Hackers](https://serversforhackers.com/) - 一个关于服务器管理的新闻通讯
878 | * [The Open Web Application Security Project (OWASP)](https://www.owasp.org/index.php/Main_Page) - 一个开放软件安全社区
879 | * [WebSec IO](https://websec.io/) - 一个web安全社区资源
880 |
881 | ## PHP书籍 PHP Books
882 | *PHP相关的非常好的书籍*
883 |
884 | * [Functional Programming in PHP](http://www.functionalphp.com) - 这本书将告诉你如何利用PHP5.3+的新功能的认识函数式编程的原则
885 | * [Grumpy PHPUnit](https://leanpub.com/grumpy-phpunit) - 一本Chris Hartjes关于使用PHPUnit进行单元测试的书
886 | * [Mastering Object-Orientated PHP](http://www.brandonsavage.net) - 一本Brandon Savage关于PHP面向对象的书
887 | * [Modern PHP New Features and Good Practices](http://shop.oreilly.com/product/0636920033868.do) - 一本Josh Lockhart关于新的PHP功能和最佳做法的书
888 | * [Modernising Legacy Applications in PHP](https://leanpub.com/mlaphp) - 一本Paul M.Jones关于遗留PHP应用进行现代化的书
889 | * [PHP 7 Upgrade Guide](https://leanpub.com/php7) - 一本Colin O'Dell的包含所有PHP 7功能和改变的书
890 | * [PHP Pandas](https://daylerees.com/php-pandas/) - 一本Dayle Rees关于如何学习写PHP的书
891 | * [Scaling PHP Applications](http://www.scalingphpbook.com) - 一本Steve Corona关于扩展PHP应用程序的电子书
892 | * [Securing PHP: Core Concepts](https://leanpub.com/securingphp-coreconcepts) - 一本Chris Cornutt关于PHP常见安全条款和实践的书
893 | * [Signaling PHP](https://leanpub.com/signalingphp) - 一本Cal Evans关于在CLI脚本捕获PCNTL信号的书
894 | * [The Grumpy Programmer's Guide to Building Testable PHP Applications](https://leanpub.com/grumpy-testing) - 一本Chris Hartjes关于构建PHP应用程序测试的书
895 | * [XML Parsing with PHP](https://www.phparch.com/books/xml-parsing-with-php/) - 这本书涵盖的解析和验证XML文档,利用XPath表达式,使用命名空间,以及如何创建和修改XML文件的编程
896 | * [Domain-Driven Design in PHP](https://leanpub.com/ddd-in-php) - 展示PHP DDD风格的实例
897 |
898 | ## 其他书籍 Other Books
899 | *与一般计算和web开发相关的书*
900 |
901 | * [Elasticsearch: The Definitive Guide](https://www.elastic.co/guide/index.html) - Clinton Cormley和Zachary Tong编写的与Elasticsearch工作的一本指南
902 | * [Eloquent JavaScript](http://eloquentjavascript.net/) - Marijin Haverbeke关于JavaScript编程的一本书
903 | * [Head First Design Patterns](http://www.headfirstlabs.com/books/hfdp/) - 解说软件设计模式的一本书
904 | * [Pro Git](https://git-scm.com/book/en/v2) - Scott Chacon和Ben Straub关于Git的一本书
905 | * [The Linux Command Line](http://linuxcommand.org/tlcl.php) - William Shotts关于Linux命令行的一本书
906 | * [The Tangled Web — Securing Web Applications](https://www.amazon.com/Tangled-Web-Securing-Modern-Applications/dp/1593273886) - Michal Zalewski关于web应用安全的一本书
907 | * [Understanding Computation](http://computationbook.com) - Tom Stuart关于计算理论的一本书
908 | * [Vagrant Cookbook](https://leanpub.com/vagrantcookbook) - Erika Heidi关于创建 Vagrant环境的一本书
909 |
910 | ## PHP视频 PHP Videos
911 | *PHP相关的非常不错的视频*
912 |
913 | * [Nomad PHP Lightning Talks](https://www.youtube.com/c/nomadphp) - PHP社区成员10到15分钟的快速会谈
914 | * [PHP UK Conference](https://www.youtube.com/user/phpukconference/videos) - 一个PHP英国会议的视频集合
915 | * [Programming with Anthony](https://www.youtube.com/playlist?list=PLM-218uGSX3DQ3KsB5NJnuOqPqc5CW2kW) - Anthony Ferrara的视频系列
916 | * [Taking PHP Seriously](https://www.infoq.com/presentations/php-history) - 来自Facebook Keith Adams 讲述PHP优势
917 |
918 | ## PHP播客 PHP Podcasts
919 | *专注于PHP话题的博客*
920 |
921 | * [PHP Town Hall](https://phptownhall.com/) - 一个随意的Ben Edmunds和Phil Sturgeon的PHP播客
922 | * [PHP Roundtable](https://www.phproundtable.com/) - PHP Roundtable是一个讨论PHP开发者关心话题的临时聚会
923 |
924 | ## PHP阅读 PHP Reading
925 | *PHP相关的阅读资料*
926 |
927 | * [Composer Primer](https://daylerees.com/composer-primer/) - Composer初级使用
928 | * [Composer Stability Flags](https://igor.io/2013/02/07/composer-stability-flags.html) - 一篇关于Composer稳定性标志的文章
929 | * [Composer Versioning](https://igor.io/2013/01/07/composer-versioning.html) - 一篇关于Composer版本的文章
930 | * [Create Your Own PHP Framework](http://fabien.potencier.org/create-your-own-framework-on-top-of-the-symfony2-components-part-1.html) - 一部Fabien Potencier的关于如何创建你自己的PHP框架的系列文章
931 | * [Don't Worry About BREACH](http://blog.ircmaxell.com/2013/08/dont-worry-about-breach.html) - 一篇关于BREACH攻击和CSRF令牌的文章
932 | * [On PHP 5.3, Lambda Functions and Closures](http://fabien.potencier.org/on-php-5-3-lambda-functions-and-closures.html) - 一篇关于lambda函数和闭包的文章
933 | * [PHP Is Much Better Than You Think](http://fabien.potencier.org/php-is-much-better-than-you-think.html) - 一篇关于PHP语言和生态圈的文章
934 | * [PHP Package Checklist](http://phppackagechecklist.com/) - 一个成功PHP包开发的清单
935 | * [PHP Sucks! But I Like It!](http://blog.ircmaxell.com/2012/04/php-sucks-but-i-like-it.html) - 一篇关于PHP利弊的文章
936 | * [Preventing CSRF Attacks](http://blog.ircmaxell.com/2013/02/preventing-csrf-attacks.html) - 一篇阻止CSRF攻击的文章
937 | * [Seven Ways to Screw Up BCrypt](http://blog.ircmaxell.com/2012/12/seven-ways-to-screw-up-bcrypt.html) - 一篇关于纠正BCrypt实现的文章
938 | * [Use Env](https://seancoates.com/blogs/use-env/) - 一篇关于使用unix环境帮助的文章
939 |
940 | ## PHP内核阅读 PHP Internals Reading
941 | *阅读PHP内核或性能相关的资料*
942 |
943 | * [Disproving the Single Quotes Myth](http://nikic.github.io/2012/01/09/Disproving-the-Single-Quotes-Performance-Myth.html) - 一篇关于单,双引号字符串性能的文章
944 | * [How Big Are PHP Arrays (And Values) Really?](http://nikic.github.io/2011/12/12/How-big-are-PHP-arrays-really-Hint-BIG.html) - 一篇关于数组原理的文章
945 | * [How Foreach Works](http://stackoverflow.com/questions/10057671/how-does-foreach-actually-work/14854568#14854568) - StackOverflow关于foreach回答的详情
946 | * [How Long is a Piece of String](http://blog.golemon.com/2006/06/how-long-is-piece-of-string.html) - 一篇关于字符串原理的文章
947 | * [PHP Evaluation Order](https://gist.github.com/nikic/6699370) - 一篇关于PHP评估顺序的文章
948 | * [PHP Internals Book](http://www.phpinternalsbook.com) - 一本由三名核心开发编写的关于PHP内核的在线书
949 | * [PHP RFCs](https://wiki.php.net/rfc) - PHP RFCs主页(请求注解)
950 | * [Print vs Echo, Which One is Faster?](http://fabien.potencier.org/print-vs-echo-which-one-is-faster.html) - 一篇关于打印和echo性能的文章
951 | * [The PHP Ternary Operator. Fast or Not?](http://fabien.potencier.org/the-php-ternary-operator-fast-or-not.html) - 一篇关于三元操作性能的文章
952 | * [Understanding OpCodes](http://blog.golemon.com/2008/01/understanding-opcodes.html) - 一篇关于opcodes的文章
953 | * [When Does Foreach Copy?](http://nikic.github.io/2011/11/11/PHP-Internals-When-does-foreach-copy.html) - 一篇关于foreach原理的文章
954 | * [Why Objects (Usually) Use Less Memory Than Arrays](https://gist.github.com/nikic/5015323) - 一篇关于对象和数组原理的文章
955 | * [You're Being Lied To](http://blog.golemon.com/2007/01/youre-being-lied-to.html) - 一篇关于内核ZVALs的文章
956 |
957 | ## PHP杂志 PHP Magazines
958 | *有趣的PHP相关的杂志*
959 |
960 | * [php[architect]](https://www.phparch.com/magazine/) - 一个致力于PHP的月更的杂志
961 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Resource And Mynotes
2 | 日常记录(持续更新中......)
3 |
--------------------------------------------------------------------------------
/Redis.md:
--------------------------------------------------------------------------------
1 | # 一、Redis安装
2 |
3 | ### 1、下载源码
4 | wget http://download.redis.io/releases/redis-4.0.1.tar.gz
5 | ### 2、解压
6 | tar -zxvf redis-4.0.1.tar.gz
7 | ### 3、进入其目录
8 | cd redis-4.0.1
9 | ### 4、编译安装
10 | ```
11 | make
12 | cd src
13 | make install PREFIX=/usr/local/redis
14 | ```
15 | ### 5、将配置文件移动到redis目录
16 | ```
17 | mkdir /usr/local/redis/etc
18 | cd ../
19 | mv redis.conf /usr/local/redis/etc/redis.conf
20 | ```
21 | ### 6、默认情况,Redis不是在后台运行,我们需要把redis放在后台运行
22 | ```
23 | vim /usr/local/redis/etc/redis.conf
24 | 将daemonize的值改为yes
25 | ```
26 | ### 7、启动redis服务
27 | ```
28 | /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf
29 | ```
30 | ### 8、客户端连接
31 | ```
32 | /usr/local/redis/bin/redis-cli
33 | ```
34 | ### 9、停止redis实例
35 | ```
36 | /usr/local/redis/bin/redis-cli shutdown
37 | 或者
38 | pkill redis-server
39 | ```
40 | ### 10、让redis开机自启
41 | ```
42 | vim /etc/rc.local
43 | 加入
44 | /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis-conf
45 | ```
46 | ### 11、接下来我们看看/usr/local/redis/bin目录下的几个文件时什么
47 | ```
48 | redis-benchmark:redis性能测试工具
49 |
50 | redis-check-aof:检查aof日志的工具
51 |
52 | redis-check-dump:检查rdb日志的工具
53 |
54 | redis-cli:连接用的客户端
55 |
56 | redis-server:redis服务进程
57 | ```
58 |
59 | ### Redis的配置
60 | ```
61 | daemonize:如需要在后台运行,把该项的值改为yes
62 |
63 | pdifile:把pid文件放在/var/run/redis.pid,可以配置到其他地址
64 |
65 | bind:指定redis只接收来自该IP的请求,如果不设置,那么将处理所有请求,在生产环节中最好设置该项
66 |
67 | port:监听端口,默认为6379
68 |
69 | timeout:设置客户端连接时的超时时间,单位为秒
70 |
71 | loglevel:等级分为4级,debug,revbose,notice和warning。生产环境下一般开启notice
72 |
73 | logfile:配置log文件地址,默认使用标准输出,即打印在命令行终端的端口上
74 |
75 | database:设置数据库的个数,默认使用的数据库是0
76 |
77 | save:设置redis进行数据库镜像的频率
78 |
79 | rdbcompression:在进行镜像备份时,是否进行压缩
80 |
81 | dbfilename:镜像备份文件的文件名
82 |
83 | dir:数据库镜像备份的文件放置的路径
84 |
85 | slaveof:设置该数据库为其他数据库的从数据库
86 |
87 | masterauth:当主数据库连接需要密码验证时,在这里设定
88 |
89 | requirepass:设置客户端连接后进行任何其他指定前需要使用的密码
90 |
91 | maxclients:限制同时连接的客户端数量
92 |
93 | maxmemory:设置redis能够使用的最大内存
94 |
95 | appendonly:开启appendonly模式后,redis会把每一次所接收到的写操作都追加到appendonly.aof文件中,当redis重新启动时,会从该文件恢复出之前的状态
96 |
97 | appendfsync:设置appendonly.aof文件进行同步的频率
98 |
99 | vm_enabled:是否开启虚拟内存支持
100 |
101 | vm_swap_file:设置虚拟内存的交换文件的路径
102 |
103 | vm_max_momery:设置开启虚拟内存后,redis将使用的最大物理内存的大小,默认为0
104 |
105 | vm_page_size:设置虚拟内存页的大小
106 |
107 | vm_pages:设置交换文件的总的page数量
108 |
109 | vm_max_thrrads:设置vm IO同时使用的线程数量
110 | ```
--------------------------------------------------------------------------------
/Windows下搭建wnmp环境.md:
--------------------------------------------------------------------------------
1 | # Windows下搭建wnmp环境
2 | ### 下载
3 | 1.在E盘下新建文件夹wnmp,在wnmp下分别建立php、mysql、www四个文件夹
4 |
5 | 2.下载nginx直接解压到E盘的wnmp文件夹,并将带有版本号的nginx文件夹重命名为nginx 路径为:E:/wnmp/nginx
6 | 下载地址:http://nginx.org/download/nginx-1.13.4.zip
7 |
8 | 3.下载win版php解压到E盘wnmp的php文件夹内 路径为:E:/wnmp/php
9 | 下载地址:http://windows.php.net/downloads/releases/php-7.1.8-nts-Win32-VC14-x86.zip
10 |
11 | 4.下载win版MySQL解压到wnmp下的mysql文件夹内 路径为:E:/wnmp/mysql
12 | 下载地址:https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.19-winx64.zip
13 |
14 | 5.下载RunHiddenConsole.exe的作用是在执行完命令行脚本后可以自动关闭脚本,而从脚本中开启的进程不被关闭。
15 | 下载地址:http://redmine.lighttpd.net/attachments/660/RunHiddenConsole.zip
16 |
17 | ### 安装与配置
18 | 6.php的安装与配置
19 | 将php文件夹内的php.ini-development文件重命名为php.ini,并打开将.将以下配置一一更改
20 | ```
21 | ;extension_dir = "./ext"
22 | ;extension = php_mysqli.dll
23 | ;extension=php_pdo_mysql.dll
24 | ;extension=php_openssl.dll
25 | ;cgi.fix_pathinfo=1
26 | ;date.timezone =
27 | enable_dl = Off
28 | ;cgi.force_redirect = 1
29 | ;fastcgi.impersonate = 1
30 | ;cgi.rfc2616_headers = 0
31 | ```
32 | 更改为
33 | ```
34 | extension_dir = "E:/wnmp/php/ext"
35 | extension = php_mysqli.dll
36 | extension=php_pdo_mysql.dll
37 | extension=php_openssl.dll
38 | cgi.fix_pathinfo=1
39 | date.timezone = Asia/Shanghai
40 | enable_dl = On
41 | cgi.force_redirect = 1
42 | fastcgi.impersonate = 1
43 | cgi.rfc2616_headers = 0
44 | ```
45 | 7.包装成.bat文件,避免每次重复敲击命令
46 | 首先把下载好的RunHiddenConsole.zip包解压到nginx目录内,然后来创建脚本,命名为“start_nginx.bat”,并将其内容编辑为:
47 | ```
48 | @echo off
49 | REM Windows 下无效
50 | REM set PHP_FCGI_CHILDREN=5
51 |
52 | REM 每个进程处理的最大请求数,或设置为 Windows 环境变量
53 | set PHP_FCGI_MAX_REQUESTS=1000
54 |
55 | echo Starting PHP FastCGI...
56 | RunHiddenConsole E:/wnmp/php/php-cgi.exe -b 127.0.0.1:9000 -c E:/wnmp/php/php.ini
57 |
58 | echo Starting nginx...
59 | RunHiddenConsole E:/wnmp/nginx/nginx.exe -p E:/wnmp/nginx
60 | ```
61 | 再另外创建一个名为stop_nginx.bat的脚本用来关闭nginx:
62 |
63 | ```
64 | @echo off
65 | echo Stopping nginx...
66 | taskkill /F /IM nginx.exe > nul
67 | echo Stopping PHP FastCGI...
68 | taskkill /F /IM php-cgi.exe > nul
69 | exit
70 | ```
71 |
72 | 做好后,是这样的。这样,我们的服务脚本也都创建完毕了。双击start_nginx.bat,这样nginx服务就启动了,而且php也以fastCGI的方式运行了。
73 |
74 | 8.安装mysql
75 | (1) 手动创建好my.ini文件
76 | ```
77 | [mysqld]
78 | character-set-server=utf8
79 | #绑定IPv4和3306端口
80 | bind-address = 0.0.0.0
81 | port = 3306
82 | # 设置mysql的安装目录
83 | basedir=E:/wnmp/mysql
84 | # 设置mysql数据库的数据的存放目录
85 | datadir=E:/wnmp/mysql/data
86 | # 允许最大连接数
87 | max_connections=200
88 | # skip_grant_tables
89 | [mysql]
90 | default-character-set=utf8
91 | [mysql.server]
92 | default-character-set=utf8
93 | [mysql_safe]
94 | default-character-set=utf8
95 | [client]
96 | default-character-set=utf8
97 | ```
98 | *将此文件放到mysql文件夹中(必须)*
99 |
100 | (2) 使用管理员身份打开命令提示符
101 | 切换目录至mysql包所在的bin目录。然后输入 `mysqld.exe -install`
102 | 执行命令后,提示:Service successfully installed. 表示安装成功.
103 |
104 | (3) 初始化mysql数据,并创建一个具有空密码的root用户,打开cmd执行如下命令:
105 | `mysqld --initialize-insecure --user=mysql`
106 | 注意:最后的参数 --user=mysql 在 windows 也可以不用添加,但在 unix 等系统下好像很重要。
107 | 执行命令后,等一会后,系统会自动生成相应的 data 目录,并自动创建好空密码的 root 用户。此时表示初始化成功。
108 |
109 | (4) 在cmd(命令提示符)中,输入下面的命令,启动mysql服务。
110 | `net start mysql`
111 |
112 | (5) 在服务启动后,因为刚创建的 root 用户是空密码的,因此,可以根据需要,进行密码设定。
113 | 可执行如下命令:
114 | `mysqladmin -u root -p password 此处输入新的密码`
115 | `Enter password: 此处输入旧的密码`
116 |
117 | *请注意:在输入旧密码(或没改过密码的就直接回车)后,系统很久没响应,然后报错(10060)。
118 | 原因:mysql没有通过windows防火墙
119 | 解决方法:将D:\mysql\bin\mysqld.exe 添加到windows防火墙允许通过的应用中。*
120 |
121 | 9.nginx配置很简单,想必大家都会,就不写了。可以参考在linux下部署的nginx配置部分(将站点根目录配置到www目录即可)
122 |
123 | ## windows下安装composer
124 | 下载composer.phar放置在php.exe处
125 | 新建一个composer.bat文件,在里面写入一下内容(在已经配置php环境变量的前提下):
126 | ```
127 | @ECHO OFF
128 | php "%~dp0composer.phar" %*
129 | ```
130 |
131 | ## Apache 安装
132 | 下载地址:https://www.apachelounge.com/download/VC15/binaries/httpd-2.4.27-Win64-VC15.zip
133 |
134 | 1.解压到wnmp中 路径为:`E:/wnmp/Apache24`
135 |
136 | 2.使用cmd进入到apache的bin目录下执行
137 | `httpd.exe -k install`
138 | 来安装服务
139 |
140 | 3.编辑配置文件
141 | ```
142 | (1)进入conf目录,然后编辑httpd.conf
143 | (2)修改`Define SRVROOT "/Apache24"`为Define SRVROOT "E:/wnmp/Apache24"
144 | (3)修改DirectoryIndex index.html为DirectoryIndex index.php index.html 则可默认支持PHP
145 | (4)将;LoadModule rewrite_module modules/mod_rewrite.so前的分号去掉,开启重写功能
146 | (5)将;Include conf/extra/httpd-vhosts.conf前的分号去掉,开启虚拟主机
147 | (6)添加php模块
148 | LoadModule php7_module E:/wnmp/php/php7apache2_4.dll
149 |
150 | PHPIniDir "E:/wnmp/php/"
151 | AddType application/x-httpd-php .php
152 | AddType application/x-httpd-php-source .phps
153 |
154 | (7)进入extra文件夹,编辑httpd-vhosts.conf
155 | 在最后面添加虚拟主机:
156 | # 指定虚拟主机的IP地址和端口号
157 | DocumentRoot "E:/wnmp/Apache24/htdocs/" # 指定web文件目录
158 | ServerName localhost
159 | DirectoryIndex index.php index.html index.htm
160 | ErrorLog "logs/error.log"
161 | CustomLog "logs/access.log" common
162 | # 定义目录访问权限
163 | Options Indexes FollowSymLinks # 固定格式-若目录下有index则自动打开index文件,如果没有则列出文件列表
164 | AllowOverride All # 固定格式
165 | # Order allow,deny # 匹配顺序为先允许,后拒绝
166 | # Allow from all # 设置允许所有人访问 (经测试这两项配置需要注释掉才能正常启动)
167 | Require all granted # 对这个目录给予授权
168 |
169 |
170 | ```
171 | 重启Apache即可解析php文件了 `httpd.exe -k restart`
172 |
173 | *注意:PHP需要是TS版的,因为NTS版没有`php7apache2_4.dll`文件*
174 |
175 | *若在开启curl扩展后仍无法加载curl,则需将php目录下的libssh2.dll文件,复制到对应apache的bin文件夹下,再重启apache即可解决*
--------------------------------------------------------------------------------
/docker+nginx负载均衡.md:
--------------------------------------------------------------------------------
1 | ## Docker和nginx实现简单的服务器负载均衡
2 | >1. 当请求负载在单节点处理能力之下时,没有必要设置负载均衡器,所有的请求都由一台服务器搞定;
3 | >2. 当请求达到一定数量,超过了单台服务器处理能力,那么现在就需要添加多台服务器,并且使用负载均衡器(Load Balancer)进行流量分发,保证业务请求平均地分散到各 web 服务器;
4 | >3. 业务的流量特点很多变,流量高峰何时到来谁也不知道,如果使用多台 web 服务器在后台值班,这样难免会造成资源的浪费,并且这样也有可能无法应对流量峰值,因此需要一个自动的负载均衡器,它能够实时检测当前到来的业务流量,并且能够控制后端资源池快速完成资源的申请、释放以及路由切换,这样就可以通过实时的流量检测数据完成 web 服务器的动态配置,在后端资源池能力足够的情况下,轻松应对多变的请求量。
5 |
6 | 现在我们使用docker-compose容器编排来构建简单的负载均衡
7 |
8 | 上篇文章已经介绍了使用docker-compose搭建lnmp容器了,[点击查看](https://www.voocel.com/dockerlnmp)可以直接将文件全部拷贝过来
9 |
10 | #### 修改docker-compose.yml文件
11 | ```
12 | version: '2'
13 | services:
14 | nginx:
15 | depends_on:
16 | - php
17 | build: ./nginx
18 | volumes:
19 | - ./nginx/www:/usr/share/nginx/html
20 | - ./nginx/nginx.conf:/etc/nginx/nginx.conf
21 | - ./nginx/log/error.log:/var/log/nginx/error.log
22 | restart: always
23 |
24 | ports:
25 | - "80:80"
26 | - "443:443"
27 | links:
28 | - nginx1
29 | - nginx2
30 | - nginx3
31 | container_name: nginx
32 |
33 | nginx1:
34 | depends_on:
35 | - php
36 | build: ./nginx
37 | volumes:
38 | - ./nginx1/www:/usr/share/nginx/html
39 | - ./nginx1/nginx.conf:/etc/nginx/nginx.conf
40 | - ./nginx1/log/error.log:/var/log/nginx/error.log
41 | restart: always
42 |
43 | ports:
44 | - "80"
45 | container_name: nginx1
46 |
47 | nginx2:
48 | depends_on:
49 | - php
50 | build: ./nginx
51 | volumes:
52 | - ./nginx2/www:/usr/share/nginx/html
53 | - ./nginx2/nginx.conf:/etc/nginx/nginx.conf
54 | - ./nginx2/log/error.log:/var/log/nginx/error.log
55 | restart: always
56 |
57 | ports:
58 | - "80"
59 | container_name: nginx2
60 |
61 | nginx3:
62 | depends_on:
63 | - php
64 | build: ./nginx
65 | volumes:
66 | - ./nginx3/www:/usr/share/nginx/html
67 | - ./nginx3/nginx.conf:/etc/nginx/nginx.conf
68 | - ./nginx3/log/error.log:/var/log/nginx/error.log
69 | restart: always
70 |
71 | ports:
72 | - "80"
73 | container_name: nginx3
74 | ```
75 |
76 | 其实就是再创建三个nginx服务器,由nginx作为作为负载均衡器把请求转发到三个web服务器上,我们用links来连接三个web服务器。nginx1、nginx2、nginx3作为web服务器(volumes根据自己的情况配置)
77 | #### 启动docker-compose 构建镜像
78 | ```
79 | docker-compose up -d
80 | ```
81 | #### 查看镜像
82 | 
83 |
84 | #### 查看状态
85 | 
86 |
87 | 这样说明nginx负载均衡器和三个web服务器都启动成功了
88 |
89 | #### 修改nginx配置文件(注意不是nginx1、nginx2、nginx3的)
90 | ```
91 | upstream myweb{
92 | server nginx1 max_fails=3 fail_timeout=20s weight=2;
93 | server nginx2 max_fails=3 fail_timeout=20s weight=10;
94 | server nginx3 max_fails=3 fail_timeout=20s weight=2;
95 | }
96 |
97 | server {
98 | listen 80;
99 | server_name localhost;
100 |
101 | #access_log logs/host.access.log main;
102 | root /usr/share/nginx/html;
103 | location / {
104 | index inde.php index.html index.htm;
105 |
106 | #如果服务器要获取客户端真实IP,可以用下三句设置主机头和客户端真实地址
107 | #proxy_set_header Host $host;
108 | #proxy_set_header X-Real-IP $remote_addr;
109 | #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
110 |
111 | proxy_pass http://myweb; #反向代理地址,表示将所有请求转发到phpServers服务器组中配置的某一台服务器上。为upstream后定义的名字
112 |
113 | }
114 | ```
115 | #### 为三个web服务器的根目录各自添加index.html,为下面的测试用
116 | 
117 |
118 | #### 在浏览器中访问测试效果
119 | 
120 |
121 | 每次刷新内容都不同说明成功。
122 |
123 |
124 | ## nginx负载均衡的四种配置方案
125 | >Nginx负载均衡是通过upstream模块来实现的,负载均衡有4种方案配置
126 | 1. 轮询
127 |
128 | 轮询即Round Robin,根据Nginx配置文件中的顺序,依次把客户端的Web请求分发到不同的后端服务器上
129 | 2. 最少连接 least_conn;
130 |
131 | Web请求会被转发到连接数最少的服务器上。
132 | 3. IP地址哈希 ip_hash;
133 |
134 | 前述的两种负载均衡方案中,同一客户端连续的Web请求可能会被分发到不同的后端服务器进行处理,因此如果涉及到会话Session,那么会话会比较复杂。常见的是基于数据库的会话持久化。要克服上面的难题,可以使用基于IP地址哈希的负载均衡方案。这样的话,同一客户端连续的Web请求都会被分发到同一服务器进行处理。
135 | 4. 基于权重 weight
136 |
137 | 基于权重的负载均衡即Weighted Load Balancing,这种方式下,我们可以配置Nginx把请求更多地分发到高配置的后端服务器上,把相对较少的请求分发到低配服务器。
138 |
139 |
140 | #### 1.轮询
141 | ```
142 | upstream phpServers { #phpServers可自定义
143 | server 172.17.0.2;
144 | server 172.17.0.3;
145 | }
146 |
147 | server {
148 | listen 80 default_server;
149 | listen [::]:80 default_server ipv6only=on;
150 |
151 | root /docker-ubuntu/www;
152 | index index.php index.html index.htm;
153 |
154 | # Make site accessible from http://localhost/
155 | server_name localhost;
156 |
157 | location / {
158 | index inde.php index.html index.htm;
159 |
160 | #如果服务器要获取客户端真实IP,可以用下三句设置主机头和客户端真实地址
161 | #proxy_set_header Host $host;
162 | #proxy_set_header X-Real-IP $remote_addr;
163 | #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
164 |
165 | proxy_pass http://phpServers; #表示将所有请求转发到phpServers服务器组中配置的某一台服务器上。为upstream后定义的名字
166 | }
167 |
168 | }
169 | ```
170 | upstream模块:配置反向代理服务器组,Nginx会根据配置,将请求分发给组里的某一台服务器。tomcats是服务器组的名称。
171 |
172 | upstream模块下的server指令:配置处理请求的服务器IP或域名,端口可选,不配置默认使用80端口。通过上面的配置,Nginx默认将请求依次分配给172.17.0.2,172.17.0.3来处理
173 |
174 | #### 2.基于权重 weight
175 | ```
176 | upstream phpServers {
177 | # weight表示权重,数值越大,表示被分配到这个server的几率越大,比如以下配置,每请求 三次,就有两次分配到了 172.17.0.2
178 | server 172.17.0.2 weight=2;
179 | server 172.17.0.3 weight=1;
180 | }
181 |
182 | server {
183 | listen 80 default_server;
184 | listen [::]:80 default_server ipv6only=on;
185 |
186 | root /docker-ubuntu/www;
187 | index index.php index.html index.htm;
188 |
189 | # Make site accessible from http://localhost/
190 | server_name localhost;
191 |
192 | location / {
193 | proxy_pass http://phpServers; #表示将所有请求转发到phpServers服务器组中配置的某一台服务器上。
194 | }
195 |
196 | }
197 | ```
198 | 除了 weight 之外,还有别的配置项
199 | ```
200 | upstream phpServers {
201 | server 172.17.0.2 weight=2 max_fails=1 fail_timeout=20 max_conns=100;
202 | server 172.17.0.3 weight=1 backup down
203 | }
204 | ```
205 | *max_fails
206 |
207 | 默认为1。某台Server允许请求失败的次数,超过最大次数后,在failtimeout时间内,新的请求将不会分配给这台机器。如果设置为0,Nginx会将这台Server置为永久无效状态,然后将请求发给定义了proxynextupstream, fastcginextupstream, uwsginextupstream, scginextupstream, and memcachednext_upstream指令来处理这次错误的请求。
208 |
209 | *fail_timeout
210 |
211 | 默认为10秒。某台Server达到maxfails次失败请求后,在failtimeout期间内,nginx会认为这台Server暂时不可用,不会将请求分配给它
212 |
213 | *backup
214 |
215 | 备份机,所有服务器挂了之后才会生效
216 |
217 | *down
218 |
219 | 标识某一台server不可用
220 |
221 | *max_conns
222 |
223 | 限制分配给某台Server处理的最大连接数量,超过这个数量,将不会分配新的连接给它。默认为0,表示不限制。注意:1.5.9之后的版本才有这个配置 表示最多给100这台Server分配1000个请求,如果这台Server正在处理1000个请求,nginx将不会分配新的请求给到它。假如有一个请求处理完了,还剩下999个请求在处理,这时nginx也会将新的请求分配给它。
224 |
225 | #### 3.IP HASH
226 | nginx中的ip_hash技术能够将某个ip的请求定向到同一台后端,这样一来这个ip下的某个客户端和某个后端就能建立起稳固的session
227 |
228 | iphash是容易理解的,但是因为仅仅能用ip这个因子来分配后端,因此iphash是有缺陷的,不能在一些情况下使用:
229 |
230 | (1)nginx不是最前端的服务器。ip_hash要求nginx一定是最前端的服务器,否则nginx得不到正确ip,就不能根据ip作hash。譬如使用的是squid为最前端,那么nginx取ip时只能得到squid的服务器ip地址,用这个地址来作分流是肯定错乱的。
231 |
232 | (2)nginx的后端还有其它方式的负载均衡。假如nginx后端又有其它负载均衡,将请求又通过另外的方式分流了,那么某个客户端的请求肯定不能定位到同一台session应用服务器上。这么算起来,nginx后端只能直接指向应用服务器,或者再搭一个squid,然后指向应用服务器。最好的办法是用location作一次分流,将需要session的部分请求通过ip_hash分流,剩下的走其它后端去。
233 |
234 | ip hash是nginx内置的另一个负载均衡的策略,流程和轮询很类似,只是其中的算法和具体的策略有些变化
235 | 配置如下
236 | ```
237 | upstream phpServers {
238 | server 172.17.0.2;
239 | server 172.17.0.3;
240 | ip_hash;
241 | }
242 | ```
243 | 4.最少连接
244 |
245 | Web请求会被转发到连接数最少的服务器上。
246 | ```
247 | upstream phpServers {
248 | server 172.17.0.2;
249 | server 172.17.0.3;
250 | least_conn;
251 | }
252 | ```
253 | fair
254 |
255 | 根据服务器的响应时间来分配请求,响应时间短的优先分配,即负载压力小的优先会分配
256 |
257 | 由于 fair 是第三方模块,需要大家另外安装
258 |
259 | 安装完成后配置文件如下
260 | ```
261 | upstream phpServers {
262 | server 172.17.0.2;
263 | server 172.17.0.3;
264 | fair;
265 | }
266 | ```
267 | 注意,使用 fair 后 weight 会无效
268 |
269 | url_hash
270 |
271 | 按请求url的hash结果来分配请求,使每个url定向到同一个后端服务器,服务器做缓存时比较有效。
272 |
273 | 1.7.2版本以后,urlhash模块已经集成到了nginx源码当中,不需要单独安装。之前的版本仍需要单独安装,下载地址:https://github.com/evanmiller/nginxupstream_hash
274 |
275 | 安装方法和fair模块一样,先下载urlhash源码,然后重新编译nginx源码,将urlhash模块添加到编译配置参数当中,最后将编译后生成的nginx二进制文件替换之前安装的nginx二进制文件即可。
276 |
277 | 安装完成后,配置文件如下
278 | ```
279 | upstream phpServers {
280 | server 172.17.0.2;
281 | server 172.17.0.3;
282 | hash $request_uri;
283 | }
284 | ```
--------------------------------------------------------------------------------
/images/images.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/voocel/resource/1df0eba0a28d96b2468091af02a8ddd0355d8fa2/images/images.jpg
--------------------------------------------------------------------------------
/images/nginx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/voocel/resource/1df0eba0a28d96b2468091af02a8ddd0355d8fa2/images/nginx.png
--------------------------------------------------------------------------------
/images/ps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/voocel/resource/1df0eba0a28d96b2468091af02a8ddd0355d8fa2/images/ps.png
--------------------------------------------------------------------------------
/images/test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/voocel/resource/1df0eba0a28d96b2468091af02a8ddd0355d8fa2/images/test.png
--------------------------------------------------------------------------------
/images/tree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/voocel/resource/1df0eba0a28d96b2468091af02a8ddd0355d8fa2/images/tree.png
--------------------------------------------------------------------------------
/mysql防注入.php:
--------------------------------------------------------------------------------
1 | sql = $Sql;
20 | $this->fetch = $Fetch;
21 | $this->param = $Param;
22 | //数据库信息存放在配置文件里面,请自行修改成正确的路径和值
23 | require($_SERVER['DOCUMENT_ROOT'] . '/configs/config.inc.php');
24 | $this->dbhost = & $DBHost;
25 | $this->dbuser = & $DBUser;
26 | $this->dbpw = & $DBPassword;
27 | $this->dbname = & $DBName;
28 | }
29 |
30 | public function Query()
31 | {
32 | $Mysqli = new mysqli($this->dbhost, $this->dbuser, $this->dbpw, $this->dbname);
33 | if ($Mysqli->connect_errno)
34 | {
35 | echo '无法连接数据库';
36 | return false;
37 | }
38 | $Mysqli->query('SET NAMES UTF8');
39 | $Mysqli->begin_transaction(MYSQLI_TRANS_START_READ_ONLY);
40 | $Stmt = $Mysqli->stmt_init();
41 | $Stmt->prepare($this->sql);
42 | if (count($this->param) > 0)
43 | {
44 | $Type = '';
45 | for ($i = 0; $i < count($this->param); $i++)
46 | {
47 | if (is_double($this->param[$i]))
48 | {
49 | $Type .= 'd';
50 | }
51 | else if (is_int($this->param[$i]))
52 | {
53 | $Type .= 'i';
54 | }
55 | else if (is_string($this->param[$i]))
56 | {
57 | $Type .= 's';
58 | }
59 | else
60 | {
61 | $Type .= 'b';
62 | }
63 | }
64 | $RefArg = array($Type);
65 | for ($I = 0; $I < count($this->param); $I++)
66 | {
67 | $RefArg[] = & $this->param[$I];
68 | }
69 | call_user_func_array(array($Stmt, 'bind_param'), $RefArg);
70 | }
71 | if (!$Stmt->execute())
72 | {
73 | echo '读取数据库时发生错误:'. $Stmt->error;
74 | echo $this->sql;
75 | print_r($this->param);
76 | $Mysqli->rollback();
77 | return false;
78 | }
79 | $Mysqli->commit();
80 | if (strtolower(substr($this->sql, 0, 6)) == 'select')
81 | {
82 | $this->res = $Stmt->get_result();
83 | $Stmt->free_result();
84 | return $this->GetRes();
85 | }
86 | else
87 | {
88 | $Stmt->free_result();
89 | return true;
90 | }
91 | }
92 |
93 | public function GetRes()
94 | {
95 | switch(strtolower($this->fetch))
96 | {
97 | case 'all':
98 | $row = $this->res->fetch_all();
99 | break;
100 | case 'array':
101 | $row = $this->res->fetch_array();
102 | break;
103 | case 'assoc':
104 | $row = $this->res->fetch_assoc();
105 | break;
106 | case 'field':
107 | $row = $this->res->fetch_field();
108 | break;
109 | case 'row':
110 | $row = $this->res->fetch_row();
111 | break;
112 | default:
113 | echo 'Please select a row return mode.';
114 | exit;
115 | }
116 | return $row;
117 | }
118 |
119 | public function NumRow()
120 | {
121 | if (isset($this->res))
122 | {
123 | return $this->res->num_rows;
124 | }
125 | else
126 | {
127 | return false;
128 | }
129 | }
130 | }
131 | ?>
132 |
133 |
134 |
135 |
136 | //PDO_MYSQL版:
137 |
138 | DBHost = & $DBHost;
150 | $this->DBUser = & $DBUser;
151 | $this->DBPW = & $DBPassword;
152 | $this->DBName = & $DBName;
153 | $this->SQL = $SQL;
154 | $this->Fetch = $Fetch;
155 | $this->Param = $Param;
156 | }
157 |
158 | public function Query()
159 | {
160 | try
161 | {
162 | $Pdo = new PDO('mysql:host=' . $this->DBHost . ';dbname=' . $this->DBName, $this->DBUser, $this->DBPW);
163 | $Pdo->query('SET NAMES UTF8');
164 | $Pdo->beginTransaction();
165 | $Stmt = $Pdo->prepare($this->SQL);
166 | if (count($this->Param) > 0)
167 | {
168 | for ($I = 0; $I < count($this->Param); $I++)
169 | {
170 | $Stmt->bindParam($I + 1, $this->Param[$I]);
171 | }
172 | }
173 | if (!$Stmt->execute())
174 | {
175 | echo '读取数据库时发生错误:' . $Stmt->errorinfo()[2];
176 | $Pdo->rollback();
177 | return false;
178 | }
179 | $Pdo->commit();
180 | if (strtolower(substr($this->SQL, 0, 6)) == 'select' || strtolower(substr($this->SQL, 0, 4)) == 'desc')
181 | {
182 | $this->Res = $Stmt;
183 | return $this->GetRes();
184 | }
185 | else
186 | {
187 | return true;
188 | }
189 | }
190 | catch (PDOException $e)
191 | {
192 | echo '无法连接数据库';
193 | $Pdo->rollback();
194 | return false;
195 | }
196 | }
197 |
198 | public function GetRes()
199 | {
200 | switch(strtolower($this->Fetch))
201 | {
202 | case 'all':
203 | $Row = $this->Res->fetchAll(PDO::FETCH_ASSOC);
204 | break;
205 | case 'array':
206 | $Row = $this->Res->fetch(PDO::FETCH_BOTH);
207 | break;
208 | case 'assoc':
209 | case 'field':
210 | $Row = $this->Res->fetch(PDO::FETCH_ASSOC);
211 | break;
212 | case 'row':
213 | $Row = $this->Res->fetch(PDO::FETCH_NUM);
214 | break;
215 | default:
216 | echo 'Please select a row return mode.';
217 | exit;
218 | }
219 | return $Row;
220 | }
221 |
222 | public function NumRow()
223 | {
224 | if (isset($this->Res))
225 | {
226 | return $this->Res->num_rows;
227 | }
228 | else
229 | {
230 | return false;
231 | }
232 | }
233 | }
234 | ?>
235 |
236 |
--------------------------------------------------------------------------------
/nginx详解/README1.md:
--------------------------------------------------------------------------------
1 | # 初识 Nginx
2 | Nginx 是一个免费的,开源的,高性能的HTTP服务器和反向代理,以及IMAP / POP3代理服务器。 Nginx 以其高性能,稳定性,丰富的功能,简单的配置和低资源消耗而闻名。很多高知名度的网站都使用 Nginx,如:Netflix,GitHub,SoundCloud,MaxCDN 等。
3 |
4 |
5 | Nginx 有一个主线程( master process)和几个工作线程(worker process)。主线程的目的是加载和验证配置文件、维护工作线程。
6 |
7 | 工作线程处理实际的请求,Nginx 采用基于事件的模型和依赖操作系统的机制在工作线程之间高效地分发请求。工作线程的数量可配置,也可自动调整为服务器CPU的数量。
8 |
9 | Nginx 及其模块的工作方式由配置文件确定。 默认情况下,配置文件名为 nginx.conf,放在 /usr/local/nginx/conf 、/etc/nginx 或者 /usr/local/etc/nginx 文件夹中。
10 |
11 | ## 基本命令.
12 |
13 | Nginx 启动之后,可以使用以下命令控制:
14 | ~~~
15 | nginx -s
16 | 其中-s意思是向主进程发送信号,signal可以为以下四个中的一个:
17 |
18 | stop — 快速关闭
19 | quit — 优雅关闭
20 | reload — 重新加载配置文件
21 | reopen — 重新打开日志文件
22 | ~~~
23 | 当运行nginx -s quit时,Nginx 会等待工作进程处理完成当前请求,然后将其关闭。当你修改配置文件后,并不会立即生效,而是等待重启或者收到nginx -s reload信号。
24 |
25 | 当 Nginx 收到 nginx -s reload 信号后,首先检查配置文件的语法。语法正确后,主线程会开启新的工作线程并向旧的工作线程发送关闭信号,如果语法不正确,则主线程回滚变化并继续使用旧的配置。当工作进程收到主进程的关闭信号后,会在处理完当前请求之后退出。
26 |
27 | ## 配置文件
28 |
29 | Nginx 配置的核心是定义要处理的 URL 以及如何响应这些 URL 请求,即定义一系列的虚拟服务器(Virtual Servers)控制对来自特定域名或者 IP 的请求的处理。
30 |
31 | 每一个虚拟服务器定义一系列的 location 控制处理特定的 URI 集合。每一个location定义了对映射到自己的请求的处理场景,可以返回一个文件或者代理此请求。
32 |
33 | Nginx 由不同的模块组成,这些模块由配置文件中指定的指令控制。 指令分为简单指令和块指令。
34 |
35 | 一个简单指令包含指令名称和指令参数,以空格分隔,以分号(;)结尾。 块指令与简单指令类似,但是由大括号({和})包围。 如果块指令大括号中包含其他指令,则称该指令为上下文(如: events, http, server 和 location)。
36 |
37 | 配置文件中的放在上下文之外的指令默认放在主配置文件中(类似继承主配置文件)。 events 和 http 放置在主配置文件中,server 放置在http块指令中,location放置在server块指令中。
38 |
39 | 配置文件的注释以 # 开始。
40 |
41 | ## 静态内容
42 |
43 | Web 服务器一个重要的功能是服务静态文件(图像或静态HTML页面)。例如,Nginx 可以很方便的让服务器从/data/www 获取 html 文件,从/data/images获取图片来返回给客户端,这只需要在http块指令中的server块指令中设置两个location块指令。
44 |
45 | 首先,创建 /data/www 目录,并放入 index.html,创建 /data/images 目录并在其中放置一些图片。
46 |
47 | 接下来,打开配置文件。 创建一个 server 块:
48 | ```nginx
49 | http {
50 | server {
51 | }
52 | }
53 | ```
54 | 通常,配置文件可以包括多个 server 块,它们以端口和服务器名称来区分。当 Nginx 决定某一个 server 处理请求后,它将请求头中的 URI 和 server 块中的 location 块进行对比。
55 | 加入 location 块指令到 server 中:
56 |
57 | 将以下位置块添加到服务器块:
58 | ```nginx
59 | location / {
60 | root /data/www;
61 | }
62 | ```
63 | 上面的 location 块指定 / 前缀与请求中的 URI 对比。对于匹配的请求,URI 将被添加到 root 指令中指定的路径,即 /data/www,以此形成本地文件系统的路径,如访问http://localhost/bog/welcome.html,对应服务器文件路径为/data/www/bog/welcome.html。 如果 URI 匹配多个 location 块,Nginx 采用最长前缀匹配原则(类似计算机网络里面的IP匹配), 上面的 location 块前缀长度为 1,因此只有当所有其他 location 块匹配时,才使用该块。
64 |
65 | 接下来,添加第二个位置块:
66 |
67 | location /images/ {
68 | root /data;
69 | }
70 | 它将匹配以/images/(/ 也匹配这样的请求,但具有较短的前缀)开始的请求。
71 |
72 | server 块的最终配置如下:
73 | ```nginx
74 | server {
75 | location / {
76 | root /data/www;
77 | }
78 |
79 | location /images/ {
80 | root /data;
81 | }
82 | }
83 | ```
84 | 到目前为止,这已经是一个可以正常运行的服务器,它监听端口80,并且可以在本地计算机上访问 http://localhost/。 对于 /images/ 开头的请求,服务器将从 /data/images 目录发送文件。 如,对于 http://localhost/images/example.png 请求,nginx 将响应 /data/images/example.png文件。 如果不存在,nginx 将返回404。URI 不以 /images/ 开头的请求将映射到 /data/www 目录。 例如,对于 http://localhost/some/example.html 请求,nginx 将响应 /data/www/some/example.html 文件。
85 |
86 | ## 代理服务器
87 |
88 | Nginx 的一个常见应用是将其设置为代理服务器(Proxy Server),即接受客户端的请求并将其转发给代理服务器,再接受代理服务器发来的响应,将它们发送到客户端。
89 |
90 | 比如我们可以用一个 Nginx 实例实现对图片文件的请求使用本地文件系统,而其他请求转发到代理服务器。
91 |
92 | 首先,向 Nginx 的配置文件中添加一个 server 块来定义代理服务器:
93 | ```nginx
94 | server {
95 | listen 8080;
96 | root /data/up1;
97 |
98 | location / {
99 | }
100 | }
101 | ```
102 | 此服务器侦听端口8080,并将所有请求映射到本地文件系统上的 /data/up1 目录。 创建此目录并将 index.html 放入其中。 注意,root 指令放在 server 上下文中,这样 当 location 块中不含 root 指令时将使用所属 server 的 root 指令。
103 |
104 | 接下来,使用上一节中的服务器配置,并将其修改为代理服务器配置。 在第一个位置块中,加上proxy_pass指令:
105 | ```nginx
106 | server {
107 | location / {
108 | # proxy_pass指令的参数为:协议+主机名+端口号
109 | proxy_pass http://localhost:8080;
110 | }
111 |
112 | location /images/ {
113 | root /data;
114 | }
115 | }
116 | ```
117 | 修改第二个 匹配 /images/ 前缀的 location 块,使其与请求图像文件的扩展名相匹配:
118 | ``` nginx
119 | location ~ \.(gif|jpg|png)$ {
120 | root /data/images;
121 | }
122 | ```
123 | 该参数是一个正则表达式,匹配以.gif,.jpg或.png结尾的所有URI。 正则表达式应该以 ~ 开头。 相应的请求将映射到 /data/images 目录。
124 |
125 | 当 Nginx 选择一个 location 块来处理请求时,它首先检查指定 location 块的前缀,记住具有最长前缀的 location 块,然后检查正则表达式。 如果与正则表达式匹配, Nginx 选择此 location 块,否则,选择先前记住的 location 块。
126 |
127 | 代理服务器的最终配置如下:
128 | ```nginx
129 | server {
130 | location / {
131 | proxy_pass http://localhost:8080/;
132 | }
133 |
134 | location ~ \.(gif|jpg|png)$ {
135 | root /data/images;
136 | }
137 | }
138 | ```
139 | 此服务器将过滤以.gif,.jpg或.png结尾的请求,并将它们映射到 /data/images 目录(通过向 root 指令的参数添加请求的URI),并将所有其他请求发送给上面配置的代理服务器。
140 |
141 | 这样,图片和其他请求就可以使用不同的服务器来处理。
142 |
143 | ## FastCGI代理
144 |
145 | Nginx 可用于将请求路由到 FastCGI 服务器。快速通用网关接口(Fast Common Gateway Interface/FastCGI)是一种让交互程序与Web服务器通信的协议。因此 Nginx 可以将请求路由到 FastCGI 运行的应用程序,如 PHP 程序。
146 |
147 | 使用 FastCGI 服务器的最基本的 Nginx 配置包括使用 fastcgi_pass 指令而不是 proxy_pass 指令,以及使用 fastcgi_param 指令来设置传递给 FastCGI 服务器的参数。 假设FastCGI服务器可在 localhost:9000 上访问。 以上一节中的代理服务器配置为基础,使用fastcgi_pass指令替换proxy_pass指令,并将参数更改为 localhost:9000 。 在 PHP 中, SCRIPT_FILENAME 参数用于确定脚本名称,而 QUERY_STRING 参数用于传递请求参数。 生成的配置将是:
148 | ```nginx
149 | server {
150 | location / {
151 | fastcgi_pass localhost:9000;
152 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
153 | fastcgi_param QUERY_STRING $query_string;
154 | }
155 |
156 | location ~ \.(gif|jpg|png)$ {
157 | root /data/images;
158 | }
159 | }
160 | ```
161 | 这将设置一个服务器,将路由除静态图像以外的所有请求到运行在 localhost:9000 的 FastCGI 服务器。
--------------------------------------------------------------------------------
/nginx详解/README2.md:
--------------------------------------------------------------------------------
1 | # 将 Nginx 配置为Web服务器
2 | 抽象来说,将 Nginx 配置为 Web 服务器就是定义处理哪些 URLS 和如何处理这些URLS 对应的请求。具体来说,就是定义一些虚拟服务器(Virtual Servers),控制具有特定 IP 和域名的请求。
3 |
4 | 更具体的来说, Nginx 通过定义一系列 locations 来控制对 URIS 的选择。每一个 location 定义了对映射到自己的请求的处理场景:返回一个文件或者代理请求,或者根据不同的错误代码返回不同的错误页面。另外,根据 URI 的不同,请求也可以被重定向到其它 server 或者 location 。
5 |
6 | ## 设置虚拟服务器
7 |
8 | listen:
9 | Nginx 配置文件至少包含一个 server 命令 ,用来定义虚拟服务器。当请求到来时, Nginx 会首先选择一个虚拟服务器来处理该请求。
10 |
11 | 虚拟服务器定义在 http 上下文中的 server 中:
12 | ```nginx
13 | http {
14 | server {
15 | # Server configuration
16 | }
17 | }
18 | ```
19 | 注意: http 中可以定义多个 server
20 | server 配置块使用 listen 命令监听本机 IP 和端口号(包括 Unix domain socket and path),支持 IPv4、IPv6,IPv6地址需要用方括号括起来:
21 | ```nginx
22 | server {
23 | listen 127.0.0.1:8080; # IPv4地址,8080端口
24 | # listen [2001:3CA1:10F:1A:121B:0:0:10]:80; # IPv6地址,80端口
25 | # listen [::]:80; # 听本机的所有IPv4与IPv6地址,80端口
26 | # The rest of server configuration
27 | }
28 | ```
29 | 上述配置,如果不写端口号,默认使用80端口,如果不写 IP ,则监听本机所有 IP。
30 |
31 | server_name:
32 | 如果多个 server 的 listen IP 和端口号一模一样, Nginx 通过请求头中的 Host 与 server_name 定义的主机名进行比较,来选择合适的虚拟服务器处理请求:
33 | ```nginx
34 | server {
35 | listen 80;
36 | server_name lufficc.com www.lufficc.com;
37 | ...
38 | }
39 | ```
40 | server_name 的参数可以为:
41 |
42 | 完整的主机名,如:api.lufficc.com 。
43 | 含有通配符(含有 *),如:*.lufficc.com 或 api.* 。
44 | 正则表达式,以 ~ 开头。
45 | 通配符只能在开头或结尾,而且只能与一个 . 相邻。www.*.example.org 和 w*.example.org 均无效。 但是,可以使用正则表达式匹配这些名称,例如 ~^www\..+\.example\.org$ 和 ~^w.*\.example\.org$ 。 而且 * 可以匹配多个部分。 名称 * .example.org 不仅匹配 www.example.org,还匹配www.sub.example.org。
46 | 对于正则表达式:Nginx 使用的正则表达式与 Perl 编程语言(PCRE)使用的正则表达式兼容。 要使用正则表达式,且必须以 ~ 开头。
47 | 命名的正则表达式可以捕获变量,然后使用:
48 | ```nginx
49 | server {
50 | server_name ~^(www\.)?(?.+)$;
51 |
52 | location / {
53 | root /sites/$domain;
54 | }
55 | }
56 | ```
57 | 小括号 () 之间匹配的内容,也可以在后面通过 $1 来引用,$2 表示的是前面第二个 () 里的内容。因此上述内容也可写为:
58 | ```nginx
59 | server {
60 | server_name ~^(www\.)?(.+)$;
61 |
62 | location / {
63 | root /sites/$2;
64 | }
65 | }
66 | ```
67 | 一个 server_name 示例:
68 | ```nginx
69 | server {
70 | listen 80;
71 | server_name api.lufficc.com *.lufficc.com;
72 | ...
73 | }
74 | ```
75 | 同样,如果多个名称匹配 Host 头部, Nginx 采用下列顺序选择:
76 |
77 | 完整的主机名,如 api.lufficc.com。
78 | 最长的,且以 * 开头的通配名,如:*.lufficc.com。
79 | 最长的,且以 * 结尾的通配名,如:api.* 。
80 | 第一个匹配的正则表达式。(按照配置文件中的顺序)
81 | 即优先级:api.lufficc.com > *.lufficc.com > api.* > 正则。
82 |
83 | 如果 Host 头部不匹配任何一个 server_name ,Nginx 将请求路由到默认虚拟服务器。默认虚拟服务器是指:nginx.conf 文件中第一个 server 或者 显式用 default_server 声明:
84 | ```nginx
85 | server {
86 | listen 80 default_server;
87 | ...
88 | }
89 | ```
90 | ## 配置 location
91 |
92 | ### URI 与 location 参数的匹配
93 | 当选择好 server 之后,Nginx 会根据 URIs 选择合适的 location 来决定代理请求或者返回文件。
94 |
95 | location 指令接受两种类型的参数:
96 |
97 | 前缀字符串(路径名称)
98 | 正则表达式
99 | 对于前缀字符串参数, URIs 必须严格的以它开头。例如对于 /some/path/ 参数,可以匹配 /some/path/document.html ,但是不匹配 /my-site/some/path,因为 /my-site/some/path 不以 /some/path/ 开头。
100 | ```nginx
101 | location /some/path/ {
102 | ...
103 | }
104 | ```
105 | 对于正则表达式,以 ~ 开头表示大小写敏感,以 ~* 开头表示大小写不敏感。注意路径中的 . 要写成 \. 。例如一个匹配以 .html 或者 .htm 结尾的 URI 的 location:
106 | ```nginx
107 | location ~ \.html? {
108 | ...
109 | }
110 | ```
111 | 正则表达式的优先级大于前缀字符串。如果找到匹配的前缀字符串,仍继续搜索正则表达式,但如果前缀字符串以 ^~ 开头,则不再检查正则表达式。
112 |
113 | 具体的搜索匹配流程如下:
114 |
115 | 将 URI 与所有的前缀字符串进行比较。
116 | = 修饰符表明 URI 必须与前缀字符串相等(不是开始,而是相等),如果找到,则搜索停止。
117 | 如果找到的最长前缀匹配字符串以 ^~ 开头,则不再搜索正则表达式是否匹配。
118 | 存储匹配的最长前缀字符串。
119 | 测试对比 URI 与正则表达式。
120 | 找到第一个匹配的正则表达式后停止。
121 | 如果没有正则表达式匹配,使用 4 存储的前缀字符串对应的 location。
122 | = 修饰符拥有最高的优先级。如网站首页访问频繁,我们可以专门定义一个 location 来减少搜索匹配次数(因为搜索到 = 修饰的匹配的 location 将停止搜索),提高速度:
123 | ```nginx
124 | location = / {
125 | ...
126 | }
127 | ```
128 | ### 静态文件和代理
129 | location 也定义了如何处理匹配的请求:返回静态文件 或者 交给代理服务器处理。下面的例子中,第一个 location 返回 /data 目录中的静态文件,第二个 location 则将请求传递给 https://lufficc.com 域名的服务器处理:
130 | ```nginx
131 | server {
132 | location /images/ {
133 | root /data;
134 | }
135 |
136 | location / {
137 | proxy_pass https://lufficc.com;
138 | }
139 | }
140 | ```
141 | root 指令定义了静态文件的根目录,并且和 URI 拼接形成最终的本地文件路径。如请求 /images/example.png,则拼接后返回本地服务器文件 /data/images/example.png 。
142 |
143 | proxy_pass 指令将请求传递到 URL 指向的代理服务器。让后将来自代理服务器的响应转发给客户端。 在上面的示例中,所有不以 /images / 开头的 URI 的请求都将传递给代理服务器处理。
144 |
145 | 比如我把 proxy_pass 设置为 https://www.baidu.com/,那么访问 http://search.lufficc.com/ 将得到百度首页一样的响应(页面)(感兴趣的童鞋可以自己试一试搜索功能,和百度没差别呢):
146 | ```nginx
147 | server{
148 | listen 80;
149 | server_name search.lufficc.com;
150 | location / {
151 | proxy_pass https://www.baidu.com;
152 | }
153 | }
154 | ```
155 | ## 使用变量(Variables)
156 |
157 | 你可以使用变量来使 Nginx 在不同的请求下采用不同的处理方式。变量是在运行时计算的,用作指令的参数。 变量由 $ 开头的符号表示。 变量基于 Nginx 的状态定义信息,例如当前处理的请求的属性。
158 |
159 | 有很多预定义变量,例如核心的 HTTP 变量,你也可以使用 set,map 和 geo 指令定义自定义变量。 大多数变量在运行时计算,并包含与特定请求相关的信息。 例如,$remote_addr 包含客户端 IP 地址,$uri 保存当前URI值。
160 |
161 | 一些常用的变量如下:
162 | ~~~
163 | 变量名称 作用
164 | $uri 请求中的当前URI(不带请求参数),它可以通过内部重定向,或者使用index指令进行修改,$uri不包含主机名,如 /foo/bar.html。
165 | $arg_name 请求中的的参数名,即“?”后面的arg_name=arg_value形式的arg_name
166 | $hostname 主机名
167 | $args 请求中的参数值
168 | $query_string 同 $args
169 | $request 代表客户端的请求地址
170 | $request_uri 这个变量等于包含一些客户端请求参数的原始URI,它无法修改,不包含主机名,如:/cnphp/test.php?arg=freemouse。
171 | ... ...
172 | ~~~
173 | 一个简单的应用就是从 http 重定向到 https 时带上路径信息:
174 | ```nginx
175 | server{
176 | ...
177 | return 301 https://lufficc.com$request_uri;
178 | ...
179 | }
180 | ```
181 | ## 返回特定状态码
182 |
183 | 如果你的网站上的一些资源永久移除了,最快最简洁的方法就是使用 return 指令直接返回:
184 | ```nginx
185 | location /wrong/url {
186 | return 404;
187 | }
188 | ```
189 | return 的第一个参数是响应代码。可选的第二个参数可以是重定向(对应于代码301,302,303和307)的 URL 或在响应正文中返回的文本。 例如:
190 | ```nginx
191 | location /permanently/moved/url {
192 | return 301 http://www.example.com/moved/here;
193 | }
194 | return 指令可以包含在 location 和 server 上下文中:
195 |
196 | server{
197 | location / {
198 | return 404;
199 | }
200 | }
201 | ```
202 | 或者:
203 | ```nginx
204 | server{
205 | ...
206 | return 404;
207 | location / {
208 | ...
209 | }
210 | }
211 | ```
212 | ## 错误处理
213 |
214 | error_page 命令可以配置特定错误码的错误页面,或者重定向到其他的页面。下面的示例将在 404 错误发生时返回 /404.html 页面。
215 |
216 | error_page 404 /404.html;
217 | error_page 命令定义了如何处理错误,因此不会直接返回,而 return 确实会立即返回。当代理服务器或者 Nginx 处理时产生相应的错误的代码,均会返回相应的错误页面。
218 |
219 | 在下面的示例中,当 Nginx 找不到页面时,它将使用代码301替换代码404,并将客户端重定向到 http://example.com/new/path.html 。 此配置很有用,比如当客户端仍尝试用旧的 URI 访问页面时,301代码通知浏览器页面已永久移除,并且需要自动替换为返回的新地址。
220 | ```nginx
221 | location /old/path.html {
222 | error_page 404 =301 http:/example.com/new/path.html;
223 | }
224 | ```
225 | ## 重写 URIs
226 |
227 | rewrite 指令可以多次修改请求的 URI。rewrite 的第一个参数是 URI需要匹配的正则表达式,第二个参数是将要替换的 URI。第三个参数可选,指示是否继续可以重写或者返回重定向代码(301或302)。例如:
228 | ```nginx
229 | location /users/ {
230 | rewrite ^/users/(.*)$ /show?user=$1 break;
231 | }
232 | ```
233 | 您可以在 server 和 location 上下文中包括多个 rewrite 指令。 Nginx 按照它们发生的顺序一个一个地执行指令。 当选择 server 时,server 中的 rewrite 指令将执行一次。
234 |
235 | 在 Nginx 处理一组 rewrite 指令之后,它根据新的 URI 选择 location 。 如果所选 location 仍旧包含 rewrite 指令,它们将依次执行。 如果 URI 匹配所有,则在处理完所有定义的 rewrite 指令后,搜索新的 location 。
236 |
237 | 以下示例将 rewrite 指令与 return 指令结合使用:
238 | ```nginx
239 | server {
240 | ...
241 | rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
242 | rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last;
243 | return 403;
244 | ...
245 | }
246 | ```
247 | 诸如 /download/some/media/file 的 URI 被改为 /download/some/mp3/file.mp3 。 由于 last 标志,后续指令(第二个 rewrite 指令和 return 指令)被跳过,但 Nginx 继续以更改后的 URI 处理请求。 类似地,诸如 /download/some/audio/file 的 URI 被替换为 /download/some/mp3/file.ra。 如果 URI 不匹配 rewrite 指令,Nginx 将403 错误代码返回给客户端。
248 |
249 | last 与 break的区别是:
250 |
251 | last : 在当前 server 或 location 上下文中停止执行 rewrite 指令,但是 Nginx 继续搜索与重写的URI匹配的 location,并应用新 location 中的任何 rewrite 指令(这意味着 URI 可能再次改变)。
252 | break :停止当前上下文中 rewrite 指令的处理,并取消搜索与新 URI 匹配的 location。 不会执行新 location中的 rewrite 指令。
253 |
254 | ## 附录
255 |
256 | ### 常用正则
257 | ~~~
258 | . : 匹配除换行符以外的任意字符
259 | ? : 重复0次或1次
260 | + : 重复1次或更多次
261 | *: 重复0次或更多次
262 | \d :匹配数字
263 | ^ : 匹配字符串的开始
264 | $ : 匹配字符串的结束
265 | {n} : 重复n次
266 | {n,} : 重复n次或更多次
267 | [c] : 匹配单个字符c
268 | [a-z]: 匹配a-z小写字母的任意一个
269 | ~~~
270 | ### 全局变量
271 | ~~~
272 | $args : #这个变量等于请求行中的参数,同$query_string
273 | $content_length : 请求头中的Content-length字段。
274 | $content_type : 请求头中的Content-Type字段。
275 | $document_root : 当前请求在root指令中指定的值。
276 | $host : 请求主机头字段,否则为服务器名称。
277 | $http_user_agent : 客户端agent信息
278 | $http_cookie : 客户端cookie信息
279 | $limit_rate : 这个变量可以限制连接速率。
280 | $request_method : 客户端请求的动作,通常为GET或POST。
281 | $remote_addr : 客户端的IP地址。
282 | $remote_port : 客户端的端口。
283 | $remote_user : 已经经过Auth Basic Module验证的用户名。
284 | $request_filename : 当前请求的文件路径,由root或alias指令与URI请求生成。
285 | $scheme : HTTP方法(如http,https)。
286 | $server_protocol : 请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
287 | $server_addr : 服务器地址,在完成一次系统调用后可以确定这个值。
288 | $server_name : 服务器名称。
289 | $server_port : 请求到达服务器的端口号。
290 | $request_uri : 包含请求参数的原始URI,不包含主机名,如:/foo/bar.php?arg=baz。
291 | $uri : 不带请求参数的当前URI,$uri不包含主机名,如/foo/bar.html。
292 | $document_uri : 与$uri相同。
293 | 例如请求:http://localhost:88/test1/test2/test.php
294 | $host:localhost
295 | $server_port:88
296 | $request_uri:/test1/test2/test.php
297 | $document_uri:/test1/test2/test.php
298 | $document_root:/var/www/html
299 | $request_filename:/var/www/html/test1/test2/test.php
300 | ~~~
301 |
302 | ## (总结)Nginx配置文件nginx.conf中文详解
303 | ~~~
304 | #定义Nginx运行的用户和用户组
305 | user www www;
306 |
307 | #nginx进程数,建议设置为等于CPU总核心数。
308 | worker_processes 8;
309 |
310 | #全局错误日志定义类型,[ debug | info | notice | warn | error | crit ]
311 | error_log /var/log/nginx/error.log info;
312 |
313 | #进程文件
314 | pid /var/run/nginx.pid;
315 |
316 | #一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(系统的值ulimit -n)与nginx进程数相除,但是nginx分配请求并不均匀,所以建议与ulimit -n的值保持一致。
317 | worker_rlimit_nofile 65535;
318 |
319 | #工作模式与连接数上限
320 | events
321 | {
322 | #参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型是Linux 2.6以上版本内核中的高性能网络I/O模型,如果跑在FreeBSD上面,就用kqueue模型。
323 | use epoll;
324 | #单个进程最大连接数(最大连接数=连接数*进程数)
325 | worker_connections 65535;
326 | }
327 |
328 | #设定http服务器
329 | http
330 | {
331 | include mime.types; #文件扩展名与文件类型映射表
332 | default_type application/octet-stream; #默认文件类型
333 | #charset utf-8; #默认编码
334 | server_names_hash_bucket_size 128; #服务器名字的hash表大小
335 | client_header_buffer_size 32k; #上传文件大小限制
336 | large_client_header_buffers 4 64k; #设定请求缓
337 | client_max_body_size 8m; #设定请求缓
338 | sendfile on; #开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
339 | autoindex on; #开启目录列表访问,合适下载服务器,默认关闭。
340 | tcp_nopush on; #防止网络阻塞
341 | tcp_nodelay on; #防止网络阻塞
342 | keepalive_timeout 120; #长连接超时时间,单位是秒
343 |
344 | #FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。下面参数看字面意思都能理解。
345 | fastcgi_connect_timeout 300;
346 | fastcgi_send_timeout 300;
347 | fastcgi_read_timeout 300;
348 | fastcgi_buffer_size 64k;
349 | fastcgi_buffers 4 64k;
350 | fastcgi_busy_buffers_size 128k;
351 | fastcgi_temp_file_write_size 128k;
352 |
353 | #gzip模块设置
354 | gzip on; #开启gzip压缩输出
355 | gzip_min_length 1k; #最小压缩文件大小
356 | gzip_buffers 4 16k; #压缩缓冲区
357 | gzip_http_version 1.0; #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
358 | gzip_comp_level 2; #压缩等级
359 | gzip_types text/plain application/x-javascript text/css application/xml;
360 | #压缩类型,默认就已经包含text/html,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn。
361 | gzip_vary on;
362 | #limit_zone crawler $binary_remote_addr 10m; #开启限制IP连接数的时候需要使用
363 |
364 | upstream blog.ha97.com {
365 | #upstream的负载均衡,weight是权重,可以根据机器配置定义权重。weigth参数表示权值,权值越高被分配到的几率越大。
366 | server 192.168.80.121:80 weight=3;
367 | server 192.168.80.122:80 weight=2;
368 | server 192.168.80.123:80 weight=3;
369 | }
370 |
371 | #虚拟主机的配置
372 | server
373 | {
374 | #监听端口
375 | listen 80;
376 | #域名可以有多个,用空格隔开
377 | server_name www.ha97.com ha97.com;
378 | index index.html index.htm index.php;
379 | root /data/www/ha97;
380 | location ~ .*\.(php|php5)?$
381 | {
382 | fastcgi_pass 127.0.0.1:9000;
383 | fastcgi_index index.php;
384 | include fastcgi.conf;
385 | }
386 | #图片缓存时间设置
387 | location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
388 | {
389 | expires 10d;
390 | }
391 | #JS和CSS缓存时间设置
392 | location ~ .*\.(js|css)?$
393 | {
394 | expires 1h;
395 | }
396 | #日志格式设定
397 | log_format access '$remote_addr - $remote_user [$time_local] "$request" '
398 | '$status $body_bytes_sent "$http_referer" '
399 | '"$http_user_agent" $http_x_forwarded_for';
400 | #定义本虚拟主机的访问日志
401 | access_log /var/log/nginx/ha97access.log access;
402 |
403 | #对 "/" 启用反向代理
404 | location / {
405 | proxy_pass http://127.0.0.1:88;
406 | proxy_redirect off;
407 | proxy_set_header X-Real-IP $remote_addr;
408 | #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
409 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
410 | #以下是一些反向代理的配置,可选。
411 | proxy_set_header Host $host;
412 | client_max_body_size 10m; #允许客户端请求的最大单文件字节数
413 | client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数,
414 | proxy_connect_timeout 90; #nginx跟后端服务器连接超时时间(代理连接超时)
415 | proxy_send_timeout 90; #后端服务器数据回传时间(代理发送超时)
416 | proxy_read_timeout 90; #连接成功后,后端服务器响应时间(代理接收超时)
417 | proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
418 | proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的设置
419 | proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2)
420 | proxy_temp_file_write_size 64k;
421 | #设定缓存文件夹大小,大于这个值,将从upstream服务器传
422 | }
423 |
424 | #设定查看Nginx状态的地址
425 | location /NginxStatus {
426 | stub_status on;
427 | access_log on;
428 | auth_basic "NginxStatus";
429 | auth_basic_user_file conf/htpasswd;
430 | #htpasswd文件的内容可以用apache提供的htpasswd工具来产生。
431 | }
432 |
433 | #本地动静分离反向代理配置
434 | #所有jsp的页面均交由tomcat或resin处理
435 | location ~ .(jsp|jspx|do)?$ {
436 | proxy_set_header Host $host;
437 | proxy_set_header X-Real-IP $remote_addr;
438 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
439 | proxy_pass http://127.0.0.1:8080;
440 | }
441 | #所有静态文件由nginx直接读取不经过tomcat或resin
442 | location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$
443 | { expires 15d; }
444 | location ~ .*.(js|css)?$
445 | { expires 1h; }
446 | }
447 | }
448 | ~~~
449 | ## 参考
450 |
451 | https://www.nginx.com/resources/admin-guide/nginx-web-server/
452 | http://seanlook.com/2015/05/17/nginx-location-rewrite/
--------------------------------------------------------------------------------
/php常用函数.php:
--------------------------------------------------------------------------------
1 | 2^32
105 | $tempArr = json_decode($result, $return_array);
106 | if ($tempArr == NULL) {
107 | $patterns = array('/,+\s*\}/', '/,+\s*\]/', '/"\s+|\s+"/', '/\n|\r|\t/','/\\\/','/ss+/');
108 | $replacements = array('}', ']', '"', ' ','',' ');
109 | $result = preg_replace($patterns, $replacements, $result);
110 | $tempArr = json_decode($result, $return_array);
111 | }
112 |
113 | return $tempArr;
114 | }
115 |
116 |
117 | //非法字符过滤函数
118 | function has_unsafeword($str) {
119 | $regex = "/\/|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\+|\{|\}|\:|\<|\>|\?|\[|\]|\.|\/|\;|\'|\`|\=|\\\|\|/";
120 | return preg_replace($regex,"",$str);
121 | }
122 |
123 | //去空格,以及字符添加斜杠
124 | function _trim(&$value) {
125 | Return addslashes(trim($value));
126 | }
127 |
128 | /**
129 | * 将多维数组转为一维数组
130 | * @param array $arr
131 | * @return array
132 | */
133 | function ArrMd2Ud($arr) {
134 | #将数值第一元素作为容器,作地址赋值。
135 | $ar_room = &$arr[key($arr)];
136 | #第一容器不是数组进去转呀
137 | if (!is_array($ar_room)) {
138 | #转为成数组
139 | $ar_room = array($ar_room);
140 | }
141 | #指针下移
142 | next($arr);
143 | #遍历
144 | while (list($k, $v) = each($arr)) {
145 | #是数组就递归深挖,不是就转成数组
146 | $v = is_array($v) ? call_user_func(__FUNCTION__, $v) : array($v);
147 | #递归合并
148 | $ar_room = array_merge_recursive($ar_room, $v);
149 | #释放当前下标的数组元素
150 | unset($arr[$k]);
151 | }
152 | return $ar_room;
153 | }
154 |
155 | /**
156 | * 判断是PC端还是wap端访问
157 | * @return type判断手机移动设备访问
158 | */
159 | function isMobile()
160 | {
161 | // 如果有HTTP_X_WAP_PROFILE则一定是移动设备
162 | if (isset ($_SERVER['HTTP_X_WAP_PROFILE']))
163 | {
164 | return true;
165 | }
166 | // 如果via信息含有wap则一定是移动设备,部分服务商会屏蔽该信息
167 | if (isset ($_SERVER['HTTP_VIA']))
168 | {
169 | // 找不到为flase,否则为true
170 | return stristr($_SERVER['HTTP_VIA'], "wap") ? true : false;
171 | }
172 | // 脑残法,判断手机发送的客户端标志,兼容性有待提高
173 | if (isset ($_SERVER['HTTP_USER_AGENT']))
174 | {
175 | $clientkeywords = array ('nokia',
176 | 'sony',
177 | 'ericsson',
178 | 'mot',
179 | 'samsung',
180 | 'htc',
181 | 'sgh',
182 | 'lg',
183 | 'sharp',
184 | 'sie-',
185 | 'philips',
186 | 'panasonic',
187 | 'alcatel',
188 | 'lenovo',
189 | 'iphone',
190 | 'ipod',
191 | 'blackberry',
192 | 'meizu',
193 | 'android',
194 | 'netfront',
195 | 'symbian',
196 | 'ucweb',
197 | 'windowsce',
198 | 'palm',
199 | 'operamini',
200 | 'operamobi',
201 | 'openwave',
202 | 'nexusone',
203 | 'cldc',
204 | 'midp',
205 | 'wap',
206 | 'mobile'
207 | );
208 | // 从HTTP_USER_AGENT中查找手机浏览器的关键字
209 | if (preg_match("/(" . implode('|', $clientkeywords) . ")/i", strtolower($_SERVER['HTTP_USER_AGENT'])))
210 | {
211 | return true;
212 | }
213 | }
214 | // 协议法,因为有可能不准确,放到最后判断
215 | if (isset ($_SERVER['HTTP_ACCEPT']))
216 | {
217 | // 如果只支持wml并且不支持html那一定是移动设备
218 | // 如果支持wml和html但是wml在html之前则是移动设备
219 | if ((strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') !== false) && (strpos($_SERVER['HTTP_ACCEPT'], 'text/html') === false || (strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') < strpos($_SERVER['HTTP_ACCEPT'], 'text/html'))))
220 | {
221 | return true;
222 | }
223 | }
224 | return false;
225 | }
226 |
227 | //判断是否为安卓手机
228 | function isAndroid()
229 | {
230 | if(isset($_SERVER['HTTP_USER_AGENT'])){
231 | $agent = strtolower($_SERVER['HTTP_USER_AGENT']);
232 | if(strpos($agent,'android') !== false)
233 | return true;
234 | }
235 | return false;
236 | }
237 |
238 | //判断是否为iphone或者ipad
239 | function isIos()
240 | {
241 | if(isset($_SERVER['HTTP_USER_AGENT'])){
242 | $agent = strtolower($_SERVER['HTTP_USER_AGENT']);
243 | if(strpos($agent, 'iphone')||strpos($agent, 'ipad'))
244 | return true;
245 | }
246 | return false;
247 | }
248 |
249 | //判断是否为微信内置浏览器打开
250 | function isWechet()
251 | {
252 | if(isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false){
253 | return true;
254 | }
255 | return false;
256 | }
257 |
258 | //整合到一起,判断当前设备,1:安卓;2:IOS;3:微信;0:未知
259 | function isDevice()
260 | {
261 | if($_SERVER['HTTP_USER_AGENT']){
262 | $agent = strtolower($_SERVER['HTTP_USER_AGENT']);
263 | if(strpos($agent, 'micromessenger') !== false)
264 | return 3;
265 | elseif(strpos($agent, 'iphone')||strpos($agent, 'ipad'))
266 | return 2;
267 | else
268 | return 1;
269 | }
270 | return 0;
271 | }
272 |
273 |
274 |
275 |
276 | /**
277 | * 日期转换成几分钟前
278 | */
279 | function formatTime($date) {
280 | $timer = strtotime($date);
281 | $diff = $_SERVER['REQUEST_TIME'] - $timer;
282 | $day = floor($diff / 86400);
283 | $free = $diff % 86400;
284 | if($day > 0) {
285 | if(15 < $day && $day <30){
286 | return "半个月前";
287 | }elseif(30 <= $day && $day <90){
288 | return "1个月前";
289 | }elseif(90 <= $day && $day <187){
290 | return "3个月前";
291 | }elseif(187 <= $day && $day <365){
292 | return "半年前";
293 | }elseif(365 <= $day){
294 | return "1年前";
295 | }else{
296 | return $day."天前";
297 | }
298 | }else{
299 | if($free>0){
300 | $hour = floor($free / 3600);
301 | $free = $free % 3600;
302 | if($hour>0){
303 | return $hour."小时前";
304 | }else{
305 | if($free>0){
306 | $min = floor($free / 60);
307 | $free = $free % 60;
308 | if($min>0){
309 | return $min."分钟前";
310 | }else{
311 | if($free>0){
312 | return $free."秒前";
313 | }else{
314 | return '刚刚';
315 | }
316 | }
317 | }else{
318 | return '刚刚';
319 | }
320 | }
321 | }else{
322 | return '刚刚';
323 | }
324 | }
325 | }
326 |
327 | /**
328 | * 截取长度
329 | */
330 | function getSubString($rawString,$length='100',$etc = '...',$isStripTag=true){
331 | $rawString = str_replace('_baidu_page_break_tag_', '', $rawString);
332 | $result = '';
333 | if($isStripTag)
334 | $string = html_entity_decode(trim(strip_tags($rawString)), ENT_QUOTES, 'UTF-8');
335 | else
336 | $string = trim($rawString);
337 | $strlen = strlen($string);
338 | for ($i = 0; (($i < $strlen) && ($length > 0)); $i++){
339 | if ($number = strpos(str_pad(decbin(ord(substr($string, $i, 1))), 8, '0', STR_PAD_LEFT), '0'))
340 | {
341 | if ($length < 1.0){
342 | break;
343 | }
344 | $result .= substr($string, $i, $number);
345 | $length -= 1.0;
346 | $i += $number - 1;
347 | }else{
348 | $result .= substr($string, $i, 1);
349 | $length -= 0.5;
350 | }
351 | }
352 | if($isStripTag)
353 | $result = htmlspecialchars($result, ENT_QUOTES, 'UTF-8');
354 |
355 | if ($i < $strlen){
356 | $result .= $etc;
357 | }
358 | return $result;
359 | }
360 |
361 | /**
362 | * utf-8和gb2312自动转化
363 | * @param unknown $string
364 | * @param string $outEncoding
365 | * @return unknown|string
366 | */
367 | function safeEncoding($string,$outEncoding = 'UTF-8')
368 | {
369 | $encoding = "UTF-8";
370 | for($i = 0; $i < strlen ( $string ); $i ++) {
371 | if (ord ( $string {$i} ) < 128)
372 | continue;
373 |
374 | if ((ord ( $string {$i} ) & 224) == 224) {
375 | // 第一个字节判断通过
376 | $char = $string {++ $i};
377 | if ((ord ( $char ) & 128) == 128) {
378 | // 第二个字节判断通过
379 | $char = $string {++ $i};
380 | if ((ord ( $char ) & 128) == 128) {
381 | $encoding = "UTF-8";
382 | break;
383 | }
384 | }
385 | }
386 | if ((ord ( $string {$i} ) & 192) == 192) {
387 | // 第一个字节判断通过
388 | $char = $string {++ $i};
389 | if ((ord ( $char ) & 128) == 128) {
390 | // 第二个字节判断通过
391 | $encoding = "GB2312";
392 | break;
393 | }
394 | }
395 | }
396 |
397 | if (strtoupper ( $encoding ) == strtoupper ( $outEncoding ))
398 | return $string;
399 | else
400 | return @iconv ( $encoding, $outEncoding, $string );
401 | }
402 |
403 | /**
404 | *对内容中的关键词添加链接
405 | *只处理第一次出现的关键词,对已有链接的关键不会再加链接,支持中英文
406 | *$content:string 原字符串
407 | *$keyword:string 关键词
408 | *$link:string,链接
409 | */
410 | function yang_keyword_link($content,$keyword,$link){
411 | //排除图片中的关键词
412 | $content = preg_replace( '|(
]*?)('.$keyword.')([^>]*?>)|U', '$1%&&&&&%$3', $content);
413 | $regEx = '/(?!((<.*?)|(]*?)>)|([^>]*?<\/a>))/si';
414 | $url=''.$keyword.'';
415 | $content = preg_replace($regEx,$url,$content,1);
416 | //还原图片中的关键词
417 | $content=str_replace('%&&&&&%',$keyword,$content);
418 | return $content;
419 | }
420 |
421 | /**
422 | * 遍历一个文件夹下的所有文件和子文件夹
423 | */
424 | function my_scandir($dir){
425 | $files = array();
426 | if (is_dir($dir)) {
427 | if ($handle = opendir($dir)) {
428 | while (($file = readdir($handle)) !== false) {
429 | if ($file != "." && $file != "..") {
430 | if (is_dir($dir . "/" . $file)) {
431 | $files[$file] = my_scandir($dir . "/" . $file);
432 | } else {
433 | $files[] = $dir . "/" . $file;
434 | }
435 | }
436 | }
437 | closedir($handle);
438 | return $files;
439 | }
440 | }
441 | }
442 |
443 | usleep() 函数延迟代码执行若干微秒。
444 | unpack() 函数从二进制字符串对数据进行解包。
445 | uniqid() 函数基于以微秒计的当前时间,生成一个唯一的 ID。
446 | time_sleep_until() 函数延迟代码执行直到指定的时间。
447 | time_nanosleep() 函数延迟代码执行若干秒和纳秒。
448 | sleep() 函数延迟代码执行若干秒。
449 | show_source() 函数对文件进行语法高亮显示。
450 | strip_whitespace() 函数返回已删除 PHP 注释以及空白字符的源代码文件。
451 | pack() 函数把数据装入一个二进制字符串。
452 | ignore_user_abort() 函数设置与客户机断开是否会终止脚本的执行。
453 | highlight_string() 函数对字符串进行语法高亮显示。
454 | highlight_file() 函数对文件进行语法高亮显示。
455 | get_browser() 函数返回用户浏览器的性能。
456 | exit() 函数输出一条消息,并退出当前脚本。
457 | eval() 函数把字符串按照 PHP 代码来计算。
458 | die() 函数输出一条消息,并退出当前脚本。
459 | defined() 函数检查某常量是否存在。
460 | define() 函数定义一个常量。
461 | constant() 函数返回常量的值。
462 | connection_status() 函数返回当前的连接状态。
463 | connection_aborted() 函数检查是否断开客户机。
464 | zip_read() 函数读取打开的 zip 档案中的下一个文件。
465 | zip_open() 函数打开 ZIP 文件以供读取。
466 | zip_entry_read() 函数从打开的 zip 档案项目中获取内容。
467 | zip_entry_open() 函数打开一个 ZIP 档案项目以供读取。
468 | zip_entry_name() 函数返回 zip 档案项目的名称。
469 | zip_entry_filesize() 函数返回 zip 档案项目的原始大小(在压缩之前)。
470 | zip_entry_compressionmethod() 函数返回 zip 档案项目的压缩方法。
471 | zip_entry_compressedsize() 函数返回 zip 档案项目的压缩文件尺寸。
472 | zip_entry_close() 函数关闭由 zip_entry_open() 函数打开的 zip 档案文件。
473 | zip_close() 函数关闭由 zip_open() 函数打开的 zip 档案文件。
474 | xml_set_unparsed_entity_decl_handler() 函数规定在遇到无法解析的实体名称(NDATA)声明时被调用的函数。
475 | xml_set_processing_instruction_handler() 函数规定当解析器在 xml 文档中找到处理指令时所调用的函数。
476 | xml_set_object() 函数允许在对象中使用 xml 解析器。
477 | xml_set_notation_decl_handler() 函数规定当解析器在 xml 文档中找到符号声明时被调用的函数。
478 | xml_set_external_entity_ref_handler() 函数规定当解析器在 xml 文档中找到外部实体时被调用的函数。
479 | xml_set_element_handler() 函数建立起始和终止元素处理器。
480 | xml_set_default_handler() 函数为 xml 解析器建立默认的数据处理器。
481 | xml_set_character_data_handler() 函数建立字符数据处理器。
482 | xml_parser_set_option() 函数为 xml 解析器进行选项设置。
483 | xml_parser_get_option() 函数从 xml 解析器获取选项设置信息。
484 | xml_parser_free() 函数释放 xml 解析器。
485 | xml_parser_create() 函数创建 xml 解析器。
486 | xml_parser_create_ns() 函数创建带有命名空间支持的 xml 解析器。
487 | xml_parse_into_struct() 函数把 xml 数据解析到数组中。
488 | xml_parse() 函数解析 xml 文档。
489 | xml_get_error_code() 函数获取 xml 解析器错误代码。
490 | xml_get_current_line_number() 函数获取 xml 解析器的当前行号。
491 | xml_get_current_column_number() 函数获取 xml 解析器的当前列号。
492 | xml_get_current_byte_index() 函数获取 xml 解析器的当前字节索引。
493 | xml_error_string() 函数获取 xml 解析器的错误描述。
494 | utf8_encode() 函数把 ISO-8859-1 字符串编码为 UTF-8。
495 | utf8_decode() 函数把 UTF-8 字符串解码为 ISO-8859-1。
496 | wordwrap() 函数按照指定长度对字符串进行折行处理。
497 | vsprintf() 函数把格式化字符串写入变量中。
498 | vprintf() 函数输出格式化的字符串。
499 | vfprintf() 函数把格式化的字符串写到指定的输出流。
500 | ucwords() 函数把字符串中每个单词的首字符转换为大写。
501 | ucfirst() 函数把字符串中的首字符转换为大写。
502 | trim() 函数从字符串的两端删除空白字符和其他预定义字符。
503 | substr_replace() 函数把字符串的一部分替换为另一个字符串。
504 | substr_count() 函数计算子串在字符串中出现的次数。
505 | substr_compare() 函数从指定的开始长度比较两个字符串。
506 | substr() 函数返回字符串的一部分。
507 | strtr() 函数转换字符串中特定的字符。
508 | strtoupper() 函数把字符串转换为大写。
509 | strtolower() 函数把字符串转换为小写。
510 | strtok() 函数把字符串分割为更小的字符串。
511 | strstr() 函数搜索一个字符串在另一个字符串中的第一次出现。
512 | strspn() 函数返回在字符串中包含的特定字符的数目。
513 | strrpos() 函数查找字符串在另一个字符串中最后一次出现的位置。
514 | strripos() 函数查找字符串在另一个字符串中最后一次出现的位置。
515 | strrev() 函数反转字符串。
516 | strrchr() 函数查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符。
517 | strpos() 函数返回字符串在另一个字符串中第一次出现的位置。
518 | strpbrk() 函数在字符串中搜索指定字符中的任意一个。
519 | strncmp() 函数比较两个字符串。
520 | strncasecmp() 函数比较两个字符串。
521 | strnatcmp() 函数使用一种“自然”算法来比较两个字符串。
522 | strnatcasecmp() 函数使用一种“自然”算法来比较两个字符串。
523 | strlen() 函数返回字符串的长度。
524 | stristr() 函数查找字符串在另一个字符串中第一次出现的位置。
525 | stripos() 函数返回字符串在另一个字符串中第一次出现的位置。
526 | stripslashes() 函数删除由 addslashes() 函数添加的反斜杠。
527 | stripcslashes() 函数删除由 addcslashes() 函数添加的反斜杠。
528 | strip_tags() 函数剥去 HTML、xml 以及 PHP 的标签。
529 | strcspn() 函数返回在找到任何指定的字符之前,在字符串查找的字符数。
530 | strcoll() 函数比较两个字符串。
531 | strcmp() 函数比较两个字符串。
532 | strchr() 函数搜索一个字符串在另一个字符串中的第一次出现。
533 | strcasecmp() 函数比较两个字符串。
534 | str_word_count() 函数计算字符串中的单词数。
535 | str_split() 函数把字符串分割到数组中。
536 | str_shuffle() 函数随机地打乱字符串中的所有字符。
537 | str_rot13() 函数对字符串执行 ROT13 编码。
538 | str_replace() 函数使用一个字符串替换字符串中的另一些字符。
539 | str_repeat() 函数把字符串重复指定的次数。
540 | str_pad() 函数把字符串填充为指定的长度。
541 | str_ireplace() 函数使用一个字符串替换字符串中的另一些字符。
542 | sscanf() 函数根据指定的格式解析来自一个字符串的输入。
543 | sprintf() 函数把格式化的字符串写写入一个变量中。
544 | soundex() 函数计算字符串的 soundex 键。
545 | similar_text() 函数计算两个字符串的匹配字符的数目。
546 | sha1_file() 函数计算文件的 SHA-1 散列。
547 | sha1() 函数计算字符串的 SHA-1 散列。
548 | setlocale() 函数设置地区信息(地域信息)。
549 | rtrim() P rtrim() 函数
550 | PHP String 函数
551 | quotemeta() 函数在字符串中某些预定义的字符前添加反斜杠。
552 | quoted_printable_decode() 函数对经过 quoted-printable 编码后的字符串进行解码,返回 8 位的字符串。
553 | printf() 函数输出格式化的字符串。
554 | print() 函数输出一个或多个字符串。
555 | parse_str() 函数把查询字符串解析到变量中。
556 | ord() 函数返回字符串第一个字符的 ASCII 值。
557 | number_format() 函数通过千位分组来格式化数字。
558 | nl2br() 函数在字符串中的每个新行 (\n) 之前插入 HTML 换行符 (
)。
559 | nl_langinfo() 函数返回指定的本地信息。
560 | money_format() 函数把字符串格式化为货币字符串。
561 | metaphone() 函数计算字符串的 metaphone 键。
562 | md5_file() 函数计算文件的 MD5 散列。
563 | md5() 函数计算字符串的 MD5 散列。
564 | ltrim() 函数从字符串左侧删除空格或其他预定义字符。
565 | localeconv() 函数返回包含本地数字及货币信息格式的数组。
566 | levenshtein() 函数返回两个字符串之间的 Levenshtein 距离。
567 | join() 函数把数组元素组合为一个字符串。
568 | implode() 函数把数组元素组合为一个字符串。
569 | htmlspecialchars() 函数把一些预定义的字符转换为 HTML 实体。
570 | html_entity_decode() chars_decode() 函数
571 |
572 | PHP String 函数
573 | htmlentities() 函数把字符转换为 HTML 实体。
574 | html_entity_decode() 函数把 HTML 实体转换为字符。
575 | hebrevc() 函数把希伯来文本从右至左的流转换为左至右的流。它也会把新行 (\n) 转换为
。
576 | hebrev() 函数把希伯来文本从右至左的流转换为左至右的流。
577 | get_html_translation_table() 函数返回被 htmlentities() 和 htmlspecialchars() 函数使用的翻译表。
578 | fprintf() 函数把格式化的字符串写到指定的输出流(例如:文件或数据库)。
579 | explode() 函数把字符串分割为数组。
580 | echo() 函数输出一个或多个字符串。
581 | crypt() 函数返回使用 DES、Blowfish 或 MD5 加密的字符串。
582 | crc32() 函数计算一个字符串的 crc32 多项式。
583 | count_chars() 函数返回字符串所用字符的信息。
584 | convert_uuencode() 函数使用 uuencode 算法对字符串进行编码。
585 | convert_uudecode() 函数对 uuencode 编码的字符串进行解码。
586 | convert_cyr_string() 函数把字符由一种 Cyrillic 字符转换成另一种。
587 | chunk_split() 函数把字符串分割为一连串更小的部分。
588 | chr() 函数从指定的 ASCII 值返回字符。
589 | chop() 函数从字符串的末端开始删除空白字符或其他预定义字符。
590 | bin2hex() 函数把 ASCII 字符的字符串转换为十六进制值。
591 | addslashes() 函数在指定的预定义字符前添加反斜杠。
592 | addcslashes() 函数在指定的字符前添加反斜杠。
593 | xpath() 函数运行对 xml 文档的 XPath 查询。
594 | simplexml_load_string() 函数把 xml 字符串载入对象中。
595 | simplexml_load_file() 函数把 xml 文档载入对象中。
596 | simplexml_import_dom() 函数把 DOM 节点转换为 SimplexmlElement 对象。
597 | registerXPathNamespace() 函数为下一次 XPath 查询创建命名空间语境。
598 | getNamespace() 函数获取在 xml 文档中使用的命名空间。
599 | getName() 函数从 SimplexmlElement 对象获取 xml 元素的名称。
600 | getDocNamespaces() 函数从 SimplexmlElement 对象返回在 xml 文档中声明的命名空间。
601 | children() 函数获取指定节点的子节点。
602 | attributes() 函数获取 Simplexml 元素的属性。
603 | asxml() 函数以字符串的形式从 SimplexmlElement 对象返回 xml 文档。
604 | addChild() 函数向指定的 xml 节点添加一个子节点。
605 | addAttribute() 函数给 Simplexml 元素添加一个属性。
606 | __construct() 函数创建一个新的 SimplexmlElement 对象。
607 | mysql_unbuffered_query() 函数向 MySQL 发送一条 SQL 查询(不获取 / 缓存结果)。
608 | mysql_thread_id() 函数返回当前线程的 ID。
609 | mysql_stat() 函数返回 MySQL 服务器的当前系统状态。
610 | mysql_select_db() 函数设置活动的 MySQL 数据库。
611 | mysql_result() 函数返回结果集中一个字段的值。
612 | mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。
613 | mysql_query() 函数执行一条 MySQL 查询。
614 | mysql_ping() 函数 Ping 一个服务器连接,如果没有连接则重新连接。
615 | mysql_pconnect() 函数打开一个到 MySQL 服务器的持久连接。
616 | mysql_num_rows() 函数返回结果集中行的数目。
617 | mysql_num_fields() 函数返回结果集中字段的数。
618 | mysql_list_processes() 函数列出 MySQL 进程。
619 | mysql_list_dbs() 函数列出 MySQL 服务器中所有的数据库。
620 | mysql_insert_id() 函数返回上一步 INSERT 操作产生的 ID。
621 | mysql_info() 函数返回最近一条查询的信息。
622 | mysql_get_server_info() 函数返回 MySQL 服务器的信息。
623 | mysql_get_proto_info() 函数返回 MySQL 协议的信息。
624 | mysql_get_host_info() 函数返回 MySQL 主机的信息。
625 | mysql_get_client_info() 函数返回 MySQL 客户端信息。
626 | mysql_free_result() 函数释放结果内存。
627 | mysql_field_type() 函数返回结果集中指定字段的类型。
628 | mysql_field_table() 函数返回指定字段所在的表名。
629 | mysql_field_seek() 函数将结果集中的指针设定为指定的字段偏移量。
630 | mysql_field_name() 函数取得结果中指定字段的字段名。
631 | mysql_field_len() 函数返回指定字段的长度。
632 | mysql_field_flags() 函数从结果中取得和指定字段关联的标志。
633 | mysql_fetch_row() 函数从结果集中取得一行作为数字数组。
634 | mysql_fetch_object() 函数从结果集(记录集)中取得一行作为对象。
635 | mysql_fetch_lengths() 函数取得一行中每个字段的内容的长度。
636 | mysql_fetch_field() 函数从结果集中取得列信息并作为对象返回。
637 | mysql_fetch_assoc() 函数从结果集中取得一行作为关联数组。
638 | mysql_fetch_array() 函数从结果集中取得一行作为关联数组,或数字数组,或二者兼有
639 | mysql_error() 函数返回上一个 MySQL 操作产生的文本错误信息。
640 | mysql_errno() 函数返回上一个 MySQL 操作中的错误信息的数字编码。
641 | mysql_db_name() 函数取得 mysql_list_dbs() 调用所返回的数据库名。
642 | mysql_data_seek() 函数移动内部结果的指针。
643 | mysql_connect() 函数打开非持久的 MySQL 连接。
644 | mysql_close() 函数关闭非持久的 MySQL 连接。
645 | mysql_client_encoding() 函数返回当前连接的字符集的名称。
646 | mysql_affected_rows() 函数返回前一次 MySQL 操作所影响的记录行数。
647 | tanh() 函数返回双曲正切。
648 | tan() 函数返回正切。
649 | srand() 函数播下随机数发生器种子。
650 | sqrt() 函数返回一个数的平方根。
651 | sinh() 函数返回一个数的双曲正弦。
652 | sin() 函数返回一个数的正弦。
653 | round() 函数对浮点数进行四舍五入。
654 | rand() 函数返回随机整数。
655 | rad2deg() 函数把弧度数转换为角度数。
656 | pow() 函数返回 x 的 y 次方。
657 | pi() 函数返回圆周率的值。
658 | octdec() 函数把八进制转换为十进制。
659 | mt_srand() 播种 Mersenne Twister 随机数生成器。
660 | mt_rand() 使用 Mersenne Twister 算法返回随机整数。
661 | mt_getrandmax() 显示随机数的最大可能值。
662 | min() 返回最小值。
663 | max() 返回最大值。
664 | log1p() 以返回 log(1 + x),甚至当 x 的值接近零也能计算出准确结果。
665 | log10() 以 10 为底的对数。
666 | log() 返回自然对数。
667 | lcg_value() 组合线性同余发生器。
668 | is_nan() 判断是否为合法数值。
669 | is_infinite() 判断是否为无限值。
670 | is_finite() 函数判断是否为有限值。
671 | hypot() 函数计算一直角三角形的斜边长度。
672 | hexdec() 函数把十六进制转换为十进制。
673 | fmod() 函数显示随机数最大的可能值。
674 | fmod() 函数返回除法的浮点数余数。
675 | floor() 函数向下舍入为最接近的整数。
676 | expm1() 函数返回 exp(x) - 1,甚至当 number 的值接近零也能计算出准确结果。
677 | exp() 函数计算 e 的指数。
678 | deg2rad() 函数将角度转换为弧度。
679 | decoct() 函数把十进制转换为八进制。
680 | dechex() 函数把十进制转换为十六进制。
681 | decbin() 函数把十进制转换为二进制。
682 | cosh() 函数返回一个数的双曲余弦。
683 | cos() 函数返回一个数的余弦。
684 | ceil() 函数向上舍入为最接近的整数。
685 | bindec() 函数把二进制转换为十进制。
686 | base_convert() 函数在任意进制之间转换数字。
687 | atanh() 函数返回一个角度的反双曲正切。
688 | atan() 和 atan2() 和 atan2() 函数
689 |
690 | PHP Math 函数
691 | atan() 和 atan2() 和 atan2() 函数
692 |
693 | PHP Math 函数
694 | asinh() 函数返回一个数的反双曲正弦。
695 | asin() 函数返回不同数值的反正弦,返回的结果是介于 -PI/2 与 PI/2 之间的弧度值。
696 | acosh() 函数返回一个数的反双曲余弦。
697 | acos() 函数返回一个数的反余弦。
698 | abs() 函数返回一个数的绝对值。
699 | mail() 函数允许您从脚本中直接发送电子邮件。
700 | libxml_use_internal_errors() 函数禁用标准的 libxml 错误,并启用用户错误处理。
701 | libxml_get_last_error() 函数从 libxml 错误缓冲中获取最后一个错误。
702 | libxml_get_errors() 函数从 libxml 错误缓冲中获取错误。
703 | libxml_clear_errors() 函数清空 libxml 错误缓冲。
704 | setrawcookie() 函数不对 cookie 值进行 URL 编码,发送一个 HTTP cookie。
705 | setcookie() 函数向客户端发送一个 HTTP cookie。
706 | headers_sent() 函数检查 HTTP 报头是否发送/已发送到何处。
707 | headers_list() 函数返回已发送的(或待发送的)响应头部的一个列表。
708 | header() 函数向客户端发送原始的 HTTP 报头。
709 | ftp_systype() 函数返回远程 FTP 服务器的系统类型标识符。
710 | ftp_ssl_connect() 函数打开一个安全的 SSL-FTP 连接。
711 | ftp_size() 函数返回指定文件的大小。
712 | ftp_site() 函数向服务器发送 SITE 命令。
713 | ftp_set_option() 函数设置各种 FTP 运行时选项。
714 | ftp_rmdir() 函数删除一个目录。
715 | ftp_rename() 函数更改 FTP 服务器上的文件或目录名。
716 | ftp_rawlist() 函数返回指定目录中文件的详细列表。
717 | ftp_raw() 函数向 FTP 服务器发送一个 raw 命令。
718 | ftp_quit() 函数关闭 FTP 连接。
719 | ftp_pwd() 函数返回当前目录名。
720 | ftp_put() 函数把文件上传到服务器。
721 | ftp_pasv() 函数把被动模式设置为打开或关闭。
722 | ftp_nlist() 函数返回指定目录的文件列表。
723 | ftp_nb_put() 函数把文件上传到服务器 (non-blocking)。
724 | ftp_nb_get() 函数从 FTP 服务器上获取文件并写入本地文件 (non-blocking)。
725 | ftp_nb_fput() 函数上传一个已打开的文件,并在 FTP 服务器上把它保存为文件 (non-blocking)。
726 | ftp_nb_fget() 函数从 FTP 服务器上下载一个文件并保存到本地已经打开的一个文件中 (non-blocking)。
727 | ftp_nb_continue() 函数连续获取 / 发送文件。
728 | ftp_mkdir() 函数在 FTP 服务器上建立新目录。
729 | ftp_mdtm() 函数返回指定文件的最后修改时间。
730 | ftp_login() 函数登录 FTP 服务器。
731 | ftp_get() 函数从 FTP 服务器上下载一个文件。
732 | ftp_get_option() 函数返回当前 FTP 连接的各种不同的选项设置。
733 | ftp_fput() 函数上传一个已经打开的文件到 FTP 服务器。
734 | ftp_fget() 函数从 FTP 服务器上下载一个文件并保存到本地一个已经打开的文件中。
735 | ftp_exec() 函数请求在 FTP 服务器上执行一个程序或命令。
736 | ftp_delete() 函数删除 FTP 服务器上的一个文件。
737 | ftp_connect() 函数建立一个新的 FTP 连接。
738 | ftp_close() 函数关闭 FTP 连接。
739 | ftp_chmod() 函数设置 FTP 服务器上指定文件的权限。
740 | ftp_chdir() 函数改变 FTP 服务器上的当前目录。
741 | ftp_cdup() 函数把当前目录改变为 FTP 服务器上的父目录。
742 | ftp_alloc() 函数为要上传到 FTP 服务器的文件分配空间。
743 | filter_var() 函数通过指定的过滤器过滤变量。
744 | filter_var_array() 函数获取多项变量,并进行过滤。
745 | filter_list() 函数返回包含所有得到支持的过滤器的一个数组。
746 | filter_input_array() 函数从脚本外部获取多项输入,并进行过滤。
747 | filter_input() 函数从脚本外部获取输入,并进行过滤。
748 | filter_id() 函数返回指定过滤器的 ID 号。
749 | filter_has_var() 函数检查是否存在指定输入类型的变量。
750 | unlink() 函数删除文件。
751 | umask() 函数改变当前的 umask。
752 | touch() 函数设置指定文件的访问和修改时间。
753 | tmpfile() 函数以读写(w+)模式建立一个具有唯一文件名的临时文件。
754 | tempnam() 函数创建一个具有唯一文件名的临时文件。
755 | symlink() 函数创建符号连接。
756 | stat() 函数返回关于文件的信息。
757 | set_file_buffer() 函数设置打开文件的缓冲大小。
758 | rmdir() 函数删除空的目录。
759 | rewind() 函数将文件指针的位置倒回文件的开头。
760 | rename() 函数重命名文件或目录。
761 | realpath() 函数返回绝对路径。
762 | readlink() 函数返回符号连接指向的目标。
763 | readfile() 函数输出一个文件。
764 | popen() 函数打开进程文件指针。
765 | pclose() 函数关闭由 popen() 打开的管道。
766 | pathinfo() 函数以数组的形式返回文件路径的信息。
767 | parse_ini_file() 函数解析一个配置文件,并以数组的形式返回其中的设置。
768 | move_uploaded_file() 函数将上传的文件移动到新位置。
769 | mkdir() 函数创建目录。
770 | lstat() 函数返回关于文件或符号连接的信息。
771 | linkinfo() 函数返回连接的信息。
772 | link() 函数建立一个硬连接。
773 | is_writeable() 函数判断指定的文件是否可写。
774 | is_writable() 函数判断指定的文件是否可写。
775 | is_uploaded_file() 函数判断指定的文件是否是通过 HTTP POST 上传的。
776 | is_readable() 函数判断指定文件名是否可读。
777 | is_link() 函数判断指定文件名是否为一个符号连接。
778 | is_file() 函数检查指定的文件名是否是正常的文件。
779 | is_executable() 函数检查指定的文件是否可执行。
780 | is_dir() 函数检查指定的文件是否是目录。
781 | glob() 函数返回匹配指定模式的文件名或目录。
782 | fwrite() 函数写入文件(可安全用于二进制文件)。
783 | ftruncate() 函数把文件截断到指定的长度。
784 | ftell() 函数在打开文件中的当前位置。
785 | fstat() 函数返回关于打开文件的信息。
786 | fseek() 函数在打开的文件中定位。
787 | fscanf() 函数根据指定的格式对来自打开的文件的输入进行解析。
788 | fread() 函数读取文件(可安全用于二进制文件)。
789 | fputs() 函数写入文件(可安全用于二进制文件)。
790 | fputcsv() 函数将行格式化为 CSV 并写入一个打开的文件。
791 | fpassthru() 函数输出文件指针处的所有剩余数据。
792 | fopen() 函数打开文件或者 URL。
793 | fnmatch() 函数根据指定的模式来匹配文件名或字符串。
794 | flock() 函数锁定或释放文件。
795 | filetype() 函数返回指定文件或目录的类型。
796 | filesize() 函数返回指定文件的大小。
797 | fileperms() 函数返回文件或目录的权限。
798 | fileowner() 函数返回文件的所有者。
799 | filemtime() 函数返回文件内容上次的修改时间。
800 | fileinode() 函数返回文件的 inode 编号。
801 | filegroup() 函数返回指定文件的组 ID。
802 | filectime() 函数返回指定文件的上次 inode 修改时间。
803 | fileatime() 函数返回指定文件的上次访问时间。
804 | file_put_contents() 函数把一个字符串写入文件中。
805 | file_get_contents() 函数把整个文件读入一个字符串中。
806 | file_exists() 函数检查文件或目录是否存在。
807 | file() 函数把整个文件读入一个数组中。
808 | fgetss() 函数从打开的文件中读取一行并过滤掉 HTML 和 PHP 标记。
809 | fgets() 函数从文件指针中读取一行。
810 | fgetcsv() 函数从文件指针中读入一行并解析 CSV 字段。
811 | fgetc() 函数从文件指针中读取一个字符。
812 | fflush() 函数将缓冲内容输出到文件。
813 | feof() 函数检测是否已到达文件末尾 (eof)。
814 | fclose() 函数关闭一个打开文件。
815 | diskfreespace() 函数返回目录中的可用空间。该函数是 disk_free_space() 函数的别名。
816 | disk_total_space() 函数返回指定目录的磁盘总大小。
817 | disk_free_space() 函数返回目录中的可用空间
818 | dirname() 函数返回路径中的目录部分。
819 | clearstatcache() 函数拷贝文件。
820 | clearstatcache() 函数清除文件状态缓存。
821 | chown() 函数改变指定文件的所有者。
822 | chmod() 函数改变文件模式。
823 | chgrp() 函数改变文件所属的组。
824 | basename() 函数返回路径中的文件名部分。
825 | set_exception_handler() handler() 函数
826 |
827 | PHP Error 和 Logging 函数
828 | set_exception_handler() 函数设置用户自定义的异常处理函数。
829 | set_error_handler() 函数设置用户自定义的错误处理函数。
830 | restore_exception_handler() 函数恢复之前的异常处理程序,该程序是由 set_exception_handler() 函数改变的。
831 | restore_error_handler() 函数恢复之前的错误处理程序,该程序是由 set_error_handler() 函数改变的。
832 | error_reporting() 设置 PHP 的报错级别并返回当前级别。
833 | error_log() 函数向服务器错误记录、文件或远程目标发送一个错误。
834 | error_get_last() 函数获取最后发生的错误。
835 | debug_print_backtrace() 函数输出 backtrace。
836 | debug_backtrace() cktrace() 函数
837 |
838 | PHP Error 和 Logging 函数
839 | scandir() 函数返回一个数组,其中包含指定路径中的文件和目录。
840 | rewinddir() 函数重置由 opendir() 打开的目录句柄。
841 | readdir() 函数返回由 opendir() 打开的目录句柄中的条目。
842 | opendir() 函数打开一个目录句柄,可由 closedir(),readdir() 和 rewinddir() 使用。
843 | getcwd() 函数返回当前目录。
844 | closedir() 函数关闭由 opendir() 函数打开的目录句柄。
845 | dir() 函数打开一个目录句柄,并返回一个对象。这个对象包含三个方法:read() , rewind() 以及 close()。
846 | chroot() 函数把当前进程的根目录改变为指定的目录。
847 | chdir() 函数把当前的目录改变为指定的目录。
848 | time() 函数返回当前时间的 Unix 时间戳。
849 | strtotime() 函数将任何英文文本的日期时间描述解析为 Unix 时间戳。
850 | strptime() 函数解析由 strftime() 生成的日期/时间。
851 | strftime() 函数根据区域设置格式化本地时间/日期。
852 | mktime() 函数返回一个日期的 Unix 时间戳。
853 | microtime() 函数返回当前 Unix 时间戳和微秒数。
854 | localtime() 函数返回本地时间(一个数组)。
855 | idate() 函数将本地时间/日期格式化为整数。
856 | gmstrftime() 函数根据本地区域设置格式化 GMT/UTC 时间/日期。
857 | gmmktime() 函数取得 GMT 日期的 UNIX 时间戳。
858 | gmdate() 函数格式化 GMT/UTC 日期/时间。
859 | gettimeofday() 函数返回一个包含当前时间信息的数组。
860 | getdate() 函数取得日期/时间信息。
861 | date() 函数格式化一个本地时间/日期。
862 | date_sunset() 函数返回指定的日期与地点的日落时间。
863 | date_sunrise() 函数返回指定的日期与地点的日出时间。
864 | date_default_timezone_set() 函数设置用在脚本中所有日期/时间函数的默认时区。
865 | date_default_timezone_get() 函数返回脚本中所有日期时间函数所使用的默认时区。
866 | checkdate() 函数验证一个格里高里日期。
867 | UnixToJD() 函数把 Unix 时间戳转换为儒略日计数。
868 | JulianToJD() 函数把儒略历转换为儒略日计数。
869 | JewishToJD() 函数把犹太历法转换为儒略日计数。
870 | JDToUnix() 函数把儒略日计数转换为 Unix 时间戳。
871 | JDToGregorian() lian() 函数
872 |
873 | PHP Array 函数
874 | JDToGregorian() wish() 函数
875 |
876 | PHP Array 函数
877 | JDToGregorian() 函数把儒略日计数转换为格利高里历法。
878 | JDToFrench() 函数把儒略日计数转换为法国共和国历法。
879 | JDMonthName() 函数返回指定历法的月份字符串。
880 | JDDayOfWeek() 函数返回日期在周几。
881 | GregorianToJD() 函数将格利高里历法转换成为儒略日计数。
882 | FrenchToJD() 函数将法国共和历法转换成为儒略日计数。
883 | easter_days() 函数返回指定年份的复活节与 3 月 21 日之间的天数。
884 | easter_date() 函数返回指定年份的复活节午夜的 Unix 时间戳。
885 | cal_to_jd() 函数把指定的日期转换为儒略日计数。
886 | cal_info() 函数返回一个数组,其中包含了关于给定历法的信息。
887 | cal_from_jd() 函数把儒略日计数转换为指定历法的日期。
888 | cal_days_in_month() 函数针对指定的年份和日历,返回一个月中的天数。
889 | usort() 函数使用用户自定义的函数对数组排序。
890 | uksort() 函数使用用户自定义的比较函数按照键名对数组排序,并保持索引关系。
891 | uasort() 函数使用用户自定义的比较函数对数组排序,并保持索引关联(不为元素分配新的键)。
892 | sort() 函数按升序对给定数组的值排序。
893 | sizeof() 函数计算数组中的单元数目或对象中的属性个数。
894 | shuffle() 函数把数组中的元素按随机顺序重新排列。
895 | rsort() 函数对数组的元素按照键值进行逆向排序。与 arsort() 的功能基本相同。
896 | reset() 函数把数组的内部指针指向第一个元素,并返
897 |
898 |
--------------------------------------------------------------------------------
/regex.php:
--------------------------------------------------------------------------------
1 | $username,
15 | 'password' => $password
16 | ));
17 |
18 | // Send a text message to '999-123-4567'
19 | $result = $router->send('Wake up!', array(9991234567), true);
20 |
21 | // result: Result is: Array ( [messages] => Array ( [19896128] => 9991234567 ) [sent_text] => Wake up! [parts_count] => 1 )
22 | //2. 根据IP查找地址
23 |
24 | function detect_city($ip) {
25 | $default = 'UNKNOWN';
26 | if (!is_string($ip) || strlen($ip) < 1 || $ip == '127.0.0.1' || $ip == 'localhost')
27 | $ip = '8.8.8.8';
28 | $curlopt_useragent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6 (.NET CLR 3.5.30729)';
29 | $url = 'http://ipinfodb.com/ip_locator.php?ip=' . urlencode($ip);
30 | $ch = curl_init();
31 | $curl_opt = array(
32 | CURLOPT_FOLLOWLOCATION => 1,
33 | CURLOPT_HEADER => 0,
34 | CURLOPT_RETURNTRANSFER => 1,
35 | CURLOPT_USERAGENT => $curlopt_useragent,
36 | CURLOPT_URL => $url,
37 | CURLOPT_TIMEOUT => 1,
38 | CURLOPT_REFERER => 'http://' . $_SERVER['HTTP_HOST'],
39 | );
40 | curl_setopt_array($ch, $curl_opt);
41 | $content = curl_exec($ch);
42 | if (!is_null($curl_info)) {
43 | $curl_info = curl_getinfo($ch);
44 | }
45 | curl_close($ch);
46 | if ( preg_match('{City : ([^<]*)}i', $content, $regs) ) {
47 | $city = $regs[1];
48 | }
49 | if ( preg_match('{State/Province : ([^<]*)}i', $content, $regs) ) {
50 | $state = $regs[1];
51 | }
52 | if( $city!='' && $state!='' ){
53 | $location = $city . ', ' . $state;
54 | return $location;
55 | }else{
56 | return $default;
57 | }
58 | }
59 |
60 | //3. 显示网页的源代码
61 |
62 | // display source code
63 | $lines = file('http://google.com/');
64 | foreach ($lines as $line_num => $line) {
65 | // loop thru each line and prepend line numbers
66 | echo "Line #{$line_num} : " . htmlspecialchars($line) . "
\n";
67 | }
68 |
69 |
70 | //4. 检查服务器是否使用HTTPS
71 |
72 | if ($_SERVER['HTTPS'] != "on") {
73 | echo "This is not HTTPS";
74 | }else{
75 | echo "This is HTTPS";
76 | }
77 |
78 |
79 | //5. 显示Facebook粉丝数量
80 |
81 | function fb_fan_count($facebook_name){
82 | // Example: https://graph.facebook.com/digimantra
83 | $data = json_decode(file_get_contents("https://graph.facebook.com/".$facebook_name));
84 | echo $data->likes;
85 | }
86 |
87 | //6. 检测图片的主要颜色
88 |
89 | $i = imagecreatefromjpeg("image.jpg");
90 | for ($x=0;$x> 16) & 0xFF;
94 | $g = ($rgb >> '?')& 0xFF;
95 | $b = $rgb & 0xFF;
96 |
97 | $rTotal += $r;
98 | $gTotal += $g;
99 | $bTotal += $b;
100 | $total++;
101 | }
102 | }
103 | $rAverage = round($rTotal/$total);
104 | $gAverage = round($gTotal/$total);
105 | $bAverage = round($bTotal/$total);
106 |
107 | //7. 获取内存使用信息
108 |
109 | echo "Initial: ".memory_get_usage()." bytes \n";
110 | /* prints
111 | Initial: 361400 bytes
112 | */
113 |
114 | // let's use up some memory
115 | for ($i = 0; $i < 100000; $i++) {
116 | $array []= md5($i);
117 | }
118 |
119 | // let's remove half of the array
120 | for ($i = 0; $i < 100000; $i++) {
121 | unset($array[$i]);
122 | }
123 |
124 | echo "Final: ".memory_get_usage()." bytes \n";
125 | /* prints
126 | Final: 885912 bytes
127 | */
128 |
129 | echo "Peak: ".memory_get_peak_usage()." bytes \n";
130 | /* prints
131 | Peak: 13687072 bytes
132 | */
133 |
134 | //8. 使用 gzcompress() 压缩数据
135 |
136 | $string =
137 | "Lorem ipsum dolor sit amet, consectetur
138 | adipiscing elit. Nunc ut elit id mi ultricies
139 | adipiscing. Nulla facilisi. Praesent pulvinar,
140 | sapien vel feugiat vestibulum, nulla dui pretium orci,
141 | non ultricies elit lacus quis ante. Lorem ipsum dolor
142 | sit amet, consectetur adipiscing elit. Aliquam
143 | pretium ullamcorper urna quis iaculis. Etiam ac massa
144 | sed turpis tempor luctus. Curabitur sed nibh eu elit
145 | mollis congue. Praesent ipsum diam, consectetur vitae
146 | ornare a, aliquam a nunc. In id magna pellentesque
147 | tellus posuere adipiscing. Sed non mi metus, at lacinia
148 | augue. Sed magna nisi, ornare in mollis in, mollis
149 | sed nunc. Etiam at justo in leo congue mollis.
150 | Nullam in neque eget metus hendrerit scelerisque
151 | eu non enim. Ut malesuada lacus eu nulla bibendum
152 | id euismod urna sodales. ";
153 |
154 | $compressed = gzcompress($string);
155 |
156 | echo "Original size: ". strlen($string)."\n";
157 | /* prints
158 | Original size: 800
159 | */
160 |
161 | echo "Compressed size: ". strlen($compressed)."\n";
162 | /* prints
163 | Compressed size: 418
164 | */
165 |
166 | // getting it back
167 | $original = gzuncompress($compressed);
168 |
169 | //9. 使用PHP做Whois检查
170 |
171 | function whois_query($domain) {
172 | // fix the domain name:
173 | $domain = strtolower(trim($domain));
174 | $domain = preg_replace('/^http:\/\//i', '', $domain);
175 | $domain = preg_replace('/^www\./i', '', $domain);
176 | $domain = explode('/', $domain);
177 | $domain = trim($domain[0]);
178 |
179 | // split the TLD from domain name
180 | $_domain = explode('.', $domain);
181 | $lst = count($_domain)-1;
182 | $ext = $_domain[$lst];
183 |
184 | // You find resources and lists
185 | // like these on wikipedia:
186 | //
187 | // http://de.wikipedia.org/wiki/Whois
188 | //
189 | $servers = array(
190 | "biz" => "whois.neulevel.biz",
191 | "com" => "whois.internic.net",
192 | "us" => "whois.nic.us",
193 | "coop" => "whois.nic.coop",
194 | "info" => "whois.nic.info",
195 | "name" => "whois.nic.name",
196 | "net" => "whois.internic.net",
197 | "gov" => "whois.nic.gov",
198 | "edu" => "whois.internic.net",
199 | "mil" => "rs.internic.net",
200 | "int" => "whois.iana.org",
201 | "ac" => "whois.nic.ac",
202 | "ae" => "whois.uaenic.ae",
203 | "at" => "whois.ripe.net",
204 | "au" => "whois.aunic.net",
205 | "be" => "whois.dns.be",
206 | "bg" => "whois.ripe.net",
207 | "br" => "whois.registro.br",
208 | "bz" => "whois.belizenic.bz",
209 | "ca" => "whois.cira.ca",
210 | "cc" => "whois.nic.cc",
211 | "ch" => "whois.nic.ch",
212 | "cl" => "whois.nic.cl",
213 | "cn" => "whois.cnnic.net.cn",
214 | "cz" => "whois.nic.cz",
215 | "de" => "whois.nic.de",
216 | "fr" => "whois.nic.fr",
217 | "hu" => "whois.nic.hu",
218 | "ie" => "whois.domainregistry.ie",
219 | "il" => "whois.isoc.org.il",
220 | "in" => "whois.ncst.ernet.in",
221 | "ir" => "whois.nic.ir",
222 | "mc" => "whois.ripe.net",
223 | "to" => "whois.tonic.to",
224 | "tv" => "whois.tv",
225 | "ru" => "whois.ripn.net",
226 | "org" => "whois.pir.org",
227 | "aero" => "whois.information.aero",
228 | "nl" => "whois.domain-registry.nl"
229 | );
230 |
231 | if (!isset($servers[$ext])){
232 | die('Error: No matching nic server found!');
233 | }
234 |
235 | $nic_server = $servers[$ext];
236 |
237 | $output = '';
238 |
239 | // connect to whois server:
240 | if ($conn = fsockopen ($nic_server, 43)) {
241 | fputs($conn, $domain."\r\n");
242 | while(!feof($conn)) {
243 | $output .= fgets($conn,128);
244 | }
245 | fclose($conn);
246 | }
247 | else { die('Error: Could not connect to ' . $nic_server . '!'); }
248 |
249 | return $output;
250 | }
251 |
252 |
253 | //10. 通过Email发送PHP错误
254 |
255 | // Our custom error handler
256 | function nettuts_error_handler($number, $message, $file, $line, $vars){
257 | $email = "
258 | An error ($number) occurred on line
259 | $line and in the file: $file.
260 |
$message
";
261 |
262 | $email .= "" . print_r($vars, 1) . "
";
263 |
264 | $headers = 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
265 |
266 | // Email the error to someone...
267 | error_log($email, 1, 'you@youremail.com', $headers);
268 |
269 | // Make sure that you decide how to respond to errors (on the user's side)
270 | // Either echo an error message, or kill the entire project. Up to you...
271 | // The code below ensures that we only "die" if the error was more than
272 | // just a NOTICE.
273 | if ( ($number !== E_NOTICE) && ($number < 2048) ) {
274 | die("There was an error. Please try again later.");
275 | }
276 | }
277 |
278 | // We should use our custom function to handle errors.
279 | set_error_handler('nettuts_error_handler');
280 |
281 | // Trigger an error... (var doesn't exist)
282 | echo $somevarthatdoesnotexist;
283 |
284 | //来源:https://zhuanlan.zhihu.com/p/30590357
--------------------------------------------------------------------------------