在PECL上找到所需要的PHP扩展,点击有DLL标识的链接地址,进行对应PHP版本的资源下载,但是你需要注意以下几点问题:
打开 php 配置文件 php.ini 添加以下配置:
1 | extension=php扩展.dll |
重启服务器,通过浏览器访问phpinfo,如果安装成功,就会看到安装扩展的信息。
你可以在 Linux 中执行以下命令来安装 MongoDB 的 PHP 扩展驱动
1 | $ sudo pecl install mongodb |
使用php的pecl安装命令必须保证网络连接可用以及root权限。
在PECL上找到所需要的PHP扩展,点击有.tgz标识的链接地址,进行对应PHP版本的资源下载。
已安装MongoDB扩展为例
1 | $ wget http://pecl.php.net/get/mongodb-1.5.2.tgz |
如果你的 php 是自己编译的,则安装方法如下(假设是编译在 /usr/local/php目录中):
1 | $ wget http://pecl.php.net/get/mongodb-1.5.2.tgz |
安装成功后,会有类似以下安装目录信息输出:
1 | ... |
执行以上命令后,你需要修改php.ini文件,在 php.ini 文件中添加mongo配置,配置如下:
1 | extension_dir=/usr/lib/php/extensions/debug-non-zts-20151012/ |
注意:你需要指明 extension_dir 配置项的路径。
可以通过以下命令查看目录地址:
1
2
3
4 > $ php -i | grep extension_dir
> extension_dir => /usr/lib/php/extensions/debug-non-zts-20151012 =>
> /usr/lib/php/extensions/debug-non-zts-20151012
>
你可以使用 autoconf 安装 PHP 扩展驱动。
你可以使用 Xcode 安装 PHP 扩展驱动。
如果你使用 XAMPP,你可以使用以下命令安装 PHP 扩展驱动:
以安装MongoDB扩展为例
1 | sudo /Applications/XAMPP/xamppfiles/bin/pecl install mongo |
如果以上命令在XMPP或者MAMP中不起作用,你需要在 Github上下载兼容的预编译包。
然后添加 extension=mongodb.so 配置到你的 php.ini 文件中。
]]>Redis
Redis是一种基于内存的数据结构存储系统,它支持多种数据结构,包括字符串(String)、哈希表(Dict)、列表(List)、集合(Set)、有序集合(sorted set)和基数估算(HyperLogLog)。
Redis的主要特点是速度快,支持高并发读写操作,并且可以持久化数据。
Redis常用于需要快速读写的场景,如缓存、消息队列、计数器、会话管理等场景,以及实时数据分析和实时推荐系统。
Memcached
Memcached也是一种基于内存的缓存系统,但它相对于Redis来说功能较为简单,只支持简单的key-value类型(键值对存储)。它是一个分布式的缓存系统,可以将数据存储在多台服务器上。
Memcached的主要特点是速度快,不支持持久化,重启后数据会丢失,
Memcached适用于缓存数据和临时数据的场景,如网页缓存和数据分析,可以提高网站的访问速度和响应速度。
MongoDB
MongoDB是一种文档型数据库,它支持JSON格式的文档存储。
MongoDB的主要特点是灵活性强和可扩展性,支持复杂的查询操作和索引以及数据分析操作。
MongoDB适用于大规模数据存储和处理的场景,例如日志、社交媒体、大数据分析、物联网设备数据存储等。
总之,Redis、Memcached和MongoDB都有着不同的优势和应用场景,需要根据具体的业务需求来选择合适的数据库。如果需要快速读写操作和缓存数据,可以选择Redis或Memcached;如果需要灵活的查询操作和大规模数据处理,可以选择MongoDB。
]]>微信官方关于分享接口开发文档
实现代码如下:
1 |
|
网站是基于ThinkCMF框架搭建的,查看版本是X2.2.3
,根据网警提供的检测报告在postman工具上操作复现漏洞情况
content=<php>die(assert('ev'.'a'.'l("'.'e'.'va'.'l(bas'.'e64_de'.'code(\"cGhwaW5mbygpOw==\"));;return 1;")'))</php>
a=fetch
点击发送,看看结果,意不意外惊不惊喜!
居然打印出了phpinfo()
那找解决方法吧,升级框架肯定是不现实的,好歹是找了解决方案
原因是构造a
参数的fetch
方法和display
方法导致了这个漏洞
1 | /** |
将HomebaseController.class.php
和AdminbaseController.class.php
类中display
和fetch
函数修饰符改为protected
因为它的这两个方法是公用的,我们需要把它改为私用的,这样才可以不被前端的用户去任意的利用。
修复后,再次访问,解决了
]]>null
1 | ....... |
如果想要保证查询结果不会出现null
,可以使用 Laravel 的「Eloquent」 ORM 中的「withDefault」方法来设置默认值。例如:
1 | public function category() |
这样,即使没有找到匹配的记录,您也可以得到一个具有默认值的结果
1 | ....... |
如果我们还想要默认分类名称值(分类名称字段我定义的是name
)
1 | public function category() |
这样,查询结果是
1 | ....... |
laravel-wechat
1 | composer require "overtrue/laravel-wechat" |
如果需要安装指定版本
4.0
的版本最新版本1 | composer require "overtrue/laravel-wechat:~4.0" |
4
的版本最新版本1 | composer require "overtrue/laravel-wechat:^4.0" |
建议laravel5.4安装4.0
版本
如果是Laravel5.4(含)以下版本,需要手动注册ServiceProvider 和 Facade
在config/app.php文件编辑
1 | 'providers' => [ |
创建配置文件
1 | php artisan vendor:publish --provider="Overtrue\LaravelWeChat\ServiceProvider" |
会生成config/wechat.php
文件
1 | WECHAT_OFFICIAL_ACCOUNT_APPID= |
WECHAT_OFFICIAL_ACCOUNT_APPID:微信公众号AppID
WECHAT_OFFICIAL_ACCOUNT_SECRET:微信公众号AppSecret
WECHAT_OFFICIAL_ACCOUNT_TOKEN:微信公众号Token
WECHAT_OFFICIAL_ACCOUNT_AES_KEY:微信公众号EncodingAESKey
1 | Route::any('wechat', 'WeChatController@serve'); |
一定是 Route::any, 因为微信服务端认证的时候是 GET, 接收用户消息时是 POST !
app/Http/Controllers/WeChatController.php
1 | namespace App\Http\Controllers; |
基本语法:
1 | location [=|~|~*|^~|@] /uri/ { |
修饰符释义:
修饰符 | 释义 |
---|---|
= | 表示精确匹配后面的url |
~ | 表示正则匹配,但是区分大小写 |
~* | 表示正则匹配,不区分大小写 |
^~ | 表示普通字符匹配,如果该选项匹配,只匹配该选项,不匹配别的选项,一般用来匹配目录 |
@ | “@” 定义一个命名的 location,使用在内部定向时,例如 error_page |
/ | 通用匹配,任何请求都会匹配到 |
上述匹配规则的优先匹配顺序:
=
前缀的指令严格匹配这个查询。如果找到,停止搜索;~*
产生匹配的话,结果被使用。否则,使用第 2 条规则~
的结果。配置文件内容:
1 | server { |
两个location匹配条件一样,都是/test.html,但是第二个为精确匹配到静态文件路径,因此第一个不会执行,会执行第二个。
指定静态资源路径用的关键字root
,还可以用alias
,那么root
和alias
的区别是什么?
root
属性指定的值是要加入到最终路径中的,匹配条件会拼接到路径中alias
属性指定的值不需要加入到最终路径中根据上述配置文件内容,请求的条件为test.html
,通过root
指定的路径为/www/wwwroot/nginx/html
,因此在匹配的时候,这个路径下就必须要有test.html
这个文件才可以,否则就会找不到而报错,如果用alias
,那么通过浏览器进行请求的时候,alias
也是指定到/www/wwwroot/nginx/html
路径下,但是会匹配默认的index.html
,而无须强制匹配test.html
,但是此时就不能使用=
来进行精确匹配,现在将root
改为alias
1 | server { |
注意:alias指定的路径结尾要加
/
来个root
和alias
的区别例子
1 | server { |
访问 域名/html
的时候,将跳转到/www/wwwroot/nginx/html/
目录下的index.html
文件
1 | server { |
访问 域名/html_alias
的时候,将跳转到/www/wwwroot/nginx/html/
目录下的index.html
文件
1 | server { |
域名/a
返回 111
域名/a/b
返回 222
域名/a/b/sdf
返回 222
从结果看,两条规则同时被匹配成功,但是第二条规则比较长,因此第二条规则优先被匹配,如果^~匹配成功了,那么表示阻断正则表达式,不再进行正则匹配。
在匹配最长规则的时候,除了通过^~来实现匹配,还有通过普通匹配来实现。
当最长规则是通过普通匹配的时候,将会继续正则匹配, 只要有一个正则成功,则使用这个正则的location,停止继续匹配,返回结果。
1 | server { |
域名/a
返回 111
域名/a/b
返回 333
域名/a/b/sdf
返回 333
从结果看,可以看出请求/a/b/
的时候,首先会到达第二条规则(最长规则),由于第二条规则为普通匹配(不是^~
匹配),因此会继续去匹配正则,也就是第三条规则,因此最终返回333
。
~*
表示不区分大小写的正则匹配
1 | server { |
域名/a/b/sdf
返回 333
域名/A/B/sdf
返回 333
从结果看,无论匹配的是大写还是小写,都会返回333
常用方法还有匹配图片后缀,并返回指定信息,如:
1 | server { |
域名/a.jpg
返回 444
域名/A.JPG
返回 444
1 | server { |
proxy_pass最后面没有斜杠/
,此时通过浏览器请求http://域名/aaa/,那么实际访问的地址就是 http://127.0.0.1:8081/aaa/,会将匹配路径/aaa一起加过去。
/
,匹配路径也有斜杠(/aaa/)1 | server { |
proxy_pass最后面有斜杠/
,此时通过浏览器请求http://域名/aaa/,那么实际访问的地址就是 http://127.0.0.1:8081,会将/aaa抛弃的。
/
, 匹配路径也有斜杠(/aaa/)1 | server { |
此时通过浏览器访问http://域名/aaa/index.html,实际请求的是http://127.0.0.1:8081/bbbindex.html(注意位置是默认路径下,不是`bbb`路径下,如果proxy_pass的路径为`/bbb/ccc`,那么实际请求的就是`bbb`路径下的`cccindex.html`)
/
, 匹配路径也有斜杠(/aaa/)1 | server { |
此时通过浏览器访问:http://域名/aaa/index.html,实际访问的是http://127.0.0.1:8081/bbb/index.html
/
,proxy_pass后面也没有/
1 | server { |
此时访问http://域名/aaa,默认将请求到http://127.0.0.1:8081/aaa/index.html的内容
]]>比如获取分类列表,类似如下数据
1 | $data = [ |
实现方法代码如下
1 | /** |
主要思路概况是,把要遍历的数组,创建基于主键的数组引用。把要生成的树结构数组也数组引用
比如案例中的 $refer[13] === $list[0]
,$tree[13] === $refer[13]
,利用了多个变量指向同地址,其中一个参数改变了数据,另外的参数数据也会改变。
nvm是一个管理node多版本的工具
系统为CentOS7
官方下载:https://github.com/nvm-sh/nvm/archive/refs/tags/v0.39.2.tar.gz
1 | // 进入文件下载目录 |
1 | [root@localhost ~]# vi ~/.bashrc |
在~/.bashrc
的末尾,添加如下语句:
1 | export NVM_DIR="$HOME/.nvm" |
wq
保存文件并退出
1 | [root@localhost ~]# source ~/.bashrc |
1 | [root@localhost ~]# nvm -v |
常用操作
1 | #nvm常用命令 |
Yii2框架定时任务代码统一放在 ./console
目录下
首先在console/controller目录下
创建一个定时任务控制器TestController.php
1 |
|
在控制台运行命令php yii
,会看到test
控制下的do
方法
1 | ······ |
执行脚步命令php yii 控制器名/方法名
,会输出
1 | php yii test/do |
这就完成了一个简单的定时任务脚步控制器
如果需要传递参数
1 |
|
其中 param1
和param2
就是参数,执行脚步命令php yii 控制器名/方法名 --参数= ····
1 | php yii test/do --param1=123 --param2=hello |
如果需要给参数设置别名
1 |
|
其中 p1
和p2
就是参数的别名,执行脚步命令php yii 控制器名/方法名 --参数= ····
1 | php yii test/do -p1=123 -p2=hello |
注意:设置参数别名后,使用别名参数用一个横杆(-)链接。
执行命令crontab -e
,我们以每分钟执行一次为例
1 | */1 * * * * /usr/bin/php /var/www/html/yii2-project/yii test/do >/dev/null 2>&1 |
其中
/usr/bin/php
是php运行文件/var/www/html/yii2-project/yii
项目目录中的yii 文件test/do
是执行脚步命令>/dev/null 2>&1
这么写就行哈,可自行查找保存退出即可。
]]>1 |
|
./config/cache.php
主要的缓存类型(驱动)
默认laravel支持缓存介质:apc
, array
, database
, file
, memcached
, redis
在配置文件.env
中修改驱动类型
1 | CACHE_DRIVER=file |
1 | use Illuminate\Support\Facades\Cache; // Cache门面 |
文件所生成的地方在
./storage/framework/cache/data/
目录下
1 | $value = Cache::get('key'); |
1 | # 检查缓存的key值是否存在,存在返回true否则返回false |
1 | # 先获取再删除 |
除了使用 Cache
门面或缓存契约,还可以使用全局的 cache()
函数来通过缓存获取和存储数据。当带有一个字符串参数的 cache()
函数被调用时,会返回给定键对应的缓存值(取值):
1 | $value = cache('key'); |
如果你提供了键值对数组和一个过期时间给该函数,则会在指定的有效期内存储缓存值(存储):
1 | cache(['key' => 'value'], $seconds); |
cache()
函数不带任何参数被调用时会返回 Illuminate\Contracts\Cache\Factory 实现的实例,从而允许你调用其它缓存方法:
1 | cache()->remember('users', $seconds, function () { |
1 | public function store(Request $request) |
简单的表单验证2
1 | public function store(Request $request) |
规则 | 说明 | ||||
---|---|---|---|---|---|
required | 验证字段必须出现在输入数据中,不能为空 | ||||
present | 验证字段必须出现在输入数据中,可以为空 | ||||
filled | 验证字段可不在输入数据中,当验证字段出现在数据中时,不能为空 | ||||
nullable | 验证字段的值可以为 null | ||||
accepted | 验证的字段必须为 yes、 on、 1、或 true | ||||
active_url | 相当于使用了 PHP 函数 dns_get_record,验证的字段必须具有有效的 A 或 AAAA 记录 | ||||
after:date | 验证的字段必须是给定日期后的值。这个日期将会通过 PHP 函数 strtotime 来验证 `’start_date’ => ‘required | date | after:tomorrow’<br>你也可以指定其它的字段来比较日期 ‘finish_date’ => ‘required | date | after:start_date’` |
after_or_equal:date | 验证的字段必须等于给定日期或之后的值。更多信息请参见 after 规则 | ||||
alpha | 验证的字段必须完全是字母的字符 | ||||
alpha_dash | 验证的字段可能具有字母、数字、破折号( - )以及下划线( _ ) | ||||
alpha_num | 验证的字段必须完全是字母、数字 | ||||
array | 验证的字段必须是一个 PHP 数组 | ||||
before:date | 验证的字段必须是给定日期之前的值。这个日期将会通过 PHP 函数 strtotime 来验证 | ||||
before_or_equal:date | 验证的字段必须等于给定日期或之前的值。这个日期将会使用 PHP 函数 strtotime 来验证 | ||||
between:min,max | 验证的字段的大小必须在给定的 min 和 max 之间。字符串、数字、数组或是文件大小的计算方式都用 size 方法进行评估 当需要验证表单数据中数字的大小时,在验证规则中一定要加入 Numeric 或 Integer 其一,size、between、max、min这些验证才会起作用 | ||||
boolean | 验证的字段必须能够被转换为布尔值。可接受的参数为 true、false、1、0、“1” 以及 “0” | ||||
confirmed | 验证的字段必须和 foo_confirmation 的字段值一致。例如,如果要验证的字段是 password,输入中必须存在匹配的 password_confirmation 字段 | ||||
date | 验证的字段值必须是通过 PHP 函数 strtotime 校验的有效日期 | ||||
date_equals:date | 验证的字段必须等于给定的日期。该日期会被传递到 PHP 函数 strtotime | ||||
date_format:format | 验证的字段必须与给定的格式相匹配。你应该只使用 date 或 date_format 其中一个用于验证,而不应该同时使用两者 | ||||
different:field | 验证的字段值必须与字段 (field) 的值不同 | ||||
digits:value | 验证的字段必须是数字,并且必须具有确切的值 | ||||
digits_between:min,max | 验证的字段的长度必须在给定的 min 和 max 之间 | ||||
dimensions | 验证的文件必须是图片并且图片比例必须符合规则'avatar' => 'dimensions:min_width=100,min_height=200' 可用的规则为: min_width、 max_width 、 min_height 、 max_height 、 width 、 height 、 ratio 比例应该使用宽度除以高度的方式来约束。这样可以通过 3/2 这样的语句或像 1.5 这样的浮点的约束 'avatar' => 'dimensions:ratio=3/2' 由于此规则需要多个参数,因此你可以 Rule::dimensions 方法来构造可读性高的规则 use Illuminate\Validation\Rule; Validator::make($data, [ 'avatar' => [ 'required', Rule::dimensions()->maxWidth(1000)->maxHeight(500)->ratio(3 / 2), ], ]); | ||||
distinct | 验证数组时,指定的字段不能有任何重复值‘foo.*.id’ => ‘distinct’ | ||||
验证的字段必须符合 e-mail 地址格式 | |||||
exists:table,column | 验证的字段必须存在于给定的数据库表中 | ||||
在 Laravel 中,一个字段满足下面任何一条都将被视为空值:
null
[ ]
或空 countable
对象scope
可以实现这些相同条件查询的复用。scope
定义
方法名为 scope
+ 首字母大写单词 (这个可以随便定义)
1 | public function scopeStatus($query) |
使用
其中调用去掉 scope
后,首字母小写的那个函数。
scopeStatus () 调用 status ()。
1 | User::status()->get(); |
scope
我们需要重新定义 boot
方法,集成父类 boot
以后,添加全局 scope
,这样默认就已经全局使用了。
1 | protected static function boot() |
我们有的时候有的查询是不需要这个全局 scope
的时候,我们只需要去掉就可以。
使用 withOutGlobalScope()
方法
1 | Post::withOutGlobalScope('avaiable')->get(); |
删除时间
字段./database/migrations/2014_10_12_000000_create_users_table.php
1 |
|
执行 php artisan migrate
运行迁移文件
修改对应的数据模型
./app/Models/User.php
1 |
|
直接调用delete()
方法或者destroy()
方法即可
1 | User::destroy($id); |
这时候查询的数据自动添加过滤条件
deleted_at = NULL
1 | User::onlyTrashed()->where('id', $id)->restore(); |
直接删除数据
1 | User::forceDeleted($id); |
使用 withTrashed()
可以查询出包含已删除的数据
1 | User::withTrashed()->get(); |
使用 onlyTrashed()
可以只查询出已删除的数据
1 | User::onlyTrashed()->get(); |
使用 mysql 命令导入语法格式为:
1 | [root@localhost /]# mysql -u用户名 -p 表名 < /要导入的文件路径.sql |
实例:
使用 mysql 命令导入语法格式为:
1 | [root@localhost /]# mysql -uroot -p test < /usr/local/src/test.sql |
以上命令将将备份的整个数据库 test.sql 导入。
source 命令导入数据库需要先登录到数库终端:
1 | mysql> create database db1; # 创建数据库 |
rowClassName
自定义带斑马纹的表格,设置后并未生效1 | <a-table |
1 | <style scoped lang="less"> |
原因是这样的样式不能放在scoped
中,应写在全局样式中
1 | <style lang="less"> |
改成这样后样式生效
]]>注意,这样可能会影响到其他组件中
class
为.ant-table-striped .table-striped td
的样式
主要用于存储访问过的网站数据,把浏览器的信息存储到本地电脑中,实现客户端和服务器端的通讯。
1 | Name:cookie的名字(键) |
1 | document.cookie='name=Peak'; |
设置一个10分钟后失效的Cookie
1 | function setCookie(name, value, expire){ |
注意:过期时间是格林威治时间(UTC时间)
把过期时间设置为小于当前时间即可
1 | setCookie('name', 'Peak', -1); |
npm run serve
或 yarn serve
,然后打开 localhost:8080
(本机的IP),此时如果调用后端接口,可能会产生跨域,那如何解决呢?解决跨域的方案
日常工作中,生产环境用得比较多的跨域方案是cors和nginx反向代理。
本地项目中调试用的最多的就是 node 代理,当然像 nginx、charles(抓包工具)做代理也可以,只要你会配置。
vue 中的 proxy
就是利用了 Node 代理,原理是因为服务器端没有跨域,使用的是 http-proxy-middleware 这个模块(这个模块相当于是node.js的一个插件)
案例
http://dev.com/api/test
,然后你可以在本地调 http://localhost:8080/api/test
,如axios.get('/api/test')
配置代理后,会做如下转发:
http://localhost:8080/api/test
-> http://dev.com/api/test
http://localhost:8080/admin/api/test
-> http://dev.com/admin/api/test
1 | // vue-cli3.0 里面的 vue.config.js做配置 |
/api
这类的标识,那么你可以自己加,也就是你可以在本地调 http://localhost:8080/api/test
,如axios.get('/api/test')
,而你要的目标接口是 http://dev.com/test
,你就可以用 pathRewrite
,遇到 /api
就去找代理 http://dev.com/test
并且把 /api
重写为 /
。所以转发效果就是:
http://localhost:8080/api/test
-> http://dev.com/test
1 | // vue-cli3.0 里面的 vue.config.js做配置 |
/api
的接口,比如:http://localhost:8080/api/test
-> http://dev.com/api/test
http://localhost:8080/test
-> http://dev.com/test
1 | devServer: { |
常用的devServer配置
当设置为true
时,此选项将绕过主机检查。不建议这样做,因为不检查主机的应用程序容易受到DNS重新绑定攻击。
1 | devServer: { |
假设服务器在http://localhost:8080
下运行,output.filename
设置为bundle.js
。默认情况下,devServer.publicPath
是/
,所以你的包可以作为http://localhost:8080/bundle.js
使用。将devServer.publicPath
更改为 /assets/
就变为 http://localhost:8080/assets/bundle.js
1 | devServer: { |
确保devServer.publicPath始终以正斜杠开头和结尾。
常用vue/cli3的配置
]]>src\services\api.js
1 | //跨域代理前缀 |
vue.config.js
1 | module.exports = { |
然后重启yarn serve