public function get_children_cate($parent_id){ $childrens_arr = array(); //check have children $children_cnt = DB::table('pms_product_category')->where('parentId', $parent_id)->count(); if($children_cnt > 0){ //get children by parent ids $childrens = DB::table('pms_product_category')->where('parentId', $parent_id)->get()->toArray(); foreach($childrens as $row){ $children = $this->get_children_cate($row->id); if(!empty($ $row->children = $children; } $childrens_arr[] = $row; } } return json_decode(json_encode($childrens_arr), true); }
分类: 技术
caffeinated/modules View
<?php namespace App\Modules\Blog\Http\Controllers; Use App\Http\Controllers\Controller; class BlogController extends Controller { function index(){ return view('blog::blog'); } }
是这样的!!!View整理要用blog::blog
mmp啊!!!文档里压根没有说明
php artisan module:optimize
删除模块后执行
实用 Docker 速查大全:快速认识 Docker 的概念和使用方法
原文 :https://laravel-china.org/articles/22822
译者序:前几天在社区看到该 仓库,中文版本翻译比较乱,部分资料也比较老旧和落后,于是自己动手丰衣足食,在通读整篇的同时对翻译和原文进行大量的改进,便产出了本文。目前,我已经提交 PR,因改动较大,是否会被合并未知。转载至 Laravel-China 只发布中文版本,英文版本欢迎到 GitHub 仓库查看。
原作者仓库:https://github.com/wsargent/docker-cheat-sheet
改进后的 Fork 仓库:https://github.com/wi1dcard/docker-cheat-sheet(中文版本位于 zh-CN 目录)
Pull Request:https://github.com/wsargent/docker-cheat-sheet/pull/164
欢迎提出任何疑问和改进,我将同步到 GitHub,谢谢。
想要一起来完善这份速查表吗?参见贡献手册部分吧!
译者注:以下部分链接需科学上网后使用。
Due to GFW, varies links below could not be accessed in China Mainland.
目录
为何使用 Docker
「通过 Docker,开发者可以使用任何语言任何工具创建任何应用。“Dockerized” 的应用是完全可移植的,能在任何地方运行 – 不管是同事的 OS X 和 Windows 笔记本,或是在云端运行的 Ubuntu QA 服务,还是在虚拟机运行的 Red Hat 产品数据中心。
Docker Hub 上有 13000+ 的应用,开发者可以从中选取一个进行快速扩展开发。Docker 跟踪管理变更和依赖关系,让系统管理员能更容易理解开发人员是如何让应用运转起来的。而开发者可以通过 Docker Hub 的共有/私有仓库,构建他们的自动化编译,与其他合作者共享成果。
Docker 帮助开发者更快地构建和发布高质量的应用。」—— 什么是 Docker
系统环境
我用的是 Oh My Zsh 和 Docker 插件,它可以自动补全 Docker 命令。你的环境可能有所不同。
Linux
Docker 对于 Linux 内核版本的 最低要求 为 3.10.x
。
MacOS
10.8「Mountain Lion」或更新版本。
检查版本
时刻关注你当前正在使用的 Docker 版本是十分重要的,这能够帮助你了解可用的特性。同时,可以让你在查找镜像时选择使用的版本。接下来让我们看看如何操作。
-
docker version
查看你正在运行的 Docker 版本。
获取 Docker 服务版本:
docker version --format '{{.Server.Version}}'
你也可以输出原始的 JSON 数据:
docker version --format '{{json .}}'
安装
Linux
Docker 官方提供了快速、易用的安装脚本:
curl -sSL https://get.docker.com/ | sh
如果你不想执行一个不明不白的 Shell 脚本,那么请看 安装说明,选择你在用的发行版本。
如果你是一个 Docker 超新手,那么你应当先去看看 系列教程。
macOS
下载并安装 Docker Community Edition。如果你在使用 Homebrew-Cask,只需在命令行输入 brew cask install docker
即可。下载安装 Docker Toolbox 亦可。Docker For Mac 很赞,但是它的安装过程与 VirtualBox 不太一样。详情请查阅 比较。
注意:Docker Toolbox 已经过时。你应当使用 Docker Community Edition,详见 Docker Toolbox
安装好 Docker Community Edition 后,点击 Launchpad 内的 Docker 图标。接着即可启动容器了:
docker run hello-world
好了,现在你有了一个运行中的 Docker 容器了。
容器(Container)
关于 Docker 进程隔离的基础。容器 (Container) 之于虚拟机 (Virtual Machine) 就好比线程之于进程。或者你可以把他们想成是「吃了类固醇的 chroots」。
生命周期
-
docker create
创建容器但不启动它。 -
docker rename
用于重命名容器。 -
docker run
一键创建并同时启动该容器。 -
docker rm
删除容器。 -
docker update
调整容器的资源限制。
通常情况下,不使用任何命令行选项启动一个容器,该容器将会立即启动并停止。若需保持其运行,你可以使用 docker run -td container_id
命令。选项 -t
表示分配一个 pseudo-TTY 会话,-d
表示自动将容器与终端分离(也就是说在后台运行容器,并输出容器 ID)。
如果你需要一个临时容器,可使用 docker run --rm
会在容器停止之后删除它。
如果你需要映射宿主机 (host) 的目录到 Docker 容器内,可使用 docker run -v $HOSTDIR:$DOCKERDIR
。详见 卷标(Volumes) 一节。
如果你想同时删除与容器相关联的卷标,那么在删除容器的时候必须包含 -v
选项,像这样 docker rm -v
。
从 Docker 1.10 起,其内置一套各容器独立的 日志引擎,每个容器可以独立使用。你可以使用 docker run --log-driver=syslog
来自定义日志引擎(例如以上的 syslog
)。
启动和停止
-
docker start
启动已存在的容器。 -
docker stop
停止运行中的容器。 -
docker restart
重启容器。 -
docker pause
暂停运行中的容器,将其「冻结」在当前状态。 -
docker unpause
结束容器暂停状态。 -
docker wait
阻塞地等待某个运行中的容器直到停止。 -
docker kill
向运行中的容器发送 SIGKILL 指令。 -
docker attach
连接到运行中的容器。
如果你想将容器的端口 (ports) 暴露至宿主机,请见 暴露端口 一节。
关于 Docker 实例崩溃后的重启策略,详见 本文。
CPU 限制
你可以限制 CPU 资源占用,无论是指定百分比,或是特定核心数。
例如,你可以设置 cpu-shares
。该配置看起来有点奇怪 — 1024 表示 100% CPU,因此如果你希望容器使用所有 CPU 内核的 50%,应将其设置为 512:
docker run -ti --c 512 agileek/cpuset-test
更多信息请参阅 https://goldmann.pl/blog/2014/09/11/resource-management-in-docker/#_cpu。
通过 cpuset-cpus
可使用特定 CPU 内核。
docker run -ti --cpuset-cpus=0,4,6 agileek/cpuset-test
请参阅 https://agileek.github.io/docker/2014/08/06/docker-cpuset/ 获取更多细节以及一些不错的视频。
注意,Docker 在容器内仍然能够 看到 全部 CPU — 它仅仅是不使用全部而已。请参阅 https://github.com/docker/docker/issues/20770 获取更多细节。
内存限制
同样,亦可给 Docker 设置 内存限制:
docker run -it -m 300M ubuntu:14.04 /bin/bash
能力(Capabilities)
Linux 的 Capability 可以通过使用 cap-add
和 cap-drop
设置。请参阅 https://docs.docker.com/engine/reference/run/#/runtime-privilege-and-linux-capabilities 获取更多细节。这有助于提高安全性。
如需要挂载基于 FUSE 的文件系统,你需要结合 --cap-add
和 --device
使用:
docker run --rm -it --cap-add SYS_ADMIN --device /dev/fuse sshfs
授予对某个设备的访问权限:
docker run -it --device=/dev/ttyUSB0 debian bash
授予对所有设备的访问权限:
docker run -it --privileged -v /dev/bus/usb:/dev/bus/usb debian bash
有关容器特权的更多信息请参阅 本文。
信息
-
docker ps
查看运行中的所有容器。 -
docker logs
从容器中读取日志。(你也可以使用自定义日志驱动,不过在 1.10 中,它只支持json-file
和journald
)。 -
docker inspect
查看某个容器的所有信息(包括 IP 地址)。 -
docker events
从容器中获取事件 (events)。 -
docker port
查看容器的公开端口。 -
docker top
查看容器中活动进程。 -
docker stats
查看容器的资源使用量统计信息。 -
docker diff
查看容器文件系统中存在改动的文件。
docker ps -a
将显示所有容器,包括运行中和已停止的。
docker stats --all
同样将显示所有容器,默认仅显示运行中的容器。
导入 / 导出
-
docker cp
在容器和本地文件系统之间复制文件或目录。 -
docker export
将容器的文件系统打包为归档文件流 (tarball archive stream) 并输出至标准输出 (STDOUT)。
执行命令
-
docker exec
在容器内执行命令。
例如,进入正在运行的 foo
容器,并连接 (attach) 到一个新的 Shell 进程:docker exec -it foo /bin/bash
。
镜像(Images)
镜像是 Docker 容器的模板。
生命周期
-
docker images
查看所有镜像。 -
docker import
从归档文件创建镜像。 -
docker build
从 Dockerfile 创建镜像。 -
docker commit
为容器创建镜像,如果容器正在运行则会临时暂停。 -
docker rmi
删除镜像。 -
docker load
从标准输入 (STDIN) 加载归档包 (tar archive) 作为镜像,包括镜像本身和标签 (tags, 0.7 起)。 -
docker save
将镜像打包为归档包,并输出至标准输出 (STDOUT),包括所有的父层、标签和版本 (parent layers, tags, versions, 0.7 起)。
其它信息
-
docker history
查看镜像的历史记录。 -
docker tag
给镜像打标签命名(本地或者仓库均可)。
清理
虽然你可以用 docker rmi
命令来删除指定的镜像,不过有个名为 docker-gc 的工具,它可以以一种安全的方式,清理掉那些不再被任何容器使用的镜像。Docker 1.13 起,使用 docker image prune
亦可删除未使用的镜像。参见 清理。
加载 / 保存镜像
从文件中加载镜像:
docker load < my_image.tar.gz
保存既有镜像:
docker save my_image:my_tag | gzip > my_image.tar.gz
导入 / 导出容器
从文件中导入容器镜像:
cat my_container.tar.gz | docker import - my_image:my_tag
导出既有容器:
docker export my_container | gzip > my_container.tar.gz
加载已保存的镜像 与 导入已导出为镜像的容器 的不同
通过 load
命令来加载镜像,会创建一个新的镜像,并继承原镜像的所有历史。
通过 import
将容器作为镜像导入,也会创建一个新的镜像,但并不包含原镜像的历史,因此会比使用 load
方式生成的镜像更小。
网络(Networks)
Docker 具备 网络 功能。我并不是很了解它,所以这是一个扩展本文的好地方。文档 使用网络 指出,这是一种无需暴露端口即可实现 Docker 容器间通信的好方法。
生命周期
其它信息
建立连接
你可以 为容器指定 IP 地址:
# 使用你自己的子网和网关创建一个桥接网络docker network create --subnet 203.0.113.0/24 --gateway 203.0.113.254 iptastic# 基于以上创建的网络,运行一个 Nginx 容器并指定 IP$ docker run --rm -it --net iptastic --ip 203.0.113.2 nginx# 在其他地方使用 CURL 访问这个 IP(假设该 IP 为公网)$ curl 203.0.113.2
仓管中心和仓库(Registry & Repository)
仓库 (repository) 是 被托管(hosted) 的已命名镜像 (tagged images) 的集合,这组镜像用于构建容器文件系统。
仓管中心 (registry) 则是 托管服务(host) — 用于存储仓库并提供 HTTP API,以便 管理仓库的上传和下载。
Docker 官方托管着自己的 仓管中心,包含着数量众多的仓库。不过话虽如此,这个仓管中心 并没有很好地验证镜像,所以如果你担心安全问题的话,请尽量避免使用它。
-
docker login
登入仓管中心。 -
docker logout
登出仓管中心。 -
docker search
从仓管中心检索镜像。 -
docker pull
从仓管中心拉取镜像到本地。 -
docker push
从本地推送镜像到仓管中心。
本地仓管中心
你可以使用 docker distribution 项目搭建本地的仓管中心,详情参阅 本地发布 (local deploy) 的介绍。
科学上网后,也可以看看 Google+ Group。
Dockerfile
当你执行 docker build
时,Docker 将会根据 配置文件 启动 Docker 容器。远优于使用 docker commit
。
以下是一些编写 Dockerfile 的常用编辑器,并链接到适配的语法高亮模块︰
-
更多信息请参阅 Docker 遇上 IDE
指令
-
FROM 为其他指令设置基础镜像 (Base Image)。
-
MAINTAINER (deprecated – use LABEL instead) 为生成的镜像设置作者字段。
-
RUN 在当前镜像的基础上生成一个新层并执行命令。
-
CMD 设置容器默认执行命令。
-
EXPOSE 告知 Docker 容器在运行时所要监听的网络端口。注意:并没有实际上将端口设置为可访问。
-
ENV 设置环境变量。
-
ADD 将文件、目录或远程文件复制到容器中。缓存无效。请尽量用
COPY
代替ADD
。 -
COPY 将文件或文件夹复制到容器中。注意:将使用 ROOT 用户复制文件,故无论 USER / WORKDIR 指令如何配置,你都需要手动修改其所有者(
chown
),ADD
也是一样。 -
ENTRYPOINT 将容器设为可执行的。
-
VOLUME 在容器内部创建挂载点 (mount point) 指向外部挂载的卷标或其他容器。
-
USER 设置随后执行 RUN / CMD / ENTRYPOINT 命令的用户名。
-
WORKDIR 设置工作目录 (working directory)。
-
ARG 定义编译时 (build-time) 变量。
-
ONBUILD 添加触发指令,当该镜像被作为其他镜像的基础镜像时该指令会被触发。
-
STOPSIGNAL 设置停止容器时,向容器内发送的系统调用信号 (system call signal)。
-
LABEL 将键值对元数据 (key/value metadata) 应用到镜像、容器或是守护进程。
教程
例子
层(Layers)
Docker 的版本化文件系统是基于层的。就像 Git 的提交或文件变更系统 一样。
链接(Links)
链接 (links) 通过 TCP/IP 端口 实现 Docker 容器之间的通讯。Atlassian 展示了可用的例子。你还可以 通过主机名 (hostname) 链接。
在某种意义上来说,该特性已经被 自定义网络 所替代。
注意: 如果你希望容器之间只通过链接进行通讯,在启动 Docker 守护进程时,请使用 -icc=false
来禁用内部进程通讯。
假设你有一个名为 CONTAINER 的容器(通过 docker run --name CONTAINER
指定)并且在 Dockerfile 中,暴露了一个端口:
EXPOSE 1337
然后,我们创建另外一个名为 LINKED 的容器:
docker run -d --link CONTAINER:ALIAS --name LINKED user/wordpress
然后 CONTAINER 暴露的端口和别名将会以如下的环境变量出现在 LINKED 中:
$ALIAS_PORT_1337_TCP_PORT$ALIAS_PORT_1337_TCP_ADDR
那么你便可以通过这种方式来连接它了。
使用 docker rm --link
即可删除链接。
通常,Docker 容器(亦可理解为「服务」)之间的链接,是「服务发现」的一个子集。如果你打算在生产中大规模使用 Docker,这将是一个很大的问题。请参阅The Docker Ecosystem: Service Discovery and Distributed Configuration Stores获取更多信息。
卷标(Volumes)
Docker 的卷标 (volumes) 是 独立的文件系统。它们并非必须连接到特定的容器上。
生命周期
信息
卷标在不能使用链接(只有 TCP/IP)的情况下非常有用。例如,如果你有两个 Docker 实例需要通讯并在文件系统上留下记录。
你可以一次性将其挂载到多个 docker 容器上,通过 docker run --volumes-from
。
因为卷标是独立的文件系统,它们通常被用于存储各容器之间的瞬时状态。也就是说,你可以配置一个无状态临时容器,关掉之后,当你有第二个这种临时容器实例的时候,你可以从上一次保存的状态继续执行。
查看 卷标进阶 来获取更多细节。Container42 非常有用。
你可以 将宿主 MacOS 的文件夹映射为 Docker 卷标:
docker run -v /Users/wsargent/myapp/src:/src
你也可以用远程 NFS 卷标,如果你觉得你 有足够勇气。
还可以考虑运行一个纯数据容器,像 这里 所说的那样,提供可移植数据。
记得,文件也可以被挂载为卷标。
暴露端口(Exposing ports)
通过宿主容器暴露输入端口相当 繁琐但有效的。
例如使用 -p
将容器端口映射到宿主端口上(只使用本地主机 (localhost) 接口):
docker run -p 127.0.0.1:$HOSTPORT:$CONTAINERPORT --name CONTAINER -t someimage
你可以使用 EXPOSE 告知 Docker,该容器在运行时监听指定的端口:
EXPOSE <CONTAINERPORT>
但是注意 EXPOSE 并不会直接暴露端口,你需要用参数 -p
。比如说你要在 localhost 上暴露容器的端口:
iptables -t nat -A DOCKER -p tcp --dport <LOCALHOSTPORT> -j DNAT --to-destination <CONTAINERIP>:<PORT>
如果你是在 Virtualbox 中运行 Docker,那么你需要配置端口转发 (forward the port)。使用 forwarded_port 在 Vagrantfile 上配置暴露的端口范围,这样你就可以动态地映射了:
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| ... (49000..49900).each do |port| config.vm.network :forwarded_port, :host => port, :guest => port end ...end
如果你忘记了将什么端口映射到宿主机上的话,可使用 docker port
查看:
docker port CONTAINER $CONTAINERPORT
最佳实践
这里有一些最佳实践,以及争论焦点:
-
Bridget Kromhout has a useful blog post on running Docker in production at Dramafever.
-
There's also a best practices blog post from Lyst.
安全(Security)
这节准备讨论一些关于 Docker 安全性的问题。Docker 官方文档 安全 页面讲述了更多细节。
首先第一件事:Docker 是有 root 权限的。如果你在 docker
组,那么你就有 root 权限。如果你将 Docker 的 Unix Socket 暴露给容器,意味着你赋予了容器 宿主机 root 权限。
Docker 不应当作为唯一的防御措施。你应当使其更加安全可靠。
为了更好地理解容器暴露了什么,可参阅由 Aaron Grattafiori 编写的 Understanding and Hardening Linux Containers。这是一个完整全面且包含大量链接和脚注的容器问题指南,介绍了许多有用的内容。即使你已经加固过容器,以下的安全提示依然十分有帮助,但并不能代替理解的过程。
安全提示
为了最大的安全性,你应当考虑在虚拟机上运行 Docker。这是直接从 Docker 安全团队拿来的资料 — slides / notes。之后,可使用 AppArmor、seccomp、SELinux、grsec 等来 限制容器的权限。更多细节,请查阅 Docker 1.10 security features。
Docker 镜像 ID 属于 敏感信息 所以它不应该向外界公开。请将它们当作密码来对待。
阅读由 Thomas Sjögren 编写的 Docker Security Cheat Sheet:关于加固容器的不错的建议。
查看 Docker 安全测试脚本,下载 最佳实践白皮书。
你应当远离使用非稳定版本 grsecurity / pax 的内核,比如 Alpine Linux。如果在产品中用了 grsecurity,那么你应该考虑使用有 商业支持 的 稳定版本,就像你对待 RedHat 那样。虽然要 $200 每月,但对于你的运维预算来说不值一提。
从 Docker 1.11 开始,你可以轻松的限制在容器中可用的进程数,以防止 fork 炸弹。 这要求 Linux 内核 >= 4.3,并且要在内核配置中打开 CGROUP_PIDS=y。
docker run --pids-limit=64
同时,你也可以限制进程再获取新权限。该功能是 Linux 内核从 3.5 版本开始就拥有的。你可以从 这篇博客 中阅读到更多关于这方面的内容。
docker run --security-opt=no-new-privileges
以下内容摘选自 Container Solutions 的 Docker Security Cheat Sheet(PDF 版本,难以使用,故复制至此):
关闭内部进程通讯:
docker -d --icc=false --iptables
设置容器为只读:
docker run --read-only
通过 hashsum 来验证卷标:
docker pull debian@sha256:a25306f3850e1bd44541976aa7b5fd0a29be
设置卷标为只读:
docker run -v $(pwd)/secrets:/secrets:ro debian
在 Dockerfile 中定义用户并以该用户运行,避免在容器中以 ROOT 身份操作:
RUN groupadd -r user && useradd -r -g user userUSER user
用户命名空间(User Namespaces)
还可以通过使用 用户命名空间 — 自 1.10 版本起已内置,但默认并未启用。
要在 Ubuntu 15.10 中启用用户命名空间 (remap the userns),请 跟着这篇博客的例子 来做。
安全相关视频
安全路线图
Docker 的路线图提到关于 seccomp 的支持。
一个名为 bane 的 AppArmor 策略生成器正在实现 安全配置文件。
小贴士
链接:
清理
最新的 数据管理命令 已在 Docker 1.13 实现:
-
docker system prune
-
docker volume prune
-
docker network prune
-
docker container prune
-
docker image prune
df 命令
docker system df
将显示当前 Docker 各部分占用的磁盘空间。
Heredoc 声明 Docker 容器
docker build -t htop - << EOFFROM alpineRUN apk --no-cache add htopEOF
最近一次的容器 ID
alias dl='docker ps -l -q'docker run ubuntu echo hello world docker commit $(dl) helloworld
带命令的提交(需要 Dockerfile)
docker commit -run='{"Cmd":["postgres", "-too -many -opts"]}' $(dl) postgres
获取 IP 地址
docker inspect $(dl) | grep -wm1 IPAddress | cut -d '"' -f 4
或使用 jq:
docker inspect $(dl) | jq -r '.[0].NetworkSettings.IPAddress'
或使用 go 模板:
docker inspect -f '{{ .NetworkSettings.IPAddress }}' <container_name>
或在通过 Dockerfile 构建镜像时,通过构建参数 (build argument) 传入:
DOCKER_HOST_IP=`ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d: | head -n1`echo DOCKER_HOST_IP = $DOCKER_HOST_IPdocker build \ --build-arg ARTIFACTORY_ADDRESS=$DOCKER_HOST_IP -t sometag \ some-directory/
获取端口映射
docker inspect -f '{{range $p, $conf := .NetworkSettings.Ports}} {{$p}} -> {{(index $conf 0).HostPort}} {{end}}' <containername>
通过正则匹配容器
for i in $(docker ps -a | grep "REGEXP_PATTERN" | cut -f1 -d" "); do echo $i; done`
获取环境变量配置
docker run --rm ubuntu env
强行终止运行中的容器
docker kill $(docker ps -q)
删除所有容器(强行删除!无论容器运行或停止)
docker rm -f $(docker ps -qa)
删除旧容器
docker ps -a | grep 'weeks ago' | awk '{print $1}' | xargs docker rm
删除已停止的容器
docker rm -v `docker ps -a -q -f status=exited`
停止并删除容器
docker stop $(docker ps -aq) && docker rm -v $(docker ps -aq)
删除无用 (dangling) 的镜像
docker rmi $(docker images -q -f dangling=true)
删除所有镜像
docker rmi $(docker images -q)
删除无用 (dangling) 的卷标
Docker 1.9 版本起:
docker volume rm $(docker volume ls -q -f dangling=true)
1.9.0 中,参数 dangling=false
居然 没 用 – 它会被忽略然后列出所有的卷标。
查看镜像依赖
docker images -viz | dot -Tpng -o docker.png
Docker 容器瘦身
-
在某层 (RUN layer) 清理 APT
这应当和其他 apt 命令在同一层中完成。
否则,前面的层将会保持原有信息,而你的镜像则依旧臃肿。
RUN {apt commands} \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
-
压缩镜像
ID=$(docker run -d image-name /bin/bash)docker export $ID | docker import – flat-image-name
-
备份
ID=$(docker run -d image-name /bin/bash)(docker export $ID | gzip -c > image.tgz)gzip -dc image.tgz | docker import - flat-image-name
监视运行中容器的系统资源利用率
检查某个容器的 CPU、内存以及网络 I/O 使用情况,你可以:
docker stats <container>
按 ID 列出所有容器:
docker stats $(docker ps -q)
按名称列出所有容器:
docker stats $(docker ps --format '{{.Names}}')
按指定镜像名称列出所有容器:
docker ps -a -f ancestor=ubuntu
删除所有未标签命名 (untagged) 的容器:
docker rmi $(docker images | grep “^” | awk '{split($0,a," "); print a[3]}')
通过正则匹配删除指定容器:
docker ps -a | grep wildfly | awk '{print $1}' | xargs docker rm -f
删除所有已退出 (exited) 的容器:
docker rm -f $(docker ps -a | grep Exit | awk '{ print $1 }')
将文件挂载为卷标
文件也可以被挂载为卷标。例如你可以仅仅注入单个配置文件:
# 从容器复制文件docker run --rm httpd cat /usr/local/apache2/conf/httpd.conf > httpd.conf# 编辑文件vim httpd.conf# 挂载修改后的配置启动容器docker run --rm -ti -v "$PWD/httpd.conf:/usr/local/apache2/conf/httpd.conf:ro" -p "80:80" httpd
小程序微信支付
wx.requestPayment( { 'timeStamp': e.data.timeStamp.toString(), 'nonceStr': e.data.nonceStr.toString(), 'package': e.data.package, 'signType': e.data.signType, 'paySign': e.data.sign, 'success': function (res) { //create order wx.request({ url: o.d.ceshiUrl + "/leokim/create_order", method: "post", data: { openid: openid, id: goods_info.goods_id, type: goods_info.type, code: goods_info.code }, header: { "Content-Type": "application/x-www-form-urlencoded" }, 'success': function (e) { var pages = getCurrentPages(); var currPage = pages[1]; currPage.setData({ is_buy: 1 }); }, 'fail': function (res) { } }) wx.showToast({ image: '/images/success.png', title: "购买成功.", duration: 2e3 }); }, 'fail': function (res) { var msg = '购买失败'; if (res.errMsg == 'requestPayment:fail cancel'){ msg = '取消支付'; }; wx.showToast({ image: '/images/failed.png', title: msg, }); }, 'complete': function (res) { console.log('支付完成'); } })
后端:
function wechat_pay() { $openid = 'ocLsr5OXtYZZe6dUrMLJxsm0CTEk'; $key = 'a81bfe3a84df3ceb5cc54bd3e1605ba2'; $post = $this->input->post(); $goods_name = $post['goods_name']; //get prepay_id $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; $data = array(); $data['appid'] = $this->appid; $data['mch_id'] = $this->mch_id; $data['nonce_str'] = mt_rand(10000000,99999999); $data['body'] = $goods_name; $data['out_trade_no'] = 'wkt' . time(). mt_rand(10000000,99999999); // $data['total_fee'] = $price * 100; $data['total_fee'] = 1; $data['spbill_create_ip'] = '114.96.242.184'; $data['notify_url'] = 'http://www.weixin.qq.com/wxpay/pay.php'; $data['trade_type'] = 'JSAPI'; $data['openid'] = $openid; $data['sign'] = $this->createSign($data,$key); $data = $this->array_to_xml($data); $result = $this->curlPost($url, $data); $result = $this->xml_to_array($result); $prepay_id = $result['prepay_id']; $return_data = array( 'appId' => $this->appid, 'timeStamp'=>time(), 'nonceStr'=>mt_rand(10000000,99999999), 'package'=>"prepay_id=$prepay_id", 'signType'=>'MD5' ); $return_data['sign'] = $this->createSign($return_data,$key); echo json_encode($return_data); } public function create_order(){ $result = array('flag'=>'N'); $post = $this->input->post(); $type = $post['type']; $id = $post['id']; $openid = $post['openid']; $code = $post['code']; $user_id = $this->get_user_id_by_open_id($openid); $goods_table_info = $this->get_table_info_by_type($type); $table = $goods_table_info['table']; $key = $goods_table_info['key']; $sql = "INSERT INTO `t_aci_bought` (`bought_id`, `type`, `related_id`, `price`, `status`, `user_id`, `add_time`) SELECT NULL, '$type', $id, price, 0, $user_id, NOW() FROM `$table` WHERE `$key`= $id"; $this->db->query($sql); $insert_id = $this->db->insert_id(); if($insert_id > 0){ $result['flag'] = 'Y'; //TODO 三级分销 } echo json_encode($result); }
小程序修改其他页面数据
var pages = getCurrentPages(); var currPage = pages[1]; currPage.setData({ is_buy: 1 });
微信发送红包
//发送红包start $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack'; //获取openID $uid = $list['uid']; $result = pdo_fetch("SELECT openid FROM ims_meepo_online_user WHERE id=:id",array(':id'=>$uid)); $open_id = $result['openid']; $money = (int)$list['money']; $package = array(); $package['nonce_str'] = random(8); $package['mch_billno'] = 'ydl'.rand(10000000000000,99999999999999); $package['mch_id'] = '1515256111'; $package['wxappid'] = 'wx57a837f1e72026c3'; $package['send_name'] = 'xxxx'; $package['re_openid'] = $open_id; $package['total_amount'] = $money*100; $package['total_num'] = 1; $package['wishing'] = 'xxxxxx'.date('Y-m-d'); $package['client_ip'] = CLIENT_IP; $package['act_name'] = 'xxxxx'; $package['remark'] = 'xxxxxxxxxxxx.'; ksort($package, SORT_STRING); $string1 = ''; foreach($package as $key => $v) { if (empty($v)) { continue; } $string1 .= "{$key}={$v}&"; } $string1 .= "key=2nHuHsDijB4Ye7mNN22QxFAP3AW6l3hT"; $package['sign'] = strtoupper(md5($string1)); $dat = array2xml($package); load()->func('communication'); $certPath = 'xxxxxx/cert/apiclient_cert.pem'; $keyPath = 'xxxxxx/cert/apiclient_key.pem'; $extra = array( CURLOPT_SSL_VERIFYPEER=>false, CURLOPT_SSL_VERIFYHOST=>false, CURLOPT_SSLCERTTYPE=>'PEM', CURLOPT_SSLKEYTYPE=>'PEM', CURLOPT_SSLCERT=>$certPath, CURLOPT_SSLKEY=>$keyPath, CURLOPT_POST=>1 ); $response = ihttp_request($url, $dat, $extra); // print_r($response); // exit; // echo $response;
获取小程序二维码
function getCode(){ $post = $this->input->post(); $openid = $post['openid']; $token = json_decode($this->get_token('wx725d23dc9ddc4223','8d5971b6282b271b23474849cb3ea562','client_credential'),true); $token_str = $token['access_token']; $url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=$token_str"; $data = array("scene"=>"1001"); $file_code = $this->https_request($url, json_encode($data)); $filename = 'uploadfile/qrcode/'.$openid.'.png'; file_put_contents($filename,$file_code); echo 'https://yj.chuanyinhulian.com/'.$filename; } function get_token($appid, $secret, $grant_type){ $url = "https://api.weixin.qq.com/cgi-bin/token?appid=$appid&secret=$secret&grant_type=$grant_type"; return $this->https_request($url); } function https_request($url, $data = null) { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); if (!empty($data)){ curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($curl); curl_close($curl); return $output; }
booking订单导入
<?php
// ini_set('display_errors', "1");
// ini_set('display_startup_errors', "1");
// ini_set('html_errors', "1");
// ini_set('memory_limit', "512M");
// error_reporting(E_ALL);
global $_W,$_GPC;
$weid = $_W['uniacid'];
$op = empty($_GPC['op'])? 'list':$_GPC['op'];
if($op=='list'){
$pindex = max(1, intval($_GPC['page']));
$psize = 10;
$categorys = pdo_fetchall("SELECT * FROM ".tablename($this->category_table)." ORDER BY createtime DESC LIMIT ".($pindex – 1) * $psize.",{$psize}");
$total = pdo_fetchcolumn('SELECT COUNT(*) FROM ' . tablename($this->category_table) );
$pager = pagination($total, $pindex, $psize);
}
elseif($op=='post'){
load()->func('tpl');
$id = intval($_GPC['id']);
$category = pdo_fetch("SELECT * FROM ".tablename($this->category_table)." WHERE weid=:weid AND id=:id",array(':weid'=>$weid,':id'=>$id));
if(empty($category)){
$category = array(
'isshow'=>1,
);
}
//数据提交的内容
if (checksubmit('submit')) {
if(!empty($id)){
function read_csv($file,$dbhost,$dbuser,$dbpass,$database) {
$keys = array();
$newArray = array();
$array = array_map("str_getcsv", file($file));
$count = count($array) – 1;
$labels = array_shift($array);
$labels[0] = "add_id"; //订单编号
$labels[1] = "booked"; //住房预定时间
$labels[2] = "arrival"; //开始入住时间
$labels[3] = "departure"; //结束入住时间
$labels[4] = "length_of_stay"; //住房时间天数
$labels[5] = "booking_window"; //订购票的窗口多少号
$labels[6] = "status"; //订单状态
$labels[7] = "comission_eur"; //人民币欧元
$labels[8] = "progress_bar"; //进度
$labels[9] = "fee"; //费用
$labels[10] = "fee_currency"; //费用货币
$labels[11] = "exchange_rate"; //汇率
$labels[12] = "ttv"; //不知道该字段
$labels[13] = "slip_nr"; //不知道该字段
$labels[14] = "affiliate_id"; //会员身份ID
$labels[15] = "hotel_name"; //酒店的名称
$labels[16] = "accomodation_type"; //住宿的类型
$labels[17] = "hotel_country"; //酒店的国家
$labels[18] = "hotel_city"; //酒店的城市
$labels[19] = "hotel_ufi"; //不知道该字段
$labels[20] = "booker_country"; //不知道该字段
$labels[21] = "booker_language"; //不知道该字段
$labels[22] = "label"; //酒店的标签
$labels[23] = "user_device"; //用户的设备订单 例如:电脑 手机
$labels[24] = "travel_purpose"; //用户旅行的目的
foreach ($labels as $label) {
$keys[] = $label;
}
$keys[] = "";
for ($i = 0; $i < $count; $i++) {
$array[$i][] = $i;
}
$newArray = array();
for ($j = 0; $j < $count; $j++) {
$d = array_combine($keys, $array[$j]);
$newArray[$j] = $d;
}
$conn = mysqli_connect($dbhost, $dbuser, $dbpass);
if(! $conn )
{
die('连接失败: ' . mysqli_error($conn));
}
mysqli_query($conn, "set names utf8");
mysqli_select_db( $conn, $database );
mysqli_query($conn, "SET AUTOCOMMIT=0");
$reslte = true;
mysqli_begin_transaction($conn);
try{
//默认成功类型
$status['type'] = "1";
foreach ($newArray as $keys => $open) {
$lable_explode = explode('-',$open['label']);
$label_1 = (int)@$lable_explode[0];
$label_2 = (int)@$lable_explode[1];
$label_1 = $label_1 == 0 ? 1 : $label_1;
$label_2 = $label_2 == 0 ? 1 : $label_2;
if(strlen($open['label']) == 5){
$label_2 = 0;
}
$open['label_1'] = $label_1;
$open['label_2'] = $label_2;
$fetch_reslte = pdo_fetch("SELECT * FROM ims_meepo_book WHERE add_id=:add_id", array(":add_id"=>$open['add_id']));
$configs = pdo_fetch("SELECT * FROM ims_meepo_online_list_config WHERE id=1 ", array(''=>''));
//千位字符去除逗号 ,
$open['commision_eur'] = str_replace(",","",@$open['commision_eur']);
$open['fee'] = str_replace(",","",$open['fee']);
//判斷下單類型
$type_info = get_type($label_1,$label_2);
$open['user_id'] = $type_info['user_id'];
$open['ascription_name'] = $type_info['ascription_name'];
$baifen = (float)$open['progress_bar']/100;
$ratio = $configs['ao_default']+@$configs['incentive_ratio'];
$open['ren_money'] = round(((($open['fee']/$baifen)*$configs['exchange_rate'])*$ratio)/100,2);
// $open['t_money'] = 0;
// if($type_info['ascription_name'] == '推荐'){
// $open['t_money'] = (int)round(((($open['fee']/$baifen)*$configs['exchange_rate'])*$configs['rr_default'])/100,2);
// }
$open['dd_zong'] = round((($open['fee']/$baifen)*$configs['exchange_rate']),2);
$open['daoru_time'] = time();
if($open['status'] !== '已完成' && $open['status'] !== '未完成' && $open['status'] !== '已取消'){ //操作订单状态
//错误订单统计
$reslte = false;
$status['type'] = "2";
$status['error'][$keys] = $open['add_id'];
break;
}
//字符转义
$open['hotel_name'] = addslashes($open['hotel_name']);
$open['label'] = addslashes($open['label']);
$open['accomodation_type'] = addslashes($open['accomodation_type']);
$open['hotel_city'] = addslashes($open['hotel_city']);
$rizhi_data = array();
$rizhi_data['label'] = $open['label'];
$rizhi_data['type'] = @$open['type'];
$rizhi_data['dd_zong'] = $open['dd_zong'];
$rizhi_data['status'] = $open['status'];
$rizhi_data['money'] = @$open['money'];
$rizhi_data['departure'] = $open['departure'];
$rizhi_data['booked'] = $open['booked'];
$rizhi_data['hotel_country'] = $open['hotel_country'];
$rizhi_data['hotel_name'] = $open['hotel_name'];
$rizhi_data['user_id'] = $open['user_id'];
$rizhi_data['add_id'] = $open['add_id'];
$rizhi_data['time '] = time();
if(!empty($fetch_reslte)){ //含有该数据
if(($open['status'] == '已完成' || $open['status'] == '已取消') && $fetch_reslte['status'] == '未完成' && $fetch_reslte['time_statics'] == 0 && $fetch_reslte['order_static'] == 0){
$non = mysqli_query($conn,"UPDATE ims_meepo_book SET
add_id='{$open['add_id']}',
booked='{$open['booked']}',
arrival='{$open['arrival']}',
departure='{$open['departure']}',
length_of_stay='{$open['length_of_stay']}',
booking_window='{$open['booking_window']}',
status='{$open['status']}',
comission_eur='{$open['comission_eur']}',
progress_bar='{$open['progress_bar']}',
fee='{$open['fee']}',
fee_currency='{$open['fee_currency']}',
exchange_rate='{$open['exchange_rate']}',
ttv='{$open['ttv']}',
slip_nr='{$open['slip_nr']}',
affiliate_id='{$open['affiliate_id']}',
hotel_name='{$open['hotel_name']}',
accomodation_type='{$open['accomodation_type']}',
hotel_country='{$open['hotel_country']}',
hotel_city='{$open['hotel_city']}',
hotel_ufi='{$open['hotel_ufi']}',
booker_country='{$open['booker_country']}',
booker_language='{$open['booker_language']}',
label='{$open['label']}',
label_1='{$label_1}',
label_2='{$label_2}',
user_device='{$open['user_device']}',
travel_purpose='{$open['travel_purpose']}',
user_id='{$open['user_id']}',
ascription_name='{$open['ascription_name']}',
ren_money='{$open['ren_money']}',
dd_zong='{$open['dd_zong']}',
daoru_time='{$open['daoru_time']}'
WHERE add_id = '{$open['add_id']}'");
$status['update'][$keys] = $open['add_id'];
//insert log record
$rizhi_data['rizhi_type'] = '导入订单更新';
add_rizhi_record($rizhi_data);
if($open['status'] == '未完成'){
process($open);
}else if($open['status'] == '已完成'){
complete($open);
}
}else{
$status['repeat'][$keys] = $open['add_id'];
}
}else{ //未含有该数据
$sql = "INSERT INTO ims_meepo_book (
add_id,
booked,
arrival,
departure,
length_of_stay,
booking_window,
status,
comission_eur,
progress_bar,
fee,
fee_currency,
exchange_rate,
ttv,slip_nr,
affiliate_id,
hotel_name,
accomodation_type,
hotel_country,
hotel_city,
hotel_ufi,
booker_country,
booker_language,
label,
label_1,
label_2,
user_device,
travel_purpose,
user_id,
ascription_name,
ren_money,
dd_zong,
daoru_time
) VALUES (
'{$open['add_id']}',
'{$open['booked']}',
'{$open['arrival']}',
'{$open['departure']}',
'{$open['length_of_stay']}',
'{$open['booking_window']}',
'{$open['status']}',
'{$open['comission_eur']}',
'{$open['progress_bar']}',
'{$open['fee']}',
'{$open['fee_currency']}',
'{$open['exchange_rate']}',
'{$open['ttv']}',
'{$open['slip_nr']}',
'{$open['affiliate_id']}',
'{$open['hotel_name']}',
'{$open['accomodation_type']}',
'{$open['hotel_country']}',
'{$open['hotel_city']}',
'{$open['hotel_ufi']}',
'{$open['booker_country']}',
'{$open['booker_language']}',
'{$open['label']}',
'{$label_1}',
'{$label_2}',
'{$open['user_device']}',
'{$open['travel_purpose']}',
'{$open['user_id']}',
'{$open['ascription_name']}',
'{$open['ren_money']}',
'{$open['dd_zong']}',
'{$open['daoru_time']}'
)";
mysqli_query($sql);
//insert log record
$rizhi_data['rizhi_type'] = '导入订单新增';
add_rizhi_record($rizhi_data);
if($open['status'] == '未完成'){
process($open);
}else if($open['status'] == '已完成'){
complete($open);
}
$non = mysqli_query($conn,$sql);
$status['insert'][$keys] = $open['add_id'];
}
}
if($reslte == false){
mysqli_rollback($conn);
return $status;
}else{
mysqli_commit($conn);
return $status;
}
}
catch (Exception $e){
$status['type'] = "3";
$status['exception'][$keys] = $e->getMessage();
mysqli_rollback($conn);
return $status;
}
finally{
mysqli_rollback($conn);
return $status;
}
}
$data_img = $_GPC['no_img'];
$file_jd = dirname(dirname(dirname(dirname(dirname(__FILE__)))));
$link = $file_jd.'/attachment/'.$data_img;
$dbhost = $_W['config']['db']['master']['host'];
$dbuser = $_W['config']['db']['master']['username'];
$dbpass = $_W['config']['db']['master']['password'];
$database = $_W['config']['db']['master']['database'];
$aData = read_csv($link,$dbhost,$dbuser,$dbpass,$database);
//检测语句
// echo "<pre>";print_r(read_csv($link,$dbhost,$dbuser,$dbpass,$database));exit();
$mix_data = array();
$mix_data['createtime'] = time();
$mix_data['no_img'] = $_POST['no_img'];
pdo_update($this->category_table,$mix_data,array('id'=>$id,'weid'=>$weid));
if($aData['type'] == '1'){
batch_calculate_rebate_ratio();
$ins = count(@$aData['insert']);
$upd = count($aData['update']);
$rep = count(@$aData['repeat']);
message('订单文件导入成功,其中新订单'.$ins.'笔,更新订单'.$upd.'笔,重复订单'.$rep.'笔',$this->createWebUrl('category_manage_list',array('op'=>'post','id'=>'5')),'success');
}else if($aData['type'] == '2'){
$arr_to_str = implode('<br/>',$aData['error']);
message('订单文件导入失败,其中错误订单号'.$arr_to_str,$this->createWebUrl('category_manage_list',array('op'=>'post','id'=>'5')),'error');
}else{
$err = count($aData['exception']);
$arr_to_str = implode('<br/>',$aData['exception']);
message('系统异常请联系管理员'.$arr_to_str,$this->createWebUrl('category_manage_list',array('op'=>'post','id'=>'5')),'error');
}
}else{
message('请勿串改URL',$this->createWebUrl('category_manage_list'),'error');
}
}
}
// 推广激勵
function batch_calculate_rebate_ratio(){
$configs = pdo_fetch("SELECT * FROM ims_meepo_online_list_config WHERE id=1 ", array(''=>''));
$rr_default = $configs['rr_default'];
$rr_10 = $configs['rr_10'];
$rr_20 = $configs['rr_20'];
$ro_2 = $configs['ro_2'];
$ro_10 = $configs['ro_10'];
$ao_default = $configs['ao_default'];
$ao_5 = $configs['ao_5'];
$ao_20 = $configs['ao_20'];
$gong_id = $configs['gong_id'];
//get all users
$result = pdo_fetchall("SELECT * FROM ims_meepo_online_user WHERE id != :gong_id ", array(":gong_id"=>$gong_id));
foreach($result as $row){
$ratio = 0;
$user_id = $row['id'];
//計算推薦總人數
$rr_count = pdo_fetchcolumn("SELECT count(*) FROM ims_meepo_online_user WHERE one=:user_id ", array(":user_id"=>$user_id));
if($rr_count >= 10 && $rr_count < 20){
$ratio+=$rr_10;
}else if($rr_count >= 20){
$ratio+=$rr_20;
}
//計算推薦下單數
$ro_count = pdo_fetchcolumn("SELECT count(*) FROM ims_meepo_book WHERE label_2=:user_id and label_2!=label_1 ", array(":user_id"=>$user_id));
if($ro_count >= 2 && $ro_count < 10){
$ratio+=$ro_2;
}else if($ro_count >= 10){
$ratio+=$ro_10;
}
//計算自主下單數
$ao_count = pdo_fetchcolumn("SELECT count(*) FROM ims_meepo_book WHERE label_2=$user_id and label_2=label_1 ");
if($ao_count >= 5 && $ao_count < 20){
$ratio+=$ao_5;
}else if($ao_count >= 20){
$ratio+=$ao_20;
}
//update user info
$sql = "UPDATE ims_meepo_online_user SET incentive_ratio = {$ratio} WHERE id={$user_id}";
pdo_query($sql);
}
}
function get_type($label_1, $label_2){
$configs = pdo_fetch("SELECT * FROM ims_meepo_online_list_config WHERE id=1 ", array(''=>''));
$gong_user_id = $configs['gong_id'];
$user_id = $gong_user_id;
$ascription_name = '平台';
$label_explode = explode("-",$user_label);
$user_info = pdo_fetch("SELECT * FROM ims_meepo_online_user WHERE id=:id ", array(":id"=>$label_1));
if(!empty($user_info) && $user_info['id'] != $gong_user_id){
$user_id = $label_explode[0];
if($label_1 == $label_2){
$ascription_name = '自主';
}else if( $label_1 != 0 && $label_2 == 0){
$ascription_name = '分享';
}else if($label_1 != $label_2 && $label_2 != 0){
$ascription_name = '推荐';
}
}
return array('user_id'=>$user_id, 'ascription_name'=>$ascription_name);
}
function process($data){
$time = time();
$baifen = (float)$data['progress_bar']/100;
$configs = pdo_fetch("SELECT * FROM ims_meepo_online_list_config WHERE id=1 ", array(''=>''));
$label_1 = $data['label_1'];
$label_2 = $data['label_2'];
//a-b 推荐 b推荐a
//a-a 自主 a
//a 分享
$dingdan_data = array();
$dingdan_data['time'] = $time;
$dingdan_data['add_id'] = $data['add_id'];
$yongjin_data = array();
$yongjin_data['add_id'] = $data['add_id'];
$yongjin_data['departure'] = $data['departure'];
if( !empty($label_1) && (int)$label_1 != 0 && !empty($label_2) && (int)$label_2 != 0 && $label_1 != $label_2){
//a-b
//a
//insert dingdan
$ratio = $configs['ao_default']+get_user_incentive_ratio($label_1);
$money = round(((($data['fee']/$baifen)*$configs['exchange_rate'])*$ratio)/100,2);
$dingdan_data['money'] = $money;
$dingdan_data['user_id'] = $label_1;
$dingdan_data['type'] = '自主';
$dingdan_data['nickname'] = get_user_nickname($label_1);
add_dingdan_record($dingdan_data);
//add_yongjin_record
$yongjin_data['user_id'] = $label_1;
$yongjin_data['money'] = $money;
$yongjin_data['ratio'] = $ratio;
$yongjin_data['type'] = '自主';
add_yongjin_record($yongjin_data);
//b
$ratio = $configs['rr_default'];
$money = round(((($data['fee']/$baifen)*$configs['exchange_rate'])*$ratio)/100,2);
$dingdan_data['money'] = $money;
$dingdan_data['user_id'] = $label_2;
$dingdan_data['type'] = '推荐';
$dingdan_data['nickname'] = get_user_nickname($label_2);
add_dingdan_record($dingdan_data);
//add_yongjin_record
$yongjin_data['user_id'] = $label_2;
$yongjin_data['money'] = $money;
$yongjin_data['ratio'] = $ratio;
$yongjin_data['type'] = '推荐';
add_yongjin_record($yongjin_data);
}else if( !empty($label_1) && (int)$label_1 != 0 && (int)$label_2 == 0 ){
//a
$ratio = $configs['rr_default'];
$money = round(((($data['fee']/$baifen)*$configs['exchange_rate'])*$ratio)/100,2);
$dingdan_data['money'] = $money;
$dingdan_data['user_id'] = $label_1;
$dingdan_data['type'] = '推荐';
$dingdan_data['nickname'] = get_user_nickname($label_1);
add_dingdan_record($dingdan_data);
//add_yongjin_record
$yongjin_data['user_id'] = $label_1;
$yongjin_data['money'] = $money;
$yongjin_data['ratio'] = $ratio;
$yongjin_data['type'] = '推荐';
add_yongjin_record($yongjin_data);
}else if( !empty($label_1) && (int)$label_1 != 0 && (int)$label_1 == (int)$label_2 ){
//a-a
$ratio = $configs['ao_default']+get_user_incentive_ratio($label_1);
$money = round(((($data['fee']/$baifen)*$configs['exchange_rate'])*$ratio)/100,2);
$dingdan_data['money'] = $money;
$dingdan_data['user_id'] = $label_1;
$dingdan_data['type'] = '自主';
$dingdan_data['nickname'] = get_user_nickname($label_1);
add_dingdan_record($dingdan_data);
//add_yongjin_record
$yongjin_data['user_id'] = $label_1;
$yongjin_data['money'] = $money;
$yongjin_data['ratio'] = $ratio;
$yongjin_data['type'] = '自主';
add_yongjin_record($yongjin_data);
}
}
function complete($data){
//check dingdan & yongjin record has been insert
$add_id = $data['add_id'];
$sql = "select count(*) from ims_meepo_online_new_dingdan where add_id = $add_id";
$dingdan_cnt = pdo_fetchcolumn($sql);
$sql = "select count(*) from ims_meepo_yongjin where add_id = $add_id";
$yongjin_cnt = pdo_fetchcolumn($sql);
if($dingdan_cnt > 0 && $yongjin_cnt > 0){
$sql = "select * from ims_meepo_yongjin where add_id = $add_id";
$result = pdo_fetchall($sql);
foreach($result as $row){
$user_id = $row['user_id'];
$money = $row['money'];
update_balance($user_id, $money+get_user_balance($user_id));
}
}else{
process($data);
complete($data);
}
}
function add_rizhi_record($rizhi_data){
$label = $rizhi_data['label'];
$type = $rizhi_data['type'];
$dd_zong = $rizhi_data['dd_zong'];
$status = $rizhi_data['status'];
$money = $rizhi_data['money'];
$departure = $rizhi_data['departure'];
$booked = $rizhi_data['booked'];
$hotel_country = $rizhi_data['hotel_country'];
$hotel_name = $rizhi_data['hotel_name'];
$user_id = $rizhi_data['user_id'];
$rizhi_type = $rizhi_data['rizhi_type'];
$add_id = $rizhi_data['add_id'];
$time = @$rizhi_data['time'];
$sql = "INSERT INTO ims_meepo_online_rizi (label,dingdan_texts,dingdan_money,dingdan_static,fanyong_money,tuifang_time,yuding_time,mingcheng,did,static,add_id,`time`)
VALUES ('{$label}','{$type}','{$dd_zong}','{$status}','{$money}','{$departure}','{$booked}','({$hotel_country}){$hotel_name}','{$user_id}','{$rizhi_type}','{$add_id}','{$time}')";
// echo $sql;
pdo_query($sql);
}
function add_dingdan_record($dingdan_data){
$add_id = $dingdan_data['add_id'];
$time = $dingdan_data['time'];
$money = $dingdan_data['money'];
$user_id = $dingdan_data['user_id'];
$type = $dingdan_data['type'];
$nickname = $dingdan_data['nickname'];
//insert ims_meepo_online_new_dingdan table
$sql = "INSERT INTO `dyl`.`ims_meepo_online_new_dingdan` (`id`, `add_id`, `static`, `times`, `money`, `uid`, `text`, `name`, `time_srat`)
VALUES (NULL, $add_id, NULL, '$time', $money, $user_id, '$type', '$nickname', NULL)";
pdo_query($sql);
}
function add_yongjin_record($data){
$add_id = $data['add_id'];
$departure = $data['departure'];
$user_id = $data['user_id'];
$money = $data['money'];
$ratio = $data['ratio'];
$type = $data['type'];
$sql = "INSERT INTO `ims_meepo_yongjin` (`add_id`, `departure`, `user_id`, `money`, `ratio`, `type`, `add_time`)
VALUES ('$add_id', '$departure', $user_id, $money, $ratio, '$type', NOW())";
pdo_query($sql);
}
function update_balance($user_id, $money){
$sql = "update `ims_meepo_online_user` set balance=$money where id = $user_id";
pdo_query($sql);
}
function get_user_incentive_ratio($user_id){
$sql = "select incentive_ratio from ims_meepo_online_user where id = $user_id";
return pdo_fetchcolumn($sql);
}
function get_user_nickname($user_id){
$sql = "select nickname from ims_meepo_online_user where id = $user_id";
return pdo_fetchcolumn($sql);
}
function get_user_balance($user_id){
$sql = "select balance from ims_meepo_online_user where id = $user_id";
return pdo_fetchcolumn($sql);
}
include $this->template('category_manage_list');
解决日期超过时间戳范围的问题
$expiry_date = $balance_arr['data']['ecash_purseExpiry'];
$expiry_date = new DateTime($expiry_date);
$details['expiry_date'] = $expiry_date->format('Y-m-d');
FIND_IN_SET
select * from new_mg.voucher_payment a, voucher b where a.payment_id =12 and b.submission_id in (a.submission_ids)
使用这种方式并没有办法 in到 ids里的所有id
解决办法是使用FIND_IN_SET
select b.voucher_id from new_mg.voucher_payment a, voucher b where a.payment_id =12 and FIND_IN_SET(b.submission_id,a.submission_ids)