关于php:ModStartCMS模块开发

模块开发模块开发介绍在开发模块之前,请在模块市场自行装置《开发示例程序》,该示例中涵盖了简直所有模块开发标准和技巧。 开发示例程序: https://modstart.com/m/Demo 开发示例程序会不断更新,请随时查看最新的开发示例程序。 模块开发入门第一步,下载模块开发助手模块开发助手能够极大效率的进步模块开发效率,通过 https://modstart.com/m/ModuleDeveloper 下载。 第二步,应用模块开发助手创立模块拜访 系统管理 → 模块开发助手,通过常用工具创立模块 第三步,实现模块代码开发第二步会依据填写的模块根本信息实现模块的创立,并且生成一些示例代码,通过批改和欠缺模块代码,实现模块的性能开发 第四步,模块打包上传到模块市场如果您开发的模块须要上传分享到模块市场,依照如下步骤实现模块分享。 注册ModStart账号:拜访 https://modstart.com 实现账号注册实名认证:在用户核心实现用户实名认证创立模块:认证实现后,在用户核心拜访开发者核心,实现模块的创立打包上传:返回到本地的模块开发助手,登录ModStart账号,在对应开发的模块中点击公布模块审核上线:公布胜利后,须要后盾审核模块,实现审核后模块即可显示在模块市场。 模块目录介绍模块具体目录介绍SomeName├── Admin → 后盾治理├── Api → API接口├── Constant → 常量├── Core → 外围资源│ └── ModuleServiceProvider.php → 模块外围ServiceProvider,会主动被零碎加载├── Docs → 模块文档目录│ ├── doc → 模块应用文档│ ├── module → 模块阐明文档│ └── release → 模块Release日志├── Migrate → 模块数据库迁徙文件├── Util → 模块工具包├── View → 模块视图├── Web → 模块前台 ├── config.json → 模块配置文件└── resources → 模块其余资源文件配置文件 config.json配置文件是一个非法的JSON,请勿在JSON中蕴含正文,以下为了参数含意会在JSON中蕴含正文 ...

December 18, 2021 · 2 min · jiezi

关于php:ModStartCMS前端开发

ModStart框架应用了 jQuery 等根底前端技术,页面不限于应用 Vue、React 作为前端技术集成。 前端代码地位ModStart根底前端代码位于 vendor/modstart/modstart/resources/asset/。不同模块的前端代码位于 module/Xxx/resources/asset/前端代码须要应用 nodejs 构建,须要事后理解前端应用 webpack, gulp 打包的基础知识。 前端代码如何编译Windows版装置 nodejs进入官网 http://nodejs.cn/ ,下载对应的nodejs安装包下载,实现装置。 举荐装置 node 14 以上版本 关上 nodejs 命令窗口装置实现后,windows启动,关上 Node.js command prompt 命令窗口 装置 cnpm 和打包依赖装置 cnpm 次要是为了解决国内拜访 npm 速度太慢的问题,可依据本人的状况自行抉择 装置cnpm npm install -g cnpm --registry=https://registry.npmmirror.com装置webpack和gulp依赖 cnpm install -g webpack-cli@4 webpack@4 gulp@4编译前端代码编译ModStart代码 通常状况下零碎的前端代码无需批改 # 进入到零碎动态资源根目录cd c:\xxx\vendor\modstart\modstart\resources\asset\# 装置依赖cnpm install# 打包前端CSS、图片等动态资源gulp# 调试模式:打包前端JS单页动态资源webpack --env dev# 生产模式:打包前端JS单页动态资源webpack# 开发模式:打包前端JS单页动态资源,边开发边刷新webpack --env dev --watch编译模块代码 编译模块前端代码前,请确保ModStart的动态资源曾经装置过依赖(cnpm install) # 进入到模块动态资源根目录cd c:\xxx\module\Xxx\resources\asset\# 装置依赖cnpm install# 打包前端CSS、图片等动态资源gulp# 调试模式:打包前端JS单页动态资源webpack --env dev# 生产模式:打包前端JS单页动态资源webpack# 开发模式:打包前端JS单页动态资源,边开发边刷新webpack --env dev --watchOSX待补充... ...

December 18, 2021 · 1 min · jiezi

关于php:全网最好用的Python工具包你一定要试

大家好,我是程序员匹克。 为什么Python被大家当作是作为入门的第一语言?不仅是因为它简略易学,还有一个起因就是:市面上有着大量开箱即用的第三方库,正是23万个由用户提供的软件包使得Python真正弱小和风行。 所以,我明天筛选了7个好用又乏味的软件包,介绍它们的性能和特点,大家感兴趣的能够持续看上来,上面我所列举的有没有踩中你的心中。 1. DashDash是比拟新的软件包,它是用纯Python构建数据可视化app的现实抉择,因而特地适宜解决数据的任何人。Dash是Flask,Plotly.js和React.js的混合体。 2. PillowPillow专门用于解决图像,您能够应用该库创立缩略图,在文件格式之间转换,旋转,利用滤镜,显示图像等等。如果您须要对许多图像执行批量操作,这是现实的抉择。 为了疾速理解它,看以下代码示例(加载并渲染图片): Emoji库十分有意思,但并非每个人都喜爱表情包,剖析视角媒体数据时,Emoji包十分有用! 以下是简略的代码示例: 4. IPython我确定您晓得Python的交互式外壳,这是运行Python的好办法。然而您也晓得IPython shell吗?如果您常常应用交互式外壳程序,但您不理解IPython,则应该检查一下! 加强的IPython shell提供的一些性能包含: 全面的自省。 输出历史记录,跨会话继续存在。 在具备主动生成的援用的会话期间缓存输入后果。 制表符补全,默认状况下反对python变量和关键字,文件名和函数关键字的补全。 “魔术”命令,用于管制环境并执行许多与IPython或操作系统相干的工作。 会话记录和从新加载。 对pdb调试器和Python分析器的集成拜访。 IPython的一个鲜为人知的性能:它的体系结构还容许并行和分布式计算。IPython是Jupyter Notebook的外围,它是一个凋谢源代码Web应用程序,可让您创立和共享蕴含实时代码,方程式,可视化成果和叙述文本的文档。 5. SimplejsonPython中的本地json模块有什么问题?没有!实际上,Python的json是simplejson。意思是,Python采纳了simplejson的一个版本,并将其合并到每个发行版中。然而应用simplejson具备一些长处: 它实用于更多Python版本。 它比Python随附的版本更新频率更高。 它具备用C编写的(可选)局部,因而十分疾速。因为这些事实,您常常会在应用JSON的脚本中看到以下内容: 我将只应用默认的json,除非您特地须要: 速度 规范库中没有的货色 Simplejson比json快很多,因为它用C实现一些要害局部。除非您正在解决数百万个JSON文件,否则您不会对这种速度感兴趣6. Chardet您能够应用chardet模块来检测文件或数据流的字符集。例如,这在剖析大量随机文本时很有用。然而,当您不晓得字符集是什么时,也能够在解决近程下载的数据时应用它。 7. FlaskFlask是我的入门库,用于创立疾速的Web服务或简略的网站。这是一个微框架,这意味着Flask旨在使外围放弃简略但可扩大。有700多个官网和社区扩大。 如果您晓得本人将开发一个大型的Web应用程序,则可能须要钻研一个更残缺的框架。该类别中最受欢迎的是Django。 以上,就是我列举的几个工具包。如果大家还有其余补充或不同意见能够在评论处进行探讨!如果此篇文章对您有帮忙的话,麻烦关注点赞一下吧~

December 18, 2021 · 1 min · jiezi

关于php:PHP实现摩斯电码加密解密

摩斯电码加密解密demo<?phpnamespace common\helpers;/** * 摩斯明码加密解密 * * @author wangjian * @since 0.1 */class Morse{ /** * @var array 摩斯默认配置 */ protected static $option = [ 'space'=> '/', 'short'=> '.', 'long'=> '-' ]; /** * @var array 摩斯明码转换 */ protected static $standard = [ 'A' => '01', 'B' => '1000', 'C' => '1010', 'D' => '100', 'E' => '0', 'F' => '0010', 'G' => '110', 'H' => '0000', 'I' => '00', 'J' => '0111', 'K' => '101', 'L' => '0100', 'M' => '11', 'N' => '10', 'O' => '111', 'P' => '0110', 'Q' => '1101', 'R' => '010', 'S' => '000', 'T' => '1', 'U' => '001', 'V' => '0001', 'W' => '011', 'X' => '1001', 'Y' => '1011', 'Z' => '1100', '0' => '11111', '1' => '01111', '2' => '00111', '3' => '00011', '4' => '00001', '5' => '00000', '6' => '10000', '7' => '11000', '8' => '11100', '9' => '11110', '.' => '010101', ',' => '110011', '?' => '001100', '\'' => '011110', '!' => '101011', '/' => '10010', '(' => '10110', ')' => '101101', '&' => '01000', ' =>' => '111000', ';' => '101010', '=' => '10001', '+' => '01010', '-' => '100001', '_' => '001101', '"' => '010010', '$' => '0001001', '@' => '011010', ]; /** * @var null 莫斯转换后果 */ protected static $standardReverse = null; /** * 默认参数配置 */ protected static function defaultOption($option = null ) { $option = $option || []; return [ isset($option['space']) ? $option['space'] : self::$option['space'], isset($option['short']) ? $option['short'] : self::$option['short'], isset($option['long']) ? $option['long'] : self::$option['long'] ]; } /** * 按utf宰割字符串 */ protected static function mbStrSplit($str) { $len = 1; $start = 0; $strlen = mb_strlen($str); while ($strlen) { $array[] = mb_substr($str,$start,$len,"utf8"); $str = mb_substr($str, $len, $strlen,"utf8"); $strlen = mb_strlen($str); } return $array; } /** * Unicode字符转换成utf8字符 */ protected static function unicodeToUtf8($unicode_str) { $utf8_str = ''; $code = intval(hexdec($unicode_str)); //这里留神转换进去的code肯定得是整形,这样才会正确的按位操作 $ord_1 = decbin(0xe0 | ($code >> 12)); $ord_2 = decbin(0x80 | (($code >> 6) & 0x3f)); $ord_3 = decbin(0x80 | ($code & 0x3f)); $utf8_str = chr(bindec($ord_1)) . chr(bindec($ord_2)) . chr(bindec($ord_3)); return $utf8_str; } protected static function charCodeAt($str, $index) { $char = mb_substr($str, $index, 1, 'UTF-8'); if (mb_check_encoding($char, 'UTF-8')) { $ret = mb_convert_encoding($char, 'UTF-32BE', 'UTF-8'); return hexdec(bin2hex($ret)); } else { return null; } } /** * 摩斯码转文本 */ protected static function morseHexUnicode($mor) { $mor = bindec($mor); if(!$mor) { return ''; } else { $mor = dechex ($mor); } return self::unicodeToUtf8($mor); } /** * unicode转二进制 */ public static function unicodeHexMorse($ch) { $r = []; $length = mb_strlen($ch, 'UTF8'); for($i = 0; $i < $length; $i++) { $r[$i] = substr(('00'. dechex(self::charCodeAt($ch,$i))), -4); } $r = join('',$r); return base_convert (hexdec($r), 10, 2); } /** * 加密摩斯电码 */ public static function encode($text, $option = null) { $option = self::defaultOption($option); // 默认参数 $morse = []; // 最终的 morse 后果 //删除空格,转大写,宰割为数组 $text = self::mbStrSplit( strtoupper(str_replace(' ', '', $text))); foreach($text as $key => $ch) { $r = @self::$standard[$ch]; if(!$r) { $r = self::unicodeHexMorse($ch); // 找不到,阐明是非规范的字符,应用 unicode。 } $morse[] = str_replace('1', $option[2], str_replace('0', $option[1], $r)); } return join( $option[0], $morse); } /** * 解密摩斯电码 */ public static function decode($morse, $option = null) { if( self::$standardReverse === null) { foreach(self::$standard as $key => $value) { self::$standardReverse[$value] = $key; } } $option = self::defaultOption($option); $msg = []; $morse = explode($option[0], $morse); // 宰割为数组 foreach($morse as $key =>$mor) { $mor = str_replace(' ', '', $mor); $mor = str_replace($option[2], '1', str_replace( $option[1], '0', $mor)); $r = @self::$standardReverse[$mor]; if(!$r) { $r = self::morseHexUnicode($mor); // 找不到,阐明是非规范字符的 morse,应用 unicode 解析形式。 } $msg[] = $r; } return join( '', $msg); }}摩斯电码加密:$txt = ''//须要加密的字符$morse = Morse::encode($txt);摩斯电码解密:$morse = ''//须要解密的摩斯电码$morse = Morse::decode($morse);实例如下:$txt = '测试';$morse = Morse::encode($txt);echo $morse . "<br/>";$txt = Morse::decode($morse);echo $txt;输出后果如下: ...

December 17, 2021 · 3 min · jiezi

关于php:开发商城系统是选择PHP还是Java语言开发

在互联网疾速倒退的明天,越来越多的企业通过开发商城零碎来拓展本人的业务,目前商城零碎开发的支流语言有两个:PHP语言和JAVA语言,很多企业也会纠结用哪种语言开发的商城更好呢?java语言算是古老,多年的倒退,其在C/S畛域和B/S畛域都占有一席之地,特地是在电信和银行行业。但随着社会需要的变动和其余语言的专一,java的市场正被一点点鲸吞,WEB畛域简直被PHP一统天下,嵌入式畛域简直被C++一统天下,客户端畛域简直被C语言一统天下。用JAVA语言开发的商城零碎,企业拿到的代码只是一些编译好的class类,无奈看到残缺的网上商城开发的源代码,这样安全性也就绝对比拟高,不容易被人偷盗。用PHP语言开发的商城零碎,企业拿到的是开发商城源码,而且源码是凋谢的,可被公众所学习钻研的,这是PHP语言开发的商城零碎的毛病,但也是其长处,是能够被大家一直批改、欠缺和降级的!就目前而言,齐全应用JAVA语言开发的商城零碎是少之又少的,因为其安全性和稳定性,开发费用是极高的!很多企业还是抉择用PHP语言开发商城零碎。两者相比,算平分秋色。关键在于看你比拟看重什么,如果你是比拟看重数据的平安和稳固,并且当前性能迭代少,那么能够选者JAVA,如果你看重老本,灵便迭代,并须要买通淘宝,天猫等各个电商平台,那么抉择PHP会更适合。总之,PHP和Java都是十分支流的开发语言,并且市面上均有很胜利的大型平台,最终抉择还是看企业本身规模及需要。如果公司有技术人员,那语言就是确定的了,你的技术人员会什么语言就采纳哪种语言,如果没有能够抉择PHP语言开发,其老本也绝对低,零碎也够用。如果大型商城我的项目,资金估算短缺,能够思考用Java开发。

December 17, 2021 · 1 min · jiezi

关于php:Python修改列表元素小技巧

增删改查是解决数据最常见的办法,前两种说过了,这里就要说说python提供的两种批改列表元素的办法,一种是批改单个元素,还有一种的批改一组数据的办法。 一、批改单个元素批改单个元素从原理上讲就是从新给指定地位的元素赋值。上面来看看代码演示。 name1 = ['python', 'java', 'php', 'MySql', 'C++', 'C', 'php', 'C#']name1[2] = 'python自学网'print(name1)返回后果:['python', 'java', 'python自学网', 'MySql', 'C++', 'C', 'php', 'C#']二、批改一组元素这里应用的就是切片这种手法来给list列表做整段元素批改的,在进行这种操作时,如果不指定步长(step 参数),Python 就不要求新赋值的元素个数与原来的元素个数雷同;这象征,该操作既能够为列表增加元素,也能够为列表删除元素。 name1 = ['python', 'java', 'php', 'MySql', 'C++', 'C', 'php', 'C#']name1[2:4] = ['python自学网', 'www.wakey.com.cn']print(name1)返回后果:['python', 'java', 'python自学网', 'www.wakey.com.cn', 'C++', 'C', 'php', 'C#']这里要留神的是切片区间蕴含的元素个数和指定列表中元素的个数要雷同。 还有一种切片办法是指定步长切片,同样能够批改多个列表元素的值。看看上面的代码演示。 name1 = ['python', 'java', 'php', 'MySql', 'C++', 'C', 'php', 'C#']name1[1:5:2] = ['python自学网', 'www.wakey.com.cn']print(name1)返回后果:['python', 'python自学网', 'php', 'www.wakey.com.cn', 'C++', 'C', 'php', 'C#']下面这段代码的意思是,从第二个元素到第六个元素,每隔2个批改成指定的列表中元素。从第二个到第六个蕴含4个元素,每隔2个批改一下正好能批改两个,如果蕴含6个元素,这是新的列表中元素不够就会报错。看看上面的演示; name1 = ['python', 'java', 'php', 'MySql', 'C++', 'C', 'php', 'C#']name1[1:7:2] = ['python自学网', 'www.wakey.com.cn']print(name1)返回后果: ...

December 17, 2021 · 1 min · jiezi

关于php:怎么把Python当偷懒神器用

在日常工作中,咱们经常会用到须要周期性执行的工作,一种形式是采纳 Linux 零碎自带的 crond[1] 联合命令行实现。另外一种形式是间接应用 Python。接下里整顿的是常见的 Python 定时工作的实现形式。 1、利用 while True: + sleep() 实现定时工作位于 time 模块中的 sleep(secs) 函数,能够实现令以后执行的线程暂停 secs 秒后再继续执行。所谓暂停,即令以后线程进入阻塞状态,当达到 sleep() 函数规定的工夫后,再由阻塞状态转为就绪状态,期待 CPU 调度。 基于这样的个性咱们能够通过 while 死循环+sleep() 的形式实现简略的定时工作。 代码示例: import datetimeimport timedef time_printer(): now = datetime.datetime.now() ts = now.strftime('%Y-%m-%d %H:%M:%S') print('do func time :', ts)def loop_monitor(): while True: time_printer() time.sleep(5) # 暂停 5 秒if __name__ == "__main__": loop_monitor()次要毛病: 只能设定距离,不能指定具体的工夫,比方每天早上 8:00sleep 是一个阻塞函数,也就是说 sleep 这一段时间,程序什么也不能操作。2、应用 Timeloop 库运行定时工作Timeloop[2] 是一个库,可用于运行多周期工作。这是一个简略的库,它应用 decorator 模式在线程中运行标记函数。 示例代码: ...

December 17, 2021 · 2 min · jiezi

关于php:10分钟用NodeJS打造一个恶劣天气实时预警系统

前一段时间,国内产生了不少劫难,咱们过后所处的郑州高新区经验了断水断电的状况,想起来就让人心惊肉跳!于是决定打造一个残缺的天气实时预警我的项目,次要利用Node.JS以及聚合数据的第三方收费接口,api治理接口用的咱们开发的apipost,没有特地浅近的技术栈,次要是抛砖引玉,心愿对大家有所帮忙!一、收费天气预报接口网上很多收费获取天气的API接口,我这里应用的是聚合数据的接口,大厂的绝对稳固。申请地址:https://www.juhe.cn/docs/api/...申请胜利后,会在集体核心生成一个申请key,这个在发送接口时,要用到。 二、应用天气预报接口并生成程序代码 依据聚合数据的应用阐明,咱们能够利用接口调试工具调试接口,咱们这里利用ApiPost测试。能够看到申请胜利后的json格局如下: { "reason": "查问胜利!", "result": { "city": "郑州", "realtime": { "temperature": "24", "humidity": "100", "info": "小雨", "wid": "07", "direct": "东北风", "power": "2级", "aqi": "32" }, "future": [ { "date": "2021-07-23", "temperature": "23/28℃", "weather": "小雨转阴", "wid": { "day": "07", "night": "02" }, "direct": "东风转北风" }, { "date": "2021-07-24", "temperature": "24/31℃", "weather": "小雨转多云", "wid": { "day": "07", "night": "01" }, "direct": "东北风转东风" }, { "date": "2021-07-25", "temperature": "23/31℃", "weather": "多云", "wid": { "day": "01", "night": "01" }, "direct": "东风转东南风" }, { "date": "2021-07-26", "temperature": "24/31℃", "weather": "小雨", "wid": { "day": "07", "night": "07" }, "direct": "东北风" }, { "date": "2021-07-27", "temperature": "23/31℃", "weather": "小雨转晴", "wid": { "day": "07", "night": "00" }, "direct": "东北风转南风" } ] }, "error_code": 0}到这一步,咱们曾经拿到了将来7天的天气数据。 ...

December 16, 2021 · 2 min · jiezi

关于php:快速掌握新版本PHP新功能的技巧

最新PHP版本更新迭代十分快,很多小伙伴都直呼学不动了。又因为文档具备肯定的滞后性,看全英文RFC也是有点门槛的事件。所以本文想教大家一种比拟疾速全面理解新性能的技巧。技巧说起来非常简单,看 PHP 源码中的单元测试. 因为单元测试要思考到的场景十分多,所以用例十分全面,有些文档中没有细说的货色,单元测试代码都能清晰地体现进去. 话不多说,开始整活. 下载源码git clone https://github.com/php/php-src看单元测试各个扩大的单元测试在 ext/扩展名/tests,以 phpt 后缀结尾的文件就是单元测试文件.内嵌函数的单元测试在 Zend/tests. 以箭头函数为例在 Zend/tests/arrow_functions 目录下,看一下 001.phpt 里的内容. --TEST--Basic arrow function functionality check--FILE--<?php$foo = fn() => 1;var_dump($foo());$foo = fn($x) => $x;var_dump($foo(2));$foo = fn($x, $y) => $x + $y;var_dump($foo(1, 2));// Closing over $var$var = 4;$foo = fn() => $var;var_dump($foo());// Not closing over $var, it's a parameter$foo = fn($var) => $var;var_dump($foo(5));// Close over $var by-value, not by-reference$var = 5;$foo = fn() => ++$var;var_dump($foo());var_dump($var);// Nested arrow functions closing over variable$var = 6;var_dump((fn() => fn() => $var)()());var_dump((fn() => function() use($var) { return $var; })()());?>--EXPECT--int(1)int(2)int(3)int(4)int(5)int(6)int(5)int(6)int(6)分成三段:第一段,本次测试的主题形容 --TEST--. 第二段,本次单测的PHP代码 --FILE--. 第三段,本次单测预期的输入,如果期待输入是谬误用 --EXPECTF--,否则应用 --EXPECT-- ...

December 16, 2021 · 1 min · jiezi

关于php:Python-多线程是鸡肋

为什么有人会说 Python 多线程是鸡肋?知乎上有人提出这样一个问题,在咱们常识中,多过程、多线程都是通过并发的形式充分利用硬件资源进步程序的运行效率,怎么在 Python 中反而成了鸡肋? 有同学可能晓得答案,因为 Python 中臭名远扬的 GIL,GIL 是什么?为什么会有 GIL?多线程真的是鸡肋吗? GIL 能够去掉吗?带着这些问题,咱们一起往下看,同时须要你有一点点急躁。 多线程是不是鸡肋,咱们先做个试验,试验非常简单,就是将数字 "1亿" 递加,减到 0 程序就终止,这个工作如果咱们应用单线程来执行,实现工夫会是多少?应用多线程又会是多少?show me the code # 工作def decrement(n): while n > 0: n -= 1单线程 import timestart = time.time()decrement(100000000)cost = time.time() - start>>> 6.541690826416016在我的4核 CPU 计算机中,单线程所花的工夫是 6.5 秒。可能有人会问,线程在哪里?其实任何程序运行时,默认都会有一个主线程在执行。(对于线程与过程这里不开展,我会独自开一篇文章) 多线程 import threadingstart = time.time()t1 = threading.Thread(target=decrement, args=[50000000])t2 = threading.Thread(target=decrement, args=[50000000])t1.start() # 启动线程,执行工作t2.start() # 同上t1.join() # 主线程阻塞,直到t1执行实现,主线程持续往后执行t2.join() # 同上cost = time.time() - start>>>6.85541033744812创立两个子线程 t1、t2,每个线程各执行 5 千万次减操作,等两个线程都执行完后,主线程终止程序运行。后果,两个线程以单干的形式执行是 6.8 秒,反而变慢了。按理来说,两个线程同时并行地运行在两个 CPU 之上,工夫应该减半才对,当初不减反增。 ...

December 16, 2021 · 1 min · jiezi

关于php:Python一行代码动态加载依赖

前几天在一个开源我的项目里遇到好多用户反馈,不会装置依赖,或者执行 pip install -r requirements.txt 没有反馈。 可能造成的起因有很多种,一一排查起来也很麻烦。 想一劳永逸解决这个问题,个别大家都是到 site-packages 外面把所须要的包导出来,放到我的项目根目录。 但这样究竟太过毛糙,不合乎Python优雅的共性。 所以我就想,能不能动静引入包,如果没有的话,再调用 pip 下载。最初也差不多实现了我的构想。 我大略查了一下,当初如同没有人用过这个计划,我本人应用感觉还是很不便的,分享给大家。 尽管想打成library给大家下载的,起初想到这又要依赖pip,违反了做动静依赖的本意 所以我举荐是应用 疾速开始 - 注入代码运行 中的形式 疾速开始通过 pip 装置运行在 PyPI 下载 dypend依赖包 pip install dypend在本地生成 requirements.txt 依赖文件 pip freeze > requirements.txt在我的项目的入口文件的最上层引入 dypend ,不必更改任何其余代码 import dypend这时 dypend会查看你的Python环境中是否都有 requirements.txt 中的包,如果没有, dypend会调用 pip下载。 注入代码运行在本地生成 requirements.txt 依赖文件 pip freeze > requirements.txt在我的项目的入口文件的最上层增加如下代码,不必更改任何其余代码 import osimport reREQUIREMENTS = os.getcwd() + '/requirements.txt'def getDepends(): requirements = open(REQUIREMENTS, 'r') libs = requirements.readlines() libList = [] for lib in libs: try: name = re.search("^.+(?===)", lib).group(0) version = re.search("(?<===).+$", lib).group(0) libDict = { "name": name, "version": version } libList.append(libDict) except: continue return libListdef importLib(): """Load python dependent libraries dynamically""" libList = getDepends() from pip._internal import main as pip_main import importlib def install(package): pip_main(['install', package]) createVar = locals() for lib in libList: print(lib) try: createVar[lib["name"]] = importlib.import_module(lib["name"]) except Exception as e: try: install(f'{lib["name"]}=={lib["version"]}') createVar[lib["name"]] = importlib.import_module(lib["name"]) except Exception as e: print(e)importLib()这时dypend会查看你的Python环境中是否都有 requirements.txt 中的包,如果没有,dypend会主动下载。 ...

December 16, 2021 · 1 min · jiezi

关于php:php数组

1.array_map $arr = ['lanting','nanfeng','xuehua','xiao'];$result = array_map(function($item){ return strtoupper($item);},$arr);$info = array_keys($data);$data = array_flip($info);$result = array_map(function ($item) { return $item + 1;}, $data);$arr1=array(1,3,5,7);$arr2=array(2,4,6,8,9);$results=array_map(function($a,$b){ return $a*$b;},$arr1,$arr2);

December 15, 2021 · 1 min · jiezi

关于php:php实现ffmpeg处理视频

最近有一个我的项目须要应用ffmpeg解决视频,这里我写了一个demo,不便咱们来实现视频操作 ffmpeg操作demo <?phpnamespace common\helpers;use common\models\Config;use common\models\VideoApiLog;use Yii;use yii\helpers\ArrayHelper;use common\helpers\Universal;use yii\helpers\FileHelper;use yii\httpclient\Client;use yii\web\ServerErrorHttpException;/** * ffmpeg视频解决 * * @author wangjian * @since 0.1 */class FfmpegVideo{ public $ffmpeg = 'ffmpeg'; public function __construct($ffmpeg = null) { if ($ffmpeg) { $this->ffmpeg = $ffmpeg; } } /** * 增加视频文字滚动 * @param $source string 视频 * @param $saveFile string 保留文件 * @param $text string 水印文字 * @param array $options 水印款式 * @param int $step 每秒步长 * @param int $star 呈现工夫 */ public function titleMod($source, $saveFile, $text, $options = [], $step = 20, $star = 0) { $command = $this->ffmpeg .' -y -i '. $source .' -async 1 -metadata:s:v:0 start_time=0 -vf '; $fonts = Yii::getAlias('@webroot') . "/fonts/simsun.ttc"; $fonts = str_replace('\\', '/', $fonts); $fonts = str_replace(':', '\\:', $fonts); $command .= '"drawtext=fontfile=\''. $fonts .'\': text=\''. $text .'\''; foreach ($options as $key => $value) { $command .= ':' . $key . '=' . $value; } $command .= ':x=\'if(gte(t,'. $star .'),((t-'. $star .') * '. $step .'),NAN)\''; $command .= '" '; $command .= $saveFile; exec($command, $output, $result_code); if ($result_code == 0) { return true; } return false; } /** * 图片水印 * @param $source string 视频 * @param $saveFile string 保留文件 * @param $waterImage string 水印图片 * @param $left integer 水印程度地位 * @param $top integer 水印垂直地位 * @param null $star 水印开始工夫 * @param null $duration 水印时长 */ public function imageWater($source, $saveFile, $waterImage, $left, $top, $star = null, $duration = null) { $waterImage = str_replace('\\', '/', $waterImage); $waterImage = str_replace(':', '\\:', $waterImage); $command = $this->ffmpeg . ' -y -i '. $source .' -vf "movie=\''. $waterImage .'\'[watermark];'; $command .= '[in][watermark] overlay='. $left .':'. $top; if ($star) { $end = ($duration) ? $star + $duration : $star; $command .= ':enable=\'between(t,'. $star .','. $end .')\''; } $command .= '[out] " ' . $saveFile; exec($command, $output, $result_code); if ($result_code == 0) { return true; } return false; } /** * 给视频增加文字水印 * @param $source string 视频 * @param $saveFile string 保留文件 * @param $text string 水印文字 * @param array $options 水印款式 * @param null $star 水印开始工夫 * @param null $duration 水印时长 */ public function titleWater($source, $saveFile, $text, $options = [], $star = null, $duration = null) { $command = $this->ffmpeg .' -y -i '. $source .' -vf '; $fonts = Yii::getAlias('@webroot') . "/fonts/STZHONGS.TTF"; $fonts = str_replace('\\', '/', $fonts); $fonts = str_replace(':', '\\:', $fonts); $command .= '"drawtext=fontfile=\''. $fonts .'\': text=\''. $text .'\''; foreach ($options as $key => $value) { $command .= ':' . $key . '=' . $value; } if ($star) { $end = ($duration) ? $star + $duration : $star; $command .= ':enable=\'between(t,'. $star .','. $end .')\''; } $command .= '" '; $command .= $saveFile; exec($command, $output, $result_code); if ($result_code == 0) { return true; } return false; } /** * 将音频合并到视频中 * @param $videoFile string 视频文件 * @param $audioFile string 音频文件 * @param $saveFile string 保留文件 * @param $delay integer 声音插入延时秒数 */ public function mergeVideoAudio($videoFile, $audioFile, $saveFile, $delay = null) { $delayTime = 0; if ($delay) { $delayTime = $delay * 1000; } $command = $this->ffmpeg . ' -y -i '. $audioFile .' -i '. $videoFile .' -c:v copy -c:a aac -strict experimental -filter_complex "[0]adelay='. $delayTime .'|'. $delayTime .'[del1],[1][del1]amix" ' . $saveFile; exec($command, $output, $result_code); if ($result_code == 0) { return true; } return false; } /** * 静音 */ public function audioMute($source, $saveFile) { $command = $this->ffmpeg . ' -y -i '. $source .' -filter:a "volume=0" ' . $saveFile; exec($command, $output, $result_code); if ($result_code == 0) { return true; } return false; } /** * 提取视频的音频 * @param $source string 须要提取声音的视频 * @param $saveFile string 提取声音后保留的音频 * @return bool */ public function collectAudio($source, $saveFile) { $command = $this->ffmpeg . ' -y -i '. $source .' -vn -acodec copy ' . $saveFile; exec($command, $output, $result_code); if ($result_code == 0) { return true; } return false; } /** * 去除视频声音 * @param $source string 须要去除声音的视频 * @param $saveFile string 去除声音后保留的视频 */ public function removeAudio($source, $saveFile) { $command = $this->ffmpeg . ' -y -i '. $source .' -an ' . $saveFile; exec($command, $output, $result_code); if ($result_code == 0) { return true; } return false; } /** * 视频拼接 * @param $sources array 须要拼接的视频/音频 * @param $saveFile string 拼接后的视频/音频 */ public function spliceVideo($sources, $saveFile) { $commands = []; $temporaryFile = []; $basePath = sys_get_temp_dir(); $index = 0; foreach ($sources as $i => $source) { $file = $basePath . '/' . $i . '.ts'; $commands[$index] = $this->ffmpeg . ' -y -i '. $source .' -vcodec copy -acodec copy -vbsf h264_mp4toannexb ' . $file; $temporaryFile[] = $file; $index++; } $commands[$index] = $this->ffmpeg . ' -y -i "concat:'. implode('|', $temporaryFile) .'" -acodec copy -vcodec copy -absf aac_adtstoasc ' . $saveFile; foreach ($commands as $command) { exec($command, $output, $result_code); } foreach ($temporaryFile as $file) { @unlink($file); } return true; } /** * 视频剪切 * @param $source string 须要剪切视频/音频 * @param $saveFile string 剪切后保留视频/音频 * @param $star string 剪切开始工夫 * @param null $duration string 剪切时长 */ public function clipVideo($source, $saveFile, $star, $duration = null) { $command = $this->ffmpeg . ' -y -ss '. $star; if ($duration) { $command .= ' -t '. $duration; } $command .= ' -i '. $source .' -acodec copy ' . $saveFile; exec($command, $output, $result_code); if ($result_code == 0) { return true; } return false; } const ROTATE_90 = 'transpose=1'; const ROTATE_180 = 'hflip,vflip'; const ROTATE_270 = 'transpose=2'; /** * 视频旋转 * @param $source string 须要旋转的视频 * @param $saveFile string 旋转后视频 * @param $rotate string 旋转角度 */ public function transposeVideo($source, $saveFile, $rotate) { $command = $this->ffmpeg . ' -y -i ' . $source . ' -vf ""transpose=1"" ' . $saveFile; exec($command, $output, $result_code); if ($result_code == 0) { return true; } return false; } /** * 视频转码 * @param $source string 须要转码的视频/音频 * @param $saveFile string 转码后的视频/音频 */ public function acodecVideo($source, $saveFile) { $command = $this->ffmpeg . ' -y -i '. $source .' -acodec copy -vcodec copy -f mp4 ' . $saveFile; exec($command, $output, $result_code); if ($result_code == 0) { return true; } return false; } /** * 视频拼接 * @param $sources array 须要拼接的视频/音频 * @param $saveFile string 拼接后的视频/音频 */ public function concatVideo($sources, $saveFile) { $file = $this->createTemporaryFile(); $fileStream = @fopen($file, 'w'); if($fileStream === false) { throw new ServerErrorHttpException('Cannot open the temporary file.'); } $count_videos = 0; if(is_array($sources) && (count($sources) > 0)) { foreach ($sources as $videoPath) { $line = ""; if($count_videos != 0) $line .= "\n"; $line .= "file '". str_replace('\\','/',$videoPath) ."'"; fwrite($fileStream, $line); $count_videos++; } } else { throw new ServerErrorHttpException('The list of videos is not a valid array.'); } $command = $this->ffmpeg .' -y -f concat -safe 0 -i '. $file . ' -c copy ' . $saveFile; exec($command, $output, $result_code); fclose($fileStream); @unlink($file);//删除文件 if ($result_code == 0) { return true; } return false; } /** * 创立一个临时文件 */ public function createTemporaryFile() { $basePath = sys_get_temp_dir(); if (false === $file = @tempnam($basePath, null)) { throw new ServerErrorHttpException('Unable to generate a temporary filename'); } return $file; } /** * 获取视频信息 * @param $source string 须要获取时长的资源 */ public function getAttributes($source) { ob_start(); $command = $this->ffmpeg . ' -i "'. $source .'" 2>&1'; passthru($command); $getContent = ob_get_contents(); ob_end_clean(); $duration = 0; $widht = 0; $height = 0; if (preg_match("/Duration: (.*?), start: (.*?), bitrate: (\d*) kb\/s/", $getContent, $match)) { $matchs = explode(':', $match[1]); $duration = $matchs[0] * 3600 + $matchs[1] * 60 + $matchs[2]; //转换播放工夫为秒数 } if (preg_match("/Video: (.*?), (.*?), (.*?)[,\s]/", $getContent, $match)) { $matchs = explode('x', $match[3]); $widht = $matchs[0]; $height = $matchs[1]; } return [ 'duration' => intval($duration), 'widht' => intval($widht), 'height' => intval($height), ]; }}应用简略示例这里留神如果无奈执行ffmpeg,实例化时须要传入ffmpeg的装置地址,例如linux下ffmpeg装置地址为/usr/local/ffmepg,那么实例化时须要传入/usr/local/ffmpeg/bin/ffmpeg ...

December 15, 2021 · 7 min · jiezi

关于php:没看过Python病毒的点进来

明天的文章来展现一个 Python“病毒”,它应用后门代码感化其余 Python 文件。 利用 Python 的内置 socket 模块来创立一个监听器,用来连贯到 Python 的内置子过程模块,从而靶机上执行命令,同时还通过创立一个 cronjob 来建设持久性,以在每天固定的工夫运行恶意软件。 最终的 Python 脚本蕴含在本文开端。 留神:请不要将本文中提供的 Python 脚本用于歹意目标。 尽管它不先进,但通过一些批改,它能够让齐全管制某人的计算机。 本文的次要目标是通过这些脚本,更好地理解黑客如何获取失常程序并使它们成为恶意程序。 话不多说,让咱们开始吧。 1、建设通信任何后门最重要的局部都是建设通信。当初,让咱们为后门拜访创立服务器,要通过 TCP 连贯连贯到靶机,咱们须要应用套接字模块模仿侦听服务器。在 socket 模块中,有一个函数也称为 socket,咱们能够应用它来创立 TCP 或 UDP 套接字。应用 socket.socket 函数创立套接字时,咱们须要提供两个参数来指定咱们要应用的 IP 版本和第 4 层协定。在这个 Python 脚本中,咱们将传入以下参数:socket.AF_INET 和 socket.SOCK_STREAM。 AF_INET : 指定 IPv4SOCK_STREAM :指定 TCP 而不是 UDP。socket.socket 函数返回一个对象,该对象由最终确定正在创立的套接字是侦听套接字(服务器)还是连贯套接字(客户端)的办法组成。要创立侦听套接字,须要应用以下办法:bind > 将 IP 地址和端口绑定到网络接口listen > 批示咱们的套接字开始监听传入的连贯accept > 承受传入连贯recv > 从连贯的客户端接收数据send > 向连贯的客户端发送数据然而,最重要的办法是 recv 和 send。 recv 办法会接管来自攻击者的命令,应用 subproces.run 函数在受害者的零碎上执行它们,而后将执行命令的规范输入重定向到与攻击者建设的 TCP 连贯。上面是 Python 代码: ...

December 15, 2021 · 3 min · jiezi

关于php:大学生有必要学Python吗

当你开始想这个问题的时候,很好,你曾经意识到了学习,然而不晓得需不需要。那么我的倡议是,思考,因为每个人的答案都不会一样。我列出几个问题本人尝试答复一下,之后就晓得这个问题的答案了。 目前你是否打算进入IT或者以编程、开发为职业指标?如果是,请持续,否则没必要往下看了。当然你可能会说我只是想学点常识,比方做数据分析解决应用。那其实你的心田曾经给出答案了不是吗? 你目前是否有一门使用非常纯熟的语言?如果有,我的倡议是继续加强你现有的语言,把它学通学透,所谓十鸟在林不如一鸟在手。如果没有,无妨把Python作为你的必备语言,目前因为人工智能的持续炽热,Python也胜利击败Java成为往年最受欢迎的语言。当然如果你感觉曾经足够了还想再学一门,那也OK!值得激励!请持续 在你的布局里,Python是否对你产生作用或重大影响?如果是,比方可能你想投身AI、数据挖掘等畛域,或者你的工作会用到,那毫无疑问,该当学并且要尽全力去学。否则,请持续看下一个问题 你是否有工夫去学习Python?当然,这个问题不是必要的。因为如果前三个问题你都是必定的,那么就算你当初没工夫,你也该当挤出工夫去学。而如果前三个问题都未能给予你足够的理由去学习它,并且你还没有工夫,那我认为你不如把本人的事件做好,没有必要去思考了。 当然以上仅是个人见解仅供参考,不喜勿喷,谢谢!

December 15, 2021 · 1 min · jiezi

关于php:Python轻松抓取微信公众号文章

明天持续向 Python 头条增加数据信息,实现了微信公号的爬虫,接下来会持续通过搜狗的知乎搜寻抓取知乎上与 Python 相干的文章、问答。微信公众号的文章链接有些是具备时效性的,过一段时间会变成参数谬误而无法访问,然而咱们发现从公众号后盾点击过来失去的链接却是永恒链接,其参数不会扭转链接也不会生效,也就是说只有可能取得这些参数就能够失去永恒链接。通过观察发现即便从搜狗搜寻入口的有时效性的链接拜访网页,其源码中也带有这些参数: 所以只有解析这几个参数,就能够结构出永恒链接。 首先通过搜狗搜寻入口,能够获取 Python 关键词搜寻的后果,地址为: HOST = 'http://weixin.sogou.com/'entry = HOST + "weixin?type=2&query=Python&page={}"提取链接、题目和摘要信息: import requests as reqimport rerInfo = r'<h4[\s\S]*?href="([\s\S]*?)".*?>([\s\S]*?)<\/a>[\s\S]*?<\/h4>\s*<p[\s\S]*?>([\s\S]*?)<\/p>'html = req.get(entry.format(1)) # 第一页infos = re.findall(rInfo, html)因为关键词搜寻会在题目或摘要中产生特定格局的标签,须要过滤: def remove_tags(s): return re.sub(r'<.*?>', '', s)而后依据时效性链接获取文章内容,并从中提取参数信息: from html import unescapefrom urllib.parse import urlencodedef weixin_params(link): html = req.get(link) rParams = r'var (biz =.*?".*?");\s*var (sn =.*?".*?");\s*var (mid =.*?".*?");\s*var (idx =.*?".*?");' params = re.findall(rParams, html) if len(params) == 0: return None return {i.split('=')[0].strip(): i.split('=', 1)[1].strip('|" ') for i in params[0]}for (link, title, abstract) in infos: title = unescape(self.remove_tag(title)) abstract = unescape(self.remove_tag(abstract)) params = weixin_params(link) if params is not None: link = "http://mp.weixin.qq.com/s?" + urlencode(params) print(link, title, abstract)看到文章最初,如果感觉此篇文章对您有帮忙的话,麻烦点个赞再走哦~谢谢浏览~ ...

December 14, 2021 · 1 min · jiezi

关于php:Python凭什么这么火

几年前 Python 在国内还只是一门小众语言,但从 2011开始到当初,Python 的百度搜寻指数翻了10 倍,从下图看得出 Python 在国内的风行度曾经直逼 Java,大有赶超之势 一个行业火不火,就看有多少(自)媒体、培训机构涌入进来为之疯狂,用百度搜关键字“python”就有5条是培训广告,而Ruby、PHP、Go 等语言一条都没有,显然还是Python的生意更好做。我最早接触 Python 是在 2010年,那时国内除了豆瓣、搜狐在用 Python 之外,很难看到有体量的公司用Python,而在美国,Python 其实始终都很风行,像 Google、Instagram、Dropbox、Youtube、Reddit、Quora 这些明星网站都在用Python做外围业务。从 Google Trands 看得出它始终处于安稳的趋势,这两年回升趋势比拟显著,显然次要奉献来自于中国。 那么国内这几年 Python 怎么忽然就火起来了? 究其原因,大略能够从分3个阶段来剖析。 12~14年是云计算最火的几年,少量守业公司和巨头挤破头地进军云计算畛域,大家都在做IAAS,最驰名的云计算开源平台OpenStack 就是基于Python 开发的,为此催生出不少Python 岗位 14~15年是「公众翻新,万众守业」口号喊得最响两年,北京大街小巷仿佛人人都是创业者,O2O、P2P产品如雨后春笋般冒出,什么语言最适宜疾速搭建原型?当然是Python,Python 的开发速度一个顶三。 16~17年人工智能火遍大江南北,AlphaGO 的呈现让业界为之兴奋,人工智能不再是概念,而人工智能、机器学习的首选语言就是Python。 这两年特地是网络爬虫火得一塌糊涂,10个写爬虫的9个在用Python,已经有一段时间知乎的Python话题全副被爬虫相干的帖子刷屏,为什么爬虫这么火,这个还是跟大数据无关,因为数据挖掘、剖析、机器学习、人工智能都须要大数据的撑持,而真正有大数据的厂商没几个,所以小厂不得不通过爬虫去获取数据。 为什么偏偏就 Python 火了,其它语言没有? Ruby on Rails 最火的那几年,有人问Python 之父吉多·范罗苏姆怎么看,他说:”Python 不须要杀手级利用,因为如果是这样的话,Python 在其它方面的作用就被忽略了。” Python 在网络爬虫、数据分析、AI、机器学习、Web开发、金融、运维、测试等多个畛域都有不俗的体现,素来没有哪一种语言能够同时在这么多畛域扎根 Python 是一门兼具简略与功能强大的编程语言,它专一于如何解决问题、自在凋谢的社区环境以及丰盛的第三方库,无需浪费时间去造轮子,各种Web框架、爬虫框架、数据分析框架、机器学习框架包罗万象,拿来即用,如果你不晓得去哪找第三库,能够看看 awesome-python 只管后起之秀 Go 语言为并发编程而生,效率高,但物理硬件性能曾经显著晋升的状况下,编程语言带来的性能影响曾经不那么重要的,开发速度才是人们首要关注的问题,即便真遇到的性能问题,那么也能够用C语言无缝对接。 虽说Java是老大哥,江湖位置无人能撼动,但体型过于臃肿、简短的语法被越来越多的开发者所诟病,这也是为什么 Google 决定把 Kotlin 作为 Android 官网反对语言的次要起因 Python 的倒退齐全是由社区自我驱动的,喜爱Python的起因很简略,因为它确确实实给开发者带来了愉悦的编程体验。 看到这点个赞再走吧~谢谢浏览~

December 14, 2021 · 1 min · jiezi

关于php:学习一个PHP中用于检测危险函数的扩展Taint

在日常的开发中,安全性始终是咱们要钻研的重点内容之一。而在安全性中,最次要的一点就是咱们的输出数据。所有的攻打和越权,都是从一个不经意间遗留的申请破绽产生的。当然,当初很多框架曾经为咱们解决了大部分的安全性问题,但百密一疏,总会有意想不到的中央忘了加过滤或者脱漏了某些验证。明天咱们要学习的这个扩大就是为咱们解决这种问题而诞生的。 什么是 Taint上篇文章中就失去过,咱们还要介绍一个鸟哥的扩大工具,Taint 这个扩大就是鸟哥大神的作品之一。不过这个扩大是不举荐装置在生产环境的,它次要的战场是在咱们的测试环境中应用。它的次要性能就是如果咱们应用了未经解决的 \$_GET 、 $_POST 、 $_COOKIE 之类的变量,就会报出正告信息。留神,只是正告,而不是谬误或者异样。个别在线上环境咱们都会习惯性地关掉正告信息的报错,所以这个扩大在线上的性能无限。 扩大的装置非常简单,下载对应的扩大而后进行一般的扩大装置即可,不须要额定的其它操作系统中组件的反对。对于这个扩大的详细信息,能够参考文末第二条链接中鸟哥文章的阐明。 怎么用?php.ini 中关上扩大,而后设置 taint.enable = 1 。就正式启用这个扩大了。而后咱们通过代码来测试。 $a = $_GET['a'];$file_name = '/tmp' . $a;$output = "Welcome, {$a} !!!";$var = "output";$sql = "Select * from " . $a;echo $a, "<br/>"; // Warning: main() [echo]: Attempt to echo a string that might be tainted in /data/www/blog/taint/1.php on line 10echo $output, "<br/>"; // Warning: main() [echo]: Attempt to echo a string that might be tainted in /data/www/blog/taint/1.php on line 12print $$var; echo "<br/>"; // Warning: main() [print]: Attempt to print a string that might be tainted in /data/www/blog/taint/1.php on line 14include($file_name);echo "<br/>"; // Warning: main() [include]: File path contains data that might be tainted in /data/www/blog/taint/1.php on line 16mysqli_query(null, $sql);echo "<br/>"; // Warning: main() [mysqli_query]: SQL statement contains data that might be tainted in /data/www/blog/taint/1.php on line 18咱们应用 php -S 来调试这个测试文件,当拜访这个测试文件并且带上 a 参数之后,就能够看到上面的这些操作都会报出正告信息。未经过滤的这个 $a ,不论是拼接到字符串中,还是作为可变变量,只有是通过 echo 、 print 、 include 或者是 mysqli_query() 这些函数调用后,都会马上呈现报警,提醒你应用的这个数据字符串是须要进行过滤的。taint 的意思是 污点 。might be tainted 也就是有污点内容的意思。 ...

December 14, 2021 · 2 min · jiezi

关于php:学Python不改正这些坏毛病等于白学

大家好呀~明天给大家分享 15个 Python 坏习惯,看看这些坏习惯你都中招了吗?呈现这些坏习惯的起因次要是开发者在 Python 方面经验不足。通过摒弃这些习惯并以 Pythonic 的形式编写代码,不仅能够进步你的代码品质,还能够给看代码的人留下好印象哦~**1、拼接字符串用 + 号**坏的做法:class="highlight`">`if subscribers > 100000: print("Wow " + name + "! you have " + str(subscribers) + " subscribers!")else: print("Lol " + name + " that's not many subs")调整后的做法是应用 f-string,而且效率会更高: # better if subscribers > 100000: print(f"Wow {name}! you have {subscribers} subscribers!") else: print(f"Lol {name} that's not many subs")**2、应用 finaly 而不是上下文管理器**坏的做法:s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)try: s.connect((host, port)) s.sendall(b'Hello, world')finally: s.close()调整后的做法是应用上下文管理器,即便产生异样,也会敞开 socket: ...

December 13, 2021 · 3 min · jiezi

关于php:常用的方法

判断字符串中是否蕴含某一个字符/*** Determine if a given string contains a given substring.** @param string $haystack* @param string|string[] $needles* @return bool* */public static function contains($haystack, $needles) { foreach ((array) $needles as $needle) { if ($needle !== '' && mb_strpos($haystack, $needle) !== false) { return true; } } return false; }Str::contains($keyword, ['_'] /** * 获取客户端IP地址 */ static public function getClientIP() { static $ip = NULL; if ( $ip !== NULL ) return $ip; if ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) { $arr = explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'] ); $pos = array_search( 'unknown', $arr ); if ( false !== $pos ) unset( $arr[$pos] ); $ip = trim( $arr[0] ); } elseif ( isset( $_SERVER['HTTP_CLIENT_IP'] ) ) { $ip = $_SERVER['HTTP_CLIENT_IP']; } elseif ( isset( $_SERVER['REMOTE_ADDR'] ) ) { $ip = $_SERVER['REMOTE_ADDR']; } // IP地址非法验证 $ip = ( false !== ip2long( $ip ) ) ? $ip : '0.0.0.0'; return $ip; } /** * 验证手机号码 */ public static function mobile( $str ) { if ( empty( $str ) ) { return true; } return preg_match( '#^13[\d]{9}$|14^[0-9]\d{8}|^15[0-9]\d{8}$|^18[0-9]\d{8}$#', $str ); }/** * 验证身份证(中国) */ public static function idCard( $str ) { $str = trim( $str ); if ( empty( $str ) ) return true; if ( preg_match( "/^([0-9]{15}|[0-9]{17}[0-9a-z])$/i", $str ) ) return true; else return false; } /** * 列出文件夹列表 * * @param $dirname * @return array */ public static function getDir( $dirname ) { $files = array(); if ( is_dir( $dirname ) ) { $fileHander = opendir( $dirname ); while ( ( $file = readdir( $fileHander ) ) !== false ) { $filepath = $dirname . '/' . $file; if ( strcmp( $file, '.' ) == 0 || strcmp( $file, '..' ) == 0 || is_file( $filepath ) ) { continue; } $files[] = self::autoCharset( $file, 'GBK', 'UTF8' ); } closedir( $fileHander ); } return $files; } /** * 获取客户端IP地址 */ static public function getClientIP() { static $ip = NULL; if ( $ip !== NULL ) return $ip; if ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) { $arr = explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'] ); $pos = array_search( 'unknown', $arr ); if ( false !== $pos ) unset( $arr[$pos] ); $ip = trim( $arr[0] ); } elseif ( isset( $_SERVER['HTTP_CLIENT_IP'] ) ) { $ip = $_SERVER['HTTP_CLIENT_IP']; } elseif ( isset( $_SERVER['REMOTE_ADDR'] ) ) { $ip = $_SERVER['REMOTE_ADDR']; } // IP地址非法验证 $ip = ( false !== ip2long( $ip ) ) ? $ip : '0.0.0.0'; return $ip; }

December 13, 2021 · 2 min · jiezi

关于php:不会还有人找不到Python学习资料吧

自己业余写python爬虫、python小工具已有两年无余了,在这里举荐一些学习时感觉比拟好的视频教程、文章教程等,纯属集体倡议,不喜勿喷 目录资料篇爬虫篇数据分析篇资料篇自学最好的还是入手操作,想用什么找什么,有很多课程波及到了Python语言程序设计、Python网络爬虫与信息提取、Python数据分析与展现、Python科学计算三维可视化等,能够说很全,其次视频举荐外面有文章介绍和视频介绍,他人偏差与文章介绍,这样更快更节省时间。 爬虫篇介绍一下爬虫波及到的第三方库及其相干文档 urllib3urllib3文档Requests文档Beautiful Soup英文版Beautiful Soup中文版正则表达式scrapyscrapy文档css选择器语法re正则表达式语法xpath语法PyMySQLPyMySQL文档数据分析篇数据分析的第三方库介绍 BlazeOpen MiningOrangePandasOptimusNumPycss选择器语法 表达式 阐明* 抉择所有节点#container 抉择id为container的节点.container 选取所有class蕴含container的节点li a 选取所有li下的所有a节点ul + p 抉择ul前面的第一个p元素div#container > ul 选取id为container的div的第一个ul子元素ul ~ p 选取与ul相邻的所有p元素a[title] 选取所有有title属性的a元素a[href="http://baidu.com"] 选取所有href属性为http://baidu.com值的a元素a[href*="baidu"] 选取所有href属性蕴含baidu的a元素a[href^="http"] 选取所有href属性值以http结尾的a元素a[href$=".jpg"] 选取所有href属性值以.jpg结尾的a元素input[type=radio]:checked 抉择选中的radio的元素div:not(#container) 选取所有id非container的div属性li:nth-child(3) 选取第三个li元素tr:nth-child(2n) 第偶数个tr## re正则表达式语法字符 匹配. 任意字符(除了\n)[...] 字符集\d/\D 数字/非数字\s/\S 空白/非空白\w/\W 单词字符[a-zA-Z0-9]/非单词字符 前一个字符0次或者有限次前一个字符1次或者有限次? 前一个字符0次或者一次{m}/{m,n} 前一个字符m次或者n次*?/+?/?? 非贪心(尽可能少匹配字符)^ 字符串结尾$ 字符串结尾\A/\Z 指定的字符串必须呈现在结尾/结尾| 匹配左右任意一个表达式(ab) 括号中表达式作为一个分组\<number> 援用编号为num的分组匹配到的字符串(?P<name>) 分组起一个别名(?P=name) 援用别名为name的分组匹配字符串[\u4E00-\u9FA5] 一个汉字 ## xpath语法表达式 阐明article 选取所有article元素的所有子节点/article 选取跟元素articlearticle/a 选取所有属于article的子元素的a元素//div 选取所有div子元素(不管呈现在文档任何中央)article//div 选取所有输出article元素的后辈的div元素,不论它呈现在article之下的任何地位//@class 选取所有名为class的属性 /article/div[1] 选取属于article子元素的第一个div元素/article/div[last()] 选取输出article子元素的最初一个div元素/article/div[last()-1] 选取属于article子元素的倒数第二个div元素//div[@lang] 选取所有领有lang属性的div元素//div[@lang='eng] 选取所有lang属性为eng的div元素 /div/* 选取属于div元素的所有子节点//* 选取所有元素//div[@*] 选取所有带属性的title元素//div/a|//div/p 选取所有div元素的a和p元素//span|//ul 选取文档中的span和ul元素article/div/p|//span 选取所有属于article元素的div元素的p元素以及文档中所有的span元素 ...

December 12, 2021 · 1 min · jiezi

关于php:日本公司诚招IT开发技术者

システムエンジニア(PL、PG、SE)■仕事内容:システム開発業務など:要件定義・設計・プログラミング・テスト・激进運用など■経 験:1年以上の開発経験、もしくはIT専門卒業生■日本語:二級以上(会話重視、資格なしでもいい)■会社住所:東京 首都圏(客先)(他区域心愿者相談可能) 【応募办法】メールアドレス:sales@citec-c.co.jp電話相談:070-1315-3777(日本側担当者・徐)Wechat(日本側担当者・徐):CITECJAPAN-XTH(ただ相談でもいいですよ~お軽く連絡ください!)所在地:東京都千代田区神田佐久間町一丁目8番4号 会社HP:http://www.citec-c.co.jp/ご応募を待ちしております。どうぞよろしく、お願い致します。

December 9, 2021 · 1 min · jiezi

关于php:PHP81之enum解析

PHP8.1公布了, 一个 enum 就有好多货色要留神.enum 基本上就是一个限定类, 先看看它的语法结构是什么样的. enum_declaration_statement: T_ENUM { $<num>$ = CG(zend_lineno); } T_STRING enum_backing_type implements_list backup_doc_comment '{' class_statement_list '}' { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_ENUM|ZEND_ACC_FINAL, $<num>2, $6, zend_ast_get_str($3), NULL, $5, $8, NULL, $4); };enum 关键字打头, 前面可选跟: (string|int), 因为是类所以能够实现接口 implement SomeInterface, MoreInterface, 又因为加了 ZEND_ACC_FINAL, 相当于 final class className, 所以是不能继承别的枚举类型. 定义<?php//不初始化值,间接这样定义是能够的enum Week { case Monday;}//这样是谬误的,外面的枚举元素初始化值,必须指定整个枚举类型的变量类型,string 或者 intenum Week { case Monday = 'monday'; }//正确的形式enum Week: string { case Monday = 'monday';}enum的一些特定操作<?phpenum Week: string { case Monday = 'monday'; case Tuesday = 'tuesday';}//获取枚举类型元素的值echo Week::Monday->value;//获取枚举类型元素的keyecho Week::Monday->name;Week::Monday 就是这个枚举类型的一个实例,相当于一般类的 object. ...

December 9, 2021 · 2 min · jiezi

关于php:两个多维数组根据对应的相同字段值匹配重组

//收到的主评论 $message = (new coachModel())->coachMessge($param); print_r($message);die;//组装主评论下的跟评论 $temp=array_column($message,'id'); $messagelists=CoachProblemModel::where('pid','in',$temp) ->field(['id','coach_id','create_time','member_id','is_reply','content','reply_id','pid']) ->select()->toArray(); print_r($messagelists);die;依据$message里的id值,获取$messagelists数组里所有pid值跟id值雷同的重组在$message['reply']字段下,冀望后果如下: //代码实现如下: $pidMap = array_combine(array_column($message, 'id'), $message); array_reduce($messagelists, function($carray, $item) use (&$pidMap) { if (isset($pidMap[$item['pid']])) { if (isset($pidMap[$item['pid']]['reply'])) { $pidMap[$item['pid']]['reply'] []= $item; } else { $pidMap[$item['pid']]['reply'] []= $item; } } else { $pidMap[] = $item; } }, []); print_r($pidMap);die;

December 8, 2021 · 1 min · jiezi

关于php:美团分销联盟-API-封装-PHP-SDK

美团分销联盟 PHP-SDK对美团分销联盟各个 api 接口,进行了个简略的封装,对 Laravel 框架也做了反对,有须要自取 GitHub: https://github.com/gaowei-spa... 装置$ composer require gaowei-space/meituan-pub-union -vvv反对✅ 获取全国省份 ProvinceAllRequest✅ 获取某省份的城市 CitiesRequest✅ 获取某个城市的一级类目蕴含的二级类目信息 CategoriesRequest✅ 获取某个城市的商圈信息(点评) RegionsByDianPingRequest✅ 获取某个城市的商圈信息(美团) RegionsByMeiTuanRequest✅ 到店商品搜寻 SearchDealsRequest✅ 分销取链 LinksRequest✅ 异样订单数据 OrdersAbnormalRequest✅ CPA 订单数据 OrdersCPARequest✅ CPS 订单数据 OrdersCPSRequest

December 8, 2021 · 1 min · jiezi

关于php:清空数组的几个方式

前言前两天在工作当中遇到一个问题,在vue3中应用reactive生成的响应式数组如何清空,当然我个别清空都是这么写: let array = [1,2,3]; array = [];复制代码不过这么用在reactive代理的形式中还是有点问题,比方这样: let array = reactive([1,2,3]); watch(()=>[...array],()=>{ console.log(array); },) array = reactive([]);复制代码很显然,因为失落了对原来响应式对象的援用,这样就间接失去了监听。 清空数据的几种形式当然,作为一名十年代码教训长年摸鱼的我,立马就给出了几个解决方案。2.1 应用ref()应用ref,这是最简便的办法: const array = ref([1,2,3]);watch(array,()=>{ console.log(array.value);},)array.value = [];复制代码2.2 应用sliceslice顾名思义,就是对数组进行切片,而后返回一个新数组,感觉和go语言的切片有点相似。当然用过react的小伙伴应该常常用slice,清空一个数组只须要这样写: const array = ref([1,2,3]);watch(array,()=>{ console.log(array.value);},)array.value = array.value.slice(0,0);复制代码 不过须要留神要应用ref。 2.3 length赋值为0集体比拟喜爱这种,间接将length赋值为0: const array = ref([1,2,3]);watch(array,()=>{ console.log(array.value);},{ deep:true})array.value.length = 0;复制代码而且,这种只会触发一次,然而须要留神watch要开启deep: 不过,这种形式,应用reactive会更加不便,也不必开启deep: const array = reactive([1,2,3]);watch(()=>[...array],()=>{ console.log(array);})array.length = 0;复制代码2.4 应用splice副作用函数splice也是一种计划,这种状况同时也能够应用reactive: const array = reactive([1,2,3]);watch(()=>[...array],()=>{ console.log(array);},)array.splice(0,array.length)复制代码不过要留神,watch会触发屡次: 当然也能够应用ref,然而留神这种状况下,须要开启deep: const array = ref([1,2,3]);watch(array,()=>{ console.log(array.value);},{ deep:true})array.value.splice(0,array.value.length)复制代码然而能够看到ref也和reactive一样,会触发屡次。 总结以上是我集体工作中的对于清空数组的总结,然而能够看到splice还是有点非凡的,会触发屡次,不过为什么会产生这种差别还有待钻研。最初如果你感觉此文对你有一丁点帮忙,点个赞。或者能够退出我的开发交换群:1025263163互相学习,咱们会有业余的技术答疑解惑 如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star: https://gitee.com/ZhongBangKe...不胜感激 ! ...

December 7, 2021 · 1 min · jiezi

关于php:一起了解PHP中YaConf扩展的使用

上篇文章咱们介绍了一个比拟闻名的 YAML 格局的配置文件相干的操作,明天我来学习另外一个配置文件扩大。这个配置文件的写法其实与 php.ini 的这种 PHP 规范的配置格局比拟相似,然而又有一些不同。不过内容非常简单,大家仅供参考。 Yaconf 配置文件及格局Yaconf 从名字是不是看出什么端倪了?没错,和 Yaf 、Yac 一样,又是咱们鸟哥的作品。不得不说大神还是为咱们奉献了很多很好的作品哦。前面咱们还会讲一个它的小众开源扩大,而 Yaf 扩大咱们将在将来学习框架的时候再深刻地进行学习。 Yaconf 的装置也是一般地扩大装置的形式,不过它须要 PHP7 以上的版本。另外,在装置之后还须要在 php.ini 文件中指定 yaconf.directory ,也就是配置文件寄存的目录。这个属性是不能通过 ini_set() 配置的,也就是必须在程序运行前就载入到 PHP 运行环境中。咱们依照文档的阐明将它配置为 /tmp/conf ,而后在这个目录下建设本人须要的配置文件就能够了。 Yaconf 的语法十分简洁,鸟哥的作品都主打性能,所以 Yaconf 也是一个高性能的配置管理扩大。对于 Yaconf 的具体介绍能够查看文章最下方第二条链接的阐明,在这里咱们就看一些它的语法以及具体的应用。 foo="bar"phpversion=PHP_VERSIONenv=${HOME}arr.0=1arr.1=2arr[]=3arr[3]=4map.foo=barmap.bar=foomap.foo.name=yaconf看进去什么特点了吗?首先,如果是带双引号的内容,会将这个配置变量当成字符串,如果不是双引号的,则会尝试以 PHP 来进行解析。而后数组和 HashMap 这样的写法也都是完满反对的。仿佛是比 php.ini 的写法强悍了一些。不过还不止。 [parent]parent="base"children="NULL"[children : parent]children="children"嗯,你没看错,它还能够反对这样的继承写法,中括号标示的内容能够看作是一个配置片断,或者说一节内容,具体作用咱们前面会看到。 获取配置内容配置语法就是这些,接下来咱们要具体看看这些配置信息要怎么读取进去。这个扩大其实就提供了两个函数,一个用于读取,一个用于查问配置是否存在,咱们先来看一下如何读取数据。 var_dump(Yaconf::get("test.foo")); // string(3) "bar"var_dump(Yaconf::get("test.phpversion")); // string(5) "7.4.4"var_dump(Yaconf::get("test.env")); // string(5) "/root"这个函数置信不必多解释了,test 是咱们的文件名,也就是在 /tmp/conf/test.ini 这个文件中,咱们把下面的测试配置信息写在了这个配置外面。当然,咱们也能够在这个目录中定义更多的配置文件,比方咱们另外定义了一个配置文件 foo.ini ,那么就能够这么读取: var_dump(Yaconf::get("foo.SectionA.key")); // string(3) "val"对于数组配置信息来说,间接获取到的内容返回的就是数组格局的。 var_dump(Yaconf::get("test.arr"));// array(4) {// [0]=>// string(1) "1"// [1]=>// string(1) "2"// [2]=>// string(1) "3"// [3]=>// string(1) "4"// }var_dump(Yaconf::get("test.arr.1")); // string(1) "2"var_dump(Yaconf::get("test.map"));// array(2) {// ["foo"]=>// array(1) {// ["name"]=>// string(6) "yaconf"// }// ["bar"]=>// string(3) "foo"// }var_dump(Yaconf::get("test.map.foo.name")); // string(6) "yaconf"在获取数组外部的数据时,咱们间接应用 . 来获取序列的内容就能够了。最初就是下面提到过的分片和继承的性能。 ...

November 30, 2021 · 1 min · jiezi

关于php:途狐GPS接口调用

最近有一个我的项目须要对接途狐GPS,这里我写了一个demo,不便咱们来调用处狐GPS的相干接口 途狐GPS接口文档:http://opendoc.tuhugc.com/thg... 途狐GPSdemo: <?phpnamespace common\helpers;use common\models\Config;use Yii;use yii\helpers\ArrayHelper;use common\helpers\Universal;use yii\httpclient\Client;/** * 途狐管车开放平台接口 * * @author wangjian * @since 0.1 */class Tuhu{ /** * @var string app_key */ public $app_key = ''; /** * @var string app_secret */ public $app_secret = ''; /** * @var string url */ public $url = ''; /** * @var string user_id */ public $user_id = ''; /** * @var string method */ public $method = 'POST'; /** * @var string access_token */ public $access_token; /** * @var array header */ public $header = [ 'Content-Type' => 'application/x-www-form-urlencoded' ]; /** * @var string expires access_token生效事件 */ public $expires = '7200'; public function __construct($api_url, $data = [], $method = 'POST') { $this->access_token = Yii::$app->cache->get('tuhu_access_token'); $this->data = [ 'appKey' => $this->app_key, 'v' => '1.0', 'timestamp' => date('Y-m-d H:i:s'), 'signMethod' => 'md5', 'format' => 'json', ]; if (empty($this->access_token)) { $this->access_token = $this->getAccessToken(); } if ($data) { $this->data = ArrayHelper::merge($this->data, $data); } $this->url = $this->url . $api_url; } /** * 调用处狐接口 */ public function curl() { $sign = $this->signMd5($this->data); $this->data['sign'] = $sign; $this->header['X-Access-Token'] = $this->access_token; $client = new Client(); $response = $client->createRequest() ->setMethod($this->method) // 申请形式 ->setUrl($this->url) // 申请地址 ->setData($this->data) ->setHeaders($this->header) ->send(); if ($response->isOk) { $result = isset($response->data['result']) ? $response->data['result'] : []; return $result; } Yii::$app->cache->delete('tuhu_access_token'); return false; } public function getAccessToken() { $data = $this->data; $url = $this->url . '/v1/token/get'; //公有参数 $data['userId'] = $this->user_id; $data['expiresIn'] = $this->expires; $sign = $this->signMd5($data); $data['sign'] = $sign; $client = new Client(); $response = $client->createRequest() ->setMethod('POST') // 申请形式 ->setUrl($url) // 申请地址 ->setData($data) ->setHeaders($this->header) ->send(); $accessToken = isset($response->data['result']['accessToken']) ? $response->data['result']['accessToken'] : ''; if ($accessToken) { Yii::$app->cache->set('tuhu_access_token', $accessToken, $this->expires); return $accessToken; } return ''; } /** * md5签名 */ public function signMd5($data) { //获取待签名字符串 ksort($data); reset($data); $query = ''; foreach ($data as $key => $value) { $query .= $key . $value; } $sign = $this->app_secret . $query . $this->app_secret; //签名 return strtoupper(md5($sign)); }}须要将demo中url,app_key,app_secret,user_id改成您本人的即可 ...

November 30, 2021 · 2 min · jiezi

关于php:海康监控接口调用

最近有一个我的项目须要对接海康监控,这里我写了一个demo,不便咱们来调用海康监控的相干接口 海康监控接口文档:https://open.hikvision.com/do... 海康监控demo: <?phpnamespace common\helpers;use common\models\Config;use Yii;use yii\helpers\ArrayHelper;use common\helpers\Universal;use yii\httpclient\Client;/** * 海康开放平台接口 * * @author wangjian * @since 0.1 */class Artemis{ //接口域名 public $url = ''; /** * @var string app_key */ public $app_key = ''; /** * @var string app_secret */ public $app_secret = ''; //毫秒级工夫戳 private $msec_time; public $content_type = "application/json";//类型 public $accept = "*/*" ;//accept public $method = 'POST'; //接口地址 private $api_url; //传递参数 private $data; /** * @param string $api_url * @param string $method * @param array $data */ public function __construct($api_url = '', $method = '', $data = []) { if ($api_url) { $this->api_url = $api_url; } if ($method) { $this->method = $method; } $this->data = $data; $this->msec_time = $this->msectime(); $this->charset = 'utf-8'; } /** * 调用海康接口 */ public function apiInterface() { $sign = $this->get_sign($this->method,$this->api_url); $headers = [ CURLOPT_HTTPHEADER => [ "Accept:".$this->accept, "Content-Type:".$this->content_type, "x-Ca-Key:".$this->app_key, "X-Ca-Signature:".$sign, "X-Ca-Timestamp:".$this->msec_time, "X-Ca-Signature-Headers:"."x-ca-key,x-ca-timestamp", ] ]; $result = $this->curl($headers); return json_decode($result,true); } /** * 海康接口调用 * @param string $url * @param string $postData * @param array $headers * @return bool|string */ public function curl($headers = array()) { $data = json_encode($this->data); if (is_array($data)) { $data = http_build_query($data); } $ch = curl_init(); $url = $this->url . $this->api_url; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); if ($this->method = 'POST') { curl_setopt($ch, CURLOPT_POST, 1); } else { curl_setopt($ch, CURLOPT_POST, 0); } if ($data) { curl_setopt($ch, CURLOPT_POSTFIELDS, $data); } curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL容许执行的最长秒数 if (!empty($headers)) { curl_setopt_array($ch, $headers); } //https申请 不验证证书和host curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($ch); curl_close($ch); return $data; } /** * 签名 * 以appSecret为密钥,应用HmacSHA256算法对签名字符串生成音讯摘要,对音讯摘要应用BASE64算法生成签名(签名过程中的编码方式全为UTF-8) */ function get_sign($method,$url){ $sign_str = $this->get_sign_str($method,$url); //签名字符串 $sign = hash_hmac('sha256', $sign_str, $this->app_secret,true); //生成音讯摘要 $result = base64_encode($sign); return $result; } /** * 获取签名字符串 * * @param $postData * @param $url * @return string */ function get_sign_str($method,$url){ $next = "\n"; $str = $method . $next; $str .= $this->accept . $next; $str .= $this->content_type . $next; $str .= "x-ca-key:" . $this->app_key.$next; $str .= "x-ca-timestamp:" . $this->msec_time.$next; $str .= $url; return $str; } /** * 获取毫秒级工夫戳 */ public function msectime() { list($msec, $sec) = explode(' ', microtime()); $msectime = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000); return $msectime; }}须要将demo中url,app_key,app_secret改成您本人的即可 ...

November 30, 2021 · 2 min · jiezi

关于php:使用和风天气接口获取天气信息

最近我的项目中应用到了获取天气相干信息,这里我应用了和风天气接口来实现此性能 和风天气接口API:https://dev.qweather.com/docs... 用户认证KEY:80d5607dd2874a2cbdfd2eeb54ab8e1d一:获取实时天气1:接口地址商业版:https://api.qweather.com/v7/w...开发版:https://devapi.qweather.com/v...2:申请参数key:用户认证keylocation:须要查问地区的经纬度(经度,纬度)3:返回数据 // 北京实况天气 // 商业版 https://api.qweather.com/v7/weather/now?location=101010100&key=你的KEY// 开发版 https://devapi.qweather.com/v7/weather/now?location=101010100&key=你的KEY{ "code": "200", "updateTime": "2020-06-30T22:00+08:00", "fxLink": "http://hfx.link/2ax1", "now": { "obsTime": "2020-06-30T21:40+08:00", "temp": "24", "feelsLike": "26", "icon": "101", "text": "多云", "wind360": "123", "windDir": "东南风", "windScale": "1", "windSpeed": "3", "humidity": "72", "precip": "0.0", "pressure": "1003", "vis": "16", "cloud": "10", "dew": "21" }, "refer": { "sources": [ "Weather China" ], "license": [ "commercial license" ] }} 二:获取将来七天天气1:接口地址商业版:https://api.qweather.com/v7/w...开发版:https://devapi.qweather.com/v...2:申请参数key:用户认证keylocation:须要查问地区的经纬度(经度,纬度)3:返回数据 // 北京3天预报 // 商业版 https://api.qweather.com/v7/weather/3d?location=101010100&key=你的KEY// 开发版 https://devapi.qweather.com/v7/weather/3d?location=101010100&key=你的KEY{ "code": "200", "updateTime": "2021-11-15T16:35+08:00", "fxLink": "http://hfx.link/2ax1", "daily": [ { "fxDate": "2021-11-15", "sunrise": "06:58", "sunset": "16:59", "moonrise": "15:16", "moonset": "03:40", "moonPhase": "盈凸月", "moonPhaseIcon": "803", "tempMax": "12", "tempMin": "-1", "iconDay": "101", "textDay": "多云", "iconNight": "150", "textNight": "晴", "wind360Day": "45", "windDirDay": "东北风", "windScaleDay": "1-2", "windSpeedDay": "3", "wind360Night": "0", "windDirNight": "北风", "windScaleNight": "1-2", "windSpeedNight": "3", "humidity": "65", "precip": "0.0", "pressure": "1020", "vis": "25", "cloud": "4", "uvIndex": "3" }, { "fxDate": "2021-11-16", "sunrise": "07:00", "sunset": "16:58", "moonrise": "15:38", "moonset": "04:40", "moonPhase": "盈凸月", "moonPhaseIcon": "803", "tempMax": "13", "tempMin": "0", "iconDay": "100", "textDay": "晴", "iconNight": "101", "textNight": "多云", "wind360Day": "225", "windDirDay": "西南风", "windScaleDay": "1-2", "windSpeedDay": "3", "wind360Night": "225", "windDirNight": "西南风", "windScaleNight": "1-2", "windSpeedNight": "3", "humidity": "74", "precip": "0.0", "pressure": "1016", "vis": "25", "cloud": "1", "uvIndex": "3" }, { "fxDate": "2021-11-17", "sunrise": "07:01", "sunset": "16:57", "moonrise": "16:01", "moonset": "05:41", "moonPhase": "盈凸月", "moonPhaseIcon": "803", "tempMax": "13", "tempMin": "0", "iconDay": "100", "textDay": "晴", "iconNight": "150", "textNight": "晴", "wind360Day": "225", "windDirDay": "西南风", "windScaleDay": "1-2", "windSpeedDay": "3", "wind360Night": "225", "windDirNight": "西南风", "windScaleNight": "1-2", "windSpeedNight": "3", "humidity": "56", "precip": "0.0", "pressure": "1009", "vis": "25", "cloud": "0", "uvIndex": "3" } ], "refer": { "sources": [ "QWeather", "NMC", "ECMWF" ], "license": [ "commercial license" ] }}三:将来24小时天气1:接口地址商业版:https://api.qweather.com/v7/w...开发版:https://devapi.qweather.com/v...2:申请参数key:用户认证keylocation:须要查问地区的经纬度(经度,纬度)3:返回数据 ...

November 30, 2021 · 6 min · jiezi

关于php:会日语的开发工程师看过来

システムエンジニア(PL、PG、SE)■仕事内容:システム開発業務など:要件定義・設計・プログラミング・テスト・激进運用など■経 験:1年以上の開発経験、もしくはIT専門卒業生■日本語:二級以上(会話重視、資格なしでもいい)■会社住所:東京 首都圏(客先)(他区域心愿者相談可能) 【応募办法】メールアドレス:sales@citec-c.co.jp電話相談:070-1315-3777(日本側担当者・徐)Wechat(日本側担当者・徐):CITECJAPAN-XTH(ただ相談でもいいですよ~お軽く連絡ください!)所在地:東京都千代田区神田佐久間町一丁目8番4号 会社HP:http://www.citec-c.co.jp/ご応募を待ちしております。どうぞよろしく、お願い致します。

November 28, 2021 · 1 min · jiezi

关于php:37-安卓手机存在监听隐患小米起诉博主索赔-100-万被驳回PHP-810-发布-思否周刊

40s 新闻速递联发科芯片固件被曝破绽:37% 安卓手机存在监听用户隐患人人影视字幕组创始人被判刑,官微表态:App 能够删了,不可能重启了腾讯回应 “腾讯云数据库泄露” 风闻:流言苹果滥用窃密协定打压员工元宇宙相干商标申请超过 4400 条下一代 AMD CPU 或将具备 12 个 CCD火狐明码管理器将于 12 月进行反对iPhone 13 系列不再反对中国电信 2G/3G 网络微软 Windows 11 不反对苹果芯片小米起诉数码博主索赔 100 万被驳回IntelliJ IDEA 2021.3 RC 公布Django 4.0 RC1 公布VirtualBox 6.1.30 公布PHP 8.1.0 正式公布Python 3.9.9 公布行业资讯联发科芯片固件被曝破绽:37% 安卓手机存在监听用户隐患平安厂商 Check Point 示意,该公司从一部运行 Android 11、配置天玑 800U 芯片的红米 Note 9 5G 手机中获取了联发科芯片的控件,发现由联发科设计的片上零碎音频解决固件存在一处安全漏洞,歹意利用能够机密将用户手机 “变成” 监听工具。Check Point 预计,寰球 37% 的智能手机存在这一破绽。联发科认为这些安全漏洞尚未被黑客利用,并曾经向手机厂商公布补丁软件。 人人影视字幕组创始人被判刑,官微表态:App 能够删了,不可能重启了11 月 22 日,上海市第三中级人民法院公开开庭审理了上海市人民检察院第三分院提起公诉的被告人梁永平涉嫌犯进犯著作权罪一案,并当庭作出一审判决,以进犯著作权罪判处被告人梁永平有期徒刑三年六个月,并处罚金人民币一百五十万元;守法所得予以追缴,扣押在案的供立功所用的自己财物等予以没收。 对于创始人被抓一事,今日人人影视官微 @人人影视字幕分享 表态称,“还是抵赖了吧, 人人影视不可能再复原或重启,App 的尸体能够删了,咱们不可能解决的了版权问题。” 人人影视还示意,涉案程序员工资是依据其开发技术领取的报酬,人人影视十几年,很多程序员参加过开发,网站、制作字幕的软件、以及起初的 App,这也是广告等支出主要用途,可没想到会最终牵累他们一起立功。 腾讯回应 “腾讯云数据库泄露” 风闻:流言在相干群截图中,呈现诸如 “腾讯云数据库泄露”“网信办拉了个腾讯云大客户列表,正在挨个打电话核查”“风传鹅厂数据库已泄露… 局部国企事业单位曾经开始从微信撤退” 等风闻,腾讯官网都予以回应是流言。同时腾讯示意,公司正继续降级对用户权利爱护的各项措施,并配合监管部门进行失常的合规检测。 ...

November 28, 2021 · 2 min · jiezi

关于php:PHP反射机制实现自动依赖注入

依赖注入又叫管制反转,应用过框架的人应该都不生疏。很多人一看名字就感觉是十分高大上的货色,就对它望而生畏,明天解开他它的神秘面纱。废话不多说,间接上代码; /**** 工具类,应用该类来实现主动依赖注入。**/class Ioc { // 取得类的对象实例 public static function getInstance($className) { $paramArr = self::getMethodParams($className); return (new ReflectionClass($className))->newInstanceArgs($paramArr); } /** * 执行类的办法 * @param [type] $className [类名] * @param [type] $methodName [办法名称] * @param [type] $params [额定的参数] * @return [type] [description] */ public static function make($className, $methodName, $params = []) { // 获取类的实例 $instance = self::getInstance($className); // 获取该办法所须要依赖注入的参数 $paramArr = self::getMethodParams($className, $methodName); return $instance->{$methodName}(...array_merge($paramArr, $params)); } /** * 取得类的办法参数,只取得有类型的参数 * @param [type] $className [description] * @param [type] $methodsName [description] * @return [type] [description] */ protected static function getMethodParams($className, $methodsName = '__construct') { // 通过反射取得该类 $class = new ReflectionClass($className); $paramArr = []; // 记录参数,和参数类型 // 判断该类是否有构造函数 if ($class->hasMethod($methodsName)) { // 取得构造函数 $construct = $class->getMethod($methodsName); // 判断构造函数是否有参数 $params = $construct->getParameters(); if (count($params) > 0) { // 判断参数类型 foreach ($params as $key => $param) { if ($paramClass = $param->getClass()) { // 取得参数类型名称 $paramClassName = $paramClass->getName(); // 取得参数类型 $args = self::getMethodParams($paramClassName); $paramArr[] = (new ReflectionClass($paramClass->getName()))->newInstanceArgs($args); } } } } return $paramArr; }}下面的代码应用php的反射函数,创立了一个容器类,应用该类来实现其余类的依赖注入性能。下面的依赖注入分为两种,一种是构造函数的依赖注入,一种是办法的依赖注入。 咱们应用上面三个类来做下测试。 ...

November 25, 2021 · 2 min · jiezi

关于php:JetBrains-官方宣布将成立-PHP-基金会历时-26-年焕发新机

近日,Phpstorm 开发商 JetBrains 在官网博客发文发表,将与 Automattic、Laravel、Laravel、Acquia 等多家公司独特成立 PHP 基金会。 这也是 PHP 语言公布 26 年以来,终于在 2021 年迎来的簇新倒退。 据悉,PHP 基金会将作为一个非盈利性组织,通过赞助对 PHP 语言有奉献的兼职/全职开发人员,以确保 PHP 语言的凋敝和可继续倒退。 事件起因:外围贡献者 Nikita Popov 来到 PHP在这 26 年里,许多人都在踊跃开发 PHP 语言,如 Rasmus Lerdorf、Zeev Suraski、Andi Gutmans、Nikita Popov 等。 据理解,此次 PHP 基金会成立的次要起因,正是因为 PHP 语言的次要贡献者之一 Nikita Popov 的一项打算 —— 将注意力从 PHP 转向 LLVM。 早在 2011 年,Nikita Popov 就开始钻研 PHP。过后他还在上高中,他在PHP5.5 中做出了第一个奉献,起初始终在 JetBrains 从事了近 3 年的 PHP 相干工作(前期共在 PHP 畛域工作了 10 年),为 PHP7.4、PHP8.0 和 PHP8.1 这些次要版本做出了重要奉献,实现了有数个性、谬误修复和对该语言开发过程的改良。 ...

November 25, 2021 · 2 min · jiezi

关于php:惊魂一夜有福新闻UfqiNews升级到PHP8

有福新闻UfqiNews的老版本仍然运行在 GWA2 PHP ( https://ufqi.com/dev/gwa2/ )上,去年底PHP编程语言自身降级到了PHP8, 获得好评,咱们即打算择日降级GWA2 PHP到PHP8版本。 思考到之前对于降级的经验教训,任何开源软件,可能在生产线部署的,肯定是以后稳固版本(latest stable release)的上一个版本,也就是上一个稳固版本的最新小版本。所以咱们思考将 有福新闻UfqiNews的GWA2 PHP降级的话,也不会间接去PHP8,而是先应用 PHP8之前的一个稳固版本PHP7.4. 又因为软件开发和应用,尤其是系统软件的开发和应用,另外一个黄金法令是可能运行就尽量不要去做任何批改(包含降级、优化等)。所以如果没有肯定的能源的话,咱们是不会去批改(降级、优化)一个运行失常的零碎。 可怜的是,时过境迁,物换星移,人们对软件系统的改良冀望是无止境的。很快咱们就遇到一个须要通过降级来解决的问题:以后的UfqiNews ( https://ufqi.com/news/ ) 零碎里在解决图片水印时,无奈在WebP格局的图片上打水印。这也不是大问题,要求图片另存为其余格局也能够绕过去,毕竟WebP格局的图片还是新事物。可是看到WebP的发展势头,仿佛遍及起来也只是工夫问题,加上对PHP8的神乎其技的“飞速”传言,咱们就依仗“艺高人胆大”的脑门一热的开启了在 UfqiNews上降级PHP8的操作了,从而遇上了惊魂一夜,PHP8有不兼容的问题,尤其是看起来像是走进路的NULL值问题和数据类型谬误抛出TypeError/ValueError。 PHP Built-in function count() Changelog ¶Version Description8.0.0 count() will now throw TypeError on invalid countable types passed to the value parameter.7.2.0 count() will now yield a warning on invalid countable types passed to the value parameter. PHP Built-in function explode() Changelog ¶Version Description8.0.0 explode() will now throw ValueError when separator parameter is given an empty string (""). Previously, explode() returned false instead. ...

November 24, 2021 · 3 min · jiezi

关于php:JAVA-String-a-abc-中发生了什么

和上次int a = 1 后续 测试代码javac TestCode.java public class TestCode { public static void main(String[] args) { // 此处写aaaa是便于看字节码 String aaaa = "bbbb"; aaaa = "cccc"; }}反编译javap -v -p -l TestCode(l是小写的L) 注解:javap是jdk自带的反解析工具。作用是依据class字节码文件,反解析出以后类对应的code区(汇编指令)、本地变量表、异样表和代码行偏移量映射表、常量池等等信息。 Classfile xxxxx/com/code/baseCode/TestCode.class Last modified 2021-11-22; size 475 bytes MD5 checksum 0a108c035194f620555926cf7d113c8b Compiled from "TestCode.java"public class com.code.baseCode.TestCode minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPERConstant pool: #1 = Methodref #5.#21 // java/lang/Object."<init>":()V #2 = String #22 // bbbb #3 = String #23 // cccc #4 = Class #24 // com/code/baseCode/TestCode #5 = Class #25 // java/lang/Object #6 = Utf8 <init> #7 = Utf8 ()V #8 = Utf8 Code #9 = Utf8 LineNumberTable #10 = Utf8 LocalVariableTable #11 = Utf8 this #12 = Utf8 Lcom/code/baseCode/TestCode; #13 = Utf8 main #14 = Utf8 ([Ljava/lang/String;)V #15 = Utf8 args #16 = Utf8 [Ljava/lang/String; #17 = Utf8 aaaa #18 = Utf8 Ljava/lang/String; #19 = Utf8 SourceFile #20 = Utf8 TestCode.java #21 = NameAndType #6:#7 // "<init>":()V #22 = Utf8 bbbb #23 = Utf8 cccc #24 = Utf8 com/code/baseCode/TestCode #25 = Utf8 java/lang/Object{ public com.code.baseCode.TestCode(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 8: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/code/baseCode/TestCode; public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=2, args_size=1 0: ldc #2 // String bbbb 2: astore_1 3: ldc #3 // String cccc 5: astore_1 6: return LineNumberTable: line 11: 0 line 12: 3 line 55: 6 LocalVariableTable: Start Length Slot Name Signature 0 7 0 args [Ljava/lang/String; 3 4 1 aaaa Ljava/lang/String;}SourceFile: "TestCode.java"反编译后,会发现aaaa存在于Constant pool(常量池)和LocalVariableTable(本地变量表)中 ...

November 23, 2021 · 3 min · jiezi

关于php:20211123日记录服务网关Gateway

SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则应用了高性能的Reactor模式通信框架Netty。Cloud全家桶中有个很重要的组件就是网关,在1.x版本中都是采纳的Zuul网关;但在2.x版本中,zuul的降级始终跳票,SpringCloud最初本人研发了一个网关代替Zuul,那就是SpringCloud Gateway—句话:gateway是原zuul1.x版的代替 Gateway是在Spring生态系统之上构建的API网关服务,基于Spring 5,Spring Boot 2和Project Reactor等技术。Gateway旨在提供一种简略而无效的形式来对API进行路由,以及提供一些弱小的过滤器性能,例如:熔断、限流、重试等。SpringCloud Gateway是Spring Cloud的一个全新我的项目,基于Spring 5.0+Spring Boot 2.0和Project Reactor等技术开发的网关,它旨在为微服务架构提供—种简略无效的对立的API路由治理形式。SpringCloud Gateway作为Spring Cloud 生态系统中的网关,指标是代替Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zul 2.0以上最新高性能版本进行集成,依然还是应用的Zuul 1.x非Reactor模式的老版本。而为了晋升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则应用了高性能的Reactor模式通信框架Netty。Spring Cloud Gateway的指标提供对立的路由形式且基于 Filter链的形式提供了网关根本的性能,例如:平安,监控/指标,和限流。3、为什么抉择Gateway?Gateway的个性 基于Spring Framework 5,Project Reactor和Spring Boot 2.0进行构建;动静路由:可能匹配任何申请属性;能够对路由指定Predicate (断言)和Filter(过滤器);集成Hystrix的断路器性能;集成Spring Cloud 服务发现性能;易于编写的Predicate (断言)和Filter (过滤器);申请限流性能;反对门路重写。 SpringCloud Gateway与Zuul的区别 在SpringCloud Finchley正式版之前,Spring Cloud举荐的网关是Netflix提供的Zuul。Zuul 1.x,是一个基于阻塞I/O的API Gateway。Zuul 1.x基于Servlet 2.5应用阻塞架构它不反对任何长连贯(如WebSocket)Zuul的设计模式和Nginx较像,每次I/操作都是从工作线程中抉择一个执行,申请线程被阻塞到工作线程实现,然而差异是Nginx用C++实现,Zuul用Java实现,而JVM自身会有第-次加载较慢的状况,使得Zuul的性能绝对较差。Zuul 2.x理念更先进,想基于Netty非阻塞和反对长连贯,但SpringCloud目前还没有整合。Zuul .x的性能较Zuul 1.x有较大晋升。在性能方面,依据官网提供的基准测试,Spring Cloud Gateway的RPS(每秒申请数)是Zuul的1.6倍。Spring Cloud Gateway建设在Spring Framework 5、Project Reactor和Spring Boot2之上,应用非阻塞API。Spring Cloud Gateway还反对WebSocket,并且与Spring严密集成领有更好的开发体验 http://www.bilibili.com/media...http://www.bilibili.com/media...http://www.bilibili.com/media...http://www.bilibili.com/media...http://www.bilibili.com/media...http://www.thinksaas.cn/user/...二、三大外围概念1、三大概念 Route(路由) : 路由是构建网关的根本模块,它由ID,指标URI,一系列的断言和过滤器组成,如断言为true则匹配该路由;Predicate(断言) : 参考的是Java8的java.util.function.Predicate,开发人员能够匹配HTTP申请中的所有内容(例如申请头或申请参数),如果申请与断言相匹配则进行路由;Filter(过滤) :指的是Spring框架中GatewayFilter的实例,应用过滤器,能够在申请被路由前或者之后对申请进行批改。 2、Gateway的工作流程 客户端向Spring Cloud Gateway发出请求。而后在Gateway Handler Mapping 中找到与申请相匹配的路由,将其发送到GatewayWeb Handler。Handler再通过指定的过滤器链来将申请发送到咱们理论的服务执行业务逻辑,而后返回。过滤器之间用虚线离开是因为过滤器可能会在发送代理申请之前(“pre”)或之后(“post")执行业务逻辑。三、Gateway配置1、环境新建模块:cloud-gateway-gateway9527pom:<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" ...

November 23, 2021 · 2 min · jiezi

关于php:学习PHP中YAML操作扩展的使用

YAML 这个货色,说实话,本人用得并不多。在学习自动化测试相干的内容时候,接触过应用这种配置文件来配置 Travis CI 的继续集成操作,当然,过后也是以学习性质为主的。虽说接触得不多,但也晓得的确这种配置格局的写法基本上曾经成为了当初的支流。所以对于具体的 YAML 相干的内容在这里就不多做解释了,还不是太理解的同学能够自行查阅一些相干的文档。 咱们明天来学习的次要是一个 PHP 中用来解析和转换 YAML 格局的扩大,装置过程并没有什么特地的能够阐明的中央,就和其它的扩大一样进行装置即可。不过这个扩大须要一个 libyaml-devel ,在 CentOS 中间接通过 yum 或者 dnf 是无奈装置的,咱们能够在文末的链接中找到下载地址。 将 PHP 数据转换成 YAML对于将 PHP 的数据转换成 YAML 来说,其实就和 JSON 相干的操作差不多,将数组转换成 YAML 格局的字符串。 $addr = array( "given" => "Chris", "family"=> "Dumars", "address"=> array( "lines"=> "458 Walkman Dr. Suite #292", "city"=> "Royal Oak", "state"=> "MI", "postal"=> 48046, ), );$invoice = array ( "invoice"=> 34843, "date"=> 980208000, "bill-to"=> $addr, "ship-to"=> $addr, "product"=> array( array( "sku"=> "BL394D", "quantity"=> 4, "description"=> "篮球", "price"=> 450, ), array( "sku"=> "BL4438H", "quantity"=> 1, "description"=> "Super Hoop", "price"=> 2392, ), ), "tax"=> 251.42, "total"=> 4443.52, "comments"=> "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.", );$yamlString = yaml_emit($invoice);var_dump($yamlString);// string(624) "---// invoice: 34843// date: 980208000// bill-to:// given: Chris// family: Dumars// address:// lines: |-// 458 Walkman Dr.// Suite #292// city: Royal Oak// state: MI// postal: 48046// ship-to:// given: Chris// family: Dumars// address:// lines: |-// 458 Walkman Dr.// Suite #292// city: Royal Oak// state: MI// postal: 48046// product:// - sku: BL394D// quantity: 4// description: "\u7BEE\u7403"// price: 450// - sku: BL4438H// quantity: 1// description: Super Hoop// price: 2392// tax: 251.42// total: 4443.52// comments: Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.// ...// "能够看到 yaml_emit() 函数转换的后果是十分规范的 YAML 格局。结尾有 --- ,结尾有 ... 。但你会发现有很多教程或者框架中的 .yml 文件中是没有这些符号的,从官网文档中得悉这些符号是倡议写得,而咱们的扩大则是十分地恪守倡议,也就是转换的后果十分地规范。 ...

November 23, 2021 · 2 min · jiezi

关于php:总结常见web安全问题分享常见的12攻击类型与防御措施第一篇

文章目录 1.明确web攻打的危害。2.分享常见的3种攻打与对应的进攻办法1.web攻打的危害。web攻打有什么危害呢?水平较轻微的攻打,或者会从你的网站上窃取到用户的信息。重大的web攻打能够删库,让网站瘫痪等等严重危害。 2.分享攻打类型:sql注入,xss,csrf攻打在此先分享3种攻打类型:sql注入,XSS攻打,csrf攻打 2.1 sql注入什么是sql注入?原本用户传了个id参数过去。如果咱们没有预防的话,产生sql注入。举个例子。用户传了个uid参数(用户id),个别状况下就会呈现,会传一个整数,比方:1 $uid = $_GET['uid'];//1select * from member where id = $uid这个sql没问题。如果黑客成心穿uid = '1 or 1=1'那么select * from member where id = 1 or 1=1;就会查出所有用户的信息。这里简答举个例子,其实sql注入狠一点的还能造成更重大的问题。 在此分享两个进攻措施 1.转化思路:对用户的提交的参数进行严格的过滤。比方uid参数,咱们进行整形转化。$uid = intval($_GET['uid']);//1 or 1=1会转化为1。 框架中,用框架封装好的办法查问。不要本人写原生语句查问。框架底层会主动过滤参数,能够避免sql注入。如果有些场景要本人写原生语句时,本人肯定要过滤好参数。 2.应用mysql的预处理机制(也叫参数化查问)。其实sql注入的基本问题是mysql执行语句时,是执行一条sql后间接返回数据的。这样子,只有sql有问题,就会呈现sql注入。如果拆开两条的话。 1.而且一条有sql注入的sql语句,通过预处理后就会被拆成两条没有sql注入的语句。 2.还能够有一次机会给mysql校验和本义。 比方执行了第一句预处理的sql后(`id` = :ThinkBind_1_454319113_ ),mysql就晓得,你查的话是id字段,所以你第二条sql的数据,必须是数字。如果不是数字mysql就抛异样上面以thinkphp为例子。 这样子有问题的sql,被拆成两条sql独自执行,就不会呈现sql注入的问题。比方:SELECT id,name FROM uf_member WHERE id = 12052 or 1 = 1 //拆成第一条: SELECT `id`,`name` FROM `uf_member` WHERE `id` = :ThinkBind_1_454319113_执行完第一条后,mysql会期待你参数的传入。 此时传入第二条sql(是一些参数) //第二条: array(1) { ["ThinkBind_1_454319113_"]=> array(2) { [0]=> string(14) "12052 or 1 = 1" [1]=> int(1) }即便是有sql注入问题,独自运行这条sql参数的话,也不会产生什么危害。 ...

November 21, 2021 · 1 min · jiezi

关于php:swoole结合thinkphp的使用详解

文章目录1.为什么要让thinkphp联合swoole?2.如何联合swoole?3.注意事项1.为什么要让thinkphp联合swoole?首先,咱们须要明确联合thinkphp和swoole的意义是什么?传统的fpm框架,在每次申请时都要从新加载大量文件,而且每次加载的文件简直都是雷同的,在这方面节约了不少效率,拉低了接口的响应速度。如果咱们能做到加载一次文件,前面就不须要加载了,那就好了,运行效率就高很多了。此时引入swoole即可做到,swoole能够让加载的文件,放到内存中。达到加载一次,前面无需加载,间接读内存的成果。这里咱们把swoole作为一个http server来剖析 2.thinkphp如何联合swoole?其次咱们要如何具体联合呢?这里咱们应用thinkphp5.1和swoole4联合。首先装置好thinkphp5.1和swoole扩大。而后在装置thinkphp-swoole(thinkphp官网写的一个thinkphp联合swoole的包)即可 composer require topthink/think-swoole=2.0.*这个包的用法具体能够去thinkphp的手册上搜寻swoole具体用法(https://www.kancloud.cn/manua...)这里会讲除了手册中阐明的问题,还会分享理论过程中,我在应用过程中遇到的问题与解决形式,这些手册上是没有的。 1.而后在config目录中新建一个swoole.php的配置文件,其中能够配置很多swoole的set办法的参数 2.再php think swoole start即可。 为什么说php think swoole start呢?其实是在源码目录下配置了两个命令而已。如下图所示 3.申请时会遇过即便屡次不同url申请,还是会走都到第一次申请url的办法中的问题。比方第一次的url是localhost:8080/api/task/demo,第二次的url是localhost:8080/api/task/test。浏览器拜访时还是会走到task控制器的demo办法。第二次其中是因为tp底层这里,有判断,把下图标记的判断去掉即可。因为$this->path变量在第一次申请时次申请时赋予值。前面的话应用到第一次$this->path的值。为什么以前没有这个问题,联合swoole之后就会有这个问题呢?我刚开始也很纳闷,浏览源码后发现原来在onWorkerStart(在此回调办法加载的文件会常驻内存)办法中165行,执行利用实例化时,其实中加载了很多类文件。其中就包含Request类,$this->path是Request类的属性。到此破案~。 4.发现拜访路由定义好的url时,每次都走到index模块index控制器的index办法的问题。tp底层依照原来的写法,会走到第二种判断,而后$_SERVER中没有argv这个参数,会把pathinfo赋值为空。会默认走到 index模块的index控制器的index办法。应该批改为上面的形式,将isCli放在前面去判断,即可解析对应的门路 或者nginx没有配置pathinfo模式。导致pathinfo解析时始终为空,所以走到了默认的index门路,此时配置nginx的配置文件即可。 #上面两句是给fastcgi权限,能够反对 ?s=/module/controller/action的url拜访模式fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;#上面两句能力真正反对 index.php/index/index/index的pathinfo模式fastcgi_param PATH_INFO $fastcgi_path_info;fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;前面就能失常运行了。也没遇到什么手册上没有的坑了。 分享如何让think-swoole作为一个webscoket服务端的例子,只须要在swoole.php的配置文件中增加这样配置。其实这个官网手册没有通知你,能够这样用。但浏览源码后发现这样配置一下,就能够搭建一个websocker Server. 3.注意事项。think-swoole为咱们做了一个批改代码后,主动重启的性能。但有时候发现,批改后也没有主动重启。通过浏览源码后,在下图中加上这样的一段即可// 如果开启了APC或OPcache,还须要刷新缓存后,平滑重启才会失效。 if (extension_loaded('apc')) { apc_clear_cache(); } if (extension_loaded('Zend OPcache')) { opcache_reset(); }此问题发现后我也是通过github反馈给thinkphp官网修复了。如果还是遇到没有主动重启的问题,能够尝试增加下面的那段代码。 本文为夜雨闻铃原创文章,转载无需和我分割,但必须注明文章出处!!!文章出处:夜雨闻铃的思否文章(https://segmentfault.com/a/11...)

November 21, 2021 · 1 min · jiezi

关于php:解决php72后报错Warning-Use-of-undefined-constant-PRE-assumed问题

解决php7.2后报错Warning: Use of undefined constant PRE - assumed问题解决此种问题其实也不是很难,只是报了”Warning正告“,咱们只须要敞开”PHP谬误提醒“就好了。具体步骤以下:php 一、关上 php.inihtml 二、设置 error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICTpost 三、设置 display_errors = Offhtm 转载于:https://www.cnblogs.com/xbden...

November 18, 2021 · 1 min · jiezi

关于php:学习PHP中的URL相关操作函数

在日常的业务开发过程中,咱们常常会有解决 URL 链接的需要,所以明天学习的函数其实都是大家常常会应用的一些函数。在之前的工作过程中,其实我对这些函数都只是有一个含糊的概念,晓得,然而真要用得时候还是要看下文档能力确定真正要应用的是哪一个函数。因而,明天咱们就当做是一次温习练习,次要是辨别和搞清楚每个函数真正的用途。 编码操作函数首先来看就是 URL 编码相干的函数。有些浏览器在咱们复制粘贴一个网址后,就会主动地对网址进行 URL 编码,也就是有很多百分号那种模式的。在 PHP 中,天然也有对应的编解码函数。 $url = "https://www.zyblog.net?opt=dev&mail=zyblog@net.net&comments=aaa bbb ccc %dfg &==*() cdg&value=“中文也有呀,还有中文符号!!”";echo $url, PHP_EOL;// https://www.zyblog.net?opt=dev&mail=zyblog@net.net&comments=aaa bbb ccc %dfg &==*() cdg&value=“中文也有呀,还有中文符号!!”$enurl = urlencode($url);echo $enurl, PHP_EOL;// https%3A%2F%2Fwww.zyblog.net%3Fopt%3Ddev%26mail%3Dzyblog%40net.net%26comments%3Daaa+bbb+ccc+%25dfg+%26%3D%3D%2A%28%29+cdg%26value%3D%E2%80%9C%E4%B8%AD%E6%96%87%E4%B9%9F%E6%9C%89%E5%91%80%EF%BC%8C%E8%BF%98%E6%9C%89%E4%B8%AD%E6%96%87%E7%AC%A6%E5%8F%B7%EF%BC%81%EF%BC%81%E2%80%9Decho urldecode($enurl), PHP_EOL;// https://www.zyblog.net?opt=dev&mail=zyblog@net.net&comments=aaa bbb ccc %dfg &==*() cdg&value=“中文也有呀,还有中文符号!!”这两个函数预计是大家应用最多的函数了。urlencode() 就是用于 URL 的编码操作,能够看到,咱们筹备好的链接曾经被编码成了蕴含各种百分号的内容。特地是对于中文字符来说,如果是 GET 形式这种在链接中的中文参数,编码之后的内容就会让链接变得十分长。urldecode() 则是绝对应的解码性能的函数,能够把编码过的链接解码回原始的状态。 $rawenurl = rawurlencode($enurl);echo $rawenurl, PHP_EOL;// https%253A%252F%252Fwww.zyblog.net%253Fopt%253Ddev%2526mail%253Dzyblog%2540net.net%2526comments%253Daaa%2Bbbb%2Bccc%2B%2525dfg%2B%2526%253D%253D%252A%2528%2529%2Bcdg%2526value%253D%25E2%2580%259C%25E4%25B8%25AD%25E6%2596%2587%25E4%25B9%259F%25E6%259C%2589%25E5%2591%2580%25EF%25BC%258C%25E8%25BF%2598%25E6%259C%2589%25E4%25B8%25AD%25E6%2596%2587%25E7%25AC%25A6%25E5%258F%25B7%25EF%25BC%2581%25EF%25BC%2581%25E2%2580%259Decho rawurldecode($rawenurl), PHP_EOL;// https%3A%2F%2Fwww.zyblog.net%3Fopt%3Ddev%26mail%3Dzyblog%40net.net%26comments%3Daaa+bbb+ccc+%25dfg+%26%3D%3D%2A%28%29+cdg%26value%3D%E2%80%9C%E4%B8%AD%E6%96%87%E4%B9%9F%E6%9C%89%E5%91%80%EF%BC%8C%E8%BF%98%E6%9C%89%E4%B8%AD%E6%96%87%E7%AC%A6%E5%8F%B7%EF%BC%81%EF%BC%81%E2%80%9Decho rawurlencode($url), PHP_EOL;// https%3A%2F%2Fwww.zyblog.net%3Fopt%3Ddev%26mail%3Dzyblog%40net.net%26comments%3Daaa%20bbb%20ccc%20%25dfg%20%26%3D%3D%2A%28%29%20cdg%26value%3D%E2%80%9C%E4%B8%AD%E6%96%87%E4%B9%9F%E6%9C%89%E5%91%80%EF%BC%8C%E8%BF%98%E6%9C%89%E4%B8%AD%E6%96%87%E7%AC%A6%E5%8F%B7%EF%BC%81%EF%BC%81%E2%80%9Decho rawurldecode($enurl), PHP_EOL;// https://www.zyblog.net?opt=dev&mail=zyblog@net.net&comments=aaa+bbb+ccc+%dfg+&==*()+cdg&value=“中文也有呀,还有中文符号!!”紧接着咱们看到的是 rawurlencode() 和 rawurldecode() 。很多小伙伴会搞不清楚它们和一般的 urlencode() 、 urldecode() 有什么区别。其实,它们的区别次要体现在一些非凡的字符上,比如说空格。在 urlencode() 中,空格被编码为 + 号,而在 urlrawencode() 中,空格是 %20 。在咱们的第三段测试代码中就可以看进去。 ...

November 16, 2021 · 3 min · jiezi

关于php:记录一次yii2项目php版本升级到74的代码变更

目前开发用的yii2基于php7.1.33构建,鉴于7.1曾经进行保护,打算更新php版本到7.4,并且将yii2的版本从2.0.15.1降级到最新的2.0.43。此文记录一下批改步骤 object批改谬误提醒:PHP Compile ErrorCannot use yii\base\Object as Object because 'Object' is a special class name谬误起因:php7.2开始不反对应用object作为类名,因而将所有继承至\yii\base\Object的Object批改为\yii\base\Object controller批改谬误提醒:Yii2 Call to a member function validateCsrfToken() on string谬误起因:自yii2.0.36开始,yii2退出了一个类变量 $request,在init函数中初始化,因而如果重写controller的init办法,必须执行 parent::init()。 花括号批改谬误提醒:PHP Deprecated WarningArray and string offset access syntax with curly braces is deprecated谬误起因:应用大括号拜访数组及字符串索引的形式在php7.4中已被废除。请应用 $var[$idx] 的语法来代替 $var{$idx}。例:php 7.4 不再容许应用花括号来拜访数组的元素。 $arr = array('1','2','3'); //定义一个数组:echo $arr[0]; //正确echo $arr{0}; //7.4以前正确,7.4谬误数组非空批改谬误提醒:Notice: Trying to access array offset on value of type null 谬误起因:php7.4不反对以数组模式拜访非数组尝试以数组形式拜访 null,bool, int,float 或 resource (例如 $null["key"])将会抛出 notice 告诉。因而在拜访一个可能为空的数组时要先判断数组非空 ...

November 15, 2021 · 1 min · jiezi

关于php:ApacheCN-PHP-译文集-20211101-更新

PHP 入门指南 零、序言一、PHP 入门二、数组和循环三、函数和类四、数据操作五、构建 PHP Web 利用六、搭建 PHP 框架七、认证与用户治理八、建设联系人管理系统应用 PHP7 构建 REST Web 服务 零、前言一、RESTful Web 服务、介绍和动机二、PHP7,以便更好地编写代码三、创立 RESTful 端点四、审查设计缺点和平安威逼五、应用 Composer 加载并解析,这是一种进化六、用 Lumen 照亮 RESTful Web 服务七、改良 restfulweb 服务八、API 测试——闸门上的防护装置九、微服务函数式 PHP 零、序言一、PHP 中的一等函数二、纯函数、援用透明性和不变性三、PHP 的函数根底四、构建函数五、函子、利用和单子六、现实生活中的单子七、函数式技术和主题八、测试九、性能效率十、PHP 框架与 FP十一、设计函数式利用十二、咱们在议论函数式编程时,议论的是什么精通更快的 PHP7、MySQL 和 JS Web 利用 零、前言一、更快的 Web——入门二、继续剖析和监测三、利用 PHP7 数据结构和函数的弱小性能四、应用异步 PHP 展望未来五、测量和优化数据库性能六、高效查问古代 SQL 数据库七、JavaScript 和危险驱动开发八、函数式 JavaScript九、进步 Web 服务器的性能十、超过性能精通 PHP7 零、前言一、全新的 PHP二、承受规范三、错误处理和日志记录四、魔术办法背地的魔法五、CLI 畛域六、突出的面向对象个性七、优化以取得高性能八、无服务器九、反应式编程十、通用设计模式十一、构建服务十二、应用数据库十三、解决依赖关系十四、应用包十五、测试重要地位十六、调试、跟踪和剖析十七、托管、资源调配和部署现代化遗留 PHP 利用 一、遗留利用二、先决条件三、实现主动加载器四、整合类和函数五、用依赖注入替换全局六、用依赖注入替换新建七、编写测试八、将 SQL 语句提取到网关八、将畛域逻辑提取到事务中十、提取示意逻辑来查看文件十一、提取动作逻辑到控制器十二、替换类中的蕴含十三、公共和非公共资源离开十四、将 URL 门路与文件门路解耦十五、删除页面脚本中的反复逻辑十六、增加依赖注入容器十七、论断十八、附录 A:典型遗留页面脚本十九、附录 B:网关前的代码二十、附录 C:网关后的代码二十一、附录 D:事务脚本后的代码二十二、附录 E:采集示意逻辑前的代码二十三、附录 F:采集示意逻辑后的代码二十四、附录 G:响应视图文件后的代码二十五、附录 H:控制器从新安排后的代码二十六、附录 I:控制器提取后的代码二十七、附录 J:控制器依赖注入后的代码PHP7 模块化编程 ...

November 13, 2021 · 2 min · jiezi

关于php:前端面试每日-31-第942天

明天的知识点 (2021.11.13) —— 第942天 (我也要出题)[html] 应用H5写一个网页版的简略扫雷游戏[css] 应用css3实现鱼钩及鱼杆[js] 写一个正则提取字符串中的手机号码[软技能] 淘宝的双11大流量下对前端有哪些挑战呢?《论语》,曾子曰:“吾日三省吾身”(我每天屡次检查本人)。前端面试每日3+1题,以面试题来驱动学习,每天提高一点!让致力成为一种习惯,让奋斗成为一种享受!置信 保持 的力量!!! 欢送在 Issues 和敌人们一起探讨学习! 我的项目地址:前端面试每日3+1【举荐】欢送跟 jsliang 一起折腾前端,零碎整顿前端常识,目前正在折腾 LeetCode,打算买通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个Star, 同时欢送微信扫码关注 前端剑解 公众号,并退出 “前端学习每日3+1” 微信群互相交换(点击公众号的菜单:交换)。 学习不打烊,充电加油只为遇到更好的本人,365天无节假日,每天早上5点纯手工公布面试题(死磕本人,愉悦大家)。心愿大家在这虚夸的前端圈里,放弃沉着,保持每天花20分钟来学习与思考。在这变幻无穷,类库层出不穷的前端,倡议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢送大家到Issues交换,激励PR,感激Star,大家有啥好的倡议能够加我微信一起交换探讨! 心愿大家每日去学习与思考,这才达到来这里的目标!!!(不要为了谁而来,要为本人而来!)交换探讨欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个[Star]

November 13, 2021 · 1 min · jiezi

关于php:在线文档在线预览功能开发分享文库系统建设

office/pdf文档各版本的预览(转png),不须要装置任何插件,反对挪动端浏览,代码如下: /** * 文件转换//新版本 * @return [type] [description] */ public function get_convert(){ error_reporting(0); ignore_user_abort(); header('HTTP/1.1 200 OK'); header('Content-Length:0'); header('Connection:Close'); flush(); if (isset($_POST) && $_POST['act']=='down') { /*取得文件门路*/ $file_name = iconv("UTF-8", "gb2312", $_POST['file_name']); if (!file_exists($file_name)) { return false; } $type = pathinfo($file_name, PATHINFO_EXTENSION); $no_pdf = ''; /*如果不是pdf文件须要转换成pdf*/ if ($type != 'pdf') { $save_pdf = 'Public/files/upload_tmp/'.$_POST['user_id']; if (!file_exists($save_pdf)) { @mkdir($save_pdf,0777,true); } $pdf_name = pathinfo($file_name, PATHINFO_FILENAME); $filename = $save_pdf.'/'.$pdf_name.'.pdf'; $source = dirname(dirname(dirname(dirname(__FILE__)))).'\\Public/'.$file_name; $export = dirname(dirname(dirname(dirname(__FILE__)))).'\\Public/'.$save_pdf; $num = D('Article')->lpdf($source,$filename,$export); // $num = D('Article')->turnPdf($file_name,$filename); // file_put_contents('get_api.txt',json_encode($source),FILE_APPEND); // file_put_contents('get_api.txt',json_encode($export),FILE_APPEND); // $num = D('PdfConverter')->execute($source,$export); $no_pdf='1'; }else{ $no_pdf = ''; $filename = $file_name; // $num = D('Article')->getPdfPages($file_name); } //pdf转换成html $fileurl = dirname(dirname(dirname(dirname(__FILE__)))).'\\Public'; $input_url = $fileurl.'/'.$filename; $output_url = $fileurl.'/Public/files/png/'.$_POST['user_id'].'/'.$_POST['article_id']; // file_put_contents('get_api.txt',$input_url,FILE_APPEND); // file_put_contents('get_api.txt',$output_url,FILE_APPEND); // $pdftohtml = D('Lc前端html5,后端.net(注:前端是仿的款式,后端从新写的)(有什么问题不懂的能够私信我V:kjwenlc)文库零碎次要实现文档的分享性能,能够上传office文档及pdf文档,office文档反对各个版本的word,excel。每一篇须要付费的文档未注册用户每次都须要付费才可下载,对于每一篇付费文档注册用户只须要付费一次即可下载本文档。 ...

November 11, 2021 · 1 min · jiezi

关于php:一起学习PHP中的Tidy扩展库

这个扩大预计很多同学可能都没听说过,这可不是泰迪熊呀,而是一个解决 HTML 相干操作的扩大,次要是能够用于 HTML 、 XHTML 、 XML 这类数据格式内容的格式化及展现。 对于 Tidy 库Tidy 库扩大是随 PHP 一起公布的,也就是说,咱们能够在编译装置 PHP 时加上 --with-tidy 来一起装置这个扩大,也能够在预先通过源码包中 ext/ 文件夹下的 tidy 目录中的源码来进行装置。同时,Tidy 扩大还须要依赖一个 tidy 函数库,咱们须要在操作系统上装置,如果是 CentOS 的话,间接 yum install libtidy-devel 就能够了。 Tidy 格式化首先咱们来看一下如何通过这个 Tidy 扩大库来格式化一段 HTML 代码。 $content = <<<EOF<html><head><title>test</title></head> <body><p>error<br>another line</i></body></html>EOF;$tidy = new Tidy();$config = [ 'indent'=>true, 'output-xhtml'=>true,];$tidy->parseString($content, $config);$tidy->cleanRepair();echo $tidy, PHP_EOL;// <html xmlns="http://www.w3.org/1999/xhtml">// <head>// <title>// test// </title>// </head>// <body>// <p>// error<br />// another line// </p>// </body>// </html>咱们定义的 $content 中的这段 HTML 代码是没有任何格局的十分不标准的一段 HTML 代码。通过实例化一个 Tidy 对象之后,应用 parseString() 办法,并执行 cleanRepair() 办法之后,再间接打印 $tidy 对象,咱们就取得了格式化之后的 HTML 代码。看起来是不是十分地标准,不论是 xmlns 还是 缩进 格局都十分规范。 ...

November 9, 2021 · 4 min · jiezi

关于php:模板导出Xls

<?phpnamespace app\admin\controller;use app\common\controller\Backend;use think\Loader;Loader::import('phpexcel.Classes.PHPExcel.IOFactory',EXTEND_PATH,'.php');/** * * * @icon fa fa-circle-o */class Order extends Backend{ /** * Order模型对象 * @var \app\admin\model\Order */ protected $model = null; protected $dataLimit = 'auth'; public function _initialize() { parent::_initialize(); $this->model = new \app\admin\model\Order; } function excel_handle($ids){ $this->success('解决胜利,正在生成报表!',null,$ids); } function excout($ids=null){ $info = db('order')->find($ids); if(empty($info)){ $this->error('订单不存在'); } $list = db('order_details') ->alias('details') ->join('goods','goods.id = details.goods_id') ->join('goods_sku','goods_sku.id = details.sku_id') ->field('details.*,goods.name as goods_name,goods_sku.name as suk_name') ->where('order_id',$info['id']) ->select(); //订单信息 error_reporting(E_ALL); ini_set('display_errors', TRUE); ini_set('display_startup_errors', TRUE); ini_set("error_reporting","E_ALL & ~E_NOTICE"); define('EOL',(PHP_SAPI == 'cli') ? PHP_EOL : '<br />'); date_default_timezone_set('Europe/London'); include 'extend/phpexcel/Classes/PHPExcel/IOFactory.php'; //设置模板文件 $objPHPExcel = \PHPExcel_IOFactory::load("PI-larkkey.xls"); //将json字符串转换为数组 //数据 //$billData = json_decode($_REQUEST["billData"],true); //月份表 $months = array( 1 => 'Jan', 2 => 'Feb', 3 => 'Mar', 4 => 'Apr', 5 => 'May', 6 => 'Jun', 7 => 'Jul', 8 => 'Aug', 9 => 'Sep', 10 => 'Oct', 11 => 'Nov', 12 => 'Dec' ); //根底信息 $basic_info = array( 'consignee_company_name' => $info['contactname'], 'consignee_address' => $info['address'], 'consignee_tel' => $info['tel'], 'loading_port' => $info['loading'], 'destination_port' => $info['destination'], 'shippment_way' => $info['shippment'], 'invoice_number' => 'INVOICE NO:'.$info['invoiceno'] ); //根底信息 日期 $basic_info['date'] = $months[(int)Date('m')]." ".Date('D').",".Date("Y"); //根底信息填充单元格 $objPHPExcel->getActiveSheet()->setCellValue('B7', $basic_info['consignee_company_name']) ->setCellValue('B8', $basic_info['consignee_address']) ->setCellValue('B9', $basic_info['consignee_tel']) ->setCellValue('B10', 'Ningbo') ->setCellValue('B11', $basic_info['destination_port']) ->setCellValue('B12', 'by express') ->setCellValue('G7', $basic_info['invoice_number']) ->setCellValue('G8', $basic_info['date']); //设置B10 $objValidation_ = $objPHPExcel->getActiveSheet()->getCell("B10")->getDataValidation(); $objValidation_ -> setType(\PHPExcel_Cell_DataValidation::TYPE_LIST) -> setErrorStyle(\PHPExcel_Cell_DataValidation::STYLE_INFORMATION) -> setAllowBlank(false) -> setShowInputMessage(true) -> setShowErrorMessage(true) -> setShowDropDown(true) -> setErrorTitle('输出的值有误') -> setError('您输出的值不在下拉框列表内.') -> setPromptTitle('设施类型') -> setFormula1('"Ningbo,Shengzhen,guangzhou"'); //设置B12 $objValidation_ = $objPHPExcel->getActiveSheet()->getCell("B12")->getDataValidation(); $objValidation_ -> setType(\PHPExcel_Cell_DataValidation::TYPE_LIST) -> setErrorStyle(\PHPExcel_Cell_DataValidation::STYLE_INFORMATION) -> setAllowBlank(false) -> setShowInputMessage(true) -> setShowErrorMessage(true) -> setShowDropDown(true) -> setErrorTitle('输出的值有误') -> setError('您输出的值不在下拉框列表内.') -> setPromptTitle('设施类型') -> setFormula1('"by express,by air,by express"'); //列表信息// $list_data = array(// '0' => array(// 'pic' => '',//图片// 'item_no' => '001',//货号// 'description' => 'wife',//形容// 'protocol' => 'sex',//属性// 'color' => 'green',//色彩// 'qty_pcs' => '100', //数量/个数 -装箱量// 'usd_pcs' => '50',//美金/个数// 'amount' => '100' //总计价格// )// ); $list_data = $list;// $PHPSheet->getColumnDimension('C')->setWidth(70);// $PHPSheet->getRowDimension(21)->setRowHeight(75);//高度 //循环填充雷同题目单元格 $row=14; foreach($list_data as $r => $dataRow) { $this->excelPic($dataRow['image'],'A'.$row,$objPHPExcel->getActiveSheet()); $objPHPExcel->getActiveSheet()->getRowDimension($row)->setRowHeight(100); $objPHPExcel->getActiveSheet()// ->setCellValue('A'.$row, $dataRow['image']) ->setCellValue('B'.$row, $dataRow['model_no']) ->setCellValue('c'.$row, $dataRow['goods_name']) ->setCellValue('D'.$row, $dataRow['suk_name']) ->setCellValue('E'.$row, $dataRow['mode']==1?'Read To Sheep':'Customization') ->setCellValue('F'.$row, $dataRow['num']) ->setCellValue('G'.$row, $dataRow['price']) ->setCellValue('H'.$row, $dataRow['num']*$dataRow['price']); $row++; } //显示总价 $objPHPExcel->getActiveSheet()->setCellValue('A'.$row, 'Total:'."") ->setCellValue('H'.$row, $info['amount']) ->setCellValue('A'.($row+2), "Note:") //上面是固定文本信息 ->setCellValue('A'.($row+3), "1,Price Term:Fob Ningbo") ->setCellValue('A'.($row+4), "2,Price Valid:30 days") ->setCellValue('A'.($row+5), "3,Payment Term:30% T/T,70% balance before shippment or L/C or Paypal") ->setCellValue('A'.($row+6), "4,Packing:white netural packing or our logo packing,") ->setCellValue('A'.($row+7), " If need customized packing,need MOQ.And packing cost need to be adjusted.") ->setCellValue('A'.($row+10), "Bank Detail:"); $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5'); ob_end_clean(); header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); header('Content-Disposition: attachment;filename=larkkey_'.time().'.xlsx'); header('Cache-Control: max-age=0'); $objWriter->save("php://output"); exit; //让拜访浏览器间接下载文件流// Header("Location: /uploads/larkkey_".time().".xls"); } function excelPic($url,$seat,$obj){ if(empty($url)){ return $obj; } $temp_pic = $this->download($url,'../public/uploads/temp/'); $temp[] =$local_pic_path = '../public/uploads/temp/'.$temp_pic; if (file_exists($local_pic_path)) { $img = new \PHPExcel_Worksheet_Drawing(); $img->setPath($local_pic_path);//写入图片门路 // $img->setHeight(100);//写入图片高度 $img->setWidth(100);//写入图片宽度// $img->setOffsetX(105);//写入图片在指定格中的X坐标值// $img->setOffsetY(5);//写入图片在指定格中的Y坐标值// $img->setRotation(1);//设置旋转角度// $img->getShadow()->setVisible(true);// $img->getShadow()->setDirection(50); $img->setCoordinates($seat);//设置图片所在表格地位 $img->setWorksheet($obj);//把图片写到以后的表格中 } return $obj; } function download($url, $path = 'images/') { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 信赖任何证书 $file = curl_exec($ch); curl_close($ch); $filename = pathinfo($url, PATHINFO_BASENAME); $resource = fopen($path . $filename, 'a'); fwrite($resource, $file); fclose($resource); return $filename; }}文件 ...

November 8, 2021 · 3 min · jiezi

关于php:小技巧分享在-Go-如何实现枚举

大家好,我是煎鱼。 在日常的业务工程开发中,咱们经常会有应用枚举值的诉求,枚举控的好,测试值边界一遍过... 有的小伙伴会说,在 Go 语言不是有 iota 类型做枚举吗,那煎鱼你这篇文章还讲什么? 讲道理,Go 语言并没有 enum 关键字,有用过 Protobuf 等的小伙伴晓得,Go 语言只是 ”无限的枚举“ 反对,咱们也会用常量来定义,枚举值也须要有字面意思的映射。 示例在一些业务场景下,是没法达到咱们的诉求的。示例如下: type FishType intconst ( A FishType = iota B C D)func main() { fmt.Println(A, B, C, D)}输入后果为:“0 1 2 3”。这时候就一脸懵逼了...枚举值,应该除了键以外,还得有个对应的值。也就是这个 “0 1 2 3” 别离对应着什么含意,是不是应该输入 ”A B C D“ 但 Go 语言这块就没有间接的撑持了,因而这不是一个残缺的枚举类型的实现。 同时假如咱们传入超过 FishType 类型申明范畴的枚举值,在 Go 语言中默认也不会有任何管制,是失常输入的。 上述这种 Go 枚举实现,在某种状况下是不齐全的,严格意义上不能成为 enum(枚举)。 应用 String 做枚举如果要反对枚举值的对应输入的话,咱们能够通过如下形式: type FishType intconst ( A FishType = iota B C D)func (f FishType) String() string { return [...]string{"A", "B", "C", "D"}[f]}运行程序: func main() { var f FishType = A fmt.Println(f) switch f { case A:  fmt.Println("脑子进煎鱼了") case B:  fmt.Println("记得点赞") default:  fmt.Println("别别别...") }}输入后果: A脑子进煎鱼了咱们能够借助 Go 中 String 办法的默认约定,针对于定义了 String 办法的类型,默认输入的时候会调用该办法。 这样就能够达到取得枚举值的同时,也能拿到其映射的字面意思。 主动生成 String但每次手动编写还是比拟麻烦的。在这一块,咱们能够利用官网提供的 cmd/string 来疾速实现。 咱们装置如下命令: go install golang.org/x/tools/cmd/stringer在所需枚举值上设置 go:generate 指令: //go:generate stringer -type=FishTypetype FishType int在我的项目根目录执行: go generate ./...会在根目录生成 fishtype\_string.go 文件: .├── fishtype_string.go├── go.mod├── go.sum└── main.gofishtype\_string 文件内容: ...

November 8, 2021 · 1 min · jiezi

关于php:PHP-与-SAML

背景因为公司有2个平台,而且历史起因每个平台都有个本人的用户零碎。当初要重构,技术老大心愿用sso做到不同平台登录。都2021了还用ucenter(没听过这个的自行百度)?老大是想用saml做sso,这个在国内,而且PHP材料少得可怜。我也是折腾了良久才弄得明确。当初咱们是用saml+oauth 做的sso。 SAML 常识介绍如上图,角色介绍user agent:浏览器,用户操作等service provider(以下都简称sp):每个零碎、平台ident provider(以下都简称idp):对立的用户验证核心 发送波及验证名词解释: metadata(元数据):SP和IDP进行集成的时候的一个配置,这个配置叫做 metadata。这个配置有两份,两边各一份,外面约定了应该怎么去映射用户信息,签名的证书等。IDP和SP会通过别的形式去替换这两份 metadata;acs:sp 、idp各自解释和生成xml的地址;sso:单点登陆页面sls:退出地址文字流程: 用户先发动申请sp,sp判断用户是否登录状态(session、token),如果不是登录状态间接带着saml 下的去重定向idp,这个过程咱们叫他AuthnRequest;idp那边会显示登录页sso,用户填写账号密码后,再提交给idp自身,而后生成response xml用post模式发送到sp 的acs解释;sp 的 acs收到response后解释xml,这过程叫断言,获取相干状态判断用是否登陆胜利,若登陆胜利生成session或token;下次用户在用sp的资源时候,直接判断session和token就好。oauth2 和 saml 在sso上的区别oauth2(Authorization):受权saml(Authentication):验证流程根本一样,如果用api办法去验证登陆,oauth2 是十分不便能够每次用token发送到认证服务器验证,登陆状态;smal登陆完要在sp在解决一次登陆凭证; PHP & saml在这里我先介绍几个PHP做的saml开源代码:oneloginlightsamlsimplesamlphp这3个预计就目前为止,php在saml中做得比较完善的开源我的项目了。 那如何把saml 跟laravel 关联呢?国际友人曾经把轮子做进去了。别离都是基于下面的开源我的项目做的。laravel-idp:https://github.com/codegreencreative/laravel-samlidplaravel-sp:https://github.com/aacotroneo/laravel-saml2 这两个库别离是用了lightsaml、onelogin去做的,所以更多的时候要看这外面的配置和源码,而且库的文档和issue可能写得简陋,须要咱们对saml整改流程清晰明确状况下,再配合浏览源码能力无效应用,有工夫我再把这两个库如何配合应用和源码解读写进去。

November 5, 2021 · 1 min · jiezi

关于php:laravel-passport-的-oauth2机制二-源码解读

如果曾经了解oauth2.0原理,也装置后laravel passport的状况下。当初从源码中看看相干的逻辑流程,是如何走的。在这之前咱们先看下laravel如何判断http客户端申请是一般申请,还是json申请,因为passport 默认是api json申请的。\vendor\laravel\framework\src\Illuminate\Http\Concerns\InteractsWithContentTypes.php 判断http header 的 Accept 是否带有json或+json。 public function expectsJson() { return ($this->ajax() && ! $this->pjax() && $this->acceptsAnyContentType()) || $this->wantsJson(); }public function wantsJson() { $acceptable = $this->getAcceptableContentTypes(); return isset($acceptable[0]) && Str::contains($acceptable[0], ['/json', '+json']); }晓得申请办法后,咱们看看如何获取oauth access_token。用php artisan route:list 能够查看到 这条记录 POST| oauth/token| passport.token|Laravel\Passport\Http\Controllers\AccessTokenController@issueToken 前期进入代码查看,\vendor\laravel\passport\src\Http\Controllers\AccessTokenController.php,再进入respondToAccessTokenRequest 这个办法,而respondToAccessTokenRequest 这个办法又是在league 这个库中。没错,passport的验证办法是援用league 的oauth2-server。 public function issueToken(ServerRequestInterface $request) { return $this->withErrorHandling(function () use ($request) { return $this->convertResponse( $this->server->respondToAccessTokenRequest($request, new Psr7Response) ); }); }当初咱们进去看看 vendor\league\oauth2-server\src\AuthorizationServer.php ...

November 5, 2021 · 2 min · jiezi

关于php:mac安装php扩展yaml

首先装置 libyaml$ brew install libyaml==> Downloading https://ghcr.io/v2/homebrew/core/libyaml/manifests/0.2.5######################################################################## 100.0%==> Downloading https://ghcr.io/v2/homebrew/core/libyaml/blobs/sha256:a436da33a05f805258c5951a365dec4e8d70a908dbe5dacdeb6b2ecd0efd5024==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:a436da33a05f805258c5951a365dec4e8d70a908dbe5dacdeb6b2ecd0efd5024?se=2021-11-05T09%3A00%3######################################################################## 100.0%==> Pouring libyaml--0.2.5.arm64_monterey.bottle.tar.gz /opt/homebrew/Cellar/libyaml/0.2.5: 10 files, 353KB记录一下这一步里的libyaml门路:/opt/homebrew/Cellar/libyaml/0.2.5 而后装置 yaml$ pecl install yaml.......Please provide the prefix of libyaml installation [autodetect] : 粘贴上一步失去的libyaml门路装置实现,检查一下$ php -m | grep yamlyaml

November 5, 2021 · 1 min · jiezi

关于php:昨日PHP面试回顾

流程是一次性面完,先口试,后技术1面、2面,最初hr面(到这里就根本过关了)口试考查内容比拟根底, 写的手累...还是有挺多不会的点 口试内容简述TCP协定的3次握手;浏览器每次申请是否都须要建设TCP连贯?为什么?说说HTTP缓存机制,其相干参数别离有哪些,含意是什么?形容网络数据包发送方与接受方的传输过程HTTP Code 301、302别离指的是什么?HTTP Code 401、403有什么区别?HTTP Code 502、503、504呢?PHP是否能够通过代码模仿以上HTTP CODE?若生产环境下PHP发现5xx类谬误,你如何筛查?是否剖析过Nginx的日志,如何筛选出日志中申请最多的url和ip?过程与线程有什么区别?同步、异步别离是什么?php如何实现异步工作?为什么MySQL应用B+树而不是均衡二叉树?InnoDB的索引是如何实现的?简述B+树在Linux硬盘上是如何查问的用过哪些nosql?简述缓存穿透、缓存雪崩。如何解决这些问题?并发达到5000、1W的时候,数据更新的计划是怎么的?MySQL中int与bigint有什么区别?int(10)与int(1)有什么区别?char与vachar有存储长度的下限吗?以用户表为例,举出一些应用案例。InnoDB有哪些锁的类型?表锁与行锁有什么区别?什么是死锁,如何解决?Redis有哪些数据类型,哪些类型工夫复杂度比拟高?如何实现Redis分布式锁?如何查看Redis的慢查问,多长时间算慢查问呢? (有点忘了, 大略这样MySQL查问慢时,你第一想到的是如何解决?有哪些优化SQL执行慢的办法Leecode第1题Leecode第3题你是如何解决技术上遇到的问题的?最近读过的技术书有哪些?技术面先次要介绍本人的工作、我的项目经验, 而后形容一下本人遇到过的问题,是如何解决的。起初因为切实说不出什么,变成了发问的形式。次要问到B+树特点、算法题的解决逻辑、Redis的数据类型及具体应用场景举例。而后问问主从,因为没有实际过于是跳过了。 插曲技术面问到算法题逻辑的时候,把“双指针”说成了“双链表”(并没有被指出来...用python写的算法题,而后答复本人接下来想要学习go,后果面试官竟狐疑php是不是我的主语言(笑我的回复是“因为不想写$,另外过后练习算法题的时候都是用python”简略总结回头一看,本人体现个别,题目还是较根底,数据库方面的问题还是较多。而后是惯例的本人做过的我的项目,遇到的技术难点之类的,因为人家想要理解你。所以还是要隔一段时间多对本人做总结。

November 5, 2021 · 1 min · jiezi

关于php:使用PHP获取顶级域名信息

在做 酷瓜云课堂 零碎受权相干性能的时候,须要针对顶级域名受权,所以就写了个函数,目前只是针对国内的复合域名做了解决, 其它国家的请自行裁减,简略够用就好。 /** * 获取顶级域名 * * @param string $host * @return string */function kg_top_domain($host){ $data = explode('.', $host); $count = count($data); if (preg_match('/\.(com|net|org|gov|edu)\.cn$/', $host)) { $domain = $data[$count - 3] . '.' . $data[$count - 2] . '.' . $data[$count - 1]; } else { $domain = $data[$count - 2] . '.' . $data[$count - 1]; } return $domain;}

November 5, 2021 · 1 min · jiezi

关于php:PHP的SPL扩展库五文件及设计模式

对于 SPL 来说,除了咱们之前学习到的各种 数据结构 以及 迭代器 之外,还有一类十分好用的性能就是对于文件的操作。明天咱们就来学习这方面的内容,同时,这也是 SPL 系列文章中最初要学习的内容。 文件操作对于 PHP 的文件操作来说,在默认状况下咱们都是应用面向过程的那些函数来进行操作,比方 fopen() 、 fwrite() 、 fread() 、 fgets() 这些。而 SPL 中提供的则是以面向对象的形式来进行这些文件相干的操作。 文件信息类首先咱们要学习的是 SplFileInfo 这个类。 $file = new SplFileInfo('./6.PHP的SPL扩大库(四)函数.php');实例化它的时候,就须要传递一个文件门路参数。比方这里咱们就间接关上上一篇文章的测试代码。而后,咱们的 $file 变量就会失去一个 SplFileInfo 对象,在这个对象中,有许多和文件函数相似的办法能够供咱们应用。 var_dump($file->getBasename());// string(39) "6.PHP的SPL扩大库(四)函数.php"var_dump($file->getPathname());// string(41) "./6.PHP的SPL扩大库(四)函数.php"var_dump($file->getFilename());// string(39) "6.PHP的SPL扩大库(四)函数.php"var_dump($file->getRealPath());// string(102) "/Users/zhangyue/MyDoc/博客文章/dev-blog/php/2021/01/source/6.PHP的SPL扩大库(四)函数.php"var_dump($file->getPathInfo());// object(SplFileInfo)#2 (2) {// ["pathName":"SplFileInfo":private]=>// string(1) "."// ["fileName":"SplFileInfo":private]=>// string(1) "."// }var_dump($file->getFileInfo());// object(SplFileInfo)#2 (2) {// ["pathName":"SplFileInfo":private]=>// string(41) "./6.PHP的SPL扩大库(四)函数.php"// ["fileName":"SplFileInfo":private]=>// string(39) "6.PHP的SPL扩大库(四)函数.php"// }咱们能够通过下面的这些测试代码来取得文件相干的一些门路信息。是不是和一般的那些文件操作函数十分相似,或者说是齐全一样的命名和应用形式。 var_dump($file->getExtension());// string(3) "php"var_dump($file->getType());// string(4) "file"var_dump($file->getCTime());// int(1611017967)var_dump($file->getOwner());// int(501)var_dump($file->getGroup());// int(20)var_dump($file->getSize());// int(3543)当然,文件的这些属性信息也都是能够失常获取到的,比方文件的 扩展名、类型、各种文件相干的工夫、拥有者、属组、大小 之类的信息。 ...

November 2, 2021 · 2 min · jiezi

关于php:基于-Xdebug-生成-PHP-火焰图

2012 年刚开始学习 PHP,那个时候的 PHP 利用很简略,没有太多简单的设计模式,像依赖注入,工厂模式这些还简直没有,Reflection API 那时也才刚进去,一个 PHP 利用就是一些包了前端代码的脚本文件,正是因为 PHP 的简略牢靠,学习老本极低,那几年 PHP 红极一时。你能够很疾速的看懂他人写的 PHP 代码,不论他写的到底有多烂。我那个时候刚毕业凭借对 PHP 的熟练掌握能够轻松在三四线城市拿到七八千工资,加上对过后各大框架(Tp、Ci、Yii、Cphalcon)源码钻研非常透彻,自认为曾经摸到 PHP 的天花板。前面换城市写 PHP 逐步少了很多,用的比拟多的是本人基于 Swoole 写的一套框架,得心应手。 不过当初所在的公司 PHP 占据了 90% 的份额,根本都是 Laravel/Lumen 利用,这让继续在做性能优化的我变得很难。Laravel 中应用了大量的设计模式、动静注入,很多时候只有在运行时能力晓得能晓得具体的对象实例,想要仅通过看源码确定服务运行状态有肯定的难度。所以在做性能剖析时火焰图和可视化调用栈很重要,能够十分直观精确看到各种耗时。 在 PHP 中咱们能够关注两个档次的火焰图:PHP 内核与 PHP Zend 调用栈。前者是抓取零碎调用的耗时火焰图,后者是 Zend VM 的耗时火焰图,上面就这两种火焰图生成做分享。 运行环境操作系统(Arch Linux)# neofech -` russell@T14 .o+` ----------- `ooo/ OS: Arch Linux x86_64 `+oooo: Host: NBLK-WAX9X M1040 `+oooooo: Kernel: 5.14.14-arch1-1 -+oooooo+: Uptime: 1 hour, 15 mins `/:-:++oooo+: Packages: 852 (pacman) `/++++/+++++++: Shell: zsh 5.8 `/++++++++++++++: Resolution: 1920x1080 `/+++ooooooooooooo/` DE: Plasma 5.23.2 ./ooosssso++osssssso+` WM: KWin .oossssso-````/ossssss+` WM Theme: Breeze -osssssso. :ssssssso. Theme: Breeze Light [Plasma], Breeze [GTK2/3] :osssssss/ osssso+++. Icons: Uos-fulldistro-icons [Plasma], Uos-fulldi /ossssssss/ +ssssooo/- Terminal: konsole `/ossssso+/:- -:/+osssso+- Terminal Font: Hack 10 `+sso+:-` `.-/+oso: CPU: AMD Ryzen 5 3500U with Radeon Vega Mobile G `++:. `-/+/ GPU: AMD ATI 03:00.0 Picasso .` `/ Memory: 1928MiB / 6880MiBPHP 版本# php -vPHP 7.4.23 (cli) (built: Sep 19 2021 12:07:04) ( NTS )Copyright (c) The PHP GroupZend Engine v3.4.0, Copyright (c) Zend Technologies with Xdebug v3.1.1, Copyright (c) 2002-2021, by Derick Rethans这个没啥要求,只有不是 5.6 版本以下就行。 ...

November 2, 2021 · 2 min · jiezi

关于php:PHP-Composer-自动加载

前言:这篇文章是从外国网站看到的,把composer写得很贴地,翻译回来记录下。 简介:在本教程中,您将学习如何应用 Composer 从应用 PSR-4 规范的文件主动加载 PHP 类。 应用 require_once 结构加载类首先,应用文件创建以下目录构造: .├── app│ ├── bootstrap.php│ └── models│ └── User.php└── index.php代码语言: PHP (php )在User.php该文件models夹蕴含的User 类: class User{ private $username; private $password; public function __construct($username, $password) { $this->username = $username; $this->password = password_hash($password); } public function getUsername(): string { return $this->username; }}代码语言: PHP (php )这User是一个简略的类。它有两个属性$username和$password。该构造函数初始化从它的参数属性。此外,它应用该password_hash()函数对$password. 该bootstrap.php文件应用require_once结构User从User.php文件models夹中的文件加载类: <?phprequire_once 'models/User.php';代码语言: PHP (php )当models文件夹中有更多类时,您能够require_once向bootstrap.php文件中增加更多语句以加载这些类。 该index.php文件加载bootstrap.php文件并应用User该类: <?php require './app/bootstrap.php'; $user = new User('admin', '$ecurePa$$w0rd1');代码语言: PHP (php )如果您有大量类,则此应用程序构造很无效。然而,当应用程序有大量的类时,require_once就不能很好地扩大。在这种状况下,您能够应用该spl_autoload_register()函数从文件中主动加载类。 ...

November 1, 2021 · 2 min · jiezi

关于php:PHP入门系列5PHP错误异常以及调试

可悲的是,不论咱们在写代码时如许小心,BUG始终是有的。 谬误PHP 有几个谬误严重性等级。三个最常见的的信息类型是谬误(error)、告诉(notice)和正告(warning)。它们有不同的严重性: E_ERROR 、E_NOTICE和 E_WARNING。谬误是运行期间的重大问题,通常是因为代码出错而造成,必须要修改它,否则会使 PHP 进行执行。告诉是倡议性质的信息,是因为程序代码在执行期有可能造成问题,但程序不会进行。 正告是非致命谬误,程序执行也不会因而而停止。 PHP 遇到一系列外部谬误时,会报告进去作为应答 php.ini 中 error_reporting 的配置 或者是运行时调用 error_reporting() 管制了哪些谬误须要报告,哪些谬误须要主动疏忽。 在开发环境里为了发现并修复 PHP 产生的问题, 应该总是把 error_reporting 设置为 E_ALL。 在生产环境里,用户可能为了升高信息的具体水平, 想要将它设置为相似 E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED, 但很多状况下 E_ALL 也同样实用,这样能够更早地正告潜在问题。 如果 PHP 默认谬误处理器还不能满足要求,用户能够通过 set_error_handler() 设置自定义谬误处理器,可解决很多类型的谬误。 PHP7之后大多数谬误被作为 Error 异样抛出。这种 Error 异样能够像 Exception 异样一样被第一个匹配的 try / catch 块所捕捉。如果没有匹配的 catch 块,则调用异样处理函数(当时通过 set_exception_handler() 注册)进行解决。 如果尚未注册异样处理函数,则依照传统形式解决:被报告为一个致命谬误(Fatal Error)。 异样异样是许多风行编程语言的标配.PHP外部函数次要应用错误报告,只有一些古代面向对象的扩大应用异样。不过,谬误很容易用 ErrorException 转化成异样。 然而,这个技术计划仅实用非 Fatal 级的谬误,PHP 能够完满化身为「重异样」的程序语言,只须要几行代码就能切换过来。基本上你能够利用 ErrorException 类抛出「谬误」来当做「异样」,这个类是继承自 Exception 类。 ...

October 31, 2021 · 1 min · jiezi

关于php:PHP入门系列4PHP命名空间与包管理

在古代的PHP我的项目中,OOP曾经遍及随同着生态的不断扩大,也带了我的项目的治理问题。命名空间和包治理曾经是理论我的项目中必不可少的组成。 命名空间什么是命名空间?从狭义上来说,命名空间是一种封装事物的办法。在很多中央都能够见到这种抽象概念。例如,在操作系统中目录用来将相干文件分组,对于目录中的文件来说,它就表演了命名空间的角色。具体举个例子,文件 foo.txt 能够同时在目录 /home/greg 和 /home/other 中存在,但在同一个目录中不能存在两个 foo.txt 文件。另外,在目录 /home/greg 外拜访 foo.txt 文件时,咱们必须将目录名以及目录分隔符放在文件名之前失去 /home/greg/foo.txt。这个原理利用到程序设计畛域就是命名空间的概念。 在 PHP 中,命名空间用来解决在编写类库或应用程序时创立可重用的代码如类或函数时碰到的两类问题: 用户编写的代码与PHP外部的类/函数/常量或第三方类/函数/常量之间的名字抵触。为很长的标识符名称(通常是为了缓解第一类问题而定义的)创立一个别名(或简短)的名称,进步源代码的可读性。PHP 命名空间提供了一种将相干的类、函数和常量组合到一起的路径。因而把你的代码放在你的命名空间下就十分重要,防止其余开发者放心与第三方类库抵触。 PSR-4 提供了一种命名空间的举荐应用形式,它提供一个规范的文件、类和命名空间的应用常规,进而让代码做到随插即用。如果你在新利用或扩大包中应用主动加载规范,应优先思考应用 PSR-4。 根底 命名空间通过关键字 namespace 来申明。如果一个文件中蕴含命名空间,它必须在其它所有代码之前申明命名空间,除了一个以外:declare关键字。拜访以后命名空间外部元素的办法,__NAMESPACE__ 魔术常量和 namespace 关键字。通过操作符 use 来应用namespace的类如果没有定义任何命名空间,所有的类与函数的定义都是在全局空间,与 PHP 引入命名空间概念前一样。在名称前加上前缀 \ 示意该名称是全局空间中的名称,即便该名称位于其它的命名空间中时也是如此。包治理PHP 有很多可供使用的库、框架和组件。目前 PHP 有两个应用较多的包管理系统 Composer 和 PEAR。Composer是PHP最风行的包管理器,受害于命名空间和主动加载, 通过Composer能够随时能够在你的我的项目中应用第三方优良的我的项目。Composer 有点相似于 Node.js 世界里的 NPM。 装置 能够从官网查看残缺的流程:官网地址, 国内的话你可能须要国内的减速镜像 中国全量镜像阿里云 Composer 全量镜像Composer是一个 卓越 的依赖管理器。在 composer.json 文件中列出你我的项目所需的依赖包,加上一点简略的命令,Composer 将会主动帮你下载并设置你的我的项目依赖。残缺学习能够查看 官网文档,或者国内的翻译文档 composer中文文档 composer.json设置{ "require": { "monolog/monolog": "1.0.*" }}你能够看到, require 须要一个 包名称 (例如 monolog/monolog) 映射到 包版本 (例如 1.0.*) 的对象。 ...

October 30, 2021 · 2 min · jiezi

关于php:Swoole-v481-版本发布支持忽略指定错误码的日志

v4.8.1 版本次要优化了 admin server 的代码,没有向下不兼容改变。 反对疏忽指定的错误码日志在此版本中减少了能够疏忽指定的错误码所对应的谬误日志,举个例子: const LOG_FILE = __DIR__ . '/log';if (is_file(LOG_FILE)) { unlink(LOG_FILE);}const ERRNO_1 = 888888;const ERRNO_2 = 999999;swoole_async_set(['log_file' => LOG_FILE]);swoole_error_log(SWOOLE_LOG_NOTICE, 'swoole_error_log msg');swoole_error_log_ex(SWOOLE_LOG_NOTICE, ERRNO_1, 'swoole_error_log_ex msg');// 疏忽错误码为ERRNO_2的日志swoole_ignore_error(ERRNO_2);swoole_error_log_ex(SWOOLE_LOG_NOTICE, ERRNO_2, 'swoole_error_log_ex ERRNO_2 msg');echo file_get_contents(LOG_FILE);疏忽了错误码为ERRNO_2的日志,所以查看谬误日志中没有swoole_error_log_ex ERRNO_2 msg的信息。 [2021-10-28 10:34:01 @23580.0] NOTICE swoole_error_log msg[2021-10-28 10:34:01 @23580.0] NOTICE zif_swoole_error_log_ex() (ERRNO 888888): swoole_error_log_ex msg同时也能够应用swoole_error_log_ex函数写入指定谬误等级、错误码的日志到日志文件中。 Admin Server此版本中优化了大量的 admin_server 的代码: 迁徙 ext-swoole_plus 中的 admin api 到 ext-swoole,能够应用 Swoole Dashboard 的全副性能 反对了并发申请多个指标和并发申请多个 API,详情能够查看 RFC #78新增 get_composer_packages 命令,能够查看我的项目中的 composer 依赖信息 ...

October 29, 2021 · 1 min · jiezi

关于php:laravel-passport-的-oauth2机制一-安装配置

一、Oauth21、定义:OAuth 2.0 是一种受权(authorization)机制,次要用来颁发令牌(token)。2、成员:Client(客户端)Service(验证服务器)3、流程: application(client) 申请 Service(认证服务器,可能是微信等第三方,也能够是本人的用户验证服务);Service 验证胜利返回access_token;application 带着access_token 即可操作相干需受权性能。4、oauth2受权模式 受权码模式(微信等第三方多用这个模式)简化模式明码模式(本身平台有子系统多用这个模式,下文次要讲这模式)客户端模式二、laravel passport1、装置composer require laravel/passport装置数据表php artisan migrate从compoer我的项目中服务配置文件到config下php artisan passport:install 增加 Laravel\Passport\HasApiTokens trait 到 App\User 模型 namespace App\Models;use Illuminate\Contracts\Auth\MustVerifyEmail;use Illuminate\Database\Eloquent\Factories\HasFactory;use Illuminate\Foundation\Auth\User as Authenticatable;use Illuminate\Notifications\Notifiable;use Laravel\Sanctum\HasApiTokens;class User extends Authenticatable{ use HasApiTokens, HasFactory, Notifiable;配置文件 config/auth.php 中 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ],],须要在 AuthServiceProvider 的 boot 办法中调用 Passport::routes 办法,该办法将会为颁发拜访令牌、撤销拜访令牌、客户端以及私人访问令牌注册必要的路由 ...

October 29, 2021 · 1 min · jiezi

关于php:PHP入门系列3PHP面向对象

只总结纪录本人学习的知识点,想要理解PHP自行搜寻就行了。毕竟比拟老的语言了,比拟成熟了材料也比拟多。面向对象编程(Object Oriented Programming,OOP)是一种计算机编程架构。OOP的一条根本准则是计算机程序是由单个可能起到子程序作用的单元或对象组合而成。OOP达到的软件工程的三个指标:重用性、灵活性、拓展性。PHP面向对象借鉴了JAVA,先看看根本的语法吧。 PHP 具备残缺的对象模型。个性包含: 访问控制,抽象类和 final 类与办法,附加的魔术办法,接口,对象复制。PHP 看待对象的形式与援用和句柄雷同,即每个变量都持有对象的援用,而不是整个对象的拷贝。参见 对象和援用。 根本语法面向对象编程的三大基本要素:封装、继承、多态,基本上一个文件一个类,类文件内无过程、类内只能有,办法。 每个类的定义都以关键字 class 结尾,前面跟着类名,前面跟着一对花括号,外面蕴含有类的属性与办法的定义。类的变量成员叫做“属性”,或者叫“字段”、“特色”,在本文档对立称为“属性”。属性申明是由关键字 public,protected 或者 private 结尾,而后跟一个一般的变量申明来组成。能够把在类中始终保持不变的值定义为常量。const关键字__construct PHP 容许开发者在一个类中定义一个办法作为构造函数。__destruct 析构函数会在到某个对象的所有援用都被删除或者当对象被显式销毁时执行。封装与解封 封装性就是把对象的属性和服务联合成一个独立的雷同单位,并尽可能荫蔽对象的外部细节。 一是把对象的全副属性和全副服务联合在一起,造成一个不可分割的独自单位(对象)二是信息隐蔽,尽可能的荫蔽对象的外部细节,对外造成一个边界,只保留无限的对外接口与内部产生分割对属性或办法的访问控制(PHP 7.1.0 当前反对常量),是通过在后面增加关键字 public(私有),protected(受爱护)或 private(公有)来实现的。被定义为私有的类成员能够在任何中央被拜访。 被定义为受爱护的类成员则能够被其本身以及其子类和父类拜访。被定义为公有的类成员则只能被其定义所在的类拜访。 不过利用PHP的魔术办法能够对封装的进行解封: __get()办法用来获取公有成员属性值,有一个参数,参数传入要获取的成员属性的名称,或者返回获取的属性值。__set()办法用来为公有成员属性设置值,有二个参数,第一个参数为要设置的属性名,第二个参数是要给属性的值。继承与重载 关键字extends。继承对于性能的设计和形象是十分有用的,而且对于相似的对象减少新性能就毋庸从新再写这些专用的性能。一个类只能间接从一个类中继承数据(单继承)继承是把父类的成员属性和办法复制过去。 类的重载就是定义雷同的办法名。调用父类被笼罩的办法: 一种是应用父类的“类名::”来调用父类中被笼罩的办法二种是应用“parent::”来调用父类中被笼罩的办法抽象类和接口 抽象类关键字abstract定义为形象的类不能被实例化。任何一个类,如果它外面至多有一个办法是被申明为形象的,那么这个类就必须被申明为形象的。被定义为形象的办法只是申明了其调用形式(参数),不能定义其具体的性能实现。 一个抽象类中至多有一个形象办法抽象类、形象办法前都必须应用abstract申明形象办法无大括号继承后要将所以的形象办法都要进行重载抽象类个别为了标准一个类的应用,标准子类的实现。 对象接口关键字interface接口就是一种契约。因而,在程序里,接口的办法必须被全副实现,否则将报 fetal 谬误。 接口不能被实例化只能被implements(援用)谁援用谁重载,援用后要将所有接口所有形象办法重载单继承多援用 先继承后援用接口中所有的办法都是形象的所有的成员属性都是常量成员办法后面无需应用abstract关键字所有属性和办法必须是公共的在实践中,往往出于两个辅助目标应用接口来标准我的项目的抒写: 因为实现了同一个接口,所以开发者创立的对象尽管源自不同的类,但可能能够替换应用。 罕用于多个数据库的服务拜访、多个领取网关、不同的缓存策略等。 可能不须要任何代码批改,就能切换不同的实现形式。可能让函数与办法承受一个合乎接口的参数,而不须要关怀对象如何做、如何实现。 这些接口经常命名成相似 Iterable、Cacheable、Renderable, 以便于体现出性能的含意。动态(static)关键字申明类属性或办法为动态,就能够不实例化类而间接拜访。动态属性不能通过一个类已实例化的对象来拜访(但静态方法能够)。因为静态方法不须要通过对象即可调用,所以伪变量 $this 在静态方法中不可 Final 关键字 如果父类中的办法被申明为 final,则子类无奈笼罩该办法。如果一个类被申明为 final,则不能被继承。final等于办法到此为止。 魔术办法__construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __serialize(), __unserialize(), __toString(), __invoke(), __set_state(), __clone() 和 __debugInfo() 等办法在 PHP 中被称为魔术办法(Magic methods)。在命名本人的类办法时不能应用这些办法名,除非是想应用其魔术性能。PHP 通过反射 API 和魔术办法,能够实现多种形式的元编程。 ...

October 29, 2021 · 1 min · jiezi

关于php:CloudAlibaba在nacos环境下整合dubbo

本章咱们来整合dubbo。那有了fegin为什么还要dubbo?这是本章的外围,本章不仅会讲怎么整合应用dubbo,同时也会讲dubbo和fegin的区别 fegin和dubbo怎么选首先,不谈技术的区别和具体作用,fegin和dubbo最大的区别就是:dubbo是alibaba的亲儿子 为什么要整合dubbodubbo按理来说,本人就是一个很好的微服务治理框架。既然SpringCloudAlibaba也是一套微服务治理计划,那这个时候应用dubbo是不是显得有很多的反复?其实不然。在Spring Cloud Alibaba的整合之下,Dubbo用户既能够享受到本来RPC带来性能劣势,又能够更好的享受Spring Cloud的各种福利;而对于Spring Cloud用户来说,在服务治理层面,又对了一个不错的可选项。能够说这块的整合是真正的让这两大用户群体失去了很好的交融,起到了相互成就的作用。 整合dubbo,入门案例利用Dubbo来实现服务提供方与服务生产方,这里咱们就须要创立对应的两个我的项目,一个是服务提供者,一个是服务消费者。咱们先来创立一个服务提供者。 创立一个简略的SpringBoot服务,这里SpringBoot的版本我抉择的:2.2.11.RELEASE引入整合dubbo须要的依赖1、spring-cloud-starter-dubbo2、spring-cloud-starter-alibaba-nacos-discovery我的server我的项目pom文件如下 <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.11.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.echo</groupId> <artifactId>dubbo-server</artifactId> <version>0.0.1-SNAPSHOT</version> <name>dubbo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-dubbo</artifactId> <version>2.2.1.RELEASE</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring-cloud-alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>复制代码编写对应的配置nacos的配置dubbo本人的配置 ...

October 28, 2021 · 1 min · jiezi

关于php:PHP入门系列2PHP基础语法

只总结纪录本人学习的知识点,想要理解PHP自行搜寻就行了。毕竟比拟老的语言了,比拟成熟了材料也比拟多。反对类型语法和数据类型根本与风行的语言差异不是特地大,查看详情:PHP官网文档语言参考 在PHP中,反对10种原始数据类型。 四种标量类型 bool(布尔型)int(整型)float(浮点型,也称作 double)string(字符串)四种复合类型 array(数组)object(对象)callable(可调用)iterable(可迭代)最初是两种非凡类型 resource(资源)NULL(无类型)变量一般变量 PHP 中的变量用一个$前面跟变量名来示意。变量名是辨别大小写的。标准参考PSR-1、PSR-1、PSR-12和其余强类型语言不统一的是一般变量不须要预约义,当然预约义是一个好的习惯。和大部分语言统一,能够是用 & 援用复制<?php //定义变量 $a = 'xxx'; //输入变量 echo $a;//xxx //援用赋值 $b = '123'; $c = &$b; var_dump($b === $c); // true?>零碎预约义变量 PHP 提供了一套附加的预约数组,这些数组变量蕴含了来自 web 服务器(如果可用),运行环境,和用户输出的数据。这些数组十分特地,它们在全局范畴内主动失效。 次要记住有以下变量,具体外面的内容能够参考文档: 文档详情地址 超全局变量 — 超全局变量是在全副作用域中始终可用的内置变量$GLOBALS — 援用全局作用域中可用的全副变量$_SERVER — 服务器和执行环境信息$_GET — HTTP GET 变量$_POST — HTTP POST 变量$_FILES — HTTP 文件上传变量$_REQUEST — HTTP Request 变量$_SESSION — Session 变量$_ENV — 环境变量$_COOKIE — HTTP Cookies$php_errormsg — 前一个错误信息$http_response_header — HTTP 响应头$argc — 传递给脚本的参数数目$argv — 传递给脚本的参数数组常量能够应用 const 关键字或 define() 函数两种办法来定义一个常量。 ...

October 28, 2021 · 2 min · jiezi

关于php:在-laravel-中轻松容易的输出完整的-sql-语句

guanguans/laravel-dump-sql - 在 laravel 中轻松容易的输入残缺的 sql 语句。 laravel 中查问构造方法失去的 sql 语句没有绑定条件参数,相似于select * from users where id= ?。这个扩大包可辅助你获取残缺的 sql 语句。 User::query()->where('id', 1)->dd(); // 自带办法 `dd` 的打印后果 User::query()->where('id', 1)->ddSql(); // 新增办法 `ddSql` 的打印后果 环境要求laravel || lumen >= 5.5装置$ composer require guanguans/laravel-dump-sql -vlumen 中配置(laravel 中请疏忽)将上面代码增加到 bootstrap/app.php 文件中的 Register Service Providers 局部 $app->register(\Guanguans\LaravelDumpSql\ServiceProvider::class);应用装置配置结束后数据库查问构造方法会新增以下几个办法: toRawSql() - 获取残缺的 sqldumpSql() - 打印残缺的 sqlddSql() - 打印残缺的 sql 并且退出logListenedSql() - 记录被监听到的 sqldumpListenedSql() - 打印被监听到的 sqlddListenedSql() - 打印被监听到的 sql 并且退出toRawSql() - 获取残缺的 sql$sql = User::query()->where('id', 1)->toRawSql();dd($sql);"select * from `xb_users` where `id` = 1"dumpSql() - 打印残缺的 sqlUser::query()->where('id', 1)->dumpSql();User::query()->where('id', 2)->dumpSql();"select * from `xb_users` where `id` = 1""select * from `xb_users` where `id` = 2"ddSql() - 打印残缺的 sql 并且退出User::query()->where('id', 1)->ddSql();User::query()->where('id', 2)->ddSql();"select * from `xb_users` where `id` = 1"logListenedSql() - 记录被监听到的 sqlUser::query()->where('id', 1)->logListenedSql()->first();User::query()->where('id', 2)->first();# 日志中[Laravel] [39.97ms] select * from `xb_users` where `id` = '1' limit 1 | GET: /[Laravel] [39.93ms] select * from `xb_users` where `id` = '2' limit 1 | GET: /dumpListenedSql() - 打印被监听到的 sqlUser::query()->where('id', 1)->dumpListenedSql()->first();User::query()->where('id', 2)->first();[Laravel] [39.97ms] select * from `xb_users` where `id` = '1' limit 1 | GET: /[Laravel] [39.93ms] select * from `xb_users` where `id` = '2' limit 1 | GET: /ddListenedSql() - 打印被监听到的 sql 并且退出User::query()->where('id', 1)->ddListenedSql()->first();User::query()->where('id', 2)->first();[Laravel] [39.97ms] select * from `xb_users` where `id` = '1' limit 1 | GET: /参考我的项目https://github.com/overtrue/laravel-query-logger

October 27, 2021 · 1 min · jiezi

关于php:Go-凭什么不支持三元运算符

大家好,我是煎鱼。 这是一个很多其余语言工程师转 Go 语言的工夫节点,这就不免不管一番比拟。其中一个经典的运算上的就是 “三元运算符”: 为什么 Go 语言不反对三元运算符,Go 不反对三元运算符就是设计的不好,是历史在开倒车吗? 明天就由煎鱼来和大家一起摸索为什么。 三元运算符是什么三元运算符,在典型的数学意义上,或者从解析器的角度来看,是一个须要三个参数的运算符。而咱们日常中,最常见的是二元运算符: x + yx / yx * y还有一元运算符: -a~b!c以及明天的男主角 “三元运算符”。在 C/C++ 等多种语言中,咱们能够依据条件申明和初始化变量的习惯来选择性应用三元条件运算符: int index = val > 0 ? val : -valGo 应用三元运算符想在 Go 语言里也应用三元运算符时,发现竟然没有...想要实现与下面雷同的代码段的形式仿佛只能: var index intif val > 0 {    index = val} else {    index = -val}看上去非常的冗余,不够简洁。 为什么 Go 没有三元运算符为什么 Go 没有 ?: 操作符,没有的话,官网举荐的形式是怎么样的。 通过 Go FAQ 咱们能够得悉: Go 官网就是举荐咱们应用后面提到的形式来代替,并且明确了如下态度: Go 中没有 ?: 的起因是语言的设计者看到这个操作常常被用来创立难以了解的简单表达式。在代替计划上,if-else 模式尽管较长,但无疑是更清晰的。一门语言只须要一个条件控制流构造。整体来讲,Go 语言的设计者是为了思考可读性回绝了实现三元运算符,"less is more." 也是标榜台词了。 社区争议Go 语言的一些点不同凡响,根本是大家皆知的。无论是 if err != nil,又或是本次的三元运算符,要大家用 if-else 代替: if expr {    n = trueVal} else {    n = falseVal}拥护和批准拥护因而有社区小伙伴给出了拥护,根本分为如下几类: 认为 if-else 也有以相似状况能被滥用,设计者的理由不够充沛,认为是 “借口”。认为三元运算符的 “俊俏” 问题,是开发者的编码问题,而不是语言问题。三元在各种语言中很常见,它们是失常的,Go 语言也应该要有。认为用 if-else 代替三元运算符也很麻烦,让开发者多读了 3-4 行和额定的缩进级别。批准认可这个决策的也有不少,为此给出了大量的实在工程案例。 一般来讲,咱们用三元运算符是心愿这么用: cond ? true_value : false_value你可能见过这么用: cond ? value_a + value_b : value_c * value_d还见过这样: (((cond_a ? val_one) : cond_b) ? val_two) : val_threecond_a ? (val_one : (cond_b ? (val_two : val_three)))还能嵌套三元运算符: ...

October 27, 2021 · 1 min · jiezi

关于php:PHP的SPL扩展库四函数

明天咱们持续来学习 SPL 中的内容,这篇文章的内容是比较简单的对于 SPL 中所提供的一系列函数相干的内容。其实在之前的不少文章中咱们都曾经接触过一些 SPL 中提供的函数了。这次咱们就具体地再好好学习一下。 类信息相干函数类信息相干的函数次要都是查看一些类的信息的函数,并没有什么操作类性能的函数。 类的继承、接口、个性查看首先,咱们来看一下,如果想要取得以后类实现了哪个接口,那么咱们就间接应用一个 class_implements() 就能够了。 interface A {}interface B {}class TestA implements A,B {}var_dump(class_implements(new TestA));// array(2) {// ["A"]=>// string(1) "A"// ["B"]=>// string(1) "B"// }能够看到,它返回的是一个数组,显示的就是咱们以后这个类对象所实现的接口名称。如果咱们查问的类没有实现任何接口,那么它返回的就是空的数组。 var_dump(class_implements(new stdClass()));// array(0) {// }同样,咱们还能够查看某个类对象的父类。 class C{}class TestB extends C {}var_dump(class_parents(new TestB));// array(1) {// ["C"]=>// string(1) "C"// }虽说 PHP 是单继承型的语言,但应用 class_parents() 这个函数仍然返回的是一个数组。如果类对象没有父类的话,那么也同样返回的是一个空的数组。 class TestC { use D, E;}var_dump(class_uses(new TestC));// array(2) {// ["D"]=>// string(1) "D"// ["E"]=>// string(1) "E"// }最初,咱们还能够通过 class_uses() 函数来获取到以后类对象所应用的 trait 个性信息。 ...

October 26, 2021 · 2 min · jiezi

关于php:程序员小强转行记0001

【程序员小强转行记】这是一个系列,从明天开始每日更新500到1000字左右。小强是我自己,又不是,过来很多年,很多记忆会含糊,同时这个人会退出我看到的听到的,身边的,身外的其他人的一些影子,性情,经验的事件。 心愿给处于其余行业有转行程序员想法的人,提供一个借鉴。他将是一个系列故事,同时也是一个一般码农出校门后十多年的一个摸爬滚打的缩影。 小强出身不好,家穷,穷到什么境地呢,上小学的时候,37块的学费缴不起,有过几次试图背着他爹酿的头子酒去顶学费,背到校外山墙边一放一整天,怕同学笑话,怕老师笑话,老师不让进校,教室门口站一天,放学时等同学走后,轻轻给老师说酒顶学费的事儿,老师虽好酒,可他还是毫不留情的回绝了。 所以,自小就晓得钱不好赚,钱很重要,要赚钱解脱贫苦,同时很不足安全感,对世界持深重的狐疑态度。这也就是前面所有抉择的原始动机和种子。 上大学,是一波三折上的,15岁他爹因为给他凑议价学费5000块,挑小猪卖,数个日夜不眠不休,吃喝很少,加上天气炎热,路边打盹儿,摔下悬崖了,他家的山高啊,百米千米的山,人摔下去能好么? 这成了这之后十数年一个微小的心结,一想到那张带血的百元钞,就忍不住锥心刺骨。这是债啊!生命之债,人情之债。这也就能解释他为什么要信佛去求心安,心安处就是西方极乐啊!心安了吗?且持续往下看。 高中被一个表哥,县里亲戚帮忙寻找的支贫善意单位和人士一起支助,还有他妈,进来打工赚钱了,当然还有和很多好心人,据说这孩子读书有天份,但家世很惨,不禁就起了同情心,这个据说送双鞋,那个晓得给点钱。小强是感恩的,又是寡恩的。与家世,小小年纪经验的这些关系莫大,后续会有交代。 高中,被电视台以贫困生受赞助的身份出镜上电视,对自尊的打击十分大的。成年人认为小孩尤其贫苦小孩没有自尊,前面交代这些事会产生什么影响。贫困没有自尊,没有体面。 待续…

October 26, 2021 · 1 min · jiezi

关于php:非官方即时通信-IM支持腾讯IM环信IM极光IM融云IM网易云信IM等

非官方即时通信 IM,反对腾讯IM,环信IM,极光IM,融云IM,网易云信IM等装置composer require whereof/easy-im申请日志开启\whereof\easyIm\Kernel\BaseClient::$request_log=true;案例腾讯IM$config = [ 'appId' => '5978322198', 'identifier' => 'administrator', 'secretKey' => 'nfugb53xtlhyfq2kgiriganruyoagh93it1zwysmh2tmj5tnnmuqhd2og5ofktjt',];$im = whereof\easyIm\Factory::Tencent($config);// 自定义申请(账号同步到云端)$params = [ 'Identifier' => 'easyim', 'Nick' => 'easyim', 'FaceUrl' => 'https://github.com/whereof/easy-im',];$im->request->send('im_open_login_svc/account_import', $params);环信IM$config = [ 'appKey' => '', 'clientId' => '', 'clientSecret' => '', 'orgName' => '', 'appName' => '',];$im = whereof\easyIm\Factory::Huanxin($config);// 自定义申请(账号同步到云端)$params = [ 'username' => 'easyim', 'password' => '123456', 'nickname' => 'easyim'];$im->request->send('post', 'users', $params);极光IM$config = [ 'appKey' => '', 'masterSecret' => '',];$im = whereof\easyIm\Factory::Jiguang($config);// 自定义申请(账号同步到云端)$params = [[ 'username' => 'easyim', 'password' => '123456',]];$im->request->send('post', 'v1/users/', $params);//IM REST Report V2//获取音讯$im->request->send('get', 'v2/messages?count=500&begin_time=2015-11-02 10:10:10&end_time=2015-11-02 10:10:12',[],true);融云IM$config = [ 'appKey' => '', 'appSecret' => '',];$im = whereof\easyIm\Factory::RongCloud($config);// 自定义申请(账号同步到云端)$params=[ 'userId' => 'easyim', 'name' => 'easyim',];$im->request->send('user/getToken.json', $params);网易云信IM$config = [ 'appKey' => '', 'appSecret' => '',];$im = whereof\easyIm\Factory::Yunxin($config);// 自定义申请(账号同步到云端)$params = [ 'accid' => 'easyim', 'name' => 'easyim',];$im->request->send('nimserver/user/create.action', $params);反对厂商腾讯IM环信IM极光IM融云IM网易云信IM退出咱们如果你认可咱们的开源我的项目,有趣味为 easy-im 的倒退做奉献,竭诚欢迎退出咱们一起开发欠缺。无论是报告谬误或是 Pull Request 开发,那怕是批改一个错别字也是对咱们莫大的帮忙。 ...

October 25, 2021 · 1 min · jiezi

关于php:详解-Go-团队不建议用的-unsafePointer

大家好,我是煎鱼。 大家在学习 Go 的时候,必定都学过 “Go 的指针是不反对指针运算和转换” 这个知识点。为什么呢? 首先,Go 是一门动态语言,所有的变量都必须为标量类型。不同的类型不可能进行赋值、计算等跨类型的操作。 那么指针也对应着绝对的类型,也在 Compile 的动态类型查看的范畴内。同时动态语言,也称为强类型。也就是一旦定义了,就不能再扭转它。 谬误的示例func main(){ num := 5 numPointer := &num flnum := (*float32)(numPointer) fmt.Println(flnum)}输入后果: # command-line-arguments...: cannot convert numPointer (type *int) to type *float32在示例中,咱们创立了一个 num 变量,值为 5,类型为 int,筹备干一番小事。 接下来咱们取了其对于的指针地址后,试图强制转换为 *float32,后果失败... 万能的破壁 unsafe针对刚刚的 “谬误示例”,咱们能够采纳明天的男主角 unsafe 规范库来解决。它是一个神奇的包,在官网的诠释中,有如下概述: 围绕 Go 程序内存平安及类型的操作。很可能会是不可移植的。不受 Go 1 兼容性指南的爱护。简略来讲就是,不怎么举荐你应用,因为它是 unsafe(不平安的)。 然而在非凡的场景下,应用了它,能够突破 Go 的类型和内存平安机制,让你取得眼前一亮的惊喜成果。 unsafe.Pointer为了解决这个问题,须要用到 unsafe.Pointer。它示意任意类型且可寻址的指针值,能够在不同的指针类型之间进行转换(相似 C 语言的 void * 的用处)。 其蕴含四种外围操作: 任何类型的指针值都能够转换为 Pointer。Pointer 能够转换为任何类型的指针值。uintptr 能够转换为 Pointer。Pointer 能够转换为 uintptr。在这一部分,重点看第一点、第二点。你再想想怎么批改 “谬误的例子” 让它运行起来? 批改如下: func main(){ num := 5 numPointer := &num flnum := (*float32)(unsafe.Pointer(numPointer)) fmt.Println(flnum)}输入后果: 0xc4200140b0在上述代码中,咱们小加改变。通过 unsafe.Pointer 的个性对该指针变量进行了批改,就能够实现任意类型(*T)的指针转换。 须要留神的是,这时还无奈对变量进行操作或拜访,因为不晓得该指针地址指向的货色具体是什么类型。不晓得是什么类型,又如何进行解析呢? 无奈解析也就天然无奈对其变更了。 unsafe.Offsetof在上大节中,咱们对一般的指针变量进行了批改。那么它是否能做更简单一点的事呢? type Num struct{ i string j int64}func main(){ n := Num{i: "EDDYCJY", j: 1} nPointer := unsafe.Pointer(&n) niPointer := (*string)(unsafe.Pointer(nPointer)) *niPointer = "煎鱼" njPointer := (*int64)(unsafe.Pointer(uintptr(nPointer) + unsafe.Offsetof(n.j))) *njPointer = 2 fmt.Printf("n.i: %s, n.j: %d", n.i, n.j)}输入后果: n.i: 煎鱼, n.j: 2在分析这段代码做了什么事之前,咱们须要理解构造体的一些基本概念: 构造体的成员变量在内存存储上是一段间断的内存。构造体的初始地址就是第一个成员变量的内存地址。基于构造体的成员地址去计算偏移量。就可能得出其余成员变量的内存地址。再回来看看上述代码,得出执行流程: 批改 n.i 值:i 为第一个成员变量。因而不须要进行偏移量计算,间接取出指针后转换为 Pointer,再强制转换为字符串类型的指针值即可。批改 n.j 值:j 为第二个成员变量。须要进行偏移量计算,才能够对其内存地址进行批改。在进行了偏移运算后,以后地址曾经指向第二个成员变量。接着反复转换赋值即可。细节剖析须要留神的是,这里应用了如下办法(来实现偏移计算的指标): ...

October 25, 2021 · 1 min · jiezi

关于php:一文秒懂电商系统商品模块初建分析与设计

为什么创立新专栏创立《一文秒懂》这个专栏与以往《Grace development》和我博客的集体分享文章不同,我对《一文秒懂》这个专栏的定位是一个有态度,高标准的技术专栏,而《Grace development》我依旧会讲一些咱们日常中会碰到的一些技术问题及我集体的教训分享。 前言本篇是以以往我在思否公布的三篇《电商零碎设计之商品(上中下)》汇总的一篇联合我这些年经验的升级版,在文字描述与流程图上更标准,这里也贴上以往的三篇文章链接。 电商零碎设计之商品 (上) https://segmentfault.com/a/11...电商零碎设计之商品 (中) https://segmentfault.com/a/11...电商零碎设计之商品 (下) https://segmentfault.com/a/11...商品的设计是电商零碎中占据重要位置,如何设计出高扩大,高性能的商品零碎并非一件简略的事件,我的设计是参考互联网各大佬的设计后自行钻研的,并非完全正确,但也不齐全谬误,当初我设计的这套电商零碎曾经在应用,如果在逻辑上遇到什么问题,会及时批改我对于电商零碎相干文章的设计思维局部。 根本思维见上图,咱们先解说下零碎规格与自定义规格、零碎属性与自定义属性的对于及其他们存在的意义。 SPUSPU(Standard Product Unit)标准化产品单元什么叫标准化产品单元? 摈弃标准化一词来看,产品单元?就是以一个产品为一个单位。例如你是手记销售商,你在厂家进货的时候说我要iphonex 100部型号随便规格随便,进货的时候没思考到内存或者屏幕尺寸,这个时候你就把iphonex这个商品当作一个单位。这就是产品单位。再谈标准化,只是一些人或一个人制订的这么一个规范,所以称为标准化产品单元,不要拿百度百科上的解释反驳我,我只是用更通俗易懂的形式解释一下SPU。 例如iphonex的价格也不同的中央,别离为iphonex 64g 是8888,iphonex 256g是18888。这个时候咱们不能建设2个spu去治理这2个商品。这个时候就须要用到spu的概念了。 SKUSKU(Stock Keeping Unit)库存量单元什么叫库存量单位? 字面意思来看,库存则是指的某个商品的某个规格还有多少件,这个时候就不能只针对商品了。下面的例子iphonex有2个不同规格的商品,这个时候无奈计算其每个规格的库存(创立2个商品可是不切实际,将来治理会很简单,就例如安踏的跑鞋有十几个尺码,难道要创立十几个商品吗?),此时只能针对以后商品再创立子商品,咱们叫它规格,例如iphonex有存储和色彩2个规格 有木有发现还是有点问题?那具体的存储大小与具体色彩该如何表白呢?这个时候须要创立规格的子商品,咱们称他为属性 这个每个属性的联合则就是一个新的商品,咱们称它为SKU,一个SPU对应着N个SKU 这样就生成了N个商品 iphonex 64G红色iphonex 32G彩色iphonex 256G红色 等等... 零碎规格/属性为什么要设立零碎规格属性呢? 盗用一张淘宝的图,以上都是依据分类品牌设定好的规格及属性 次要是为了不便商家增加商品及其对商品的规格属性进行对立的治理,当然一个电商零碎在后期经营的状况下尽量减少零碎属性规格的应用(不便商家入住嘛)。 自定义属性就不用说了,不让商家增加本人的规格和尺码什么的怎么能行? SPU与SKU的关联SPU对应多个SKU,SPU理论就是主商品表,相似于iphonex这款手机,而SKU则是这个商品绑定的规格表,相似与iphonex 红色款,iphonex 彩色款等。 而主表与规格表也关联了其余表 商品专辑在淘宝的逻辑中,商家可为商品增加视频和图片,可为每个sku增加图片。咱们称为专辑。将一组图片及视频相似歌手作家出专辑一样,绑定到商品表和sku表上 相干品牌每个商品都归属与一个品牌,例如iphonex归属与苹果公司,小米8归属与小米公司一样。品牌无需关联到sku内,情理很简略,以后的sku是iphonex归属与苹果公司,自然而然iphonex上面的规格都属于苹果了。 绑定类目有时品牌不仅仅归属与一个类目,还是以iphonex举例,他是一部手机又是苹果产品但他又是一个音乐播放器。留神,这个时候不要将以后品牌绑定到三个类目上,如果你这样做了,将来的可维护性会很低。应该每个类目中绑定雷同的品牌名称,你肯定会问那这样数据垃圾不就产生了吗?我没有具体数据给你展示这样做的益处。 但从业务说起,当初我须要统计每个类目下商品的购买数去做用户画像,你时你要如何辨别以后这个商品到底是哪个类目下呢?无奈辨别,因为你将品牌绑定到了3个类目下,不知用户到底是通过哪个类目点击进去购买的。 再者很多品牌公司不仅仅是做一个商品,相似索尼做mp3也做电视,手机,游戏机等。所以类目对应多个品牌,品牌应对应多个类目并非关联多个类目 链路解析商品零碎与订单零碎是相铺相成的,当买家购买商品后将经验一个过程 商品零碎->订单零碎->交易系统->订单零碎->物流零碎->售后零碎 实现上述流程则是实现了一笔交易,常常网上购物的童鞋都懂这个。明天咱们讲下从商品零碎到交易系统和订单零碎的存储过程及其设计上的应该留神的“坑”。 关联问题当初有这么一个场景 小明在某宝买了一部爱疯手机,色彩是红色,存储是32G,他抉择应用某宝领取.SKU产品色彩存储001爱疯手机红色32G002爱疯手机红色256G003爱疯手机彩色32G004爱疯手机彩色256G小明抉择购买SKU=001的产品,失常状况下订单表应该与此SKU编码相关联来维持数据一致性。像这样 订单号用户SKUSN110小明001这种设计有个弊病,商品的名称及价格都不是固定,如果商户批改了商品的题目或者其余的属性,那小明过后买的爱疯手机是8000元,后果过了几年提价了商户批改了价格,后果小明的购买清单里也变成了批改后的价格,所以说这种仅仅关联的设计是不可取的(至多在电商零碎中不可取)。 订单号用户SKU商品题目商品价格商品封面图商品其余属性SN110小明001爱疯手机8000iphone.png其余属性像上表中设计,有人会问了 “那关联的意义何在呢?” 我的答复是 “保持数据关联” ,尽管商户有可能扭转商品属性,但应该尽可能的记录用户所有的动作。 多商户电商理论在电商零碎设计上,个人感觉不应辨别多商户的电商与单用户的电商(至多开发者不应辨别他们),但后期设计上就应把多商户概念带入到零碎内。哪怕只有一个官网专卖店呢?! 波及到多商户就须要思考用户对立下单问题了。 ...

October 24, 2021 · 1 min · jiezi

关于php:一文秒懂电商系统商品模块初建分析与设计

为什么创立新专栏创立《一文秒懂》这个专栏与以往《Grace development》和我博客的集体分享文章不同,我对《一文秒懂》这个专栏的定位是一个有态度,高标准的技术专栏,而《Grace development》我依旧会讲一些咱们日常中会碰到的一些技术问题及我集体的教训分享。 前言本篇是以以往我在思否公布的三篇《电商零碎设计之商品(上中下)》汇总的一篇联合我这些年经验的升级版,在文字描述与流程图上更标准,这里也贴上以往的三篇文章链接。 电商零碎设计之商品 (上) https://segmentfault.com/a/11...电商零碎设计之商品 (中) https://segmentfault.com/a/11...电商零碎设计之商品 (下) https://segmentfault.com/a/11...商品的设计是电商零碎中占据重要位置,如何设计出高扩大,高性能的商品零碎并非一件简略的事件,我的设计是参考互联网各大佬的设计后自行钻研的,并非完全正确,但也不齐全谬误,当初我设计的这套电商零碎曾经在应用,如果在逻辑上遇到什么问题,会及时批改我对于电商零碎相干文章的设计思维局部。 根本思维见上图,咱们先解说下零碎规格与自定义规格、零碎属性与自定义属性的对于及其他们存在的意义。 SPUSPU(Standard Product Unit)标准化产品单元什么叫标准化产品单元? 摈弃标准化一词来看,产品单元?就是以一个产品为一个单位。例如你是手记销售商,你在厂家进货的时候说我要iphonex 100部型号随便规格随便,进货的时候没思考到内存或者屏幕尺寸,这个时候你就把iphonex这个商品当作一个单位。这就是产品单位。再谈标准化,只是一些人或一个人制订的这么一个规范,所以称为标准化产品单元,不要拿百度百科上的解释反驳我,我只是用更通俗易懂的形式解释一下SPU。 例如iphonex的价格也不同的中央,别离为iphonex 64g 是8888,iphonex 256g是18888。这个时候咱们不能建设2个spu去治理这2个商品。这个时候就须要用到spu的概念了。 SKUSKU(Stock Keeping Unit)库存量单元什么叫库存量单位? 字面意思来看,库存则是指的某个商品的某个规格还有多少件,这个时候就不能只针对商品了。下面的例子iphonex有2个不同规格的商品,这个时候无奈计算其每个规格的库存(创立2个商品可是不切实际,将来治理会很简单,就例如安踏的跑鞋有十几个尺码,难道要创立十几个商品吗?),此时只能针对以后商品再创立子商品,咱们叫它规格,例如iphonex有存储和色彩2个规格 有木有发现还是有点问题?那具体的存储大小与具体色彩该如何表白呢?这个时候须要创立规格的子商品,咱们称他为属性 这个每个属性的联合则就是一个新的商品,咱们称它为SKU,一个SPU对应着N个SKU 这样就生成了N个商品 iphonex 64G红色iphonex 32G彩色iphonex 256G红色 等等... 零碎规格/属性为什么要设立零碎规格属性呢? 盗用一张淘宝的图,以上都是依据分类品牌设定好的规格及属性 次要是为了不便商家增加商品及其对商品的规格属性进行对立的治理,当然一个电商零碎在后期经营的状况下尽量减少零碎属性规格的应用(不便商家入住嘛)。 自定义属性就不用说了,不让商家增加本人的规格和尺码什么的怎么能行? SPU与SKU的关联SPU对应多个SKU,SPU理论就是主商品表,相似于iphonex这款手机,而SKU则是这个商品绑定的规格表,相似与iphonex 红色款,iphonex 彩色款等。 而主表与规格表也关联了其余表 商品专辑在淘宝的逻辑中,商家可为商品增加视频和图片,可为每个sku增加图片。咱们称为专辑。将一组图片及视频相似歌手作家出专辑一样,绑定到商品表和sku表上 相干品牌每个商品都归属与一个品牌,例如iphonex归属与苹果公司,小米8归属与小米公司一样。品牌无需关联到sku内,情理很简略,以后的sku是iphonex归属与苹果公司,自然而然iphonex上面的规格都属于苹果了。 绑定类目有时品牌不仅仅归属与一个类目,还是以iphonex举例,他是一部手机又是苹果产品但他又是一个音乐播放器。留神,这个时候不要将以后品牌绑定到三个类目上,如果你这样做了,将来的可维护性会很低。应该每个类目中绑定雷同的品牌名称,你肯定会问那这样数据垃圾不就产生了吗?我没有具体数据给你展示这样做的益处。 但从业务说起,当初我须要统计每个类目下商品的购买数去做用户画像,你时你要如何辨别以后这个商品到底是哪个类目下呢?无奈辨别,因为你将品牌绑定到了3个类目下,不知用户到底是通过哪个类目点击进去购买的。 再者很多品牌公司不仅仅是做一个商品,相似索尼做mp3也做电视,手机,游戏机等。所以类目对应多个品牌,品牌应对应多个类目并非关联多个类目 链路解析商品零碎与订单零碎是相铺相成的,当买家购买商品后将经验一个过程 商品零碎->订单零碎->交易系统->订单零碎->物流零碎->售后零碎 实现上述流程则是实现了一笔交易,常常网上购物的童鞋都懂这个。明天咱们讲下从商品零碎到交易系统和订单零碎的存储过程及其设计上的应该留神的“坑”。 关联问题当初有这么一个场景 小明在某宝买了一部爱疯手机,色彩是红色,存储是32G,他抉择应用某宝领取.SKU产品色彩存储001爱疯手机红色32G002爱疯手机红色256G003爱疯手机彩色32G004爱疯手机彩色256G小明抉择购买SKU=001的产品,失常状况下订单表应该与此SKU编码相关联来维持数据一致性。像这样 订单号用户SKUSN110小明001这种设计有个弊病,商品的名称及价格都不是固定,如果商户批改了商品的题目或者其余的属性,那小明过后买的爱疯手机是8000元,后果过了几年提价了商户批改了价格,后果小明的购买清单里也变成了批改后的价格,所以说这种仅仅关联的设计是不可取的(至多在电商零碎中不可取)。 订单号用户SKU商品题目商品价格商品封面图商品其余属性SN110小明001爱疯手机8000iphone.png其余属性像上表中设计,有人会问了 “那关联的意义何在呢?” 我的答复是 “保持数据关联” ,尽管商户有可能扭转商品属性,但应该尽可能的记录用户所有的动作。 多商户电商理论在电商零碎设计上,个人感觉不应辨别多商户的电商与单用户的电商(至多开发者不应辨别他们),但后期设计上就应把多商户概念带入到零碎内。哪怕只有一个官网专卖店呢?! 波及到多商户就须要思考用户对立下单问题了。 ...

October 24, 2021 · 1 min · jiezi

关于php:Laravel8学习笔记日志组件

配置配置文件 config/logging.php默认状况下,Laravel 应用 stack 通道来记录日志信息,stack 通道被用于聚合多个日志通道到单个通道。 例:single通道默认写入larave.log文件,daily通道默认写入larave-*.log文件,若配置stack如下 'stack' => [ 'driver' => 'stack', 'channels' => ['single','daily'],]则日志会同时写入larave.log和larave-*.log文件 日志级别LOG_LEVEL=debug 日志信息被通道记录所必须达到的最低「级别」emergency、alert、critical、error、warning、 notice、info 和 debug 假如LOG_LEVEL=error,则Log::debug('An informational message.');不会记录日志 写入日志信息Log::emergency($error);Log::alert($error);Log::critical($error);Log::error($error);Log::warning($error);Log::notice($error);Log::info($error);Log::debug($error);写入上下文信息Log::info('User failed to login.', ['id' => 123]);//local.INFO: User failed to login. {"id":123} 写入指定通道'test' => [ 'driver' => 'single', 'path' => storage_path('logs/laravel.log'),],Log::channel('test')->info('Something happened!');通道自定义'single' => [ 'driver' => 'single', 'tap' => [App\Logging\CustomizeFormatter::class], 'path' => storage_path('logs/laravel.log'), 'level' => 'debug',],注:所有「tap」类都通过服务容器解析,所以他们须要的所有构造函数依赖都会被主动注入。<?phpnamespace App\Logging;use Monolog\Formatter\LineFormatter;class CustomizeFormatter{ /** * Customize the given logger instance. * * @param \Illuminate\Log\Logger $logger * @return void */ public function __invoke($logger) { foreach ($logger->getHandlers() as $handler) { $handler->setFormatter(new LineFormatter( '[%datetime%] %channel%.%level_name%: %message% %context% %extra%' )); } }}

October 22, 2021 · 1 min · jiezi

关于php:laravel8-console调度示例

<?phpnamespace App\Console;use Illuminate\Console\Scheduling\Schedule;use Illuminate\Foundation\Console\Kernel as ConsoleKernel;use Illuminate\Support\Facades\Log;class Kernel extends ConsoleKernel{ /** * The Artisan commands provided by your application. * * @var array */ protected $commands = [ \App\Console\Commands\EsInit::class, \App\Console\Commands\EnterpriseStatus::class, \App\Console\Commands\ExportExcel::class, \App\Console\Commands\OldData::class, \App\Console\Commands\DeleteRemoved::class,//将自定义注入到console中 ]; /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { $schedule->command('es:init')->dailyAt('1:00'); $schedule->command('enterprise:status')->dailyAt('2:00'); $schedule->command('delete:removed')->sundays();//每周日执行一次 } /** * Register the commands for the application. * * @return void */ protected function commands() { $this->load(__DIR__ . '/Commands'); require base_path('routes/console.php'); }}<?phpnamespace App\Console\Commands;use App\Models\Product\KnowledgeDict;use App\Models\Product\LibraryCheckList;use App\Models\Product\LibraryCheckSystem;use App\Models\Product\LibraryQuestionList;use App\Models\Product\LibraryQuestionSystem;use App\Models\Product\LibrarySection;use App\Models\Product\Notice;use Illuminate\Console\Command;class DeleteRemoved extends Command{ /** * The name and signature of the console command. * * @var string */ protected $signature = 'delete:removed'; /** * The console command description. * * @var string */ protected $description = 'remove field data'; protected $removeClass = [ KnowledgeDict::class, LibraryQuestionList::class, LibraryQuestionSystem::class, LibraryCheckList::class, LibraryCheckSystem::class, LibrarySection::class, Notice::class, ]; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return int */ public function deleteRemoved() { if ($this->removeClass) { foreach ($this->removeClass as $value) { $model = new $value; $model::where('isRemoved', 1)->delete(); } } return true; } public function handle() { $this->deleteRemoved(); }}

October 21, 2021 · 1 min · jiezi

关于php:Go-开发时要了解的-1-个内存模型细节

大家好,我是煎鱼。 在日常工作中,如果咱们可能理解 Go 语言内存模型,那会带来十分大的作用。这样在看一些极其状况,又或是变态面试题的时候,就可能明确程序运行体现下的很多根本原因了。 当然,靠一篇一般文章讲完 Go 内存模型,不可能。因而明天这篇文章,把重点划在给大家解说 Go 语言的 happens-before 准则这 1 个细节。 开吸,和煎鱼揭开他的神秘面纱! 内存模型定义是什么既然要理解 happens-before 准则,咱们得先晓得 The Go Memory Model(Go 内存模型)定义的是什么,官网解释如下: The Go memory model specifies the conditions under which reads of a variable in one goroutine can be guaranteed to observe values produced by writes to the same variable in a different goroutine.在 Go 内存模型规定:“在一个 goroutine 中读取一个变量时,能够保障察看到不同 goroutine 中对同一变量的写入所产生的值” 的条件。 这是学习后续常识的一个大前提。 happens-before 是什么Happens Before 是一个专业术语,与 Go 语言没有间接关系,也就是并非是特有的。用大白话来讲,其定义是: ...

October 21, 2021 · 2 min · jiezi

关于php:PHP的opensslencrypt的补充说明

在PHP(PHP 5 >= 5.3.0, PHP 7, PHP 8)中,openssl_encrypt的参数大抵如下: openssl_encrypt( string $data, string $cipher_algo, string $passphrase, int $options = 0, string $iv = "", string &$tag = null, string $aad = "", int $tag_length = 16): string|false其中$data待加密的数据字符串,这很好了解,这里不做过多阐释。 $cipher_algo为加密算法,如AES-128-ECB,两头这个数字示意密钥长度为128位。所有加密算法可通过openssl_get_cipher_methods取得。$passphrase为密钥。既然下面的算法都规定了密钥长度,那这个密钥的字符串长度就曾经确定下来了。但PHP随性的一点是如果密钥小于或超过算法指定的长度,也都能失常返回加密后果,而不像Java等语言间接抛出密钥长度不正确的异样。依据手册解释: 若 passphrase 比预期长度短,将静默用 NUL 填充; 若比预期长度更长,将静默截断。那么NUL在PHP中体现又是什么?查了PHP源代码下的openssl实现,找到如下代码: if (key_len > password_len) { if ((OPENSSL_DONT_ZERO_PAD_KEY & options) && !EVP_CIPHER_CTX_set_key_length(cipher_ctx, password_len)) { php_openssl_store_errors(); php_error_docref(NULL, E_WARNING, "Key length cannot be set for the cipher algorithm"); return FAILURE; } key = emalloc(key_len); memset(key, 0, key_len); memcpy(key, *ppassword, password_len); *ppassword = (char *) key; *ppassword_len = key_len; *free_password = 1;}memset(key, 0, key_len); 应该对应的就是ASCII中的零,也就是PHP里的chr(0)。所以如果一个密钥长度不够,PHP会主动在密钥前面用chr(0)有余。例如:AES-128-ECB算法,密钥长度应为128位,也就是字符串长度为16。这时如果密钥为"1234567890abcde"和"1234567890abcde".chr(0)的意义是一样的,失去的加密后果也是一样的。至于超出长度主动截断,这应该很好了解了。 ...

October 21, 2021 · 1 min · jiezi

关于php:分享开发商城系统系统过程中遇到的问题处理

发表评论把文本框做双向数据绑定<textarea placeholder="请输出内容" maxlength="120" v-model="msg"></textarea>data中 msg: “” // 评论 输出的内容 为发表按钮绑定一个事件<mt-button type="primary" size="large" @click="postComment">发表评论</mt-button> 校验评论内容是否为空,如果为空,则Toast提醒用户 评论内容不能为空main.js中Vue.http.options.root上面写 //应用ajax的post形式时,第三个参数个别都是一样的,所以每次都重写,还不如全局定义一下,就省略这个反复写的过程。// 全局设置 post 时候表单数据格式组织模式 application/x-www-form-urlencodedVue.http.options.emulateJSON = true;通过 vue-resource 发送一个申请,把评论内容提交给 服务器当发表评论OK后,从新刷新列表,以查看最新的评论如果调用 getComments 办法从新刷新评论列表的话,可能只能失去 最初一页的评论,前几页的评论获取不到换一种思路: 当评论胜利后,在客户端,手动拼接出一个 最新的评论对象,而后 调用 数组的 unshift 办法, 把最新的评论,追加到 data 中 comments 的结尾;这样,就能 完满实现刷新评论列表的需要;想要开发的商城零碎开发零碎我的项目征询v:kjwenlc,心愿能帮到您! postComment() { // 校验是否为空内容 trim() 办法去除字符串的头尾空格: if (this.msg.trim().length === 0) { return Toast("评论内容不能为空!"); } // 发表评论 // 参数1: 申请的URL地址 // 参数2: 提交给服务器的数据对象 { content: this.msg } // 参数3: 定义提交时候,表单中数据的格局 { emulateJSON:true } this.$http .post("api/postcomment/" + this.$route.params.id, { content: this.msg.trim() }) .then(function(result) { if (result.body.status === 0) { // 1. 拼接出一个评论对象 var cmt = { user_name: "匿名用户", add_time: Date.now(), content: this.msg.trim() }; this.comments.unshift(cmt); this.msg = ""; } });} }革新图片剖析 按钮为 路由的链接并显示对应的组件页面 ...

October 20, 2021 · 1 min · jiezi

关于php:PHP的SPL扩展库三迭代器

对于迭代器,咱们在之前设计模式相干的文章中曾经讲过迭代器具体是个啥,而且也应用过 SPL 的例子来演示过,要是没有看过之前的文章的能够穿梭回去看一下哦!PHP设计模式之迭代器模式:https://mp.weixin.qq.com/s/uycac0OXYYjAG1BlzTUjsw。 因而,对于迭代器的概念,咱们这里就不会多说了,明天的次要内容就是来理解一下 SPL 扩大中都蕴含哪些迭代器以及它们的性能成果。另外,上一篇文章中咱们接触过的数组迭代器 ArrayIterator 因为曾经学习过了,也就不放在这里讲了。此外还有文件目录相干的迭代器,也会放在和其相干的文件目录操作的文章中解说,包含上面学习的这些迭代器还有不少都有绝对应的 递归式 的迭代器,比方咱们上面要讲到的 CachingIterator 、 FilterIterator 等等,都有它们对应的 RecursiveCachingIterator 、 RecursiveFilterIterator 类,这个大家就本人去钻研下吧,带递归迭代器,也就是多了两个办法 getChildren() 和 hasChildren() 而已,最初咱们还会实现一个本人的迭代器类,其中就会讲到递归这块。 IteratorIterator 包装迭代器首先咱们来看一下什么是包装迭代器。它自身也是个迭代器,然而在实例化的时候,又必须给他再传递进来一个迭代器并保留在外部,是一个外部迭代器 InnerIterator 。对于它本身的那些迭代器接口函数来说,其实都是转发调用的那个外部迭代器相干的操作函数。感觉上其实就有点像是一个装璜器模式,咱们能够通过继承 IteratorIterator 来实现对原有迭代器性能的降级。 $iterator = new IteratorIterator(new ArrayIterator([1, 2, 3]));$iterator->rewind();while ($iterator->valid()) { echo $iterator->key(), ": ", $iterator->current(), PHP_EOL; $iterator->next();}// 0: 1// 1: 2// 2: 3从代码中能够看出,它的结构参数必须还得是一个迭代器,自身的参数签名就是须要一个实现了 Traversable 接口的对象。Traversable 接口是所有迭代器所必须要实现的接口。 class OutIterator extends IteratorIterator{ public function rewind() { echo __METHOD__, PHP_EOL; return parent::rewind(); } public function valid() { echo __METHOD__, PHP_EOL; return parent::valid(); } public function current() { echo __METHOD__, PHP_EOL; return parent::current() . '_suffix'; } public function key() { echo __METHOD__, PHP_EOL; return parent::key(); } public function next() { echo __METHOD__, PHP_EOL; return parent::next(); } public function getInnerIterator() { echo __METHOD__, PHP_EOL; return parent::getInnerIterator(); }}$iterator = new OutIterator(new ArrayIterator([1, 2, 3]));foreach ($iterator as $k => $v) { echo $k, ': ', $v, PHP_EOL;}// OutIterator::rewind// OutIterator::valid// OutIterator::current// OutIterator::key// 0: 1_suffix// OutIterator::next// OutIterator::valid// OutIterator::current// OutIterator::key// 1: 2_suffix// OutIterator::next// OutIterator::valid// OutIterator::current// OutIterator::key// 2: 3_suffix// OutIterator::next// OutIterator::valid咱们本人写了一个 OutIterator 类并继承自 IteratorIterator 类,而后重写所有迭代器相干的办法函数。在这些函数中,减少一些输入调试信息,最初通过 foreach 来遍历迭代器。能够看出,foreach 在判断对象是否可迭代后,就会像咱们应用 while 遍历迭代器一样地去调用对应的迭代器办法函数。这个例子相当地直观,也十分有助于咱们了解迭代器这堆办法函数到底在干嘛。 ...

October 19, 2021 · 5 min · jiezi

关于php:PHP实现关注公众号登陆网站功能

要求必须公众号曾经认证原理通过生成带参数二维码+随机字符串存入库中而后用户扫描关注后,微信推送音讯中带 随机字符串,与库中相比实现登录 只贴外围代码 生成二维码推送 <?php include('./curl.php'); include('./file.php'); $appid = "APPID"; $secret = "SECRET"; $get_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$secret}";//获取access_token的url //获取token过程开始 $token = curl_get($get_token_url); $token = json_decode($token,true); $token = $token['access_token']; //获取token过程完结 $get_code_url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token={$token}";//获取ticket的url $string = createToken(24);//随机字符串 $get_code_url_parmeter = array( 'expire_seconds'=>2592000,//二维码有效期 2592000是30天 'action_name'=>'QR_STR_SCENE',//微信推送音讯时的参数类型,QR_STR_SCENE为字符串 'action_info'=>array( 'scene'=>array( 'scene_str'=>$string,//微信随送音讯时的参数。 ) ) ); //模拟器数据库存入开始 $logininfo_array = array('string'=>$string,'islogin'=>0); writeArrayToFile($logininfo_array,"logininfo.txt"); //模拟器数据库存入完结 //获取ticket开始 $get_code_url_parmeter = json_encode($get_code_url_parmeter); $qrcode = curl_post($get_code_url,$get_code_url_parmeter); $ticket = json_decode($qrcode,true); $ticket = $ticket['ticket']; //获取ticket完结 $qrcodeimg = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket={$ticket}"; echo $qrcodeimg; //向前端返回二维码链接 function createToken($long){//创立随机字符串 long参数为字符串长度 $char = '1234567890ABCDEFGHIGHLMNOPQRSTUVWXYZ'; $token = ''; for ($i = 0; $i <= $long; $i++) { $token.= $char[rand(0, strlen($char) - 1) ]; } return $token; } ?>//接管微信推送音讯 ...

October 18, 2021 · 1 min · jiezi

关于php:Laravel-管道机制

一、背景有简单的业务,性能是程序层层递进,而且每层业务重用率也高的状况下,如果依照传统所有货色都写在一个办法,无论是代码可读性,还是解耦都是比拟差的。如果这时有个管道,这个管道能够随便新增、批改就能实现一个新性能就好了。讲到管道机制,比拟经典案例就是中间件了,也能够aop(Aspect Oriented Programming 切面编程),又能够称洋葱模式。 二、代码模仿层层递进的各项业务 class ALogic{ public static function handle($data, $next) { print "开始 A 逻辑"; $ret = $next($data+1); print "完结 A 逻辑"; return $ret; }}class BLogic{ public static function handle($data, $next) { print "开始 B 逻辑"; $ret = $next($data+1); print "完结 B 逻辑"; return $ret; }}class CLogic{ public static function handle($data, $next) { print "开始 C 逻辑"; //$data = $data+1; $ret = $next($data+1); print "完结 C 逻辑"; return $ret; }}组装成一整块 ...

October 15, 2021 · 1 min · jiezi

关于php:Laravel-反射机制

一、背景在laravel中,无论是路由,还是privoder都能够实现主动递归实例化。其实现的原理就是用php的反射,PHP相干反射文档:reference 二、文字表述1、依据classname实例化反射类 new ReflectionClass($classname);2、取得$classname构造函数(如果$classname有构造函数就获取结构函数参数,如果没有就间接 new $classname获取实例);3、依据结构函数参数,判断是否为class类型,如果是class类型,持续递归,获取其所属class类型,如果不是class类型,就用返回默认值;4、依据结构函数参数,获取去参数依赖(dependencies),而后$reflect->newInstanceArgs(dependencies),取得$classname的实例; 三、模仿实现laravel代码这里只是把外围大略模仿进去,实在的laravel比此代码简单,性能多得多foo.php <?phpnamespace ABC;use ABC\F\Baz;include 'F/baz.php';class Bar{}class Foo{ public $bar; public $baz; public function __construct(Bar $bar,Baz $baz){ $this->bar = $bar; $this->baz = $baz; }}F/baz.php <?phpnamespace ABC\F;class Baz{}run.php <?phpnamespace ABC;include 'foo.php';class Run{ public function build($class){ $reflect = new \ReflectionClass($class); //php反射 //判断$class 这个类是否能实例化,即非abstract、interface if(!$reflect->isInstantiable()){ throw new \Exception('不能实例化'); } //获取类构造函数 $constructor = $reflect->getConstructor(); //如果没有构造函数间接new if(is_null($constructor)){ return new $class; } //获取$class构造函数中的参数 $params = $constructor->getParameters(); //获取参数及其依赖 $dependencies = $this->getDependenes($params); //从给出的参数创立一个$class类实例 return $reflect->newInstanceArgs($dependencies); } public function getDependenes($params){ $dependenes = []; //循环构造函数中的参数 foreach($params as $param){ //取得参数所属类 $dependency = $param->getClass(); //如果参数不是class类型,返回默认值 if(is_null($dependency)){ $dependenes[]= $this->resloveNonClass($param); }else{ //如果参数是class类型,递归build,获取参数实例 $dependenes[] = $this->build($dependency->name); } } return $dependenes; } public function resloveNonClass($param){ if($param->isDefaultValueAvailable()){ return $param->getDefaultValue(); } throw new \Exception('不能没有默认值');//实在的laravel是有相应的解决 }}$class = 'ABC\Foo';$run = new Run();$object = $run->build($class);var_dump($object);//object(Foo){object(ABC/Bar),object(ABC/F/Baz)}

October 15, 2021 · 1 min · jiezi

关于php:Swoole-v480-版本发布增加-Swoole-Dashboard-面板

间隔上个版本v4.7.1公布近两个月了,v4.8.0 版本终于公布了。 此版本蕴含了新性能、BUG 修复以及向下不兼容的改变。 不兼容改变在 base 模式下,onStart 回调将始终在第一个工作过程 (worker id 为 0) 启动时回调,先于 onWorkerStart 执行。在 onStart 函数中始终能够应用协程 API,Worker-0 呈现致命谬误重启时,会再次回调 onStart 在之前的版本中,onStart 在只有一个工作过程时,会在 Worker-0 中回调。有多个工作过程时,在 Manager 过程中执行。 admin_server在此版本中重要的性能就是减少了admin_server的选项,用于提供 API 服务,能够用于在 Swoole Dashboard 面板中查看以后服务的信息,例如 PHP 加载的扩大、文件、类、函数、常量,以及 Swoole 相干的过程、协程、连贯信息等。 //创立Server对象,监听 127.0.0.1:9501 端口$server = new Swoole\Server('127.0.0.1', 9501);$server->set([ 'admin_server' => '0.0.0.0:9502', // 启用 admin_server 服务 'worker_num' => 2, 'task_worker_num' => 3]);//监听连贯进入事件$server->on('Connect', function ($server, $fd) { echo "Client: Connect.\n";});//监听数据接管事件$server->on('Receive', function ($server, $fd, $reactor_id, $data) { $server->send($fd, "Server: {$data}");});//监听连贯敞开事件$server->on('Close', function ($server, $fd) { echo "Client: Close.\n";});//启动服务器$server->start();能够在更新 Swoole v4.8.0 版本后,返回 https://dashboard.swoole.com/ 进行体验。 ...

October 14, 2021 · 2 min · jiezi

关于php:Laravel-静态绑定与容器原理

一、PHP中的动态绑定 “前期绑定”的意思是说,static:: 不再被解析为定义以后办法所在的类,而是在理论运行时计算的。也能够称之为“动态绑定”,因为它能够用于(但不限于)静态方法的调用。<?phpclass A { public static function who() { echo __CLASS__; } public static function test() { static::who(); // 前期动态绑定从这里开始 }}class B extends A { public static function who() { echo __CLASS__; }}B::test();//后果是 B?>说白了就是哪个类调用静态方法,该动态方法就属于哪个类上面。 二、Laravel中的动态绑定laravel中用app() 能够实例化一个容器进去,而后这个容器是繁多的,在外面操作laravel各种provider、event、等。代码跟踪看看其容器实现的原理;先看app() 这个办法,helpers.php是入口文件中曾经加载到框架外面;\vendor\laravel\framework\src\Illuminate\Foundation\helpers.php function app($abstract = null, array $parameters = []) { if (is_null($abstract)) { return Container::getInstance(); } return Container::getInstance()->make($abstract, $parameters); }从下面代码看到次要是运行Container这个类的getInstance这个静态方法。 那咱们从入口文件public/index.php跟踪,看下哪里有setInstance, $app = require_once __DIR__.'/../bootstrap/app.php';bootstrap/app.php //实例化一个容器,这里就是LARAVEL的外围,用这个一直调用laravl外部$app = new Illuminate\Foundation\Application( $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__));\vendor\laravel\framework\src\Illuminate\Foundation\Application.php先看继承关系 ...

October 14, 2021 · 1 min · jiezi

关于php:群里又吵起来了Go-是传值还是传引用

大家好,我是煎鱼。 前几天在咱们的 Go 交换群里,有一个小伙伴问了 “xxx 是不是援用类型?” 这个问题,引发了将近 5 小时的探讨: 兜兜转转回到了日经的问题,简直每个月都要有人因而吵一架。就是 Go 语言到底是传值(值传递),还是传援用(援用传递)? Go 官网的定义本局部援用 Go 官网 FAQ 的 “When are function parameters passed by value?”,内容如下。 如同 C 系列的所有语言一样,Go 语言中的所有货色都是以值传递的。也就是说,一个函数总是失去一个被传递的货色的正本,就像有一个赋值语句将值赋给参数一样。 例如: 向一个函数传递一个 int 值,就会失去 int 的正本。而传递一个指针值就会失去指针的正本,但不会失去它所指向的数据。map 和 slice 的行为相似于指针:它们是蕴含指向底层 map 或 slice 数据的指针的描述符。 复制一个 map 或 slice 值并不会复制它所指向的数据。复制一个接口值会复制存储在接口值中的货色。如果接口值持有一个构造,复制接口值就会复制该构造。如果接口值持有一个指针,复制接口值会复制该指针,但同样不会复制它所指向的数据。划重点,Go 语言中一切都是值传递,没有援用传递。不要间接把其余概念硬套上来,会犯先入为主的谬误的。 传值和传援用传值传值,也叫做值传递(pass by value)。其指的是在调用函数时将理论参数复制一份传递到函数中,这样在函数中如果对参数进行批改,将不会影响到理论参数。 简略来讲,值传递,所传递的是该参数的正本,是复制了一份的,实质上不能认为是一个货色,指向的不是一个内存地址。 案例一如下: func main() { s := "脑子进煎鱼了" fmt.Printf("main 内存地址:%p\n", &s) hello(&s)}func hello(s *string) { fmt.Printf("hello 内存地址:%p\n", &s)}输入后果: ...

October 13, 2021 · 2 min · jiezi

关于php:详解-Go-空结构体的-3-种使用场景

大家好,我是煎鱼。 在 Go 语言中,有一个比拟非凡的类型,常常会有刚接触 Go 的小伙伴问到,又或是不了解。 他就是 Go 里的空构造体(struct)的应用,经常会有看到有人应用: ch := make(chan struct{})还清一色的应用构造体,也不必其余类型。高度常见,也就不是一个偶发景象了,必定是背地必然有什么起因。 明天煎鱼这篇文章带大家理解一下为什么要这么用,知其然知其所以然。 一起欢快地开始吸鱼之路。 为什么应用说白了,就是心愿节俭空间。但,新问题又来了,为什么不能用其余的类型来做? 这就波及到在 Go 语言中 ”宽度“ 的概念,宽度形容了一个类型的实例所占用的存储空间的字节数。 宽度是一个类型的属性。在 Go 语言中的每个值都有一个类型,值的宽度由其类型定义,并且总是 8 bits 的倍数。 在 Go 语言中咱们能够借助 unsafe.Sizeof 办法,来获取: // Sizeof takes an expression x of any type and returns the size in bytes// of a hypothetical variable v as if v was declared via var v = x.// The size does not include any memory possibly referenced by x.// For instance, if x is a slice, Sizeof returns the size of the slice// descriptor, not the size of the memory referenced by the slice.// The return value of Sizeof is a Go constant.func Sizeof(x ArbitraryType) uintptr该办法可能失去值的宽度,自然而然也就能晓得其类型对应的宽度是多少了。 ...

October 12, 2021 · 2 min · jiezi

关于php:pflag-更好的PHP命令行选项解析库

php-toolkit/pflag 是一个PHP编写的,通用的命令行标记(选项和参数)解析库。 Github 仓库: php-toolkit/pflag性能阐明通用的命令行选项和参数解析器反对设置值数据类型(int,string,bool,array),将主动格式化输出值反对为选项/参数设置默认值反对为一个选项设置多个短名称反对从环境变量读取标记值反对设置选项/参数为必须的(required)反对设置验证器以查看输出值反对主动渲染丑陋的帮忙信息。命令行选项: 选项以 - 或者 -- 结尾的,且首字符必须是字母以 -- 结尾的为长选项. eg: --long --long value以 - 结尾的为短选项 -s -a value反对定义数组选项 eg: --tag php --tag go 将会失去 $tag = [php, go]命令行参数: 不能满足选项的都认作参数反对绑定命名参数反对定义数组参数装置composer 装置 composer require toolkit/pflagFlags 应用Flags - 是一个命令行标记(选项和参数)解析器和管理器。 示例代码请参见 example/flags-demo.php创立解析器创立和初始化解析器 use Toolkit\PFlag\Flags;require dirname(__DIR__) . '/test/bootstrap.php';$flags = $_SERVER['argv'];// NOTICE: must shift first element.$scriptFile = array_shift($flags);$fs = Flags::new();// (可选的)能够增加一些自定义设置$fs->setScriptFile($scriptFile);/** @see Flags::$settings */$fs->setSettings([ 'descNlOnOptLen' => 26]);// ...定义选项定义选项 - 定义好反对的选项设置,解析时将会依据定义来解析输出 增加选项定义的示例: use Toolkit\PFlag\Flag\Option;use Toolkit\PFlag\FlagType;use Toolkit\PFlag\Validator\EnumValidator;// add options// - quick add$fs->addOpt('age', 'a', 'this is a int option', FlagType::INT);// - 应用字符串规定疾速增加选项定义$fs->addOptByRule('name,n', 'string;this is a string option;true');// -- 一次增加多个选项$fs->addOptsByRules([ 'tag,t' => 'strings;array option, allow set multi times', 'f' => 'bool;this is an bool option',]);// - 应用数组定义/** @see Flags::DEFINE_ITEM for array rule */$fs->addOptByRule('name-is-very-lang', [ 'type' => FlagType::STRING, 'desc' => 'option name is to lang, desc will print on newline', 'shorts' => ['d','e','f'], // TIP: add validator limit input value. 'validator' => EnumValidator::new(['one', 'two', 'three']),]);// - 应用 Option 对象$opt = Option::new('str1', "this is string option, \ndesc has multi line, \nhaha...");$opt->setDefault('defVal');$fs->addOption($opt);定义参数定义参数 - 定义好反对的选项设置,解析时将会依据定义来解析输出 ...

October 11, 2021 · 4 min · jiezi

关于php:国外交友网站开发源码-第十二篇

最近因为工作生存的事件比拟多,所以就没有更新,这篇是国外交友网站开发源码 第十二篇心愿大家可能喜爱。如果有什么问题须要征询的,能够加我的扣236-0248-666 私信列表 class WechatController extends SiteController { public function __construct() { parent::__construct (); if(!$this->uinfo){ redirect(U("Public/index")); exit; } $this->assign('nav', 'Wechat'); } public function sixin(){//私信列表 $myuid = $this->uinfo["id"]; $user_count = M("User_count")->where("uid=".$myuid)->find(); $message = M("Message"); //->cache('ltlist',30) /*$list= M()->table("(select * from __MESSAGE__ order by msgid desc) as tb")->field("msgid,content,fromuid,touid,isread,sendtime,hash,sum(if(isread=0,'1','0')) as count")->where("fromuid =".$myuid." or touid=".$myuid)->group("hash")->order('msgid desc')->select();*/ $where = "fromuid =".$myuid." or touid=".$myuid; $count = $message ->where($where) -> count(); $Page = new \Think\Page($count, 15); $show = $Page -> show(); //$list = $message->distinct(true)->field("hash")->where($where)->order('msgid desc')->limit($Page -> firstRow . ',' . $Page -> listRows)->select(); $list = $message->field("max(msgid)as mid,msgid,hash,fromuid,touid")->where($where)->group("hash")->order('mid desc')->limit($Page -> firstRow . ',' . $Page -> listRows)->select(); foreach($list as $key =>$val){ $arr[]=$val['fromuid']; $arr[]=$val['touid']; $arr2[]=$val["mid"]; } $arr = array_unique($arr); $arrstr = implode($arr,','); $arrstr2 = implode($arr2,','); if($arrstr) $userarr = M("Users")->field("id,idmd5,avatar,user_nicename,user_rank")->where("id in (".$arrstr.")")->select(); if($arrstr2) $list2 = $message->field("content,msgid,sendtime,is_zh,fromuid,touid,isread,type")->where("msgid in (".$arrstr2.")")->select(); foreach($userarr as $key =>$val){ unset($userarr[$key]); $userarr[$val['id']]=$val; } foreach($list2 as $key =>$val){ unset($list2[$key]); $list3[$val['msgid']]=$val; } foreach($list as $key =>$val){ $list[$key]['list2arr']=$list3[$val['mid']]; if($val['fromuid']==$myuid){ $list[$key]['avatar']=$userarr[$val['touid']]['avatar']; $list[$key]['user_nicename']=$userarr[$val['touid']]['user_nicename']; $list[$key]['user_rank']=$userarr[$val['touid']]['user_rank']; $list[$key]['uid']=$userarr[$val['touid']]['idmd5']; }else{ $list[$key]['avatar']=$userarr[$val['fromuid']]['avatar']; $list[$key]['user_nicename']=$userarr[$val['fromuid']]['user_nicename']; $list[$key]['user_rank']=$userarr[$val['fromuid']]['user_rank']; $list[$key]['uid']=$userarr[$val['fromuid']]['idmd5']; } if($list[$key]['list2arr']['isread']==0 && $list[$key]['list2arr']['fromuid']!=$myuid){ $list[$key]['list2arr']['noread']=1; } if($list[$key]['list2arr']['is_zh']==1 && $list[$key]['list2arr']['fromuid']==$myuid){ unset($list[$key]); } } $media=$this->getMedia('私信'); cookie('wdsxnum',0,3600); $this->assign('media', $media); $this->assign('list', $list); $this->assign('nav2', 'sixin_a'); $this->assign('user_count', $user_count); $this->assign ( 'page', $show ); if($_GET['p']>=200)exit; if (I("get.ajax") == 1){ if($list) $data = $this->sitefetch('ajax_sixin_a'); $this->ajaxReturn($data); } $this->siteDisplay ( 'sixin_a' ); }关注 ...

October 9, 2021 · 3 min · jiezi

关于php:常见排序算法PHP的实现

冒泡排序比拟相邻的元素。如果第一个比第二个大,就替换他们两个。对每一对相邻元素作同样的工作,从开始第一对到结尾的最初一对。这步做完后,最初的元素会是最大的数。针对所有的元素反复以上的步骤,除了最初一个function bubbleSort($arr){ for($i=0;$i<count($arr);$i++) { for($j=$i+1;$j<count($arr); $j++) { if ($arr[$j] > $arr[$i]) { $arr[$j] = $arr[$j] + $arr[$i]; $arr[$i] = $arr[$j] - $arr[$i]; $arr[$j] = $arr[$j] - $arr[$i]; } } } return $arr;}疾速排序从数列中挑出一个元素,作为基准;从新排序数列,所有元素比基准值小的摆放在基准后面,所有元素比基准值大的摆在基准的前面(雷同的数能够到任一边)。在这个分区退出之后,该基准就处于数列的两头地位。递归地把小于基准值元素的子数列和大于基准值元素的子数列排序;function quickSort($arr){ $arrLength = count($arr); if ($arrLength <= 1) { return $arr; } $divider = $arr[0]; // 获取两头值 $left = []; $right = []; for ($i=1; $i<$arrLength; $i++) { if ($divider < $arr[$i]) { $right[] = $arr[$i]; // 小于两头值的放左边 } else { $left[] = $arr[$i]; // 大于两头值的放右边 } } // 递归排好另外两侧 $left = quickSort($left); $right = quickSort($right); return array_merge($left, [$divider], $right);}抉择排序 ...

October 9, 2021 · 1 min · jiezi

关于php:基于-hprosehprosephp-开发的Laravel扩展whereoflaravelhprose

基于 hprose/hprose-php 开发的Laravel扩大:whereof/laravel-hprose装置composer require whereof/laravel-hprose配置文件<?phpreturn [ //rpc 服务 'server' => [ // hprose 调试模式 'debug' => true, //监听地址 'tcp_uris' => [ 'tcp://0.0.0.0:1314', ], //注册rpc 服务 目录地址 'route_path' => glob(base_path("rpc") . '/*.php'), // 通过路由查看注册的办法 'http' => [ // 如果设置false 在控制台显示调用办法,否在在路由显示调用办法 'enable' => false, //如果设置了true 这里就是路由前缀 'route_prefix' => 'rpc' ], ], //rpc 客户端 'client' => [ // 服务端监听地址 'tcp_uris' => [ 'tcp://127.0.0.1:1314', ], //是否异步 'async' => false ],];日志记录 /config/logging.php'channels' => [ ............ 'hprose' => [ 'driver' => 'daily', 'path' => storage_path('logs/hprose.log'), 'days' => 14, ],]非强制配置,不配置,就会走默认的日志记录laravel配置//在 `config/app.php` 注册 HproseServiceProvider 'providers' => [ ..... \whereof\laravel\hprose\HproseServiceProvider::class]php artisan vendor:publish --provider="whereof\laravel\hprose\HproseServiceProvider"Lumen配置将配置信息放在/config/hprose.php/bootstrap/app.php$app->register(\whereof\laravel\hprose\HproseServiceProvider::class);/路由注册 rpc/demo.php<?phpuse whereof\laravel\hprose\Facades\HproseRoute;// 注册callbackHproseRoute::add(function () { return 'service hello';}, 'hello');// 注册classHproseRoute::add(\whereof\laravel\hprose\Services\UserServer::class);//注册中间价HproseRoute::addInvokeHandler(function ($name, array &$args, stdClass $context, Closure $next) { \whereof\laravel\hprose\Support\LaravelHelper::log('调用的近程函数/办法名:' . $name, 'debug', $args); $result = $next($name, $args, $context); return $result;});服务端 办法注入,类注入以及目录下类注入<?phpuse whereof\laravel\hprose\Facades\HproseRoute;// 注册callbackHproseRoute::add(function () { return 'service hello';}, 'hello');// 注册classHproseRoute::add(\whereof\laravel\hprose\Services\UserServer::class);//注册中间价HproseRoute::addInvokeHandler(function ($name, array &$args, stdClass $context, Closure $next) { \whereof\laravel\hprose\Support\LaravelHelper::log('调用的近程函数/办法名:' . $name, 'debug', $args); $result = $next($name, $args, $context); return $result;});// 注册整个目录HproseRoute::addPath(app_path('Services'));应用addPath的时候要留神:在类中构造方法__construct 参数不能是必传参数.启动rpc服务php artisan hprose:socket客户端调用$uris =['tcp://127.0.0.1:1314'];$client = new \whereof\laravel\hprose\Clients\SocketClient($uris, false);$client->hello()$client->whereof_hprose_demoService->kan()须要配置配置'client' => [ 'tcp_uris' => [ 'tcp://127.0.0.1:1314', ], 'async' => false],app('hprose.socket.client')->hello()

October 6, 2021 · 1 min · jiezi

关于php:禅道集成PhpSpreadsheet

背景PHPEXCEL停更很久,无奈反对最新的Offce版本,因而宽泛的采纳phpSpreadsheet来作为excel的导出计划,github地址https://github.com/PHPOffice/PhpSpreadsheet,文档地址https://phpspreadsheet.readthedocs.io/en/latest/ 环境PHP 7.2.34Apache httpd 2.4Mysql5.7.33禅道开源版15.4装置SDK1、装置 ComposerWindows 环境:请拜访 Composer 官网 下载安装包并进行装置,地址https://getcomposer.org/downl...。' Linux环境:请运行一下代码 curl -sS [https://getcomposer.org/installer](https://getcomposer.org/installer) | phpsudo mv composer.phar /usr/local/bin/composer2、获取SDK文件在禅道的www目录下,新建一个excel目录,命令行切到www/excel目录下,运行一下命令 composer require phpoffice/phpspreadsheet运行胜利后,会生成一个vendor的文件夹以及若干文件 禅道短信类编写在module目录下,新建一个excel文件夹,其中依照禅道构造,新建一个lang文件夹和lang文件,以及model文件 1、zh-cn.php临时无内容,有须要再增加 2、model.php<?phprequire_once '../../www/excel/vendor/autoload.php';use PhpOffice\PhpSpreadsheet\Helper\Sample;use PhpOffice\PhpSpreadsheet\IOFactory;use PhpOffice\PhpSpreadsheet\Spreadsheet;use PhpOffice\PhpSpreadsheet\Style;class excelModel extends model{ function export($name,$title,$data) { // Create new Spreadsheet object $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); //设置列宽度(这个能够做一个数组配置成输出参数,这里偷懒了) $sheet->getColumnDimension('A')->setWidth(10); $sheet->getColumnDimension('B')->setWidth(10); $sheet->getColumnDimension('C')->setWidth(10); $sheet->getColumnDimension('D')->setWidth(10); $sheet->getColumnDimension('E')->setWidth(10); $sheet->getColumnDimension('F')->setWidth(10); $sheet->getColumnDimension('G')->setWidth(10); $sheet->getColumnDimension('H')->setWidth(10); $sheet->getColumnDimension('I')->setWidth(10); $sheet->getColumnDimension('J')->setWidth(12); $sheet->getColumnDimension('K')->setWidth(12); $sheet->getColumnDimension('L')->setWidth(10); $sheet->getColumnDimension('M')->setWidth(10); $sheet->getColumnDimension('N')->setWidth(15); $sheet->getColumnDimension('O')->setWidth(10); $sheet->getColumnDimension('P')->setWidth(10); $sheet->getColumnDimension('Q')->setWidth(18); $sheet->getColumnDimension('R')->setWidth(10); $sheet->getColumnDimension('S')->setWidth(18); //左对齐 $styleArray1 = [ 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_LEFT, ], ]; $sheet->getStyle('G')->applyFromArray($styleArray1); //右对齐 $styleArray2 = [ 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_RIGHT, ], ]; $sheet->getStyle('I')->applyFromArray($styleArray2); //单元格线框 $styleArray3 = [ 'borders' => [ 'outline' => [ 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN, 'color' => ['argb' => '0000000'], ], ], ]; // 办法二,应用 setCellValue //表头 //设置单元格内容 $titCol = 'A'; foreach ($title as $key => $value) { // 单元格内容写入 $sheet->setCellValue($titCol . '1', $value); //设置线框 $sheet->getStyle($titCol . '1')->applyFromArray($styleArray3); //设置背景 $sheet->getStyle($titCol . '1')->getFont()->setBold(true); $titCol++; } $row = 2; // 从第二行开始 foreach ($data as $item) { $dataCol = 'A'; foreach ($item as $value) { // 单元格内容写入 $sheet->setCellValue($dataCol . $row, $value); //设置线框 $sheet->getStyle($dataCol . $row)->applyFromArray($styleArray3); $dataCol++; } $row++; } // Redirect output to a client’s web browser (Xlsx) header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); header('Content-Disposition: attachment;filename="'.$name.'"'); header('Cache-Control: max-age=0'); // If you're serving to IE 9, then the following may be needed header('Cache-Control: max-age=1'); // If you're serving to IE over SSL, then the following may be needed header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified header('Cache-Control: cache, must-revalidate'); // HTTP/1.1 header('Pragma: public'); // HTTP/1.0 $writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); $writer->save('php://output'); exit; } }应用禅道短信类在任意的control文件里$this->loadModel('excel'); ...

October 3, 2021 · 2 min · jiezi

关于php:PHP的SPL扩展库一数据结构

SPL 库也叫做 PHP 规范库,次要就是用于解决典型问题的一组接口或类的汇合。这些典型问题包含什么呢?比方咱们明天要讲的数据结构,还有一些设计模式的实现,就像咱们之前讲过的观察者模式相干的接口在 SPL 库中都有提供。话说回来,在 PHP 中,因为语言的特点,其实很多数据结构都和咱们用 C 语言实现的略有不同,比如说链表,因为没有构造的概念,所以咱们个别会应用类来代表链表的结点。除了这个之外,要手写链表还须要链表的增、删、改、查等操作,而 SPL 库中其实曾经帮咱们提供了一个双向链表的实现,并且还能够在这个链表的根底上间接实现栈和队列的操作。 双向链表在 SPL 库中,双向链表只须要实例化一个 SplDoublyLinkedList 类就能够了,而后咱们就能够对这个实例化之后的双向链表对象进行各种操作。 $dll = new SplDoublyLinkedList();var_dump($dll->isEmpty()); // bool(true)$dll->push(200);$dll->push(300);$dll->unshift("五号");$dll->add(2, "六号");var_dump($dll->isEmpty()); // bool(false)var_dump($dll);// object(SplDoublyLinkedList)#1 (2) {// ["flags":"SplDoublyLinkedList":private]=>// int(0)// ["dllist":"SplDoublyLinkedList":private]=>// array(4) {// [0]=>// string(6) "五号"// [1]=>// int(200)// [2]=>// string(6) "六号"// [3]=>// int(300)// }// }从代码中能够看出,push() 、 unshift() 、add() 办法都是向链表中增加数据,而 isEmpty() 则用于判断链表是否为空。间接打印显示链表的内容,能够看到链表的外部是一个数组数据。 var_dump($dll->top()); // int(300)var_dump($dll->bottom()); // string(6) "五号"var_dump($dll->pop()); // int(300)var_dump($dll->shift()); // string(6) "五号"var_dump($dll->serialize()); // string(25) "i:0;:i:200;:s:6:"六号";"var_dump($dll->count()); // int(2)top() 和 bottom() 别离获取的是链表的顶部和底部的数据。而 pop() 和 shift() 则是别离从底部和顶部弹出数据。前面咱们会看到,依据设置的不同,它他们也会遵循应用栈还是队列的形式来弹出数据。 ...

September 30, 2021 · 5 min · jiezi

关于php:PHP中的FFmpeg安装及使用

本文和大家分享PHP中的FFmeg装置及应用,心愿能帮忙到大家 FFmpeg简介FFmpeg是视频解决最罕用的开源软件。它功能强大,用处宽泛,大量用于视频网站和商业软件(比方 Youtube 和 iTunes),也是许多音频和视频格式的规范编码/解码实现。对于FFMPEG视音频编解码的常识能够参考大神雷霄骅的系列教程https://blog.csdn.net/leixiao... FFmpeg装置下载fmmpeg代码git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg 装置依赖库文件次要装置三个:yasm ,sdl1.2 和 sdl2.0 装置 yasmsudo apt-get install yasm 装置sdl1.2sudo apt-get install libsdl1.2-dev 装置 sdl2.0sudo apt-get install libstl2-dev 编译装置FFmpeg进入到解压之后的 ffmpeg文件夹,顺次执行以下命令: ./configuremakesudo make install测试装置胜利与否输出以下命令查看输入: linux下 FFmpeg 命令介绍FFmpeg 罕用的命令行参数如下。 -c:指定编码器-c copy:间接复制,不通过从新编码(这样比拟快)-c:v:指定视频编码器-c:a:指定音频编码器-i:指定输出文件-an:去除音频流-vn: 去除视频流-preset:指定输入的视频品质,会影响文件的生成速度,有以下几个可用的值 ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow。-y:不通过确认,输入时间接笼罩同名文件。常见命令查看文件信息查看视频文件的元信息,比方编码格局和比特率,能够只应用-i参数。$ ffmpeg -i input.mp4 拆散视频音频流ffmpeg -i input_file -vcodec copy -an output_file_video //拆散视频流ffmpeg -i input_file -acodec copy -vn output_file_audio //拆散音频流视频转码转换编码格局(transcoding)指的是, 将视频文件从一种编码转成另一种编码。比方转成 H.264 编码,个别应用编码器libx264,所以只需指定输入文件的视频编码器即可。$ ffmpeg -i [input.file] -c:v libx264 output.mp4 ...

September 28, 2021 · 2 min · jiezi

关于php:深入理解Go从0到1实现一个validator

validator是咱们平时业务中用的十分宽泛的框架组件,很多web框架、微服务框架都有集成。通常用来做一些申请参数的校验以防止写出反复的测验逻辑。接下来的文章中,咱们就去看看如何去实现一个validator。 初体验实际是第一生产力,我先提供一个场景,当初咱们有一个接口,作用是填写用户信息,须要咱们保留入库。咱们该怎么做呢? 首先,咱们先定义一个构造体,规定用户信息的几个参数: type ValidateStruct struct { Name string `json:"name"` Address string `json:"address"` Email string `json:"email"`}用户传进来数据,咱们须要校验能力入库,例如Name是必填的,Email是非法的这些等等,那咱们要怎么去实现它?能够是这样: func validateEmail(email string) error { //do something return nil}func validateV1(req ValidateStruct) error{ if len(req.Name) > 0 { if len(req.Address) > 0 { if len(req.Email) > 0 { if err := validateEmail(req.Email); err != nil { return err } }else { return errors.New("Email is required") } } else { return errors.New("Address is required") } } else { return errors.New("Name is required") } return nil}也能够是这样: ...

September 27, 2021 · 3 min · jiezi

关于php:Workerman的使用

Workerman是什么? Workerman是一款纯PHP开发的开源高性能的PHP socket 服务框架。Workerman不是反复造轮子,它不是一个MVC框架,而是一个更底层更通用的socket服务框架,你能够用它开发tcp代理、梯子代理、做游戏服务器、邮件服务器、ftp服务器、甚至开发一个php版本的redis、php版本的数据库、php版本的nginx、php版本的php-fpm等等。Workerman能够说是PHP畛域的一次翻新,让开发者彻底解脱了PHP只能做WEB的解放。实际上Workerman相似一个PHP版本的nginx,外围也是多过程+Epoll+非阻塞IO。Workerman每个过程能维持上万并发连贯。因为自身常住内存,不依赖Apache、nginx、php-fpm这些容器,领有超高的性能。同时反对TCP、UDP、UNIXSOCKET,反对长连贯,反对Websocket、HTTP、WSS、HTTPS等通信协定以及各种自定义协定。领有定时器、异步socket客户端、异步Mysql、异步Redis、异步Http、异步音讯队列等泛滥高性能组件。 Workerman的一些利用方向Workerman不同于传统MVC框架,Workerman不仅能够用于Web开发,同时还有更广大的应用领域,例如即时通讯类、物联网、游戏、服务治理、其它服务器或者中间件,这无疑大大提高了PHP开发者的视线。目前这些畛域的PHP开发者奇缺,如果想在PHP畛域有本人的技术劣势,不满足于每天的增删改查工作,或者想向架构师方向或者技术大牛的方向倒退,Workerman都是十分值得学习的框架。倡议开发者不仅会用,而且能基于Workerman开发出属于本人的开源我的项目,晋升技能减少本人的影响力,比方Beanbun多过程网络爬虫框架就是一个很好的例子,刚刚上线不久就取得泛滥好评。Workerman的一些利用方向如下:1、即时通讯类例如网页即时聊天、即时消息推送、微信小程序、手机app音讯推送、PC软件音讯推送等等[示例 workerman-chat聊天室 、 web音讯推送 、 小蝌蚪聊天室]2、物联网类例如Workerman与打印机通信、与单片机通信、智能手环、智能家居、共享单车等等。[客户案例如 易联云、易泊时代等]3、游戏服务器类例如棋牌游戏、MMORPG游戏等等。[示例 browserquest-php]4、HTTP服务例如 写高性能HTTP接口、高性能网站。如果想要做HTTP相干的服务或者站点强烈推荐 webman5、SOA服务化利用Workerman将现有业务不同性能单元封装起来,以服务的模式对外提供对立的接口,达到零碎松耦合、易保护、高可用、易伸缩。[示例 workerman-json-rpc、 workerman-thrift]6、其它服务器软件例如 GatewayWorker,PHPSocket.IO,http代理,sock5代理,分布式通信组件,分布式变量共享组件,音讯队列、DNS服务器、WebServer、CDN服务器、FTP服务器等等7、中间件例如异步MySQL组件,异步redis组件,异步http组件,异步音讯队列组件,异步dns组件,文件监控组件,还有很多第三方开发的组件框架等等显然传统的mvc框架很难实现以上的性能,所以也就是workerman诞生的起因。 上面应用workerman建设websocket连贯,实现一个简略的聊天事例。 下载workerman源码包在start.php中引入源码,将源码包vendor目录放在与start.php同级目录 start.php 代码如下:<?phprequire_once 'vendor/autoload.php';use Workerman\Worker;/** 多端口,多协定 */// 应用websocket协定$ws_worker = new Worker("websocket://0.0.0.0:10086");// 启动过程对外服务。如果过程启动后建设一个外部通信端口,则过程数必须为1$ws_worker->count = 1;// 连贯事件,阻断非法连贯$ws_worker->onConnect = function ($connection) use ($domains){};// 过程启动后建设一个外部通信端口$ws_worker->onWorkerStart = function ($ws_worker){$inner_text_worker = new Worker("Text://0.0.0.0:10087"); $inner_text_worker->onMessage = function ($connection, $buffer) use ($ws_worker) { $data = json_decode($buffer, true); $id = $data['id']; // 通过workerman向id的页面推送数据 $ret = sendMessageById($id, $buffer); // 返回推送后果 $connection->send($ret ? 'ok' : 'fail');}; $inner_text_worker->listen(); $inner_text_worker = new Worker("http://0.0.0.0:10087"); $inner_text_worker->onMessage = function ($http) use ($ws_worker) { ...

September 24, 2021 · 2 min · jiezi

关于php:Go-并发读写-syncmap-的强大之处

大家好,我是煎鱼。 在之前的 《为什么 Go map 和 slice 是非线程平安的?》 文章中,咱们探讨了 Go 语言的 map 和 slice 非线程平安的问题,基于此引申出了 map 的两种目前在业界应用的最多的并发反对的模式。 别离是: 原生 map + 互斥锁或读写锁 mutex。规范库 sync.Map(Go1.9及当前)。有了抉择,总是有抉择艰难症的,这两种到底怎么选,谁的性能更加的好?我有一个敌人说 规范库 sync.Map 性能菜的很,不要用。我到底听谁的... 明天煎鱼就带你揭秘 Go sync.map,咱们先会理解分明什么场景下,Go map 的多种类型怎么用,谁的性能最好! 接着依据各 map 性能剖析的后果,针对性的对 sync.map 进行源码解剖,理解 WHY。 一起欢快地开始吸鱼之路。 sync.Map 劣势在 Go 官网文档中明确指出 Map 类型的一些倡议: 多个 goroutine 的并发应用是平安的,不须要额定的锁定或协调控制。大多数代码应该应用原生的 map,而不是独自的锁定或协调控制,以取得更好的类型安全性和维护性。同时 Map 类型,还针对以下场景进行了性能优化: 当一个给定的键的条目只被写入一次但被屡次读取时。例如在仅会增长的缓存中,就会有这种业务场景。当多个 goroutines 读取、写入和笼罩不相干的键汇合的条目时。这两种状况与 Go map 搭配独自的 Mutex 或 RWMutex 相比拟,应用 Map 类型能够大大减少锁的抢夺。 性能测试听官网文档介绍了一堆益处后,他并没有讲到毛病,所说的性能优化后的劣势又是否真实可信。咱们一起来验证一下。 首先咱们定义根本的数据结构: // 代表互斥锁type FooMap struct { sync.Mutex data map[int]int}// 代表读写锁type BarRwMap struct { sync.RWMutex data map[int]int}var fooMap *FooMapvar barRwMap *BarRwMapvar syncMap *sync.Map// 初始化根本数据结构func init() { fooMap = &FooMap{data: make(map[int]int, 100)} barRwMap = &BarRwMap{data: make(map[int]int, 100)} syncMap = &sync.Map{}}在配套办法上,常见的增删改查动作咱们都编写了相应的办法。用于后续的压测(只展现局部代码): func builtinRwMapStore(k, v int) { barRwMap.Lock() defer barRwMap.Unlock() barRwMap.data[k] = v}func builtinRwMapLookup(k int) int { barRwMap.RLock() defer barRwMap.RUnlock() if v, ok := barRwMap.data[k]; !ok {  return -1 } else {  return v }}func builtinRwMapDelete(k int) { barRwMap.Lock() defer barRwMap.Unlock() if _, ok := barRwMap.data[k]; !ok {  return } else {  delete(barRwMap.data, k) }}其余的类型办法根本相似,思考反复篇幅问题因而就不在此展现了。 压测办法根本代码如下: func BenchmarkBuiltinRwMapDeleteParalell(b *testing.B) { b.RunParallel(func(pb *testing.PB) {  r := rand.New(rand.NewSource(time.Now().Unix()))  for pb.Next() {   k := r.Intn(100000000)   builtinRwMapDelete(k)  } })}这块次要就是增删改查的代码和压测办法的筹备,压测代码间接复用的是大白大佬的 go19-examples/benchmark-for-map 我的项目。 ...

September 24, 2021 · 2 min · jiezi

关于php:在MAC上利用Docker镜像搭建PHP52开发环境

背景随着MAC操作系统和各种软件的一直降级,在零碎上搭建APACHE2.4+PHP5.2的环境变得异样艰难,笔者尝试过通过brew install php@5.6的环境,并利用brew-php-swithcer或者brew link php 5.6来和PHP7做切换,但理论应用中,PHP5依赖一些软件包,比方openssl比拟老,导致呈现各种问题,并不能很好的解决在一个电脑上,运行两套PHP开发环境的需要。基于此,笔者只能另辟蹊径,通过Dokcer来解决这个问题。 运行环境macOS Big Sur v11.1docker3.1(能够通过brew install docker装置,也能够通过官网下载img装置)步骤1、官网查找一下php能够应用的镜像(他人做好上传的),间接搜比方php5.2之类的 2、笔者找的是flandera/php5.2-apache这个,自带apache,因为不足文档,把镜像拉下来,跑一下进去看看 进去后,钻研下构造,后果如下: apache的conf文件目录在/etc/conf/apache2/apache2.conf,此外这个conf文件include了一个空的httpd.conf文件网站根目录在/var/www下 3、解决思路 编制一个dockerfile文件,将httpd.conf文件打包成新的镜像将程序通过docker命令映射到容器中 4、编制conf文件 Alias /webapp "/var/webapp/www"<Directory "/var/webapp/www"> Options None AllowOverride None Order allow,deny Allow from all</Directory>5、编制dockerfile(参考,名称和目录依据理论批改) FROM flandera/php5.2-apache:latestLABEL maintainer="author" EXPOSE 80RUN mkdir -p /var/webappCOPY httpd.conf /etc/apache2/httpd.conf6、从新编译并运行 docker build -t company-php:5.2 .docker run -d -p 9987:80 -v /Users/divsun/webapp:/var/webapp --name=php company-php:5.2执行命令时候,httpd.conf须要和Dockerfile在同一个目录,如果conf文件有改变,须要从新打包 5、mac电脑打http://localhost:9987/webapp看是不是失常了

September 24, 2021 · 1 min · jiezi

关于php:Apizza-快速导入Chrome请求

平时在调试网站的时候,会利用控制台->网络查看具体的网络申请    然而想调试下具体申请的接口比拟麻烦,须要一个字段一个字段复制过来,可能还有header复制。   Apizza 能够十分不便的间接导入chrome的申请,以下是如何操作 1. 关上控制台 2. 点击 Copy as fetch 并关上 【导入Chrome申请】 3. 点击导入即可   导入之后,就能够间接点击发送,就会申请接口了,也能够批改参数申请,十分不便

September 24, 2021 · 1 min · jiezi

关于php:使用-PHP-管理营业时间

对于几个不同的客户,咱们须要在他们的网站上显示凋谢工夫的时间表。他们还想在您拜访该网站的那一刻显示百货公司/商店/...是否凋谢。我的共事Seb将凋谢工夫四周的所有性能提取到新公布的opening-hours包中。 您创立了一个OpeningHours形容企业营业时间的对象。它能够查问open或closed日期或特定日期,或用于显示每天的工夫。 通过传入惯例时间表和例外列表来创立一组凋谢工夫。 $openingHours = OpeningHours::create([ 'monday' => ['09:00-12:00', '13:00-18:00'], 'tuesday' => ['09:00-12:00', '13:00-18:00'], 'wednesday' => ['09:00-12:00'], 'thursday' => ['09:00-12:00', '13:00-18:00'], 'friday' => ['09:00-12:00', '13:00-20:00'], 'saturday' => ['09:00-12:00', '13:00-16:00'], 'sunday' => [], 'exceptions' => [ '2016-11-11' => ['09:00-12:00'], '2016-12-25' => [], ],]);该对象能够查问一周中的一天,它会依据惯例时间表返回后果: // Open on Mondays:$openingHours->isOpenOn('monday'); // true// Closed on Sundays:$openingHours->isOpenOn('sunday'); // false也能够查问特定的日期和工夫: // Closed because it's after hours:$openingHours->isOpenAt(new DateTime('2016-09-26 19:00:00')); // false// Closed because Christmas was set as an exception$openingHours->isOpenAt(new DateTime('2016-12-25')); // false它还能够返回一周或一天的凋谢工夫数组: ...

September 23, 2021 · 1 min · jiezi

关于php:音乐dj网站小程序公众号开发项目-第三篇

接着后面两篇,当初是第三篇,如果须要用到的,大家能够看看后面的就能够了。 在我的文章主页有的,当初也是讲会员局部的。 有其余问题的能够分割我的扣就行了,是8582-36016 集体音乐页面 public function index() { $title = '我的音乐 - ' . config('web_site_title'); return $this->fetch('', ['meta_title' => $title]);}/** * 集体音乐待审页面 * @return \think\response */public function audit(){ $title = '审核的音乐 - ' . config('web_site_title'); return $this->fetch('', ['meta_title' => $title]);}/** * 集体音乐驳回页面 * @return \think\response */public function back(){ $title = '驳回列表 - ' . config('web_site_title'); return $this->fetch('', ['meta_title' => $title]);}/** * 集体音乐下载页面 * @return \think\response */public function down(){ $title = '我的下载 - ' . config('web_site_title'); return $this->fetch('', ['meta_title' => $title]);}/** * 创立歌曲 * @return \think\response */public function create(){ if(config('only_musician_upload') && !$this->user['is_musician']) { $this->error('你还没有认证音乐人,请先认证!!', 'user/Musician/auth', '', 5); } //获取以后用户的专辑 $albums = Album::where('add_uid', UID)->field('id,name')->select(); $this->meta_title = '分享音乐 - ' . config('web_site_title'); return $this->fetch('share', ['albums' => $albums]);}编辑歌曲 ...

September 23, 2021 · 2 min · jiezi

关于php:为什么-Go-map-和-slice-是非线程安全的

大家好,我是煎鱼。 初入 Go 语言的大门,有不少的小伙伴会疾速的 3 天精通 Go,5 天上手我的项目,14 天上线业务迭代,21 天排查、定位问题,顺带捎个检查报告。 其中最常见的初级错误,Go 面试较最爱问的问题之一: (来自读者的发问) 为什么在 Go 语言里,map 和 slice 不反对并发读写,也就是是非线程平安的,为什么不反对? 见招拆招后,紧接着就会开始探讨如何让他们俩 ”朋友“ 反对并发读写? 明天咱们这篇文章就来理一理,理解其前因后果,一起吸鱼学懂 Go 语言。 非线程平安的例子slice咱们应用多个 goroutine 对类型为 slice 的变量进行操作,看看后果会变的怎么样。 如下: func main() { var s []string for i := 0; i < 9999; i++ {  go func() {   s = append(s, "脑子进煎鱼了")  }() } fmt.Printf("进了 %d 只煎鱼", len(s))}输入后果: // 第一次执行进了 5790 只煎鱼// 第二次执行进了 7370 只煎鱼// 第三次执行进了 6792 只煎鱼你会发现无论你执行多少次,每次输入的值大概率都不会一样。也就是追加进 slice 的值,呈现了笼罩的状况。 因而在循环中所追加的数量,与最终的值并不相等。且这种状况,是不会报错的,是一个呈现率不算高的隐式问题。 这个产生的次要起因是程序逻辑自身就有问题,同时读取到雷同索引位,天然也就会产生笼罩的写入了。 map同样针对 map 也如法炮制一下。反复针对类型为 map 的变量进行写入。 如下: func main() { s := make(map[string]string) for i := 0; i < 99; i++ {  go func() {   s["煎鱼"] = "吸鱼"  }() } fmt.Printf("进了 %d 只煎鱼", len(s))}输入后果: fatal error: concurrent map writesgoroutine 18 [running]:runtime.throw(0x10cb861, 0x15)        /usr/local/Cellar/go/1.16.2/libexec/src/runtime/panic.go:1117 +0x72 fp=0xc00002e738 sp=0xc00002e708 pc=0x1032472runtime.mapassign_faststr(0x10b3360, 0xc0000a2180, 0x10c91da, 0x6, 0x0)        /usr/local/Cellar/go/1.16.2/libexec/src/runtime/map_faststr.go:211 +0x3f1 fp=0xc00002e7a0 sp=0xc00002e738 pc=0x1011a71main.main.func1(0xc0000a2180)        /Users/eddycjy/go-application/awesomeProject/main.go:9 +0x4c fp=0xc00002e7d8 sp=0xc00002e7a0 pc=0x10a474cruntime.goexit()        /usr/local/Cellar/go/1.16.2/libexec/src/runtime/asm_amd64.s:1371 +0x1 fp=0xc00002e7e0 sp=0xc00002e7d8 pc=0x1063fe1created by main.main        /Users/eddycjy/go-application/awesomeProject/main.go:8 +0x55好家伙,程序运行会间接报错。并且是 Go 源码调用 throw 办法所导致的致命谬误,也就是说 Go 过程会中断。 不得不说,这个并发写 map 导致的 fatal error: concurrent map writes 谬误提醒。我有一个敌人,曾经看过少说几十次了,不同组,不同人... 是个日经的隐式问题。 如何反对并发读写对 map 上锁实际上咱们依然存在并发读写 map 的诉求(程序逻辑决定),因为 Go 语言中的 goroutine 切实是太不便了。 ...

September 22, 2021 · 1 min · jiezi