技术扩展阅读

最后更新于:2022-04-02 01:47:38

> # 技术扩展阅读 - 公众号回复关键字【000】获取技术扩展阅读 ![](https://oscimg.oschina.net/oscnet/up-856e3f10fc8528cbe965e0c0970269b016b.png)
';

十七节 GRPC PHP客户端

最后更新于:2022-04-02 01:47:35

>[success] # GRPC PHP客户端 - [GRPC 官方文档中文版](http://doc.oschina.net/grpc?t=58008) - GRPC 是一款语言中立、平台中立、开源的远程过程调用(RPC)系统 - 有了 GRPC, 我们可以一次性的在一个 .proto 文件中定义服务并使用任何支持它的语言去实现客户端和服务器; 可以很容易地用Go创建一个 GRPC 服务端,用 PHP、Go、Python、Ruby 来创建客户端 - PHP没有GRPC的服务端, 本案例的服务端用Go来实现 > ### 客户端下载 - Tip:公众号回复【026】获取源代码 - GRPC Go的服务端 - GRPC PHP的客服端 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/de/d6/ded6e495eb8a39d2c7a8b0547b329d19_430x430.jpg) > ### GRPC PHP客户端 - [安装GRPC 扩展](http://pecl.php.net/package/gRPC) - 先运行main_go.exe(gRPC Go的服务端), 在运行GRPC PHP的客服端 ![img](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/8ceccc7d18c85993e349e66ee69d819c_1162x864.png) > ### 相关阅读 - [GRPC的PHP客户端](https://my.oschina.net/laixhe/blog/1476644)
';

代码2

最后更新于:2022-04-02 01:47:33

- 视频转化: https://cloudconvert.com/avi-to-mp4 ~~~ import os import cv2 from cv2 import VideoWriter, VideoWriter_fourcc, imread, resize from PIL import Image, ImageFont, ImageDraw # 图片填充的字符 #ascii_char = list("#ABCDEFGHIJKLMNOPQRSTUVWXYZ@$%??__ff--++~~'' ::.. `` ") ascii_char = list("MNHQ$OC67+>!:-. ") # 将像素转换为ascii码 def get_char(r, g, b, alpha=256): if alpha == 0: return '' length = len(ascii_char) gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b) unit = (256.0 + 1) / length return ascii_char[int(gray / unit)] # 将txt转换为图片 def txt2image(file_name): im = Image.open(file_name).convert('RGB') # gif拆分后的图像,需要转换,否则报错,由于gif分割后保存的是索引颜色 raw_width = im.width raw_height = im.height width = int(raw_width / 6) height = int(raw_height / 15) im = im.resize((width, height), Image.NEAREST) txt = "" colors = [] for i in range(height): for j in range(width): # 获取当前位置的三原色 pixel = im.getpixel((j, i)) # 字符上颜色 #colors.append((pixel[0], pixel[1], pixel[2])) # 字符上黑色 colors.append((0, 0, 0)) if len(pixel) == 4: txt += get_char(pixel[0], pixel[1], pixel[2], pixel[3]) else: txt += get_char(pixel[0], pixel[1], pixel[2]) txt += '\n' colors.append((255, 255, 255)) im_txt = Image.new("RGB", (raw_width, raw_height), (255, 255, 255)) dr = ImageDraw.Draw(im_txt) # font = ImageFont.truetype(os.path.join("fonts","汉仪楷体简.ttf"),18) font = ImageFont.load_default().font x = y = 0 # 获取字体的宽高 font_w, font_h = font.getsize(txt[1]) font_h *= 1.37 # 调整后更佳 # ImageDraw为每个ascii码进行上色 for i in range(len(txt)): if txt[i] == '\n': x += font_h y = -font_w dr.text((y, x), txt[i], fill=colors[i]) y += font_w name = file_name im_txt.save(name) # 将视频拆分成图片 def video2txt_jpg(file_name): vc = cv2.VideoCapture(file_name) c = 1 if vc.isOpened(): r, frame = vc.read() if not os.path.exists('Cache'): os.mkdir('Cache') os.chdir('Cache') else: r = False while r: # 生成拆分的图片 cv2.imwrite(str(c) + '.jpg', frame) # 将图片转换为ascii图 txt2image(str(c) + '.jpg') r, frame = vc.read() c += 1 os.chdir('..') return vc # 将图片合成视频 def jpg2video(outfile_name, fps): fourcc = VideoWriter_fourcc(*"MJPG") images = os.listdir('Cache') im = Image.open('Cache/' + images[0]) vw = cv2.VideoWriter(outfile_name + '.avi', fourcc, fps, im.size) os.chdir('Cache') for image in range(len(images)): frame = cv2.imread(str(image + 1) + '.jpg') vw.write(frame) os.chdir('..') vw.release() # 递归删除目录 def remove_dir(path): if os.path.exists(path): if os.path.isdir(path): dirs = os.listdir(path) for d in dirs: if os.path.isdir(path + '/' + d): remove_dir(path + '/' + d) elif os.path.isfile(path + '/' + d): os.remove(path + '/' + d) os.rmdir(path) return elif os.path.isfile(path): os.remove(path) return if __name__ == '__main__': # 输入视频路径 INPUT = r"D:\video\demo2.mp4" # 将视频拆分成图片, 将图片转像素, vc = video2txt_jpg(INPUT) # 将像素图片合成视频 jpg2video(INPUT.split('.')[0], vc.get(cv2.CAP_PROP_FPS)) # 移出拆分出来的图片 remove_dir("Cache") ~~~
';

源代码

最后更新于:2022-04-02 01:47:31

> Python 视频转代码视频 - 代码来源: https://blog.csdn.net/mp624183768/article/details/81161260 ``` # -*- coding:utf-8 -*- #coding:utf-8 import argparse import os import cv2 import subprocess from cv2 import VideoWriter, VideoWriter_fourcc, imread, resize from PIL import Image, ImageFont, ImageDraw # 命令行输入参数处理 # aparser = argparse.ArgumentParser() # aparser.add_argument('file') # aparser.add_argument('-o','--output') # aparser.add_argument('-f','--fps',type = float, default = 24)#帧 # aparser.add_argument('-s','--save',type = bool, nargs='?', default = False, const = True) # 是否保留Cache文件,默认不保存 # 获取参数 # args = parser.parse_args() # INPUT = args.file # OUTPUT = args.output # SAVE = args.save # FPS = args.fps # 像素对应ascii码 ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:oa+>!:+. ") # ascii_char = list("MNHQ$OC67+>!:-. ") # ascii_char = list("MNHQ$OC67)oa+>!:+. ") # 将像素转换为ascii码 def get_char(r, g, b, alpha=256): if alpha == 0: return '' length = len(ascii_char) gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b) unit = (256.0 + 1) / length return ascii_char[int(gray / unit)] # 将txt转换为图片 def txt2image(file_name): im = Image.open(file_name).convert('RGB') # gif拆分后的图像,需要转换,否则报错,由于gif分割后保存的是索引颜色 raw_width = im.width raw_height = im.height width = int(raw_width / 6) height = int(raw_height / 15) im = im.resize((width, height), Image.NEAREST) txt = "" colors = [] for i in range(height): for j in range(width): pixel = im.getpixel((j, i)) colors.append((pixel[0], pixel[1], pixel[2])) if (len(pixel) == 4): txt += get_char(pixel[0], pixel[1], pixel[2], pixel[3]) else: txt += get_char(pixel[0], pixel[1], pixel[2]) txt += '\n' colors.append((255, 255, 255)) im_txt = Image.new("RGB", (raw_width, raw_height), (255, 255, 255)) dr = ImageDraw.Draw(im_txt) # font = ImageFont.truetype(os.path.join("fonts","汉仪楷体简.ttf"),18) font = ImageFont.load_default().font x = y = 0 # 获取字体的宽高 font_w, font_h = font.getsize(txt[1]) font_h *= 1.37 # 调整后更佳 # ImageDraw为每个ascii码进行上色 for i in range(len(txt)): if (txt[i] == '\n'): x += font_h y = -font_w # self, xy, text, fill = None, font = None, anchor = None, #*args, ** kwargs dr.text((y, x), txt[i], fill=colors[i]) #dr.text((y, x), txt[i], font=font, fill=colors[i]) y += font_w name = file_name #print(name + ' changed') im_txt.save(name) # 将视频拆分成图片 def video2txt_jpg(file_name): vc = cv2.VideoCapture(file_name) c = 1 if vc.isOpened(): r, frame = vc.read() if not os.path.exists('Cache'): os.mkdir('Cache') os.chdir('Cache') else: r = False while r: cv2.imwrite(str(c) + '.jpg', frame) txt2image(str(c) + '.jpg') # 同时转换为ascii图 r, frame = vc.read() c += 1 os.chdir('..') return vc # 将图片合成视频 def jpg2video(outfile_name, fps): fourcc = VideoWriter_fourcc(*"MJPG") images = os.listdir('Cache') im = Image.open('Cache/' + images[0]) vw = cv2.VideoWriter(outfile_name + '.avi', fourcc, fps, im.size) os.chdir('Cache') for image in range(len(images)): # Image.open(str(image)+'.jpg').convert("RGB").save(str(image)+'.jpg') frame = cv2.imread(str(image + 1) + '.jpg') vw.write(frame) #print(str(image + 1) + '.jpg' + ' finished') os.chdir('..') vw.release() # 递归删除目录 def remove_dir(path): if os.path.exists(path): if os.path.isdir(path): dirs = os.listdir(path) for d in dirs: if os.path.isdir(path + '/' + d): remove_dir(path + '/' + d) elif os.path.isfile(path + '/' + d): os.remove(path + '/' + d) os.rmdir(path) return elif os.path.isfile(path): os.remove(path) return # 调用ffmpeg获取mp3音频文件 def video2mp3(file_name): outfile_name = file_name.split('.')[0] + '.mp3' subprocess.call('ffmpeg -i ' + file_name + ' -f mp3 ' + outfile_name, shell=True) # 合成音频和视频文件 def video_add_mp3(file_name, mp3_file): outfile_name = file_name.split('.')[0] + '-txt.mp4' subprocess.call('ffmpeg -i ' + file_name + ' -i ' + mp3_file + ' -strict -2 -f mp4 ' + outfile_name, shell=True) if __name__ == '__main__': INPUT = r"G:\py\学习python\视频到代码\video39.mp4" OUTPUT = r"G:\py\学习python\视频到代码\video39_2.mp4" SAVE = r"G:\py\学习python\视频到代码\\video39_3" FPS = "24" vc = video2txt_jpg(INPUT) FPS = vc.get(cv2.CAP_PROP_FPS) # 获取帧率 print(FPS) vc.release() jpg2video(INPUT.split('.')[0], FPS) print(INPUT, INPUT.split('.')[0] + '.mp3') video2mp3(INPUT) video_add_mp3(INPUT.split('.')[0] + '.avi', INPUT.split('.')[0] + '.mp3') if (not SAVE): remove_dir("Cache") os.remove(INPUT.split('.')[0] + '.mp3') os.remove(INPUT.split('.')[0] + '.avi') ```
';

十六节 Python 视频转代码视频

最后更新于:2022-04-02 01:47:29

[源代码](%E6%BA%90%E4%BB%A3%E7%A0%81.md) [代码2](%E4%BB%A3%E7%A0%812.md)
';

十四节 图片转ASCII码图

最后更新于:2022-04-02 01:47:26

>[success] # 图片转ASCII码图 * [案例图](http://www.degraeve.com/img2txt.php) * [手把手教你图片转ASCII码图](https://www.cnblogs.com/jelly7723/p/5657891.html) * [图片转字符](https://segmentfault.com/a/1190000007692741) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/b577e6d90fa106b736db964948927712_896x428.png) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/bd855ff2eadf838f37becc2a62f9d23a_919x525.jpg) ~~~php = $len) { $index = $len - 1; } return $char[(int)$index]; } function tosmallim($const = 100, $width, $height, $image) { if ($width > $const) { $times = floor($width / $const); $smwidth = $const; $smheight = floor($height / $times); $im = imagecreatetruecolor($smwidth, $smheight); imagecopyresampled($im, $image, 0, 0, 0, 0, $smwidth, $smheight, $width, $height); return [$im, $smwidth, $smheight]; } return [$image, $width, $height]; } $imname = 'http://images2015.cnblogs.com/blog/763758/201606/763758-20160612082543871-1901077809.png'; //返回一图像标识符,代表了从给定的文件名取得的图像 $image = ImageCreateFromPng($imname); //$im = ImageCreateFromJpeg($imname); $size = getimagesize($imname); $width = $size[0]; $height = $size[1]; list($image, $width, $height) = tosmallim(100, $width, $height, $image); $arr = []; for ($i = 0; $i < $height; $i++) { for ($j = 0; $j < $width; $j++) { $rgb = ImageColorat($image, $j, $i); $r = ($rgb >> 16) & 0xFF; $g = ($rgb >> 8) & 0xFF; $b = $rgb & 0xFF; $arr[] = floor(($r + $g + $b) / 3); } } $num = count(array_unique($arr)); $str = ''; for ($i = 0; $i < $height; $i++) { for ($j = 0; $j < $width; $j++) { $rgb = ImageColorat($image, $j, $i); $r = ($rgb >> 16) & 0xFF; $g = ($rgb >> 8) & 0xFF; $b = $rgb & 0xFF; $str .= tochars($r, $g, $b, $num); } $str .= '
'; } echo $str . '
'; ~~~
';

十三节 实战笔记 – MySQL 篇

最后更新于:2022-04-02 01:47:24

>[success] # [实战笔记 - MySQL 篇](https://www.kancloud.cn/xiaohuamao/mysql) - 一条 SQL 语句的执行流程 - InnoDB 数据读取和写入过程 - 误删表数据如何恢复 - 基本数据结构介绍 - 存储引擎 InnoDB、MyISAM、Memory、NDB、Archive 介绍 - Join 语句还能不能用 - EXPLAIN 分析 SQL 语句 - SQL优化工具SQLAdvisor - 事务 ACID:原子性、一致性、隔离性、持久性 - 乐观锁和悲观锁 - 视图 - 分区分表 - 高并发高可用方案:MyCat、MySQL-Proxy - 应用场景 - 代码示例 - MySQL 相关阅读
';

十二节 实战笔记 – Redis 篇

最后更新于:2022-04-02 01:47:22

>[success] # [实战笔记 - Redis 篇](https://www.kancloud.cn/xiaohuamao/source-open-6) - 数据结构以及应用场景 - 为什么需要缓存 - Redis 和 Memcached 对比分析 - 缓存雪崩、缓存击穿、缓存穿透 - Key 的过期淘汰机制 - 全量模式 RDB 冷备份(内存快照) - 增量模式 AOF 热备份(文件追加) - 集群模式: Redis Sentine 和 Redis Cluster - 为什么会出现类似 MOVED 2602 127.0.0.1:8001 错误 - 集群中如何将两个 Key 存储在同一个 slot 中 - 如何定位大 Key - 假如 Redis 里面有 1 亿个 key,其中有 10w 个 key 是以某个固定的已知的前缀开头的,如何将它们全部找出来 - 三主三从集群部署过程 - 可视化工具 Redis Desktop Manager - 代码示例 - Redis 相关阅读
';

十一节 实战笔记 – Kafka 篇

最后更新于:2022-04-02 01:47:20

>[success]# 为什么需要消息队列 - 异步 :一个下单流程,你需要扣积分,扣优惠卷,发短信等,有些耗时又不需要立即处理的事,可以丢到队列里异步处理。 - 削峰 :按平常的流量,服务器刚好可以正常负载。偶尔推出一个优惠活动时,请求量极速上升。由于服务器 Redis,MySQL 承受能力不一样,如果请求全部接收,服务器负载不了会导致宕机。加机器嘛,需要去调整配置,活动结束后用不到了,即麻烦又浪费。这时可以将请求放到队列里,按照服务器的能力去消费。 - 解耦 :一个订单流程,需要扣积分,优惠券,发短信等调用多个接口,出现问题时不好排查。像发短信有很多地方需要用到, 如果哪天修改了短信接口参数,用到的地方都得修改。这时可以将要发送的内容放到队列里,起一个服务去消费, 统一发送短信。 ![](https://oscimg.oschina.net/oscnet/up-a7bd5635c96cb2d0a2c16e5d1fc10653a93.png) >[success] # [实战笔记 - Kafka 篇](https://www.kancloud.cn/xiaohuamao/phpapi) - 为什么需要消息队列 - ActiveMQ、RabbitMQ、RocketMQ、Kafka、ZeroMQ 对比分析 - Kafka 相关概念 -  分区、副本、消费组 - Zookeeper 上与 Kafka 相关的节点 - 偏移量的最大值,消息的存储策略 - 如何解决重复消费和数据丢失问题 - 如何确保一条消息只被一个服务消费 - 如何让一条消息被多个服务消费 - Kafka 相关命令行操作示例 - Windows 可视化工具 Kafka Tool - 生产者代码示例 - 消费者代码示例 - Kafka 相关阅读
';

第二章

最后更新于:2022-04-02 01:47:17

[十一节 实战笔记 - Kafka 篇](%E5%8D%81%E4%B8%80%E8%8A%82Kafka%E7%9F%A5%E8%AF%86%E7%82%B9.md) [十二节 实战笔记 - Redis 篇](%E5%8D%81%E4%BA%8C%E8%8A%82Redis%E7%9F%A5%E8%AF%86%E7%82%B9.md) [十三节 实战笔记 - MySQL 篇](%E5%8D%81%E4%B8%89%E8%8A%82MySQL%E7%9F%A5%E8%AF%86%E7%82%B9.md) [十四节 图片转ASCII码图](1.14%E5%9B%BE%E7%89%87%E8%BD%ACASCII%E7%A0%81%E5%9B%BE.md) [十六节 Python 视频转代码视频](%E5%8D%81%E5%85%AD%E8%8A%82python%E8%A7%86%E9%A2%91%E8%BD%AC%E4%BB%A3%E7%A0%81%E8%A7%86%E9%A2%91.md) [十七节 GRPC PHP客户端](GRPCPHP%E5%AE%A2%E6%88%B7%E7%AB%AFPHP.md)
';

第十节 PHPExcel 表格导入和导出

最后更新于:2022-04-02 01:47:15

>[success] # PHPExcel导入导出 * PHPExcel 是用来操作Office Excel 文档的一个PHP类库,它基于微软的OpenXML标准和PHP语言。可以使用它来读取、写入不同格式的电子表格,如 Excel (BIFF) .xls, Excel 2007 (OfficeOpenXML) .xlsx, CSV, Libre/OpenOffice Calc .ods, Gnumeric, PDF, HTML等等 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/6a04027bedad6dee749e667745f6c5e3_611x192.png) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/7d740d143047e22812a1991231e261c2_706x746.png) > ### 相关阅读 * [PHP操作Excel – PHPExcel 基本用法详解](http://blog.csdn.net/diandian_520/article/details/7827038) > ### 源码下载 - Tip:公众号回复【027】获取源代码 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/de/d6/ded6e495eb8a39d2c7a8b0547b329d19_430x430.jpg)
';

第九节 PHP 跟踪调试代码 XDebug

最后更新于:2022-04-02 01:47:13

>[success] # PHP 跟踪调试代码 XDebug - [下载XDebug扩展](https://xdebug.org/download.php) - 下载对应PHP版本的Xdebug ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/c17f1f1e965522c2fe1411e1759e4447_870x524.png) - 线程安全(TS)和非线程安全(NTS) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/24efc18d4299f35a0618e8566751692c_834x139.png) - 安装Xdebug扩展-php.ini ``` [XDebug] xdebug.profiler_output_dir="D:\phpStudy\tmp\xdebug" xdebug.trace_output_dir="D:\phpStudy\tmp\xdebug" zend_extension="D:\phpStudy\php\php-7.1.7-nts-64\ext\php_xdebug-2.5.3-7.1-vc14-nts-x86_64.dll" xdebug.idekey=PHPSTORM xdebug.remote_port=9005 xdebug.remote_enable=on ``` - 配置PHPStorm ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/24efc18d4299f35a0618e8566751692c_834x139.png) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/51b711b3bbc9249174ffce1a4b9f945b_1029x779.png) - 配置Debug ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/1edc8f99d4ef5ba2716c67ee7cde5b1f_1085x698.png) - 运行Debug ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/28d7820fd72af5b2b500f0c038cff27b_425x134.png) - 调试 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/36e26a415303e32f1832bbc850ee2dd7_1887x727.png) - return 处 Step into F7 跳进去 > ### 相关阅读 - [为PHPStorm配置Xdebug调试环境](http://blog.csdn.net/zhyh1986/article/details/45172685) - [Configure Xdebug Helper for Chrome to be used with PhpStorm](https://confluence.jetbrains.com/display/PhpStorm/Configure+Xdebug+Helper+for+Chrome+to+be+used+with+PhpStorm)
';

第八节 PHP 接口调试工具 SocketLog

最后更新于:2022-04-02 01:47:11

>[success] # PHP 接口调试工具 SocketLog - demo1下载: 链接:https://pan.baidu.com/s/1ZdCpU4cH7pXxEFib5rRneA 密码:8e0c > ### 安装Node - 下载链接: http://nodejs.cn/download/ - 因为服务端是Node.Js写的, 所以要安装Node > ### 启动SocketLog服务端 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/03c46f8461cd51e4d493248480d414e3_726x177.png) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/51d3b87d35a4dbe7fd9f44ac7371bdd5_960x432.png) > ### 安装扩展插件 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/c90fc2891ac20f73d3ed14d4c5296701_1527x426.png) > ### 配置SocketLog ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/c90fc2891ac20f73d3ed14d4c5296701_1527x426.png) > ### 运行程序 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/b6df94b2fd07eaf4c018f0427da9d5eb_914x461.png)
';

第七节 百度地图

最后更新于:2022-04-02 01:47:08

>[success] # 百度地图 * 百度地图API是一套为开发者免费提供的基于百度地图的应用程序接口,包括JavaScript、iOS、Andriod、静态地图、Web服务等多种版本,提供基本地图、位置搜索、...... - [百度地图文档](http://lbsyun.baidu.com/) * [地图API示例](http://lbsyun.baidu.com/jsdemo.htm#a1_2) * [申请密匙](http://lbsyun.baidu.com/apiconsole/key/create) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/e0158ce53b9e4adcf181295762af79a1_1142x484.png) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/4a0c1a9fcd1eea7c1217bca75644c988_1140x498.png) > ### 项目源码下载 - Tip:公众号回复【024】获取源代码 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/de/d6/ded6e495eb8a39d2c7a8b0547b329d19_430x430.jpg)
';

第六节 ThinkPHP 验证码

最后更新于:2022-04-02 01:47:06

>[success] # ThinkPHP 验证码 * 验证码可以防止机器人的恶意请求(恶意表单提交、破解密码、刷票、论坛灌水......) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/98570d04717f59331b20808fd201df5f_475x153.png) >[info] # 源码下载 - Tip:公众号回复【023】获取源代码 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/de/d6/ded6e495eb8a39d2c7a8b0547b329d19_430x430.jpg) >[success] # 原生PHP 实现验证码 * 字体文件下载msjh.ttf 链接:https://pan.baidu.com/s/1jHLpYku 密码:el2k ```php font = 'msjh.ttf';//注意字体路径要写对,否则显示不了图片 } //生成验证码 private function createCode() { $len = strlen($this->charset) - 1; for ($i = 0; $i < $this->codelen; $i++) { $this->code .= $this->charset[mt_rand(0, $len)]; } } //生成背景 private function createBg() { $this->img = imagecreatetruecolor($this->width, $this->height); //imagecreatetruecolor — 新建一个真彩色图像 $color = imagecolorallocate($this->img, mt_rand(157, 255), mt_rand(157, 255), mt_rand(157, 255)); //imagecolorallocate — 为一幅图像分配颜色 imagefilledrectangle($this->img, 0, $this->height, $this->width, 0, $color); } //生成文字 private function createFont() { //每个字符的平均宽度 $x = $this->width / $this->codelen; for ($i = 0; $i < $this->codelen; $i++) { //字体的颜色 $this->fontColor = imagecolorallocate($this->img, mt_rand(0, 156), mt_rand(0, 156), mt_rand(0, 156)); imagettftext($this->img, $this->fontSize, mt_rand(-10, 10), $i * $x + mt_rand(1, 3), $this->height / 1.3, $this->fontColor, $this->font, $this->code[$i]); //imagestring($this->img,5,$i*$x+mt_rand(1,5),5,$this->code[$i],$this->fontColor); } } //生成线条、雪花 private function createDisturb() { for ($i = 0; $i < 6; $i++) { $color = imagecolorallocate($this->img, mt_rand(0, 156), mt_rand(0, 156), mt_rand(0, 156)); imageline($this->img, mt_rand(0, $this->width), mt_rand(0, $this->width), mt_rand(0, $this->width), mt_rand(0, $this->width), $color); //imageline() 用 color 颜色在图像 image 中从坐标 x1,y1 到 x2,y2(图像左上角为 0, 0)画一条线段。 } for ($i = 0; $i < 100; $i++) { $color = imagecolorallocate($this->img, mt_rand(200, 255), mt_rand(200, 255), mt_rand(200, 255)); imagestring($this->img, mt_rand(1, 5), mt_rand(0, $this->width), mt_rand(0, $this->height), '*', $color); //imagestring — 水平地画一行字符串 } } //输出 private function outPut() { header("Content-Type:image/png"); imagepng($this->img); imagedestroy($this->img); } //显示验证码 public function showCode() { $this->createBg(); echo $this->code; $this->createCode(); //$_SESSION['code'] = $this->getCode(); $this->createDisturb(); $this->createFont(); $this->outPut(); } //获取验证码 public function getCode() { return strtolower($this->code); } } $code = new VerificationCode(); $code->showCode(); ``` ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/b193e6c8c13cb5688764bd0249c0159e_460x195.png)
';

第五节 UEditor 文本编辑器

最后更新于:2022-04-02 01:47:04

>[success] # UEditor文本编辑器 * UEditor是由百度WEB前端研发部开发的所见即所得的开源富文本编辑器,具有轻量、可定制、用户体验优秀等特点。开源基于BSD协议,所有源代码在协议允许范围内可自由修改和使用 - [官网介绍](http://ueditor.baidu.com/website/) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/5f9e7308c9ad20e6a986e56312867990_869x566.png) >[info] # 简单应用 ```html
``` >[info] # 相关阅读 * [定制工具栏图标](http://fex.baidu.com/ueditor/#start-toolbar) * [上传路径配置](http://fex.baidu.com/ueditor/#server-path) >[info] # 源码下载 - Tip:公众号回复【022】获取源代码 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/de/d6/ded6e495eb8a39d2c7a8b0547b329d19_430x430.jpg)
';

第四节 WebUpload 文件上传

最后更新于:2022-04-02 01:47:02

>[success] # WebUpload文件上传 - WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件 - 分片与并发结合(将一个大文件分割成多块,并发上传,提高大文件的上传速度) - [官网介绍](http://fex.baidu.com/webuploader/) >[info] # 效果图1 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/296c6af17b63f87e3a5b10687e934f0e_588x203.png) >[info] # 效果图2 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/c549837c018d858f633b24661132da81_821x591.png) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/a65521d1bbcccc4f3b63b8f6ea1d9806_852x519.png) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/88f4d21848a2957f76b2fb229724fd50_854x283.png) >[info] # 源码下载 - Tip:公众号回复【021】获取源代码 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/de/d6/ded6e495eb8a39d2c7a8b0547b329d19_430x430.jpg)
';

第三节 ThinkPHP 自定义分页模板

最后更新于:2022-04-02 01:46:59

>[success] # 默认分页模板 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/e62f97e2699a9355038e4fdf8645ad24_586x316.png) >[success] # 自定义分页模板 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/ff14988e37b002a6f3e2379b3c14b305_666x321.png) ```php currentPage() <= 1) { return $this->getDisabledTextWrapper($str); } $url = $this->url(1); return $this->getPageLinkWrapper($url, $str); } //TODO : 上一页 protected function getPreviousButton($text = "«") { if ($this->currentPage() <= 1) { return $this->getDisabledTextWrapper($text); } $url = $this->url( $this->currentPage() - 1 ); return $this->getPageLinkWrapper($url, $text); } //TODO : 页码 protected function getLinks() { if ($this->total > $this->listRows) { if ($this->lastPage < $this->bnumber) { return $this->getUrlLinks($this->getUrlRange(1, $this->lastPage)); } else { $min = 1; if ($this->currentPage > $this->bnumber / 2) $min = $this->currentPage - floor($this->bnumber / 2); if ($this->lastPage - $this->currentPage < $this->bnumber / 2) $min = $this->lastPage - $this->bnumber + 1; return $this->getUrlLinks($this->getUrlRange($min, $min + $this->bnumber - 1)); } } } //TODO : 下一页 protected function getNextButton($text = '»') { if (!$this->hasMore) { return $this->getDisabledTextWrapper($text); } $url = $this->url($this->currentPage() + 1); return $this->getPageLinkWrapper($url, $text); } //TODO : 末页 protected function getlastButton($text = '') { if (!$this->hasMore) { return $this->getDisabledTextWrapper($text); } $url = $this->url($this->lastPage()); return $this->getPageLinkWrapper($url, $text); } //TODO : 渲染页 public function render() { //数据是否足够分页 if ($this->hasPages()) { return sprintf( '
    %s %s %s %s %s
', $this->getfirstButton('首页'), $this->getPreviousButton('上一页'), $this->getLinks(), $this->getNextButton('下一页'), $this->getlastButton('末页') ); } } //TODO : 生成禁用按钮 protected function getDisabledTextWrapper($text) { return '
  • ' . $text . '
  • '; } //TODO : 生成普通按钮 protected function getPageLinkWrapper($url, $page) { if ($page == $this->currentPage()) { return $this->getActivePageWrapper($page); } return $this->getAvailablePageWrapper($url, $page); } //TODO : 生成当前页按钮 protected function getActivePageWrapper($text) { return '
  • ' . $text . '
  • '; } //TODO : 可点击按钮 protected function getAvailablePageWrapper($url, $page) { return '
  • ' . $page . '
  • '; } //TODO : 批量生成页码按钮 protected function getUrlLinks(array $urls) { $html = ''; foreach ($urls as $page => $url) { $html .= $this->getPageLinkWrapper($url, $page); } return $html; } } ``` * 将 TpPageHelper.php 放在extend\tool下 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/d2f9796713cadd91d6fc66d371d7c634_225x73.png) * 修改默认模板 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/0e0f5f5427c7c5fedbf205d510b00f5d_850x305.png) > ### 项目源码下载 - Tip:公众号回复【025】获取源代码 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/de/d6/ded6e495eb8a39d2c7a8b0547b329d19_430x430.jpg)
    ';

    第二节 PHP 实现日历功能

    最后更新于:2022-04-02 01:46:57

    >[success] # PHP 实现日历功能 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/bb1b932d357938a48ae6c4a241b574e0_505x243.png) ~~~php //show_calendar.php 12) { $month = 1; $year++; } elseif ($month < 0) { $month = 12; $year--; } $t = strtotime("$year-$month-1"); $last = date('t', strtotime('-1 month', $t)); $start = date('w', $t) ? range($last - date('w', $t) + 1, $last) : range($last - 6, $last); $days = range(1, date('t', $t)); $end = range(1, 6 * 7 - count($start) - count($days)); $daytable = ""; $w = 1; for ($i = 0; $i < count($start); $i++) { if ($w % 7 == 0) { $daytable .= "$start[$i]"; } else { $daytable .= "$start[$i]"; } $w++; } for ($i = 0; $i < count($days); $i++) { if ($w % 7 == 0) { $daytable .= "$days[$i]"; } else { $daytable .= "$days[$i]"; } $w++; } for ($i = 0; $i < count($end); $i++) { if ($w % 7 == 0) { $daytable .= "$end[$i]"; } else { $daytable .= "$end[$i]"; } $w++; } $daytable .= ""; ?>
    上一月 月份 下一月
    星期日 星期一 星期二 星期三 星期四 星期五 星期六
    ~~~
    ';

    第一节 PHP与Golang 项目案例 – 留言板

    最后更新于:2022-04-02 01:46:55

    >[success] # PHP与Golang 项目案例 - 留言板 - 简单的增删改查 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2c5053937f941535eed301095a172d56_1362x773.png) >[info] # 源码下载 - Tip:公众号回复【020】获取源代码 - 留言板-Html模板源码 - 留言板-原生PHP - 留言板-PHP-ThinkPHP5 - 留言板-Go-Gin ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/de/d6/ded6e495eb8a39d2c7a8b0547b329d19_430x430.jpg)
    ';