关于php:使用laradock快速搭建docker下php开发环境

Laradock是docker下集成多版本php开发环境,使用方便,疾速构建搭建开发环境装置docker形式一:brew install --cask docker 形式二:手动下载 Docker Desktop for Mac 下载Laradock//开发环境根目录(任意定义比方新建文件夹www)git clone https://github.com/Laradock/laradock.git进入laradock目录//在这个文件中,配置了很多在docker-composer.yml用到的变量cp .env.example .env 到这里曾经把根本的php环境搭建好了docker-compose up -d nginx mysql phpmyadmin redis workspace我的项目配置默认的nginx配置根目录是指向public文件。你只须要在跟laradock同级目录下新建public目录,在public 目录下新建index.php文件,浏览器拜访localhost即可部署新我的项目退出你要开发新我的项目了。将我的项目放在与laradock我的项目同级目录下即可,如blog 本地hosts文件配置域名127.0.0.1 myblog.com 3.在ngnix/site目录下复制一份default.conf 命名别的名字即可,如下配置 简略粗犷,跟多细节请浏览官网文档http://laradock.io/

July 28, 2021 · 1 min · jiezi

关于php:PHP数据结构图的概念和存储结构

随着学习的深刻,咱们的常识也在一直的扩大丰盛。树结构有没有让大家蒙圈呢?置信我,学完图当前你就会感觉二叉树几乎是简略得没法说了。其实咱们说所的树,也是图的一种非凡模式。 图的概念还记得咱们学习树的第一篇文章时看到的那张对于树的图片吗? 在过后,咱们就说过,图c 不是一颗树,而是一个图。为什么呢?从树的定义咱们能够看出,树只能有一个根结点,平级之间不能有分割,能够有多个子结点。而图就不必恪守这些规定,图的特点就是结点之间都能够相互有分割。比方下图这样的都是图。 在下面所画的图中,图b 是的箭头的,而 图a 的连接线是没有箭头的,像这样有明确的方向的指向的图就叫做 有向图 。而没有箭头的,也就是没有方向指向的图就叫作 无向图 。 咱们先将眼光移到 图a-1 ,其实它就是把 图a 旋转了一下。大家能看进去了吗?如果疏忽掉结点 4 和 1 之间的连线,那么它就是一颗树。是不是和咱们下面对于树的图中的 图c 的概念统一了。 对于图的比拟正式的官网定义是: 图(Graph)G 由两个汇合 V 和 E 组成,记为 G=(V, E) ,其中 V 是顶点的有穷非空集合,E 是 V 中顶点的有穷汇合,这些顶点偶对称为边。在 有向图 中,连贯两点的那个线段,从开始的结点到指向的那个结点能够记为 <x, y> 。<x, y> 和 <y, x> 是两个不同的边,也能够叫作 弧 。依据 图a ,咱们能够看到这个图中有 <1, 2> 、 <2, 1> 、 <1, 3> 、 <3, 1> 、 <1, 4> 、 <4, 1> 、 <3, 4> 、 <4, 3> 这几条边。而 图b 中,因为它是有向图,所以它的边只有 <1, 2> 、 <1, 3> 、 <3, 4> 、 <4, 1> 这四条。 ...

July 28, 2021 · 1 min · jiezi

关于php:dcatlogincaptcha-dcat-admin-登录验证码扩展

guanguans/dcat-login-captcha - dcat admin 登录验证码扩大。环境要求dcat-admin >= 2.0装置Composer 装置$ composer require guanguans/dcat-login-captcha -vvv后盾 -> 开发工具 -> 扩大列表启用本扩大。 视图示例 1示例 2示例 3源码连贯https://github.com/guanguans/dcat-login-captcha参考链接https://github.com/deatil/dcat-login-captcha

July 27, 2021 · 1 min · jiezi

关于php:laradock-php-多版本容器共存

thinkPHP3.2的我的项目用到mongodb,\MongoClient 提醒报错如图,只能在低于php7的环境,因而须要在laradock再部署一个php56 进入laradock 目录,复制一份php-fpm,命名php-fpm-56cp -r php-fpm php-fpm-562.关上docker-compose.yml 文件,复制一份 php-fpm,如下图3.注意如果开启了xdebug此处构建php-fpm-56的时候会报错端口抵触4.如果发现此谬误,可自行配置别的端口如:90045.配置好后从新build一下docker-compose build php-fpm-566.nginx下site目录的service配置OK,没有别的问题都能失常运行了

July 27, 2021 · 1 min · jiezi

关于php:PHP数据结构完全二叉树线索二叉树及树的顺序存储结构

在上篇文章中,咱们学习了二叉树的根本链式构造以及建树和遍历相干的操作。明天咱们学习的则是一些二叉树相干的概念以及二叉树的一种变形模式。 齐全二叉树什么叫齐全二叉树呢?在说到齐全二叉树之前,咱们先说另外一个名词:“满二叉树”。像咱们之前文章中演示过的那个二叉树,就是一颗“满二叉树”。在这颗树中,所有的结点都有两个孩子结点,没有哪个结点是只有一个孩子结点的,并且所有最底层的叶子结点都在同一层,这种树就称为“满二叉树”,也称为“完满二叉树”。 是不是十分丑陋的一颗树?没错,这种二叉树十分地完满,它没有多余的结点,也没有短少的结点,十分的丑陋。然而,在事实中,完满的货色是很稀少的,人生总会有一点缺憾嘛。咱们尽量不要让本人有太多的缺憾,但也总不能过上没有一丝缺憾的人生。所以,咱们容许叶结点呈现在最上层和次上层,而且最上层的叶结点集中在树的左部,也就是叶结点只能有左子树,那么,这样的一颗略带缺憾的树就叫做“齐全二叉树”。不要放心它不完满,因为这样略带缺憾的人生才是残缺的嘛,所以“齐全二叉树”是一种现实的树结构。 从定义中,咱们能够看出,一颗“满二叉树”,必然是一颗“齐全二叉树”,而一颗叶子结点都在一层的并且所有结点都有左右孩子结点的“齐全二叉树”也就是一颗”满二叉树“。 为什么要讲”满二叉树“和”齐全二叉树“呢?当然是为了咱们接下来的内容做铺垫。因为”满二叉树“是最合乎二叉树性质的一颗树。还记得树系列的第一篇文章中介绍过的二叉树的那五个性质吗?过后咱们就是以那颗”满二叉树“为例进行解说的。而其中的 性质5 ,就是咱们学习应用程序构造存储二叉树的根底。 二叉树的顺序存储通过”满二叉树“的概念,以及二叉树的 性质5 咱们就能够实现应用一个数组来存储程序构造的实现。 $treeList = ['', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'];置信大家不生疏吧,在上篇文章中,咱们就是通过这个数组来建设链树的,而这个数组其实就是一个线性存储的二叉树。咱们通过比照二叉树的 性质5 来看一下。 A 结点的下标是 1 ,它是咱们的树根。它的子结点是 B 和 C ,对应的下标别离是 2 和 3 ,也就是 1 2 和 1 2 + 1 。同理,咱们再选取一个结点 F 。它的下标是 6 ,所以它的左孩子结点的下标是 6 2 = 12 ,对应的是 L ;它的右孩子结点是 6 2 + 1 = 13 ,对应的是 M 。反过来看,一个结点的父结点就是 i / 2 。咱们看下 K 结点的下标是 11 ,它的父结点就是 11 / 2 ,舍去小数点是下标 5 的地位,也就是结点 E ;结点 J 的下标是 10 ,它的父结点是 10 / 2 ,也是下标为 5 的 E 结点。这下想以大家就明确了用数组是如何示意一颗二叉树构造了吧。而且数组这种构造更加的一维,更能体现出对于树的操作就是二维化一维的一种示意,也就是非线性转线性,这样能力让咱们不便地操作这些数据。 ...

July 27, 2021 · 3 min · jiezi

关于php:crmeb-多商户系统特别注意事项

1、环境要求举荐应用宝塔linux面板装置php版本 7.3mysql 5.7mysql5.7版本注意事项:http://help.crmeb.net/crmeb_m...supervIsor 管理器最新版http://help.crmeb.net/crmeb_m...2、php须要装置的扩大fileinfo redis swoole4 swoole-loaderhttp://help.crmeb.net/crmeb_m...3、伪动态和运行目录不须要设置,如果配置了伪动态会导致反向代理增加不上4、反向代理必须配置,如果不配置反向代理客服等泛滥性能将不能失常应用http://help.crmeb.net/crmeb_m...5、挪动端 http:// 域名总治理后盾:http://域名/admin/商户后盾: http://域名/merchant/6、装置完批改总治理后盾 设置-商城配置-根底配置-网站域名 改成本人的域名(注:只改成本人的域名、不要扭转格局) 领取回调状态也是通过此域名回调的,如果不改会导致上传图片不胜利和回调失败 7、增加商户后须要开启 商户后盾 设置-根底设置 外面的开关开启 ,不然会导致上架的商品不显示 8、商户商品必须放在三级分类下,礼包产品不在商品列表页展现,只在用户集体核心分销外面展现 ,购买礼包可开启分销员权限。9、批改了php代码或者文件有变动都须要重启swoole过程能力失效10、用户端页面 view/uniapp 批改后须要应用 HBuilder X 工具编译总后盾前端页面 view/admin 批改后应用 node.js 编译商户后盾前端页面 view/merchant 批改后应用 node.js 编译编译后生成的文件笼罩到 public目录下笼罩完重启swoole过程11、支付宝配置阐明:http://help.crmeb.net/crmeb_m...12、腾讯地图key配置:http://help.crmeb.net/crmeb_m...13、快递查问配置:http://help.crmeb.net/crmeb_m...14、小票打印机配置:http://help.crmeb.net/crmeb_m...15、公众号开发配置:http://help.crmeb.net/crmeb_m...16、手册目录阐明:http://help.crmeb.net/crmeb_m...17、编译小程序阐明:http://help.crmeb.net/crmeb_m...18、编译H5和公众号教程:http://help.crmeb.net/crmeb_m...19、微信平台配置:http://help.crmeb.net/crmeb_m...20、程序目录构造:http://help.crmeb.net/crmeb_m...21、财务对账阐明:http://help.crmeb.net/crmeb_m...22、数据库构造:http://help.crmeb.net/crmeb_m...23、分销规定:http://help.crmeb.net/crmeb_m...24、短信阐明:http://help.crmeb.net/crmeb_m...25、首页模块阐明:http://help.crmeb.net/crmeb_m... 如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star: http://github.crmeb.net/u/defu不胜感激 !

July 26, 2021 · 1 min · jiezi

关于php:PHP数据结构二叉树的遍历及逻辑操作

上篇文章咱们讲了许多实践方面的常识,虽说很干燥,但那些都是咱们明天学习的前提,一会看代码的时候你就会发现这些理论知识是如许地重要了。首先,咱们还是要阐明一下,咱们学习的次要内容是二叉树,因为二叉树是最典型的一种树的利用,不论是考试还是面试,它都是必知必学的内容。 首先,在学习树的操作之前,咱们先要明确在树的操作中,最外围的就是“遍历”。为什么这么说呢?不同于栈和队列,树结构其实曾经不是一维的了,它有分支,有不同的角度,更重要的是它有了层级的概念。一维空间的货色就是咱们常见的“线”,它只有长度,没有高度,而这个长度就是它惟一的维度,栈和队列很显著都是一维的。而树就不同了,因为层级的概念,所以它有了“高度”,也就是说,它降级到了二维的概念。就像上一篇文章中介绍的那一堆名词中,就有“树的高度(深度)”的概念。 可能遍历一颗树之后,咱们就能够在遍历的根底上对这颗树的结点进行增、删、改等操作,这些根本的逻辑操作全都是建设在遍历的根底之上的,认真回忆一下栈和队列,其实它们的这些逻辑操作不也是从遍历动手吗?不论是出栈入栈还是出队入队,咱们都是建设在一种固定的遍历规定之下的(FILO、FIFO)。 对于二维的事物,如何遍历它就是一个重点的内容。一维的数据结构咱们只有程序地去遍历就能够了,而二维的数据后果则不能简略的按程序一个一个地去遍历了,因为结点之间有档次关系的存在,所以咱们要思考以后的结点如果没有子结点了,咱们的遍历操作应该怎么办呢? 幸好,咱们是站在伟人的肩膀上来学习这些常识。许多的前辈曾经为咱们总结进去了一些非常简单的对于树的遍历办法,有多简略呢?先卖个关子,咱们先来看看如何建设一颗树,也就是咱们在上篇文章中展现过的那颗二叉树。 二叉树的链式存储构造应用链式存储二叉树非常简单,而且也很形象,小伙伴们先收起对顺序存储二叉树的疑难,因为在下一篇文章中咱们就会解说在什么状况下应用顺序存储。 class BiTree{ public $data; public $lChild; public $rChild;}其实,在链式存储中,咱们就是应用一个个地结点来保留这颗树。每个二叉树结点都有一个数据域,也就是 data 属性。另外两个属性就可以看做是两个分叉的指针,别离是这个结点的左孩子结点 lChild 和右孩子结点 rChild 。比照栈和队列来说,咱们只是将 next 结点换成了左、右两个孩子结点而已,实质上其实与栈和队列并没有太大的差异。说白了,从数据结构上来看,咱们还是用一维的存储来示意二维的概念,而这个概念的转变则是咱们须要从对概念了解的角度登程的。 二叉树建树// 建设二叉树function CreateBiTree($arr, $i){ if (!isset($arr[$i])) { return null; } $t = new BiTree(); $t->data = $arr[$i]; $t->lChild = CreateBiTree($arr, $i * 2); $t->rChild = CreateBiTree($arr, $i * 2 + 1); return $t;}就这么一个简略的办法,咱们就能够实现一个链式二叉树的建设。小伙伴们请认真看好了,这一个简略的建树操作其实内含不少玄机: 咱们应用一个数组来顺次示意树的各个结点,比方顺次输出 A 、 B 、 C 、 D 、 E …… (树的顺序存储中咱们会再次看到它们的身影)赋值的内容是以后 $i 下标的数据,留神咱们在给左、右孩子赋值时进行了递归操作在学习栈的时候,咱们学习过“递归”就是一种栈式的操作,所以,在这段代码中,咱们是以栈的模式来建树的留神到每次的 i 2 和 i 2 + 1 了吧?请温习二叉树的 性质5最初咱们测试一下这个办法是否可能胜利的建设一颗链式树结构。 ...

July 26, 2021 · 3 min · jiezi

关于php:PHP数据结构树和二叉树

树的概念其实十分地宽泛,也十分地常见,大家见到这个词千万不要惊恐,因为真的每天你都能见到树结构在咱们生存中的利用。比如说公司的组织构造: 另外像咱们家里的族谱,或者说是咱们的家庭构造,也是一个典型的树结构。此外,在计算机领域,咱们天天要打交道的【文件夹】、数据库中咱们存储的数据,都是树的典型的利用。明天咱们来学习的就是比拟偏实践的对于树和二叉树的定义以及它们的一些属性特点。 树从下面理论生存中的例子里,咱们能够看出,树这种构造是能够演绎出它的一些特点的。 树 (Tree)是 N (N>0)个结点的无限集,它或为空树(N=0);或为非空树 T 。在这个定义中,咱们须要明确两个问题:一是树肯定是有结点的,二是依据结点数量能够分为空树和非空树两种。不过这只是最根本的定义,它还有一些个性。 有且仅有一个称之为根的结点。也就是说,这个树肯定是从某一个结点开始扩大进去的,这个结点就向树根一样。从它开始向外开枝散叶。 除根结点以外的其余结点可分为 m ( m > 0 ) 个互不相交的无限集 T1,T2 ……,Tm 其中每一个汇合自身又是一颗树,并且称为根的子树(SubTree)这一段可能会不太好了解,其实说白了就是每个结点只有一个下级结点,不能有多个下级结点。同理,平级结点之间也不能有分割,然而它能够有多个上级结点。 对于树的定义咱们能够看下上面这个图。 上图中简略的列举了规范的树和不规范的树是什么样子的。其中: (a) ,是只有一个根结点的树,只有有一个结点,它就能够称为一个树结构(b) ,是一个规范的树结构(c) ,留神它的 C 和 H 结点之间有一条连接线,这个就不是树了,结点只能有一个下级结点的才称为树,这个其实就是咱们未来要学的【图】了树的相干术语绝对于栈的压(入)栈、出栈,队列的入队、出队来说,树的相干术语可就简单的多了。不论如何,首先你得先记住这些术语,要不前面讲的货色用得那些术语只会让你更晕。不过咱们一时记不住也没关系,先有个大略的印象,在前面的学习过程中遇到了再回来温习,这样印象反而会更加粗浅。 结点:一个结点可能蕴含一组数据,或者指向其它结点的分支,能够看作是树枝分叉的那个中央,(b)图中 A、 B、 C、 D、 E 等等这些都是结点结点的度:结点领有的子树数量就叫做结点的度,其实就是它的上级子结点有几个就是几度,(b)图中,C 结点的度为 1 , D 结点的度为 3树的度:树内各结点度的最大值,就是领有最多子结点的度是多少,这个树的度就是多少,(b) 图这个树的度为 3叶子:度为0的结点,也就是没有子结点的结点,(b) 图中的 K 、 L 、 F 、 G 、 M 、 I 、 J 就是这颗树的叶子结点双亲和孩子:一个结点的子结点,就是它的孩子;对于这些子结点来说,以后这个结点就是它的双亲,(b) 图中,D 的孩子是 H 、 I 、 J ,而 H 、 I 、 J 的双亲就是 D档次:从根结点算起,根结点就是第一层,根的孩子就是第二层,顺次类推,(b) 图中 G 结点所在的档次为 3 ,(a) 图的全副档次都只有 1树的深度(高度):以后这颗树的最大档次,很显著,(b) 图的深度就是 4兄弟、先人和子孙:兄弟结点就是这些结点的双亲是同一个结点;先人结点就是从根结点到某个指定结点路上的通过的所有结点;子孙就是从某一个节点登程,达到指标结点这一路上的所有结点。(b) 图中, E、 F 是兄弟,E 的先人是 A 、 B , E 的子孙为 K 或者 L堂(表)兄弟:所有在同一层的结点但双亲不同的结点都是堂兄弟,同样还是在 (b) 图中,G 的堂(表)兄弟有 E、 F ,另外还有 H 、 I 、 J 也是它的表兄弟二叉树对于树的概念有了肯定的理解之后,咱们再来进一步的学习另一个概念,同时也是在数据结构和算法中最重要的一种树的模式:二叉树。 ...

July 25, 2021 · 2 min · jiezi

关于php:PHP数据结构栈和队列的应用

通过栈和队列的学习,咱们仿佛会感觉到其实数据结构还是非常简单的嘛。当然,这只是一个开始,咱们从程序表、链表开始,到当初的栈和队列,其实都是为了未来在铺路。在树和图的遍历算法中,都能够见到栈和队列的身影。在这里,咱们先简略的看看栈和队列的一些理论利用。 回文题假如有一段文字,咱们要判断它是不是“回文”(不是回族兄弟的文字)。就能够利用栈来解决这个问题。 回文指的就是将这段文字一分为二之后,后面一段内容和前面一段内容是完全相同的,然而程序是相同的。比方十分闻名的:上海自来水来自海上。上海自来,来自海上,这样的两段构造在一句话里就形成了一段回文。又比方单数长度的一段字符:abcddcba,这也是一段回文。 相似的这种题目其实很容易呈现在一些简略的算法面试题中,置信也有不少小伙伴曾经看出端倪了,咱们能够将前半段入栈,而后再一个一个的出栈与后半段进行比对就能够判断以后的字符串是否是回文了。别光说不练,咱们就上代码来实现。 $string1 = 'abcdedcba';$string2 = 'abcdeedcba';$string3 = 'abcdefcba';function getIsPlalindrome($string){ if (gettype($string) != 'string') { return false; } $strlen = strlen($string); $mid = floor($strlen / 2); $arr = []; if ($strlen < 2) { return false; } // 入栈 for ($i = 0; $i < $mid; $i++) { array_push($arr, $string[$i]); } $j = $mid; $i = $strlen % 2 == 0 ? $mid : $mid + 1; // $i 从中位数开始 for (; $i < $strlen; $i++) { $v = $arr[$j - 1]; // 取得栈顶元素 if ($v != $string[$i]) { return false; } array_pop($arr); // 弹出栈顶元素 $j--; } if ($arr) { return false; } return true;}var_dump(getIsPlalindrome($string1)); // bool(true)var_dump(getIsPlalindrome($string2)); // bool(true)var_dump(getIsPlalindrome($string3)); // bool(false)很简略吧,就是应用 array_push() 和 array_pop() 来进行的程序栈的操作而已。惟一须要留神的就是对于字符长度奇偶数的不同,咱们要取的中位数也相应的要产生扭转。 ...

July 24, 2021 · 2 min · jiezi

关于php:海外多语言国际婚恋相亲网站开发制作第四篇

第一篇:https://blog.csdn.net/weixin_... 第二篇:https://segmentfault.com/a/11... 第三篇:https://segmentfault.com/a/11... 这个是国内多语言婚恋交友网站开发制作的专栏: https://blog.csdn.net/weixin_... 如果有什么疑难能够,找我,各位,我的扣是2360248-666 国内多语言婚恋交友网站开发制作,第四篇粉丝局部的性能开发 浏览粉丝 public function index(){ //echo "浏览"; $atten = D('byattention'); $total = $atten->where('uid='.session('user')['id'])->count(); $page = new \Think\Page($total,9); $mod = $atten->order('byaid desc')->field('uid')->limit($page->firstRow,$page->listRows)->where('byattenid='.session('user')['id'])->select(); //定义一个空数组 $list = array(); //依据attenid获取关注的用户详情 foreach($mod as $k=>$v){ $list[] = $v['uid']; } //定义一个空数组承受查问信息 $res = array(); $resu = array(); //遍历$list数组 foreach($list as $v1){ //执行查问 $res[$v1] = D('user_params')->where('userid='.$v1)->field('id,gender,ageyear,marrystatus,height,cityid,monolog')->find(); if(strlen($res[$v1]['monolog'])>27){ $res[$v1]['monolog1'] = mb_substr($res[$v1]['monolog'],0,12,"utf-8")."..."; } $resu[$v1] = D('user')->where('id='.$v1)->field('username,avatar,id')->find(); } //依据出世年算出年龄 $sex = array('1'=>'未婚','2'=>'已婚','3'=>'离异'); foreach($res as $k=>$v){ $res[$k]['ageyear'] = date('Y',time())-$res[$k]['ageyear']; $res[$k]['marrystatus'] = $sex[$res[$k]['marrystatus']]; $city[$k] = D('district')->where('id='.$res[$k]['cityid'])->field('name,upid')->find(); $city1[$k] = D('district')->where('id='.$city[$k]['upid'])->field('name')->find(); } $users = array(); foreach($resu as $k=>$v){ $users[$k] = $v; if($users[$k]['avatar'] == null){ if($res[$k]['gender'] == 1){ $users[$k]['avatar'] = 'male.gif'; }else{ $users[$k]['avatar'] = 'female.gif'; } } } $this->assign('city1',$city1); $this->assign('city',$city); $this->assign('users',$users); $this->assign('res',$res); $this->assign('pageInfo',$page->show()); $this->display('byattention'); }}?> ...

July 23, 2021 · 3 min · jiezi

关于php:PHP数据结构队列的相关逻辑操作

在逻辑构造中,咱们曾经学习了一个十分经典的构造类型:栈。明天,咱们就来学习另外一个也是十分经典的逻辑构造类型:队列。置信不少同学曾经应用过 redis 、 rabbitmq 之类的缓存队列工具。其实,数据库、程序代码,这些都能够实现队列的操作,就和栈一样,队列也是有其特定的规定,只有合乎这个规定,它就叫做队列。 什么是队列?绝对于栈来说,队列是一种先进先出(FIFO)的程序逻辑构造。什么叫先进先出呢?就和咱们的排队一样,当咱们去银行或者医院的时候,总是要在门口取一个号,这个号是按程序叫的。先来的人就能够先办业务或者看病,这就是一个典型的队列。同理,日常的排队就是一个规范的队列模式。如果有插队的,在有正当理由的状况下,咱们能够认为它的优先级更高,这是队列中元素的一种非凡模式。就像咱们会在等地铁或者公交的时候让孕妇优先,在排队买火车票的时候也有军人的优先窗口。不过,这个并不在咱们这次的探讨范畴之内。 在公交站排队时,排第一个的当然能够第一个上车,而后顺次。这时,你来到了公交站,那么你只能排到最初一位。这个就是队列的具体表现形式。 同样,和栈一样,也有一些名词咱们须要理解。当你来到公交站并排到最初一位时,这个操作叫作“入队”。当公交车进站后,第一位乘客上车,这个操作叫做“出队”。第一位乘客所处的地位叫做“队头”,你做为以后队列的最初一位乘客,你的地位就叫做“队尾”。回到代码逻辑下面来看,也就是说队列是从“队尾”“入队”,从“队头”“出队”。 程序队列OK,咱们还是间接素来代码来看,首先看到的仍然是程序队的实现。 class SqQueue{ public $data; public $front; public $rear;}既然是程序队,咱们仍然还是用一个数组 data 来示意队内的元素。而后定义两个指针 front 和 rear 来示意队头和队尾。因为是程序队,所以这里的指针其实也就是保留的是数组的下标。接下来的操作其实就十分的简略了,“入队”时 rear++ ,“出队”时 front++ 。 function InitSqQueue(){ $queue = new SqQueue(); $queue->data = []; $queue->front = 0; $queue->rear = 0; return $queue;}function EnSqQueue(SqQueue &$queue, $e){ $queue->data[$queue->rear] = $e; $queue->rear ++;}function DeSqQueue(SqQueue &$queue){ // 队列为空 if($queue->front == $queue->rear){ return false; } $e = $queue->data[$queue->front]; $queue->front++; return $e;}$q = InitSqQueue();EnSqQueue($q, 'A');EnSqQueue($q, 'B');print_r($q);// SqQueue Object// (// [data] => Array// (// [0] => A// [1] => B// )// [front] => 0// [rear] => 2// )是不是感觉学过了栈之后,队列也很好了解了。初始化队列时,就是让队头和队尾指针都是 0 下标的记录就能够了。入队的时候让队尾减少,在这段代码中,咱们入队了两个元素,打印进去的程序队列内容就如正文所示。 ...

July 23, 2021 · 4 min · jiezi

关于php:PHP-Data-Structures-扩展介绍

在 PHP 中因为数组太过弱小,把这些数据结构都囊括进来了,所以不太须要去关注这些数据结构,长此以往这些概念也就淡化了,不是说 PHP 中没有数据结构。 在 PHP 中有个扩大 Data Structures,这个扩大蕴含了这些常见的 数据结构,具体的能够查看连贯 数据结构 PHP 数据结构优先级队列 PriorityQueue双端队列 Deque队列 FIFO(先进先出)栈 LIFO(先进后出)散列表 Hash Set 汇合Map 字典数据结构介绍优先级队列 PriorityQueuePriorityQueue 与 Queue 十分类似。 值被推入具备指定优先级的队列中,具备最高优先级的值将始终位于队列的后面。 留神 对于具备雷同优先级的值,保留“先进先出”程序。迭代 PriorityQueue 是破坏性的,相当于间断弹出操作,直到队列为空。设置容量默认容量是 8,能够手动设置容量,这个容量不是指队列的长度,而是说存储空间。再调配容量时确保有足够的内存 如果该值小于或等于以后容量,容量将放弃不变。 $queue = new Ds\PriorityQueue(); $queue->allocate(8);获取容量以后手动设置了容量时,如果设置的容量大于理论占用容量,则返回设置的容量。反之,返回理论的容量。 $queue = new Ds\PriorityQueue(); // 此时返回默认值 8$queue->capacity();设置优先级数值越大优先级越高 $queue = new Ds\PriorityQueue(); $queue->push('value1', 1);$queue->push('value2', 2);示例$queue = new Ds\PriorityQueue(); $queue->push('沙僧', 2);$queue->push('唐僧', 5);$queue->push('白龙马', 1);$queue->push('猪八戒', 3);$queue->push('孙悟空', 4);$cout = $queue->count();for($i=0; $i<$cout; $i++) { echo $queue->pop(); echo PHP_EOL;}输入唐僧孙悟空猪八戒沙僧白龙马利用场景MySQL 查问时为了放慢查问速度,防止排序无奈应用索引,没有进行排序,在服务端代码层面进行手动排序再返回。其余利用场景...双端队列 Deque有两个指针别离指向头部和尾部。别离能够在头部和尾部进行插入和弹出。 ...

July 22, 2021 · 1 min · jiezi

关于php:ThinkPHP-V609版本发布常规更新

V6.0.9版本为惯例更新,次要增加了事件监听的通配符反对,并修改了框架的一处可能的序列化破绽,同时对模型做了一些改良和优化。次要更新更新league/flysystem版本事件监听反对通配符反对工夫字段的对立配置改良Request类all办法因为league/flysystem低版本存在破绽,官网进行了平安降级,该降级使得框架的PHP版本依赖也晋升到7.2+。ThinkORM 次要更新如下:强化虚构模型反对改良模型事件和数据库事件改良动静获取器解决优化分页查问改良聚合查问关联减少withoutField办法软删除destroy办法优化装置和更新V6版本开始仅反对Composer装置及更新,反对上个版本的无缝更新,间接应用 composer update更新到最新版本即可。 如果你的PHP版本是7.1.*,能够仅仅更新topthink/think-orm库而无需更新框架。如果须要全新装置,应用: composer create-project topthink/think tp官网文档官网6.0齐全开发手册6.0入门必读教程 官网服务官网服务市场——生态服务交易及交付平台ThinkPHP应用服务市场是官网作为策略服务倾力打造的生态服务交易及交付平台,为ThinkPHP开发者和爱好者严选官网及第三方产品和服务,并提供交易保障。 ThinkAPI——官网对立API接口服务ThinkAPI对立API接口服务是由官网联结合作伙伴封装的一套接口调用服务及SDK,旨在帮忙ThinkPHP开发者更不便和更低成本调用官网及第三方的提供的各类API接口及服务,从而更好的构建开发者生态。目前曾经接入包含实名认证、人工智能、电子商务、新闻资讯和生存服务在内的罕用API接口。 ThinkSSL——官网自营SSL证书服务ThinkSSL服务是ThinkPHP官网联结合作伙伴推出的自营SSL/TLS证书服务,精选了多个优质证书品牌和证书类型,为集体和企业提供极具性价比的证书服务,反对DV(域名型)和OV(企业型),同时也提供收费证书服务(包含通配符证书)。

July 22, 2021 · 1 min · jiezi

关于php:PHP数据结构栈的相关逻辑操作

对于逻辑构造来说,咱们也是从最简略的开始。堆栈、队列,这两个词对于大部分人都不会生疏,然而,堆和栈其实是两个货色。在面试的时候千万不要被面试官绕晕了。堆是一种树结构,或者说是齐全二叉树的构造。而明天,咱们次要讲的就是这个栈的利用。 什么是栈?栈个别就是一种程序的数据结构。它最大的特点就是后进先出(LIFO),或者反过来说先进后出(FILO)也是能够的。这两句话到底是什么意思呢?最典型的例子就是大家看电视剧时,特地是枪战片时相对会看到的一样货色:弹匣。 弹匣在装弹的时候都是一个一个的将子弹压进弹匣的,也就是说,第一颗子弹是被压在最底下的,而开枪的时候则是按相同的程序从弹匣的最顶部弹出来的,第一颗放进去的子弹是最初一个才被打进去的。 这个例子其实曾经十分形象了,咱们再对立一下术语。将子弹压进弹匣叫做“入栈”,第一颗子弹在最底下,这个地位叫做“栈底”,最初一颗子弹在最顶上,这个地位叫做“栈顶”,打出的这颗子弹是“栈顶”的那颗子弹,这个操作叫做“出栈”。 通过下面术语的定义,咱们就能够看出,栈的逻辑操作次要就是“入栈”和“出栈”,而逻辑构造最须要关怀的是这个“栈顶”和“栈底”在进行出入栈时的状态。当然,栈的逻辑构造应用程序或链式构造都是没有问题的,咱们就一个一个地来看一下。 程序栈首先还是比较简单的程序栈的实现。既然是程序构造,那么就是用数组了。不过,咱们还须要记录一下“栈顶”或“栈底”的状况,所以咱们将程序栈的这个数组封装到一个类中。同时,在这个类中定义一个属性来表明以后栈的“栈顶”或“栈底”指针,其实就是以后“栈顶”或“栈底”在数组中的下标地位。通常来说,咱们只须要记录“栈顶”的地位就能够了,将“栈底”默认为 -1 即可。因为数组下标自身是从 0 开始的,所以当“栈顶”属性为 -1 时,这个栈就是一个空栈,因为它的“栈顶”和“栈底”在一起,外面并没有元素。 class SqStack{ public $data; public $top;}初始化程序栈很简略,一个空的数组并将 $top 设置为 -1 。 function InitSqStack(){ $stack = new SqStack(); $stack->data = []; $stack->top = -1; return $stack;}接下来就是“入栈”和“出栈”的操作了,先看代码。 function PushSqStack(SqStack &$stack, $x){ $stack->top ++; $stack->data[$stack->top] = $x;}function PopSqStack(SqStack &$stack){ // 栈空 if($stack->top == -1){ return false; } $v = $stack->data[$stack->top]; $stack->top--; return $v;}入栈很简略,给数组元素增加内容,而后 $top++ 就能够了。不过如果是 C 语言的话,因为它有数组长度的限度,所以在入栈的时候,咱们也须要判断一下栈是否曾经满了。当然,在 PHP 中咱们就没有这个顾虑啦。 程序栈入栈图示 ...

July 22, 2021 · 2 min · jiezi

关于php:redis整数集为什么不能降级

前言整数汇合置信有的同学没有据说过,因为redis对外提供的只有封装的五大对象!而咱们本系列宗旨是学习redis内部结构。内部结构是redis五大构造重要撑持! 后面咱们别离从redis内部结构剖析了redis的List、Hash、Zset三种数据结构了。明天咱们再来剖析set数据结构外部是如何存储的 根本构造在src/t_set.c中咱们发现这样一段代码 由此咱们可知在set中是由两种数据结构形成的: hashtable+intset 。对于redis外部其余的构造我专门在【redis专栏中有介绍】。hashtable不是咱们明天的配角,咱们明天先剖析intset俗称整数汇合。 从上图中咱们能够看出,我结构了两个set汇合别离为【commonset】、【cs】。两个汇合前者存储字符串、后者专门存储数字。 咱们在通过object encoding key 来查看下两个汇合的底层数据结构,发现一个是hashtable 一个是intset 。这也验证了咱们上面对set根本构造的形容。 在redis中对外提供五大类型实际上都是redis的一个形象对象叫做redisobject。在外部映射了咱们redis外部的数据结构 针对commonset和cs两个汇合在外部数据结构大略能够这么了解 何时应用intset你能够单纯的认为只有是数字就会应用intset构造来存储,我恐怕要给你当头一棒了。实际上并不是这样 须要同时满足以下两个条件: intset 图中示意的很分明了,在intset中的encoding有三种取值别离代表contents保留数据类型。这里有人可能会有疑难了contents的类型不就是int8_t吗?为什么还须要encoding呢?这里通过源码跟踪外部确实跟int8_t没啥关系。而且数据的默认类型就是int16_t 。对于length这里无需太多解释,记住一点示意contents元素的个数并非示意contents数组的长度!理解intset的同学都晓得在encoding三种取值范畴中波及了降级的操作!在讲降级之前咱们先来理解下C、C++中int的取值范畴是如何定义的int8_t的取值范畴是【-128,127】 。 相似于java中byte占1个字节也就是8位。他的取值范畴是−27∼27−1即−128∼127−27∼27−1即−128∼127 增加元素sadd juejin -123sadd juejin -6sadd juejin 12sadd juejin 56sadd juejin 321 juejin这个key外部就是intset 。 下面咱们增加了5个元素且这五个元素的长度都在16之内!所以以后的intset的encoding=INTSET_ENC_INT16。-123在contents中占前16位。 所以以后五个元素占contents的长度是16*5=80 ; 留神set在存储int类型数据时,外部是依照从小到大的顺序存储的。 类型变动 下面的问题不晓得你有没有思考过,或者说有没有遇到过!intset默认是int16位,正如咱们下面增加的五个元素。退出此时咱们增加第6个元素是65535(32位)。那么此时16位的长度就不够存储了这个时候intset会怎么做!另外当咱们增加第6个元素后又将65535删除了之后,构造和增加之前是否一样!上面咱们带着这两个问题来一探到底!!!降级首先咱们针对第一问题来看看。原来五个元素都是16位就能够满足了,这个时候增加的65535是32位长度的。那么是不是能够间接追加32位调配给65535呢?答案是必定不行,首先间接追加无奈保障数组元素的大小程序!其次如果前五个别离是16位,第6个是32位那么在intset构造中没有多余的字段来进行标记。也就是说在解析的时候就无奈判断应该解析16位还是32位了.redis为了不便解析所以在有高长度退出时会将整个contents进行降级。意思就是将整个contents先进行扩容,而后在从新填充数据 退出65535首先依据length能够确定扩容后元素个数为6 , 每个占位32,所以contents长度为32*6=192 。 此时前80位内容放弃不变 旧数据移位开拓了足够的空间后,咱们就能够对旧数据进行移位了这里咱们从原数组的开端开始挪动,在挪动之前须要明确在新数组中的排序地位。此时咱们首先将321进行比对确定在新数组中他的排名是第五名,那么他将占用新contents中128~159区间。 最终前5 个元素就会被挪动好 。 最初将新退出的元素填充进去。当产生降级时必定是因为新元素的长度大于原有长度了。那么他的值肯定会是在新数组的两端。正数在最左侧,负数在最右侧 降级接下来就是第二个问题当新退出的65535又被删除了redis该怎么办,这个时候元素长度理论16位就能够满足了,然而此时encoding却是32位的。依照我的认识应该在实现降级!然而遗憾的是redis并没有,那么请思考为什么没有?如果让你实现你将如何实现为什么不实现降级当退出元素超过以后长度咱们很容易就晓得此时须要进行降级操作,然而当咱们删除一个数据时咱们如何判断是否须要降级却很艰难,咱们须要从新遍历一遍剩下的元素是否小于以后长度,实现复杂度O(N) 。这就是为什么不进行降级起因之一你可能会说从新遍历一遍很快的反正在内存中,那么你有没有想过如果降级之后又遇到降级状况,这样来回的降级降级就升高了咱们程序的性能了。咱们晓得降级是必须的所以这里降级redis采取的是疏忽的策略小结

July 21, 2021 · 1 min · jiezi

关于php:crmeb多商户系统开发和构建说明

装置依赖在终端执行命令 装置依赖npm install 倡议不要间接应用 cnpm 装置依赖,会有各种诡异的 bug。能够通过如下操作解决 npm 下载速度慢的问题npm install --registry=https://registry.npm.taobao.org开发在终端执行命令: $ npm run dev运行胜利后在浏览器拜访http://localhost:9527 构建在终端执行命令进行我的项目打包: $ npm run build:prod构建打包胜利之后,默认会在根目录生成dist文件夹,外面就是构建打包好的文件,通常是.js、.css、index.html等动态文件。 配置阐明配置文件.env.development 开发环境.env.production 正式环境配置阐明 接口地址VUE_APP_BASE_API = '' socket 连贯地址VUE_APP_WS_URL = '' 如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star: http://github.crmeb.net/u/defu不胜感激 !

July 21, 2021 · 1 min · jiezi

关于php:国际多语言婚恋交友网站开发制作第三篇

后面介绍了会员局部的一些性能实现,大家也能够看看一下 第一篇:https://blog.csdn.net/weixin_... 第二篇:https://blog.csdn.net/weixin_... 这个是国内多语言婚恋交友网站开发制作的专栏: https://blog.csdn.net/weixin_... 如果有什么疑难能够,找我,各位,我的扣是2360248-666 这个是性能介绍图  上面是一些零碎设置的性能实现 间接上传到OSS public function mjdr(){//间接上传到OSS $p = I("get.p");if(!$p) $p=0;$page = 10;$list = M()->table("lx_users")->limit($p*$page,$page)->order('userid asc')->select();foreach($list as $val){ if($val["avatar"] && !strstr('http:',$val["avatar"])){ $re = $this->oos_upimg('http://www.aiqing.com/'.$val["avatar"]); if($re) M()->table("lx_users")->where("userid=".$val['userid'])->setField("avatar",$re); echo $val['userid']."<img src='".$re."' width='100'>"; } }$p++;$nexurl = U("mjdr",array("p"=>$p)); echo '<script>window.location.href="'.$nexurl.'";</script>'; exit; } public function mjdr2(){ $p = I("get.p");if(!$p) $p=0;$page = 50;$list = M()->table("lx_users")->limit($p*$page,$page)->order('userid asc')->select();if(!$list) exit("none");foreach($list as $val){ if($val["avatar"] && !strstr($val["avatar"],'http:')){ $uid = md5($val["userid"]-652); $filename1 = $uid.".jpg"; $re = $this->GrabImage2('http://www.aiqing.com/'.$val['avatar'],$filename1,'http://www.aiqing.com'); if(file_exists($re)){ $re2 = "http://www.yueai.me/".$re; M()->table("lx_users")->where("userid=".$val['userid'])->setField("avatar",$re2); } echo $val['userid']."<img src='".$re."' width='100'>"; } }$p++;$nexurl = U("mjdr2",array("p"=>$p)); echo '<script>window.location.href="'.$nexurl.'";</script>'; exit; } ...

July 21, 2021 · 2 min · jiezi

关于php:PHP数据结构链表的其它形式

在上篇文章中,咱们曾经说过了链表除了简略的那一种单向链表外,还有其它的几种模式。当然,这也是链表这种构造的一大特点,十分地灵便和不便。咱们简略的想一想,如果让最初一个节点的 next 指回第一个节点,那么这就样就造成了一个环,这就是一个循环链表了。如果咱们在每个节点上减少一个指向上一个节点的 prev 属性,那么这个链表就变成了一个双向链表了。如果咱们在双向链表的根底上也让最初一个节点的 next 指向第一个节点,同时让第一个节点的 prev 指向最初一个节点,这不就是一个双向循环链表了嘛。上面咱们就来具体的看一看。 循环链表就像上文所说的,咱们让最初一个节点指向第一个节点,这样造成的链表就是一个循环链表,如下图所示: 对于循环的链表的操作咱们不做具体的阐明,其实大部分代码和单向链表是一样的,只是须要留神两个中央: 1.初始化、插入操作的时候,留神最初一个节点的指向,最初一个节点的 next 要指向第一个节点 2.判断链表遍历是否实现的条件为 item->next == head ,也就是说,判断这个节点的下一个节点如果是头节点的话,链表就遍历实现了。 双向链表双向链表则是在 LinkedList 这个类外面减少一个属性来指向上一个节点。 // 双向链表class LinkedList{ public $data; public $prev; public $next;} 接下来,咱们初始化一个双向链表。 /** * 生成链表 */function createLinkedList(){ $list = new LinkedList(); $list->data = null; $list->next = null; $list->prev = null; // ** 全副都初始化为 null ** return $list;}/** * 初始化链表 * @param array $data 链表中要保留的数据,这里以数组为参考 * @return LinkedList 链表数据 */function Init(array $data){ // 初始化 $list = createLinkedList(); $r = $list; foreach ($data as $key => $value) { $link = new LinkedList(); $link->data = $value; $link->next = null; $r->next = $link; $link->prev = $r; // ** 减少下级指向 ** $r = $link; } return $list;}$link = Init(range(1, 10));var_dump($link);var_dump($link->next->next->next->next);// object(LinkedList)#5 (3) {// ["data"]=>// int(4)// ["prev"]=>// object(LinkedList)#4 (3) {// ["data"]=>// int(3)// ["prev"]=>// object(LinkedList)#3 (3) {// ["data"]=>// int(2)// ["prev"]=>// object(LinkedList)#2 (3) {// ["data"]=>// int(1)// ["prev"]=>// object(LinkedList)#1 (3) {// ["data"]=>// NULL// ["prev"]=>// NULL// ["next"]=>// *RECURSION*// }// ["next"]=>// *RECURSION*// }// ["next"]=>// *RECURSION*// }// ["next"]=>// *RECURSION*// }// ["next"]=>// object(LinkedList)#6 (3) {// ["data"]=>// int(5)// ["prev"]=>// *RECURSION*// ["next"]=>// object(LinkedList)#7 (3) {// ["data"]=>// int(6)// ["prev"]=>// *RECURSION*// ["next"]=>// object(LinkedList)#8 (3) {// ["data"]=>// int(7)// ["prev"]=>// *RECURSION*// ["next"]=>// object(LinkedList)#9 (3) {// ["data"]=>// int(8)// ["prev"]=>// *RECURSION*// ["next"]=>// object(LinkedList)#10 (3) {// ["data"]=>// int(9)// ["prev"]=>// *RECURSION*// ["next"]=>// object(LinkedList)#11 (3) {// ["data"]=>// int(10)// ["prev"]=>// *RECURSION*// ["next"]=>// NULL// }// }// }// }// }// }// }echo $link->next->next->next->next->data, PHP_EOL; // 4echo $link->next->next->next->next->prev->data, PHP_EOL; // 3能够看出,与单向链表不同的中央就在于多减少了对于 prev 属性的操作。这里还是比拟好了解的。间接打印链表会显示很多的 *RECURSION* 内容,这是 PHP 的一种输入的爱护机制,这个标识阐明以后这个属性变量是有递归类型的。 ...

July 21, 2021 · 3 min · jiezi

关于php:婚恋交友网站开发制作第二篇

前端工夫因为工夫太慢了,没有接着更新,当初接着把这个我的项目的婚恋交友网站开发制作开发过程的前面代码公布一下,心愿可能帮到帮到大家的学习和应用。 这个是前台的,会员局部控制器 举荐局部 class IndexController extends SiteController { public function index($w=""){ if(!$this->uinfo){ redirect(U("Public/index")); exit; } if(C("onlywx")==1 && strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') === false){ $this->siteDisplay('jg_qzwxdk'); exit; } $media=$this->getMedia('举荐'); $this->assign('media', $media); $where = " 1=1 "; $sex = I("post.sex",'','intval'); if(!$sex){//默认 $sex = $this->uinfo['sex']==1?'2':'1'; $cookiesex =cookie('defsex'); $sex = $cookiesex?$cookiesex:$sex; }else{ $sex = $sex; cookie('defsex',$sex,3600); } if($sex>0) $where.=" and sex=".$sex; $where.=" and ismj=1"; $age = I("post.age",'','intval'); if($age>0){ $now = date("Y"); switch($age){ case 1: $where.=" and age between ".($now-25)." and ".($now-18); break; case 2: $where.=" and age between ".($now-35)." and ".($now-26); break; case 3: $where.=" and age between ".($now-40)." and ".($now-36); break; case 4: $where.=" and age between ".($now-50)." and ".($now-40); break; case 5: $where.=" and age between ".($now-100)." and ".($now-50); break; } } 地区局部 ...

July 20, 2021 · 2 min · jiezi

关于php:Go-面试官什么是协程协程和线程的区别和联系

微信搜寻【脑子进煎鱼了】关注这一只爆肝煎鱼。本文 GitHub github.com/eddycjy/blog 已收录,有我的系列文章、材料和开源 Go 图书。大家好,我是煎鱼。 最近金三银四,是面试的节令。在我的 Go 读者交换群里呈现了许多小伙伴在探讨本人面试过程中所遇到的一些 Go 面试题。 明天的男主角,是工程师的必修技能,那就是 “什么是协程,协程和线程的区别和分割?” 既要了解线程,还要解说协程,并且诠释两者间的区别,然而因为提到线程,就必然波及过程,因而本文将会同时梳理介绍 “过程、协程、协程” 三者的随笔常识。 心愿能引发大家的一些思考。 过程过程是什么过程是操作系统对一个正在运行的程序的一种形象,过程是资源分配的最小单位。 为什么有过程为什么会有 ”过程“ 呢?说白了还是为了正当压迫 CPU 的性能和调配运行的工夫片,不能 “闲着“。 在计算机中,其计算外围是 CPU,负责所有计算相干的工作和资源。单个 CPU 一次只能运行一个工作。如果一个过程跑着,就把惟一一个 CPU 给齐全占住,那是十分不合理的。 那为什么要压迫 CPU 的性能?因为 CPU 切实是太快,太快,太快了,寄存器仅仅可能追的上他的脚步,RAM 和别的挂在各总线上的设施则更是可望不可即。 多过程的原因如果总是在运行一个过程上的工作,就会呈现一个景象。就是工作不肯定总是在执行 ”计算型“ 的工作,会有很大可能是在执行网络调用,阻塞了,CPU 岂不就节约了? 这又呈现了多过程,多个 CPU,多个过程。多过程就是指计算机系统能够同时执行多个过程,从一个过程到另外一个过程的转换是由操作系统内核治理的,个别是同时运行多个软件。 线程有了多过程,想必在操作系统上能够同时运行多个过程。那么为什么有了过程,还要线程呢? 起因如下: 过程间的信息难以共享数据,父子过程并未共享内存,须要通过过程间通信(IPC),在过程间进行信息替换,性能开销较大。创立过程(个别是调用 fork 办法)的性能开销较大。大家又把眼光转向了过程内,能不能在过程里做点什么呢? 一个过程能够由多个称为线程的执行单元组成。每个线程都运行在过程的上下文中,共享着同样的代码和全局数据。 多个过程,就能够有更多的线程。多线程比多过程之间更容易共享数据,在上下文切换中线程个别比过程更高效。 起因如下: 线程之间可能十分不便、疾速地共享数据。 只需将数据复制到过程中的共享区域就能够了,但须要留神防止多个线程批改同一份内存。创立线程比创立过程要快 10 倍甚至更多。 线程都是同一个过程下自家的孩子,像是内存页、页表等就不须要了。协程是怎么回事协程是什么协程(Coroutine)是用户态的线程。通常创立协程时,会从过程的堆中调配一段内存作为协程的栈。 线程的栈有 8 MB,而协程栈的大小通常只有 KB,而 Go 语言的协程更夸大,只有 2-4KB,十分的笨重。 协程的诞生依据维基百科的说法,马尔文·康威于 1958 年创造了术语 “coroutine” 并用于构建汇编程序,对于协程最后的出版讲解在 1963 年发表。 ...

July 20, 2021 · 1 min · jiezi

关于php:php图片上传函数Curl上传图片

php curl上传图片示例<?phpheader("Content-type:application/json");function uploadimg($url,$data){ $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $headers[] = "user-agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3947.100 Safari/537.36"; curl_setopt($ch, CURLOPT_HTTPHEADER,$headers); return curl_exec($ch); curl_close($ch);}// 调用函数$data = array( '上传参数' => new CURLFile(realpath('test.jpg')),);echo uploadimg('上传接口URL',$data);?>Author:TANKING

July 20, 2021 · 1 min · jiezi

关于php:crmeb-多商户系统商户后台目录结构说明

├── public # 动态资源│ ├── favicon.ico # favicon图标│ └── index.html # html 模板├── src # 源代码│ ├── api # 所有接口api│ │ └──request.js # 申请封装│ │ └──accounts.js # 无关财务的接口│ │ └──dashboard.js # 无关首页的接口│ │ └──freight.js # 无关运费模板的接口│ │ └──marketing.js # 无关优惠券的接口│ │ └──order.js # 无关订单的接口│ │ └──product.js # 无关商品的接口│ │ └──settingMer.js # 无关权限治理的接口│ │ └──system.js # 无关系统配置的接口│ │ └──systemForm.js # 无关表单组件的接口│ │ └──user.js # 无关登录、用户的接口│ ├── assets # 图片、svg 等动态资源│ ├── icons # svg 等动态资源│ ├── components # 公共组件│ │ └──attrFrom # 商品规格│ │ └──Breadcrumb # 头部题目标签│ │ └──cards # 统计│ │ └──couponList # 优惠劵列表│ │ └──goodsList # 商品列表│ │ └──Hamburger # 导航膨胀组件│ │ └──HeaderSearch # 导航搜寻组件│ │ └──iconFrom # 导航增加图标│ │ └──RightPanel # 右侧设置按钮,设置导航相干│ │ └──Screenfull # 全屏│ │ └──SvgIcon # svg图标│ │ └──ThemePicker # 右侧设置按钮,设置组题色彩│ │ └──templatesFrom # 运费模板│ │ └──ueditorFrom # 富文本编辑器│ │ └──uploadPicture # 上传图片组件│ │ └──UploadExcel # 下载Excel│ │ └──userList # 用户列表│ ├── layouts # 导航布局│ │ ├──index # 主页面│ │ ├──components # 导航组件│ │ └──Settings # 左边小按钮,设置导航等│ │ └──Sidebar # 侧边导航│ │ └──TagsView # tab标签页导航│ │ └──Navbar # 头部导航│ │ └──AppMain # 导航路由│ │ └──index.js # 组件援用│ │ └──mixins # 自适应大小│ ├── libs # 公共js办法│ │ └──settingMer # 配置申请地址│ ├── views # 所有页面│ │ └──login # 登录│ │ └──index # 登录│ │ └──dashboard # 首页│ │ └──product # 商品│ │ └──addProduct # 增加商品│ │ └──productAttr # 商品规格│ │ └──productClassify # 商品分类│ │ └──productList # 商品列表│ │ └──Reviews # 商品评论│ │ └──order # 订单治理│ │ └──index # 订单列表│ │ └──orderDetail # 订单详情│ │ └──logistics # 物流单号│ │ └──orderRefund # 退款单│ │ └──accounts # 财务│ │ └──reconciliation # 财务对账│ │ └──index # 财务对账│ │ └──record # 对账订单│ │ └──charts # 统计图│ │ └──marketing # 营销│ │ └──coupon # 优惠劵│ │ └──index # 路由│ │ └──couponList # 优惠券列表│ │ └──couponList # 会员支付记录│ │ └──system # 设置│ │ └──config # 素材治理│ │ └──freight # 运费模板│ │ └──service # 客服治理│ │ └──groupData # 组合设置│ │ └──list # 组合数据│ │ └──data # 组合数据列表│ │ └──setting # 设置-权限治理│ │ └──systemRole # 身份治理│ │ └──systemAdmin # 管理员治理│ │ └──systemLog # 操作日志│ │ └──systemForm # 设置-商城设置│ │ └──index # 店铺配置│ │ └──modifyStoreInfo # 根底配置│ │ └──error-page # 谬误页│ │ └──404 # 谬误页404│ │ └──403 # 谬误页403│ ├── filters # 过滤器│ ├── router # 路由配置│ │ └──modules # 页面路由模块│ │ └──accounts.js # 无关财务│ │ └──charts.js # 无关首页统计图│ │ └──config.js # 无关系统配置│ │ └──marketing.js # 无关优惠券│ │ └──group.js # 无关组合数据│ │ └──order.js # 无关订单│ │ └──product.js # 无关商品│ │ └──settingMer.js # 无关权限│ │ └──systemForm.js # 无关商城设置│ │ └──index.js # 路由的汇总│ ├── store # Vuex 状态治理│ ├── utils # 全局专用办法│ ├── styles # 款式治理│ ├── permission.js # 路由拦挡│ ├── settingMer.js # 业务配置文件│ ├── main.js # 入口文件 加载组件 初始化等│ └── App.vue # 入口页面├── tests # 测试├── .env.xxx # 环境变量配置├── .eslintrc.js # eslint 配置项├── .babelrc # babel-loader 配置├── .travis.yml # 自动化CI配置├── vue.config.js # vue-cli 配置├── postcss.config.js # postcss 配置└── package.json # package.json ...

July 20, 2021 · 3 min · jiezi

关于php:crmeb多商户系统总后台目录结构说明

├── public # 动态资源│ ├── favicon.ico # favicon图标│ └── index.html # html 模板├── src # 源代码│ ├── api # 所有接口api│ │ └──request.js # 申请封装│ │ └──accounts.js # 无关财务的接口│ │ └──promoter.js # 无关分销的接口│ │ └──app.js # 无关利用(小程序、公众号)的接口│ │ └──cms.js # 无关内容(文章治理、分类)的接口│ │ └──home.js # 无关首页的接口│ │ └──order.js # 无关订单的接口│ │ └──product.js # 无关商品的接口│ │ └──setting.js # 无关权限治理的接口│ │ └──system.js # 无关系统配置的接口│ │ └──systemForm.js # 无关表单组件的接口│ │ └──maintain.js # 无关平安保护的接口│ │ └──merchant.js # 无关商户的接口│ │ └──sms.js # 无关短信设置的接口│ │ └──user.js # 无关登录、用户的接口│ │ └──userFeedback.js # 无关用户反馈的接口│ │ └──freight.js # 无关物流设置的接口│ ├── assets # 图片、svg 等动态资源│ ├── icons # svg 等动态资源│ ├── components # 公共组件│ │ └──Breadcrumb # 头部题目标签│ │ └──cards # 统计│ │ └──echarts # 统计图│ │ └──goodsList # 商品列表│ │ └──Hamburger # 导航膨胀组件│ │ └──HeaderSearch # 导航搜寻组件│ │ └──iconFrom # 导航增加图标│ │ └──newsCategory # 图文组件│ │ └──RightPanel # 右侧设置按钮,设置导航相干│ │ └──Screenfull # 全屏│ │ └──SvgIcon # svg图标│ │ └──ThemePicker # 右侧设置按钮,设置组题色彩│ │ └──ueditorFrom # 富文本编辑器│ │ └──uploadPicture # 上传图片组件│ ├── layouts # 导航布局│ │ ├──index # 主页面│ │ ├──components # 导航组件│ │ └──Settings # 左边小按钮,设置导航等│ │ └──Sidebar # 侧边导航│ │ └──TagsView # tab标签页导航│ │ └──Navbar # 头部导航│ │ └──AppMain # 导航路由│ │ └──index.js # 组件援用│ │ └──mixins # 自适应大小│ ├── libs # 公共js办法│ │ └──settingMer # 配置申请地址│ ├── views # 所有页面│ │ └──login # 登录│ │ └──index # 登录│ │ └──dashboard # 首页│ │ └──product # 商品│ │ └──band # 品牌治理│ │ └──productClassify # 商品分类│ │ └──productExamine # 商品审核│ │ └──productComment # 商品评论治理│ │ └──order # 订单治理│ │ └──promoter # 分销│ │ └──user # 分销员列表│ │ └──config # 分销设置│ │ └──cms # 内容│ │ └──addArticle # 增加文章/编辑文章│ │ └──article # 文章治理│ │ └──articleCategory # 文章分类│ │ └──user # 用户│ │ └──group # 用户分组│ │ └──group # 用户标签│ │ └──list # 用户治理│ │ └──accounts # 财务│ │ └──bill # 充值记录│ │ └──capital # 资金记录│ │ └──extract # 提现治理│ │ └──reconciliation # 财务对账│ │ └──merchant # 商户│ │ └──list # 商户列表│ │ └──classify # 商户分类│ │ └──system # 商户菜单治理│ │ └──app # 利用│ │ └──wechat # 公众号│ │ └──menus # 微信菜单│ │ └──newsCategory # 图文治理│ │ └──save # 图文增加│ │ └──reply # 主动回复│ │ └──follow # 微信关注回复/有效关键词回复│ │ └──keyword # 关键字回复│ │ └──wxTemplate # 微信/小程序模板音讯│ │ └──system # 设置│ │ └──config # 零碎设置│ │ └──classify # 配置分类│ │ └──setting # 配置管理│ │ └──picture # 素材治理│ │ └──groupData # 组合设置│ │ └──list # 组合数据│ │ └──data # 组合数据列表/登录页幻灯片/首页幻灯片/首页导航按钮/首页举荐区/集体核心幻灯片/集体核心菜单/热门搜寻/分销特权/分销海报/充值金额配置│ │ └──setting # 设置-权限治理│ │ └──systemRole # 身份治理│ │ └──systemAdmin # 管理员治理│ │ └──systemLog # 操作日志│ │ └──systemMenu # 菜单治理│ │ └──systemForm # 设置-商城设置│ │ └──setSystem # 根底配置/商城配置/余额充值设置/文件上传/短信揭示开关/公众号领取配置/小程序领取配置/公众号配置/小程序配置│ │ └──sms # 短信设置│ │ └──smsConfig # 短信账户│ │ └──smsTemplate # 短信模板│ │ └──smsPay # 短信购买│ │ └──freight # 物流设置│ │ └──express # 物流公司│ │ └──maintain # 平安保护│ │ └──dataBackup # 数据备份│ │ └──auth # 商业受权│ │ └──safe # 保护-页面链接│ │ └──pageLinks # 页面链接│ │ └──userFeedback # 用户-用户反馈│ │ └──list # 反馈列表│ │ └──classify # 反馈分类│ │ └──error-page # 谬误页│ │ └──404 # 谬误页404│ │ └──403 # 谬误页403│ ├── filters # 过滤器│ ├── router # 路由配置│ │ └──modules # 页面路由模块│ │ └──accounts.js # 无关财务│ │ └──app.js # 无关利用(公众号)│ │ └──cms.js # 无关内容(文章治理、文章分类)│ │ └──config.js # 无关系统配置│ │ └──freight.js # 无关物流设置│ │ └──group.js # 无关组合数据│ │ └──maintain.js # 无关平安保护│ │ └──merchant.js # 无关商户│ │ └──order.js # 无关订单│ │ └──product.js # 无关商品│ │ └──promoter.js # 无关分销│ │ └──routine.js # 无关小程序│ │ └──safe.js # 无关保护│ │ └──setting.js # 无关权限│ │ └──sms.js # 无关短信│ │ └──systemForm.js # 无关商城设置│ │ └──user.js # 无关用户│ │ └──feedback.js # 无关用户反馈│ │ └──index.js # 路由的汇总│ ├── store # Vuex 状态治理│ ├── utils # 全局专用办法│ ├── styles # 款式治理│ ├── permission.js # 路由拦挡│ ├── setting.js # 业务配置文件│ ├── main.js # 入口文件 加载组件 初始化等│ └── App.vue # 入口页面├── tests # 测试├── .env.xxx # 环境变量配置├── .eslintrc.js # eslint 配置项├── .babelrc # babel-loader 配置├── .travis.yml # 自动化CI配置├── vue.config.js # vue-cli 配置├── postcss.config.js # postcss 配置└── package.json # package.json ...

July 20, 2021 · 4 min · jiezi

关于php:PHP数据结构链表的相关逻辑操作

链表的操作绝对程序表(数组)来说就简单了许多。因为 PHP 的确曾经为咱们解决了很多数组操作上的问题,所以咱们能够很不便的操作数组,也就不必为数组定义很多的逻辑操作。比方在 C 中,数组是有长度限度的,而在 PHP 中咱们就不会思考这个问题。如果是应用 C 的话,这个长度限度就是数组构造的一大劣势,而链表,不论是在 C 还是在 PHP 中,都不会受到长度问题的限度。可能限度链表的只有内存的大小。另外,链表的链式构造也可能为咱们带来一种全新的不同于数组操作的体验,对某些性能算法来说,链表也更有劣势。 话不多说,间接来进入明天的内容吧! 链式构造的定义首先,在之前的对于线性表的第一篇文章中咱们就说过链表的定义,在这里,咱们再温习一下之前的那个对于链表的图来更清晰的了解链表的概念。 咱们将图中的节点 Node 用类来示意: /** * 链表构造 */class LinkedList{ public $data; public $next;}一个链表类就看能够看做是链表中的一个节点,它蕴含两个内容,data 示意数据,next 示意下一个节点的指针。就像链条一样一环套一环,这就是传说中的链表构造。 生成链表及初始化操作/** * 生成链表 */function createLinkedList(){ $list = new LinkedList(); $list->data = null; $list->next = null; return $list;}/** * 初始化链表 * @param array $data 链表中要保留的数据,这里以数组为参考 * @return LinkedList 链表数据 */function Init(array $data){ // 初始化 $list = createLinkedList(); $r = $list; foreach ($data as $key => $value) { $link = new LinkedList(); $link->data = $value; $link->next = null; $r->next = $link; $r = $link; } return $list;}$link = Init(range(1, 10));print_r($link);// LinkedList Object// (// [data] =>// [next] => LinkedList Object// (// [data] => 1// [next] => LinkedList Object// (// [data] => 2// [next] => LinkedList Object// (// [data] => 3// [next] => LinkedList Object// (// [data] => 4// [next] => LinkedList Object// (// [data] => 5// [next] => LinkedList Object// (// [data] => 6// [next] => LinkedList Object// (// [data] => 7// [next] => LinkedList Object// (// [data] => 8// [next] => LinkedList Object// (// [data] => 9// [next] => LinkedList Object// (// [data] => 10// [next] =>// )// )// )// )// )// )// )// )// )// )// )在应用链表的时候,咱们个别会让第一个结点不蕴含任何数据,仅仅是做为一个空的结点来指向第一个有数据的结点。这种结点咱们能够称之为头结点,如果须要判断链表是否为空的话,只须要判断第一个结点的 next 是否为空就能够了。在下面的代码中,创立链表 createLinkedList() 函数其实就是生成了这样一个头结点。 ...

July 20, 2021 · 3 min · jiezi

关于php:Hyperf-22-版发布-企业级的渐进式-PHP-协程框架

前言首先感激所有 Hyperf 的支持者,从公布至今两年的工夫里,咱们保持每周公布一个小版本,截止至今曾经公布了超过 106 个版本,这是 Hyperf 团队传播对用户保持和负责任精力最间接的一种形式,咱们用口头来阐明所有,往后咱们仍将判若两人地持续放弃 Hyperf 的迭代与保护。 同时咱们也很荣幸看到越来越多的公司抉择了 Hyperf 作为公司我的项目的框架来应用,并反哺了很多的 Pull Request 和 Bugfixs 给 Hyperf,以后 Hyperf 的 Contributors 已超 200 人,感激大家一起共造了生态的凋敝,咱们必然不负众望! Thanks ALL 在继续迭代的过程中,咱们又产生了一些新的思路。咱们对这些思路进行迭代、验证,并最终积淀到了 2.2 版本中,明天很荣幸向大家颁布,Hyperf 2.2 版本公布! 次要性能迭代DI 底层实现重构在 2.0-2.1 版本时,为了实现 AOP 作用于非 DI 治理的对象(如 new 关键词实例化的对象时),底层实现采纳了BetterReflection 组件来实现相干性能,带来新的编程体验的同时,也还是存在一些此前未攻克的问题,如下: 无扫描缓存时我的项目启动很慢非凡场景下 Inject 和 Value 不失效BetterReflection尚未反对 PHP 8 (截止发版时)在新的版本里,咱们弃用了 BetterReflection 的利用,采纳了 子过程扫描的形式 来解决此前的问题,以上这些痛点,咱们全副解决了~ 用正向的角度来形容这个性能的变更: 无缓存下,启动工夫缩减一个数量级,以笔者所在公司的某个巨型我的项目为例,原启动工夫长达 5分钟,新版本只需 10秒!丰盛了 Inject 注解注入的实用场景,但惋惜仍有一种状况下有效(父类 private 属性注入时生效,与此前版本体现统一),咱们会持续致力攻克该场景的实现反对 PHP 8 及 Attributes 原生注解个性简而言之,DI 组件作为 Hyperf 的外围组件之一,当初曾经达到了一个全新的阶段,翻新与实用值满格~ ...

July 19, 2021 · 3 min · jiezi

关于php:PHP数据结构顺序表数组的相关逻辑操作

在定义好了物理构造,也就是存储构造之后,咱们就须要对这个存储构造进行一系列的逻辑操作。在这里,咱们就从程序表动手,因为这个构造非常简单,就是咱们最罕用的数组。那么针对数组,咱们通常都会有哪些操作呢? 不必想得太简单,咱们只须要这几个简略的操作就能够了: 1.查找2.插入3.删除 是不是很简略?为什么没有遍历呢?咱们常常要去遍历一个数组呀? 请留神,在这里,咱们是以数据结构的角度来讲程序表这个物理构造。遍历操作个别针对的会是更简单的一些构造,比方树、图,从一个结点开始去遍历所有的门路之类的。而对于程序表这个物理构造来说来说,咱们只须要把握上述那三个操作,不须要蕴含遍历。 又有同学说了,在 PHP 中,这三个操作几乎太简略好不好,齐全没有技术含量呀! 小心不要入坑了哦,查找咱们说的是找到这个值所在的下标,而不是给你一个下标简略的输入一个值。另外,插入和删除咱们是须要思考一个问题的,那就是咱们第 i 个地位插入或者删除数据之后,i+1 及其之后的数据是不是也要相应的挪动呢?要小心,咱们是插入和删除一个下标地位的内容,而不是批改替换这个下标的内容!!! 好吧,还是间接以实例来阐明。 插入/** * 数组插入 * @param array $list 程序表数组 * @param int $i 插入数据下标 * @param mixed $e 数组元素 * return bool 成功失败后果 */function ListInsert(array &$list, int $i, $e){ $c = count($list); if ($i < 0 || $i > $c) { return false; } $j = $c - 1; while ($j >= $i) { // 从后往前,下一个地位的值变成当初这个地位的值 // 数据向后移动 $list[$j + 1] = $list[$j]; $j--; } // 在指定地位插入值 $list[$i] = $e; return true;}插入操作首先要判断是否下标越界。接下来就从后往前地将插入地位之后的数据向后移动一位,最初将新减少的数据放到指定的地位。须要留神的是,在这个操作中,咱们最次要关怀的就是这个数据地位的挪动。咱们为什么要从数组最初一位开始进行移动,而不是从插入地位开始挪动呢?如果从插入地位开始,那么前面的数据就会都是一个数据了,也就是插入地位的下一个数据。大家有趣味的能够本人尝试一下。 ...

July 19, 2021 · 2 min · jiezi

关于php:开发微商城分销系统有什么优势

随着挪动互联网的疾速倒退,新批发和共享经济将会是将来电商行业倒退的支流模式。开发微商城分销零碎整合了传统批发的线下渠道和线上渠道,每一个品牌商、厂商、供货商甚至分销商通过开发微商城分销零碎,而后通过倒退分销商、治理分销商来达到本人扩充销售、进步知名度的目标。开发微商城分销零碎的劣势:1、运行机制微商城分销零碎与传统销售模式不一样,它采纳三级分销的模式。能够让分销商疾速的将本人的好友转化为上级分销商。不仅能够促成产品的推广,还能够使分销商的社交更加扩充,想成一个裂变的倒退模式。这是它最显著的特点。2、佣金模式传统销售形式采纳的是卖了多少产品能够失去多少利润,这样对于上级销售商来说没有多少利润空间。而绝对传统销售而言,分销零碎有俩种获取利润的形式,第一种是:与传统销售一样,间接获取利润,也就是卖多少失去多少;第二种是:倒退分销商,当分销商卖出产品时咱们也能够分得一笔佣金。简略来说,就是你让一个人成为你的上级,当那个卖出货色的时候,你也能够分舵一笔钱。这是它佣金方面的长处。3、推广形式很多人会放心产品卖不出去无奈进行销售,怎么办?而分销零碎就是为此诞生的,它能够通过朋友圈、微信群、好友之间流传,让每一个好友都有可能成为你的分销商,更有可能成为你的客户。4、轻松治理分销商,把握市场动向 开发微商城分销零碎可能精确即时治理分销商,把握分销商的销售状况,从而理解产品的销售状况,最重要的是不仅实现了产品的销售与推广,还能够依据消费者的需要来扭转产品的供求,理解市场动向。5、多样化的销售前端模式开发微商城分销零碎实现了多层级的分销,企业与分销商分工合作,分销商能够领有本人的微分店,微商城的洽购下单,举荐返佣和发动互动等流动,很好地利用了朋友圈的社交劣势,实现了裂变式增长,使销售前端的模式更加多样化。6、精准播送品牌、疾速进步品牌知名度比方,100家分销商上架你们的产品,分销商将你们的产品通过社交工具分享进来,以单品每家10个流量计算,流量上千个别都不成问题。类比淘宝直通车、百度推广就晓得省多少银子了。招募100个分销商上架,至多须要分割几千个微商分享商,这个过程,是在向几千个业内人士精准地宣讲你的品牌和产品。几百个分销商在销售你的品牌产品,也能疾速进步品牌认知度和知名度。7、理解用户的需要开发微商城分销零碎的商家能够利用微信做相干的产品考察制作销售计划,比方在微信敌人圈里发动投票流动,采集用户信息,开掘用户的需要,而后分 销商再依据用户的需要,摸索分销商城里销售的商品卖点和价值。只有投合了微信消费者的想法,晋升分销零碎的服务服务质量,做到粗疏化分销,这样微商城商家 能力取得更好的营销成果。 如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star: http://github.crmeb.net/u/defu 不胜感激 !

July 19, 2021 · 1 min · jiezi

关于php:PHP数据结构线性表顺序表链表别再傻傻分不清楚

听从所有教材以及各类数据结构相干的书书籍,咱们先从线性表开始入门。明天这篇文章更偏概念,是对于有线性表的一个知识点的汇总。 上文说过,物理构造是用于确定数据以何种形式存储的。其余的数据结构(树、图)、算法等根本都是建设在这样一个物理构造之上的,也能够说,物理构造就是数据结构的基本。在这里,咱们先介绍两个物理构造,也是咱们未来学习数据结构的基石,它们就是程序表和链表。 程序表不扯简单的定义,不扯什么数学表达式,咱们最直观的了解,程序表就是数组。 是不是非常简单,没错,在 PHP 或者 C 的世界中,咱们就把程序表定义为数组,而雷同的名词还包含:顺序存储、程序构造等。只有看到这种名词,马上想到数组就能够了。当然,在 Java 中,咱们也能够将 List 这类的汇合当成是顺序存储构造。不过须要留神的是,Java 的 HashMap ,在 PHP 中是以键值对模式定义的数组,它们是哈希表(Hash),从模式上来说,他们并不是程序的。在这里咱们肯定要记住,像数组下标递增这样程序构造的才是顺序存储构造。 程序表个别占用间断的内存空间。不仅逻辑上,连物理空间上都是相邻间断的。 链表链表个别在 C 中会定义为一个构造体,其中包含数据和指向下一个链表的指针,它不是程序的,尽管逻辑是有程序的(按指针指向),但在物理是能够离开的。也就是说,链表不必占用间断的内存空间,不须要在初始化的时候像数组一样给定长度。 在 PHP 中,咱们没有构造体这种语法模式,所以咱们间接应用类来示意链表构造。 class Node{ public $data; public Node $next;}这就是一个简略的链表构造,咱们能够把它叫做一个“结点”。data 中寄存咱们要保留的数据,能够是任意类型。而 next 则是咱们下一个链表结点。如果咱们须要简略的遍历链表,间接不停的调用 next 直到它为空即可。 while($n->next){ $n = $n->next; echo $n->data, PHP_EOL;} 上图就是对于链表的逻辑状态以及它的遍历方向。具体的链表操作相干函数咱们将在前面的文章中进行解说。 链表有很多种形式,下面咱们定义的是一个简略的单向链表。咱们还能够定义双向链表(加一个 prev 指向上一个结点),循环链表(最初一个next指回第一个结点)以及双向循环链表(最初一个next指回第一个结点,第一个的 prev 指向最初一个结点)。对于这些内容,咱们也会放到前面的文章中一一解说。 线性表理解了程序表和链表之后,咱们最初就来说说线性表。 其实,程序表和链表这两种物理构造在默认状态下所实现的就是“程序表”这个逻辑数据结构。 程序表:由n(n>0)个数据个性雷同的元素形成的无限序列(严蔚敏版) 留神几个关键点: 无限:数组长度、链表内存大小序列:逻辑有序(数组是逻辑和物理都有序,链表是逻辑有序而物理无序)数据个性雷同:PHP 中不显著,C 或 Java 中数组是固定类型的,而且也要给一个初始长度为什么说线性表这么重要呢?咱们想想 MySQL 这样一行一行存储数据的关系型数据库,一张数据表不就是一个线性表吗?特地是咱们做 PHP 的程序员,天天都是在和数组(数据库读出来的数据个别都放到数据中)打交道(当然,咱们用哈希可能更多些),也就是说,咱们在做开发的时候,天天都在接触这个货色,你说它重要不重要。 而 树 和 图 这些数据结构却并不是线性表,在事实的归类中,它们是属于 非线性表 的领域的。线性表在个很大的特点是只有前后关系,不论是链表还是数组,它们都是遵循着这种前后关系的,然而在 树 和 图 中,除了前后之外,还有上下左右等更简单的关系。虽说它们的根本表现形式仍然是应用数组和链表,然而从严格的角度来说,或者从考试面试的角度来说,它们真的不属于线性构造,而应该划分到 非线性构造 中。 ...

July 18, 2021 · 1 min · jiezi

关于php:构建php自己的无浸入式的链路追踪和性能监控

最近浏览php源码,为了验证成果,写了一个php扩大,次要性能就是打造php本人的链路追踪和性能监控先从github下载源码 https://github.com/wuxian12/i... 编译装置就能够应用了 当初只是一个基本功能,前面缓缓欠缺 外围性能就是改写php的执行函数,就是平时常常写的代理 PHP_MINIT_FUNCTION(pid){ REGISTER_INI_ENTRIES(); ori_execute_ex = zend_execute_ex; zend_execute_ex = pid_execute_ex; ori_execute_internal = zend_execute_internal; zend_execute_internal = pid_execute_internal; return SUCCESS;}执行时发现是要拦挡的函数就获取函数的参数返回值记录日志,继续执行php原始的执行函数 ZEND_API void pid_execute_core(int internal, zend_execute_data *execute_data, zval *return_value){ char *logs_dir = {0}; char *re_func = {0}; char *file_log = "trace.log"; //从php.ini文件读取拦挡函数和日志目录 logs_dir = INI_STR("pid.log_path"); re_func = INI_STR("pid.function"); char *name = (char *) malloc(strlen(logs_dir) + strlen(file_log)); sprintf(name, "%s%s", logs_dir, file_log); FILE *fp; if((fp = fopen(name, "a+")) == NULL){ printf("file cannot open \n"); } zend_function *zf = obtain_zend_function(execute_data); int flag = 0; char str_1[512] = {0}; char *token; const char s[2] = ","; if (zf->common.function_name != NULL){ sprintf(str_1, ZSTR_VAL(zf->common.function_name)); /* 获取第一个子字符串 */ token = strtok(re_func, s); /* 持续获取其余的子字符串 */ while( token != NULL ) { printf( "%s\n", token ); if(strcmp(str_1, token) == 0){ flag = 1; fputs("\n执行函数的名字:", fp); fputs( str_1, fp); break; }else{ flag = 0; } token = strtok(NULL, s); } } int arg_count = 0; arg_count = ZEND_CALL_NUM_ARGS(execute_data); smart_str res = {0}; smart_str buf = {0}; if (arg_count) { zval *p = ZEND_CALL_ARG(execute_data, 1); if (execute_data->func->type == ZEND_USER_FUNCTION) { uint32_t first_extra_arg = execute_data->func->op_array.num_args; if (first_extra_arg && arg_count > first_extra_arg) { p = ZEND_CALL_VAR_NUM(execute_data, execute_data->func->op_array.last_var + execute_data->func->op_array.T); } } int i; for (i = 0; i < arg_count; i++) { php_var_export_ex(p, 2, &buf); p++; } if(flag == 1){ fputs(";执行函数的参数:", fp); fputs( ZSTR_VAL(buf.s), fp); //printf("执行函数的参数 %s ......\n", ZSTR_VAL(buf.s)); } } if (internal) { if (ori_execute_internal) { ori_execute_internal(execute_data, return_value); } else { execute_internal(execute_data, return_value); } } else { ori_execute_ex(execute_data); } if (return_value) { /* internal */ php_var_export_ex(return_value, 2, &res); if(flag == 1){ fputs(";执行函数的返回后果:", fp); fputs( ZSTR_VAL(res.s), fp); //printf("外部函数返回的后果 %s === \n", ZSTR_VAL(res.s)); } } else if (execute_data->return_value) { /* user function */ php_var_export_ex(execute_data->return_value, 2, &res); if(flag == 1){ fputs(";执行函数的返回后果:", fp); fputs( ZSTR_VAL(res.s), fp); //printf("自定义函数返回后果 %s ===\n", ZSTR_VAL(res.s)); } } fclose(fp);}

July 17, 2021 · 2 min · jiezi

关于php:PHP数据结构在学数据结构和算法的时候我们究竟学的是啥

一说到数据结构与算法,大家都会避之不迭。这原本是一门业余基础课,然而大部分人都并没有学好,更不用说我这种科班出身的码农了。说实话,还是很艳羡科班出身的程序员,因为你们在日常工作或者面试中,只须要温习一下就好了,而我则是齐全的从头开始学。不过,还好所有都不晚,在这里,咱们就用 PHP 作为示例代码,来和大家一起真正的从头学一遍恐怖的数据结构与算法。 数据结构什么是数据结构呢? 数据结构是带“构造”的数据元素的汇合,“构造”就是指数据元素之间存在的关系 这是严蔚敏老师在《数据结构》第二版中对数据结构的定义。其实,就是对于数据的一种组合模式。就像你去一家书店,或者是图书馆,或者是你家的书柜。这些书应该怎么摆放呢?对于书的摆放模式,就是数据结构。你能够乌七八糟的摆放,也能够分门别类的摆放,也能够依据本人的兴趣爱好摆放,也能够将最罕用的书放在手边,将不常看的书放在柜子的深处。这些都是数据结构。 在程序世界中,数据结构蕴含两种模式,一种是逻辑构造,一种是物理构造。 逻辑构造即便你齐全没有接触过数据结构,但只有你学习过编程,肯定会多多少少地据说过这样一些名词:汇合、线性表、树、图,它们指的就是数据结构中的逻辑构造。也就是从逻辑关系上形容数据,是具体问题形象进去的数学模型。比方咱们将书进行分类,每个分类下放着绝对应的书籍,这就是一种树形构造。或者咱们将书按书名拼音建设索引,而后在书架上贴上索引标签,这就是一种哈希构造。 逻辑构造将是咱们整个学习中的一个重点,因为各种算法都是针对这些构造的操作实现。这个咱们在上面的算法解释中再进行具体的阐明。 物理构造物理构造次要是数据的物理存储形式,也叫做存储构造。这个十分好记,它只有两种模式,顺序存储构造和链式存储构造。通常,顺序存储构造咱们应用数组来示意,而链式存储构造在 C语言 中应用构造体的指针来示意,但在 PHP 中,链式构造咱们将应用类来表述。 下面说的那些逻辑构造,都能够用程序或者链式的形式来实现,不论应用哪种形式,都能够实现对应逻辑构造的算法操作,但不同的模式或者算法又有不同的效率。而效率,正是整个数据结构和算法学习外围中的外围。 算法接下来咱们看看什么是算法。 算法是一个无限指令集,它承受一些输出(有些状况下不须要输出),产生输入,并肯定在无限步骤之后终止 这是陈越老师在浙大版《数据结构》第二版中对于算法的定义。其实咱们简略点了解的话,针对下面的数据结构的一系列操作,就是算法。比如说咱们定义了一个树,如何遍历这颗树呢?这就是一个算法,遍历一颗树有先序、中序、后序,也能够进行层序遍历,有这么多种办法,哪种好?哪种不好?用哪种物理构造?线性还是链式?这些论断都以算法的执行效率为根底。能够说,算法品种繁多,效率也千差万别,然而,不能一棒子打死说某个算法肯定不好,每种算法也有它不同的利用场景。这就是咱们要钻研算法的起因。 对于算法,咱们最关怀的是它的效率,这个效率在这里咱们应用的是工夫复杂度和空间复杂度来定义的。 工夫复杂度工夫复杂度个别应用 O(n) 来示意,它关怀的是问题规模和语句频度,个别会以 n 示意问题规模 (留神,这个 n 是未知的,如果这个 n 是已知的,那么它就是常数阶)。这个 n 有可能是一个常数(n 明确等于多少),记成 O(1) 。这是最好的状况,也能够线性增长,如 O(n) 。当然也可能对数或指数级增长,O(logN) 、 O(N^2),当然最要不得的是 O(2^N) 级的增长,这种状况下可能有生之年你都看不到运算的后果了。 咱们能够看看简略的一段代码来剖析它的工夫复杂度: echo $a++, PHP_EOL; // O(1)$n = 10; // 假如一个数量用于测试,理论这个 n 是未知的,如果面试题代码中真的呈现了这种已知 n 的状况,那么这个算法就是 O(1)for($i = 0;$i<$n;$i++){ echo $i, PHP_EOL;}// O(n)for($i = 0;$i<$n;$i*=2){ echo $i, PHP_EOL;}// O(logN)for($i = 0;$i<$n;$i++){ for($j = 0;$j<$n;$j++){ echo $i, $j, PHP_EOL; }}// O(N^2)从下面代码中能够看出,循环嵌套次数与 n 的增长有很大的关系,另外就是看在循环外部的操作也会影响到增长的状况。比方如果咱们是这样一段代码: ...

July 17, 2021 · 1 min · jiezi

关于php:事件消费者之-Projector-事件溯源

本文转载自【何以解耦】:https://codedecoupled.com/php... 在事件溯源架构中,通过事件流获取利用的以后状态可能造成性能问题,Projector(放映机)通过监听事件,生成独立的视图保留利用的以后状态。咱们能够将其设想成数据库中的物化视图,或者是一种缓存。 以下是从咱们的实战经验中总结出的几种 Projector 用例。 实战用例查问模型用户对页面的反应速度要求较高,咱们能够应用 Projector 生成服务于用户的查问模型。 值得一提的是 Projector 可应用与事件流不同的数据长久化形式,比方事件流本来贮存在 MySQL, Projector 可应用 ElastiSearch 长久化查问模型: 让咱们看一个简略的案例,应用 Projector 生成订单查问模型: 反对业务实现当其余客户须要及时获取利用的以后状态,然而无奈通过简略的事件传送时,咱们能够应用 Projector 生成相似于缓冲的 Repository。 此 Repository 将为实现业务逻辑提供及时的利用状态。 让咱们看一个简略的案例,应用 Projector 生成车辆可预约 Repository: 值得注意的是,这种用例偏向于同步解决计划,因为其时效性个别比拟大。 总结Projector 是一个简略且弱小的模式,Projector 的职责繁多且专一,易于编写单元测试。 本文转载自【何以解耦】:https://codedecoupled.com/php...,如果你也对 TDD,DDD以及简洁代码感兴趣,欢送关注公众号【何以解耦】,一起摸索软件开发之道。

July 17, 2021 · 1 min · jiezi

关于php:视频二次裁剪时间计算出原片的时间片段算法

视频裁剪:最近遇到了一个如下的需要, 对原片进行裁剪经营第一次裁剪视频, 会对视频进行删减(掐掉片头片尾之类), (此处疏忽视频的总时长, 单位秒) [10, 15][20, 70]以上的两个片段会合并成一个新的视频:(15-10)+(70-20)=55经营第二次裁剪视频的时候, 会对第一次裁剪后的视频裁剪(如删除两头局部, 在之前的片头片尾根底上) 裁剪的工夫应该用第一次裁剪的工夫根底上计算理论的裁剪工夫应该从原片上计算说来简单,用例子阐明一下$first = [ // F1 [10, 15], // F2 [20, 70],];$second = [ // S1 [2, 3], // S2 [4, 9], // S3 [45, 55],];## 理论应该返回一个列表$output = [ // S1 在 F1 失去片段 [12, 13] // S2 在 F1 失去的片段 [14, 15] // S2 在 F2 失去的片段 [20, 24] // S3 在 F2 失去的片段 [60, 70]];通过下面的过程之后,拿到$output的后果, 再去原片裁剪即可.代码如下$first = [ [10, 15], [20, 70],];$second = [ // 这个是第一段够的 [2, 3], // 第一段不够, 用第二段来补全 [4, 9], // 这个间接跳到第二段 [45, 55],];var_dump(makeSections($first, $second));function makeSections(array $firstCutSections, array $secondCutSections) : array{ // 不论是哪一个为空, 间接返回另外一个即可 if (empty($firstCutSections)) { return $secondCutSections; } if (empty($secondCutSections)) { return $firstCutSections; } $newSections = []; foreach ($secondCutSections as $currSection) { $usableSections = $firstCutSections; $start = 0; $usableLength = 0; // 残余的长度 // 残余的开始对齐长度 $remainLength = $currSection[1] - $currSection[0]; $remainStart = $currSection[0]; while ($remainLength != 0) { // 如果没有可用的时间段, 取出一个来用 if ($usableLength == 0) { $sec = array_shift($usableSections); if (is_null($sec)) { throw new Exception('第二次截取的视频比第一次长'); } $usableLength = $sec[1] - $sec[0]; $start = $sec[0]; continue; } // 如果坐标没对齐, 那么去对齐坐标 if ($remainStart > 0) { // 两种状况 if ($remainStart > $usableLength) { $remainStart -= $usableLength; $start += $usableLength; $usableLength = 0; } else { $usableLength -= $remainStart; $start += $remainStart; $remainStart = 0; } continue; } // 长度应该用哪一种 $contentLength = 0; if ($remainLength > $usableLength) { $contentLength = $usableLength; $remainLength -= $usableLength; $usableLength = 0; } else { $contentLength = $remainLength; $usableLength -= $remainLength; $remainLength = 0; } var_dump($contentLength); // 取出每一端工夫存储 $newSections[] = [ $start, $start + $contentLength, ]; } } return $newSections;}博客原文https://www.shiguopeng.cn/archives/522 ...

July 16, 2021 · 2 min · jiezi

关于php:Swoole-v470-版本正式发布Swoole-官网支持直接运行-Swoole-代码

在 Swoole 官网减少了 在线运行 的按钮,能够间接运行首页提供的一些示例代码,当然也能够手动输入一些 PHP 代码进行测试。 能够拜访 Swoole 官网首页进行测试应用:https://www.swoole.com/ 目前还处于测试阶段,有遇到 BUG 能够向识沃科技客服反馈或交换群中反馈。 版本阐明在未正式公布时,对于一些新个性和性能公布过文章进行阐明,所以反复的在此就不再赘述,能够查看: Swoole v4.7 版本新个性预览之 Process\Pool::detach()Swoole v4.7 版本新个性预览之 onDisconnect 事件回调Swoole v4.7 版本新个性预览之 Co::cancel()Swoole v4.7 版本预览之反对 c-aresSwoole v4.7 版本新个性预览之反对为每个端口设置不同的心跳检测时间对于其余的一些批改进行阐明: 禁止 Hook 曾经被 PHP 禁用的函数在之前的版本中,如果应用disable_functions将办法进行了禁用,在 HOOK 之后仍旧能失常调用。 如下代码: var_dump(`ls`);Swoole\Coroutine\run(function () { var_dump(`ls`);});保留到test.php中,命令行应用php -d disable_functions=shell_exec test.php执行 之前的版本输入为: PHP Warning: shell_exec() has been disabled for security reasons in /Users/lufei/Swoole/test.php on line 3NULLstring(11) "swoole.php"而降级 v4.7.0 之后,行为和 HOOK 前统一。 PHP Warning: shell_exec() has been disabled for security reasons in /Users/lufei/Swoole/test.php on line 3NULLPHP Warning: shell_exec() has been disabled for security reasons in /Users/lufei/Swoole/test.php on line 6NULLCoroutine\go() 办法减少了返回值之前的版本中应用 Coroutine\go() 办法不会返回协程 ID,从v4.7.0中开始减少了返回值,返回以后协程 ID。 ...

July 16, 2021 · 2 min · jiezi

关于php:基于-飞鹅云开放平台-的-PHP-接口组件

基于 飞鹅云开放平台 的 PHP 接口组件 装置composer require fendui/feieyun -vvv配置请先注册 飞鹅云开放平台 账号,获取到相应的用户名和 api key 应用$username = 'username';$u_key = 'u_key';$feieyun = new \fendui\Feieyun($username, $u_key);// 各个接口定义公有参数$private_params = ['sn' => '打印机编号'];// 形式1,设置公共参数apiname, eg: Open_printerAddlist$response_data = $feieyun->setApiName('Open_printerAddlist')->request($private_params);// 形式2,应用已定义的接口类$response_data = $feieyun->printerAddlist($private_params);已定义的接口类增加打印机 printerAddlist打印订单 printMsg标签机打印订单 printLabelMsg删除批量打印机 printerDelList批改打印机信息 printerEdit清空待打印队列 delPrinterSqs查问订单是否打印胜利 queryOrderState查问指定打印机某天的订单统计数 queryOrderInfoByDate获取某台打印机状态 queryPrinterStatus

July 16, 2021 · 1 min · jiezi

关于php:基于NginxPHP实现的带权限验证的静态文件服务器如某些情景需要校验参数后才能返回资源或者缩略图生成等

基于Nginx+PHP实现的带权限验证的动态文件服务器,如某些情景须要校验参数后能力返回资源,或者缩略图生成等。1、Nginx配置1、动态文件存储在download中,会被设置为internal,即只能外部拜访不容许内部间接拜访 2、所有动态资源申请均打到PHP程序上,通过权限验证后能力拜访图片实在存储门路 /download 禁止内部间接拜访location ^~ /download { internal; # alias可选 用于额定配置理论门路,即非download目录 #alias /home/qii/imgtest/download;}# 图片文件捕捉 能够增加本人对应的动态资源后缀location ~* \.(png|jpg|jpeg|gif)$ { #如果文件不存在,则rewrite到PHP脚本文件进行解决 if (!-f $request_filename) { rewrite ^/.*$ /autoimg.php; } #如果文件存在,则设置过期工夫,实际上是在PHP脚本文件解决后交给nginx时会到此逻辑 if ( -f $request_filename ) { expires 30d; }}2、PHP解决脚本<?php// autoimg.php// 假如sign参数为校验参数,有该参数即可通过验证,否则不通过if (!isset($_GET['sign'])) { exit('get img failed!');}// 图片实在寄存门路$imagePath = $_SERVER['DOCUMENT_ROOT'] . '/download/';// 获取url中的图片名 如 http://localhost/111.jpg 获取值为111.jpg$image = trim(parse_url($_SERVER['REQUEST_URI'])['path'], '/');// 拼接图片实在全门路 如 /home/qii/imgtest/download/111.jpg$fullPath = $imagePath . $image;// 获取图片mime信息 设置Content-type头$mime = getimagesize($fullPath)['mime'];header("Content-Type: $mime");// 设置sendfile头部,让nginx跳转到download下查找对应图片 相当于交给nginx进行后续解决header("X-Accel-Redirect: /download/$image");最终成果网站根目录 /home/qii/imgtest/home/qii/imgtest.├── autoimg.php└── download └── 111.jpg拜访门路为 http://localhost/111.jpg?sign 胜利拜访门路为 http://localhost/111.jpg 失败如间接拜访 http://localhost/download/111.jpg 失败,因为download文件夹只能外部拜访 ...

July 16, 2021 · 1 min · jiezi

关于php:PHP中的文件对比扩展

文件比照这个扩大当初用得比拟少,因为大部分状况下咱们都在应用一些代码管理工具,比方 Git 或者 Svn 之类的,其实它的作用就十分相似这类工具,另外还有一个十分罕用的 Beyond Compare 工具也能不便地让咱们可能进行文件的比照。 装置及筹备工作在 PHP 中的这个文件扩大叫做 xdiff 扩大,咱们能够间接在 pecl 中下载并装置。 须要留神的是,装置这个扩大须要操作系统装置 libxdiff 工具,在文章最下方的参考链接中有这个工具的官网地址。libxdiff 无奈应用默认的 yum 装置,所以须要下载之后自行装置。和其它的 Linux 工具一样,装置过程非常简单,这里就不多赘述了。 xdiff 扩大反对字符串和文件两种模式的差别比照以及一些相干的操作,这里咱们以字符串的操作为主进行解说,文件相干的操作将在最初给出全副的操作函数用法。首先,咱们须要定义一些字符串以及相干的文件便于后续的操作。 $old_article = "我本有为野客,飘飘浪迹世间。一时被命住名山。未免随机应变。识破尘劳扰扰,何如乐取安闲。流霞细酌咏诗篇。且与白云为伴。";$new_article = "我本有为野客,飘飘浪迹世间。一时被命住名山。未免随机应变。识破尘劳扰扰,何如乐取安闲。一流霞细酌咏诗篇。且与白云为伴。";$new_article1 = "我本有为野客,飘飘浪迹世间。一时被命住名山。未免随机应变。二识破尘劳扰扰,何如乐取安闲。流霞细酌咏诗篇。且与白云为伴。三一四一";file_put_contents('old_file.txt', $old_article);file_put_contents('new_file.txt', $new_article);file_put_contents('new_file1.txt', $new_article1);字符串差异$diff = xdiff_string_diff($old_article, $new_article);var_dump($diff);// string(273) "@@ -1,4 +1,4 @@// 我本有为野客,飘飘浪迹世间。// 一时被命住名山。未免随机应变。// -识破尘劳扰扰,何如乐取安闲。// +识破尘劳扰扰,何如乐取安闲。一// 流霞细酌咏诗篇。且与白云为伴。// \ No newline at end of file// "应用 xdiff_string_diff() 函数就能够取得两段字符串中的差别信息。能够看到它的内容构造和 Git 的文件差别比照返回的内容十分类似。像用 + 、 - 号示意的那一行的差别,咱们只有应用过 Git 或 Svn 就肯定不会生疏。 合并字符串var_dump(xdiff_string_merge3($old_article, $new_article, $new_article1, $error));// string(180) "我本有为野客,飘飘浪迹世间。// 一时被命住名山。未免随机应变。// 识破尘劳扰扰,何如乐取安闲。一// 流霞细酌咏诗篇。且与白云为伴。"var_dump($error); // NULLxdiff_string_merge3() 函数用于将三个字符串合并到一起,也是相似于 Git 中的 merge 性能。不过这个函数须要三个字符串,然而通过测试咱们发现只有第一个 \$new_article 和原始的 $old_article 合并胜利了。第三个 $new_article1 并没有合并到最初返回的字符串中。对于这个函数的性能和理论的成果并不统一的问题并没有找到任何相干的参考资料,官网文档的介绍也十分地简略,所以如果大家如果有晓得这个函数的实在具体情况的,能够留言一起探讨哦! ...

July 16, 2021 · 2 min · jiezi

关于php:在PHP中操作文件的扩展属性

在操作系统的文件中,还存在着一种咱们能够本人定义的文件属性。这些属性不是保留在文件内容中,也不是间接能够通过 ls -al 所能看到的内容。它们能够将一个键值对信息永恒得关联到文件上,个别当初的 Linux 零碎都反对这样的文件扩大属性的性能。在操作系统中咱们能够通过 setfattr、 getfattr、 attr 这些命令来操作它们。当然,PHP 也为咱们提供了一个扩大能够用于对文件的扩大属性进行操作。 增加扩大属性$file = __FILE__;var_dump(xattr_set($file, 'Author', 'ZyBlog')); // bool(true)var_dump(xattr_set($file, 'Num.', 121 )); // bool(true)var_dump(xattr_set($file, 'Description', 'shuo ming', XATTR_ROOT)); // bool(true)首先咱们定义了操作的文件,在这里咱们间接应用 \_\_FILE\_\_ 魔术常量来操作以后咱们测试的这个 php 文件。而后应用 xattr_set() 就能够设置文件的扩大属性了。文件的扩大属性有命名空间的概念,PHP 中也相应地为咱们提供了 一般(user)命名空间 和 XATTR_ROOT(root命令空间) 两种模式。root 命名空间中的属性能够由超级用户设置,对其余用户不可见,而 user 命名空间则是依据文件的权限来定义的,也就是以后能够操作这个文件的用户就能够读取到这个文件的 user命名空间 所设置的这些扩大属性。 查看扩大属性列表var_dump(xattr_list($file, XATTR_ROOT));// array(1) {// [0]=>// string(11) "Description"// }var_dump(xattr_list($file));// array(2) {// [0]=>// string(4) "Num."// [1]=>// string(6) "Author"// }xattr_list() 函数能够获取文件所定义的所有命名空间的键。它也是辨别 user 和 root 命名空间的。 取得扩大属性内容var_dump(xattr_get($file, 'Author')); // string(6) "ZyBlog"var_dump(xattr_get($file, 'Description')); // bool(false)var_dump(xattr_get($file, 'Description', XATTR_ROOT)); // string(9) "shuo ming"xattr_get() 函数用于取得指定键的扩大属性内容。配合下面的 xattr_list() 函数就能够获取某个文件的所有扩大属性信息。如果咱们不减少 XATTR_ROOT 参数的话,是无奈读取到 root命名空间 中的内容的。 ...

July 15, 2021 · 1 min · jiezi

关于php:PHP中的文件系统函数三

总算来到咱们最关怀的局部了,也就是 f 相干函数的操作。基本上大部分的文件操作都是以明天学习的这些内容为根底的,话不多说,咱们就一个一个的来学习学习吧。 文件读取文件的读取其实非常简单,fopen() 关上句柄,fread() 读取内容,fclose() 敞开句柄,一套流程下来操作就实现了。 $f = fopen('./test.txt', 'r+');while (!feof($f)) { $contents = fread($f, 4); echo $contents, PHP_EOL;}// Rain// is// fall// ing// all// arou// nd,// It f// alls// on// ……// ……fopen() 函数的第二个参数是咱们能够操作的权限。这个大家应该不会生疏,w 就是可写,r 就是可读,r+ 就是读写形式关上并将文件指针指向文件头,a 是追加写入。 模式阐明'r'只读形式关上,将文件指针指向文件头。'r+'读写形式关上,将文件指针指向文件头。'w'写入形式关上,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创立之。'w+'读写形式关上,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创立之。'a'写入形式关上,将文件指针指向文件开端。如果文件不存在则尝试创立之。'a+'读写形式关上,将文件指针指向文件开端。如果文件不存在则尝试创立之。'x'创立并以写入形式关上,将文件指针指向文件头。如果文件已存在,则 fopen() 调用失败并返回 FALSE,并生成一条 E_WARNING 级别的错误信息。如果文件不存在则尝试创立之。这和给 底层的 open(2) 零碎调用指定 O_EXCLO_CREAT 标记是等价的。'x+'创立并以读写形式关上,其余的行为和 'x' 一样。'c'只关上文件进行写入。如果文件不存在,则创立该文件。如果它存在,它既不会被截断(与“w”相同),也不会导致对该函数的调用失败(与“x”一样)'c+'关上文件进行读写;否则它的行为与“c”雷同。fread() 函数的第二个参数是每次要读取的字节数,能够看到在测试代码中咱们是以 4 个字节为单位进行读取的,所以文件内容都是按 4 个字节离开的一行一行的输入的。feof() 用于判断以后文件的游标指针是否曾经挪动到开端了。 游标操作既然说到游标,那么咱们就来看看游标相干的操作。 while (!feof($f)) { $contents = fread($f, 1024); echo $contents, PHP_EOL;}//rewind($f);while (!feof($f)) { $contents = fread($f, 1024); echo $contents, PHP_EOL;}// Rain is falling all around,// It falls on field and tree,// It rains on the umbrella here,// And on the ships at sea.当应用最上方的代码读取过一遍内容后,游标就曾经到底了,这时候再次循环是无奈读取文件内容的,须要应用 rewind() 函数将游标进行重置。 ...

July 14, 2021 · 4 min · jiezi

关于php:PHP中的文件系统函数二

这次咱们来学习的是一些不是太罕用,但却也十分有用的一些函数。它们中有些大家可能见过或者应用过,有一些可能就真的没什么印象了。它们都是 PHP 中文件系统相干操作函数的一部分。存在即正当,或者只是咱们的业务开发中还没有接触到而已。不论别的,先混个脸熟,在真正须要它们的时候你能马上想起来 PHP 就自带一个这样的函数就能够了。 目录判断、创立、删除、门路缓存信息var_dump(is_dir("./")); // bool(true)var_dump(disk_free_space("./")); // float(7727517696)var_dump(disk_total_space("./")); // float(250790436864)is_dir() 函数预计大家会比拟罕用,就是用来判断给定的门路是否存在或者是否失常。个别在手动创立目录之前都会应用这个函数来判断一下目录是否曾经创立过了,常见于上传相干的业务场景开发中。disk_free_space() 和 disk_total_space() 则是获取指定目录的残余磁盘空间和总的磁盘空间数据的函数。因为我的电脑是 Mac 零碎,所以总的磁盘空间就是 250G 的,可用的空间为 7G ,看来马上就要筹备清理一下电脑了。 var_dump(mkdir("./a")); // bool(true)var_dump(rmdir("./a")); // bool(true)mkdir() 函数用于创立一个目录,它除了给定的门路参数外,还有一个可选参数能够设置目录的文件权限,也是传递 0777 之类的值就能够了,这个函数置信大家不会很生疏,大部分的文件上传分目录的能力正是应用 is_dir() 来配合 mkdir() 进行目录创立的。rmdir() 是用于删除目录的,这个函数有两个前提,一是要删除的目录必须是空的,二是要有删除这个目录的权限,如果任一条件不满足的话,就会报出一个 E_WARNING 级别的谬误。 realpath('./');var_dump(realpath_cache_get());// array(8) {// ["/Users/zhangyue/MyDoc/博客文章/dev-blog/php/202010/source"]=>// array(4) {// ["key"]=>// float(1.4990943845035E+19)// ["is_dir"]=>// bool(true)// ["realpath"]=>// string(61) "/Users/zhangyue/MyDoc/博客文章/dev-blog/php/202010/source"// ["expires"]=>// int(1603327834)// }// ["/Users/zhangyue/MyDoc/博客文章"]=>// array(4) {// ["key"]=>// int(8597410586338680)// ["is_dir"]=>// bool(true)// ["realpath"]=>// string(34) "/Users/zhangyue/MyDoc/博客文章"// ["expires"]=>// int(1603327834)// }// ["/Users"]=>// ……// ……var_dump(realpath_cache_size()); // int(673)realpath_cache_get() 函数用于获取实在目录缓存的详情,咱们须要先应用 realpath() 取得一个目录门路,而后就能够看到 realpath_cache_get() 外面的内容。能够看出它返回的数组中,是这条门路从第一个目录到这个目录中的所有目录信息,包含每一级目录的 realpath 、 is_dir 等属性信息。realpath_cache_size() 获取的是实在门路缓冲区的大小,也就是实在门路缓存区大小在内存中的使用量。 ...

July 13, 2021 · 3 min · jiezi

关于php:一个新细节Go-117-将允许切片转换为数组指针

微信搜寻【脑子进煎鱼了】关注这一只爆肝煎鱼。本文 GitHub github.com/eddycjy/blog 已收录,有我的系列文章、材料和开源 Go 图书。大家好,我是煎鱼。 明天是周末的,尽管只有一天。给大家分享一个 Go1.17 的小快讯。一天增长一个吸鱼小技巧! 在 Go 语言中,一个切片(slice)蕴含了对其反对数组的援用,无论这个数组是作为一个独立的变量存在于某个中央,还是仅仅是一个为反对分片而调配的匿名数组。 其切片根本构造都如下: // runtime/slice.gotype slice struct { array unsafe.Pointer // 指向底层数组的指针 len int // 长度 cap int // 容量}目前切片这种反对数组的形式可能会导致切片呈现乏味的内存透露或对你的切片产生令人诧异的变动。 另外很重要的一点,在 Go 1.16 及以前,不存在将从切片类型转换为数组类型的平安办法,比拟无奈。 咱们只能通过调用规范库 reflect 或 unsafe,通过编写不平安的代码来做到这一点: (*[10]byte)(unsafe.Pointer(&b[0]))显然这是不优雅的,官网本人都不举荐应用 unsafe,一旦解决出错了,可能还会导致致命谬误,比拟不可控。 其实早在2009 年,在 Go 公布后不久(远在 Go 1.0 公布之前),就有人提出相干纳闷,心愿解决这个问题: 终于,在行将到来的 Go 1.17 中,这将成为可能,因为从 commit-id #1c268431f4 开始的一系列变动,更新了标准: 新的标准中对此的形容很间接: Converting a slice to an array pointer yields a pointer to the underlying array of the slice. If the length of the slice is less than the length of the array, a run-time panic occurs.如果切片的长度比数组的长度长是有害,可能失常运行。如果比数组长的切片,意味着你的数组将不能拜访原始切片的所有反对数组。另外标准中提供了一些新的例子,在 Go1.17 中咱们能够这么用: ...

July 12, 2021 · 1 min · jiezi

关于php:PHP中的文件系统函数一

从这篇文章开始,咱们将学习一系列的 PHP 文件系统相干函数。其实这些函数中,有很多都是咱们常常用到的,大家并不需要刻意地去记住它们,只有晓得有这么个货色,在应用的时候记得来查文档就能够了。 文件门路相干函数文件门路相干的函数往往在一些框架中会比拟常见,而且多会配合 \_\_FILE\_\_ 、 \_\_DIR\_\_ 之类的魔术常量应用。 echo "1) ".basename("/etc/sudoers.d", ".d"), PHP_EOL;echo "2) ".basename("/etc/passwd"), PHP_EOL;echo "3) ".basename("/etc/"), PHP_EOL;echo "4) ".basename("."), PHP_EOL;echo "5) ".basename("/"), PHP_EOL;echo "6) ".basename("/usr/local/Cellar/php/7.3.9_1/README.md"), PHP_EOL;// 1) sudoers// 2) passwd// 3) etc// 4) .// 5) // 6) README.mdbasename() 函数是取得门路中的文件名,它有两个参数,第一个是文件的门路,第二个是过滤掉的内容,比方第一条测试语句咱们过滤掉文件的后缀名。 echo "1) " . dirname("/etc/passwd") , PHP_EOL;echo "2) " . dirname("/etc/") , PHP_EOL;echo "3) " . dirname("."), PHP_EOL;// 1) /etc// 2) /// 3) .dirname() 返回的是门路中的门路局部,也就是不蕴含文件名的那局部内容,和 basename() 正好是相同的性能。 print_r(pathinfo('/usr/local/Cellar/php/7.3.9_1/README.md'));// Array// (// [dirname] => /usr/local/Cellar/php/7.3.9_1// [basename] => README.md// [extension] => md// [filename] => README// )echo realpath('./../../..//../etc/passwd'), PHP_EOL;// /private/etc/passwdpathinfo() 函数用于以数组的模式返回门路中的信息,从后果来看,咱们能够看到文件的 dirname 局部,basename 局部,以及文件的扩展名 extension 和不蕴含扩展名的 filename 内容。 ...

July 12, 2021 · 2 min · jiezi

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

https://github.com/fendui/lar... 装置composer require fendui/laravel-hprose dev-master配置在 config/app.php 注册 HproseServiceProvider 'providers' => [ ..... \fendui\HproseServiceProvider::class ]创立配置和demo路由文件php artisan vendor:publish --provider="fendui\HproseServiceProvider"服务端 办法注入和类注入\fendui\Facades\HproseRoute::add(function () { return 'service hello';}, 'hello');\fendui\Facades\HproseRoute::add(\fendui\demoService::class);启动rpc服务php artisan hprose:socket客户端调用$uris =['tcp://127.0.0.1:1314'];$client = new \fendui\Clients\SocketClient($uris, false);$client->hello()$client->fendui_demoService->kan()须要配置配置'client' => [ 'tcp_uris' => [ 'tcp://127.0.0.1:1314', ], 'async' => false],app('hprose.socket.client')->hello()demo 查看注册的办法 http://127.0.0.1:8000/rpc能够通过路由查看调用形式 http://127.0.0.1:8000/rpc/kanhttp://127.0.0.1:8000/rpc/demo/sayhttp://127.0.0.1:8000/rpc/demo/kanhttp://127.0.0.1:8000/rpc/demo/can

July 11, 2021 · 1 min · jiezi

关于php:如何用PHPUnit生成代码覆盖率报告

PHPUnit集成了PHPCoverage能够间接通过命令行在运行测试的时候顺带生成测试覆盖率报告。之前版本的PHPUnit还须要xdebug插件能力生成报告,但PHPUnit 8x之后,能够装置PCOV插件作为code coverage driver。 > apt install php7.4-pcov而后装置pcov代码包 > composer require --dev pcov/clobber:^2.0就此实现了所有的根底装置,接下来开始用命令行生成测试报告 > ./vendor/bin/phpunit --coverage-html tests/html --coverage-filter app/models --bootstrap tests/bootstrap.php tests/model/video/block--coverage-html 选项通知phpunit将生成好的html文件寄存在哪个文件夹--coverage-filter 选项通知phpunit剖析哪个文件夹上面的代码 生成的笼罩报告如图所示: 援用:https://www.lambdatest.com/bl...

July 10, 2021 · 1 min · jiezi

关于php:学习PHP中Fileinfo扩展的使用

明天来学习的这个扩大其实当初也曾经是标配的一个扩大了,为什么呢?因为 Laravel 框架在装置的时候它就是必须的一个扩大,没有关上它的话,连 Laravel 框架都是无奈应用的。 Fileinfo 介绍Fileinfo 是通过给定的 magic 字节序列库来取得文件的内容类型及编码。它所获取的序列库是依据操作系统来定的,比方在 Linux 零碎中默认应用的就是 /usr/share/misc/magic 这个文件。其实咱们就是能够用这个扩大的函数来取得文件的 MIME 信息,就像咱们常见的 image/png 、 text/html 这些内容。 Fileinfo 这个扩大也是为了兼容新老开发模式,所以提供了面向过程和面向对象的两种模式,咱们先来看看面向对象的模式如何应用。 面向对象应用$finfo = new finfo(FILEINFO_MIME);echo $finfo->file("./1.PHP中的日期相干函数(三).php"), PHP_EOL;// text/x-php; charset=us-asciiecho $finfo->buffer(file_get_contents("https://www.baidu.com")) . "\n";// text/html; charset=utf-8$finfo->set_flags(FILEINFO_EXTENSION);echo $finfo->file('timg.jpeg') . "\n";// jpeg/jpg/jpe/jfif首先,咱们通过 new 一个 finfo 类来取得文件操作对象,参数中的常量是可选的,默认状况下是 FILEINFO_NONE ,代表无非凡解决,这里咱们应用的是 FILEINFO_MIME 表明依照 RFC2045 定义的格局返回文件 mime 类型和编码。 而后应用 file() 办法,就能够取得指定文件的 mime 信息了。buffer() 办法则是返回字符串内容的信息,比方咱们获取一个网页信息的内容,就可能失去它的字符串代表的文件编码格局为 text/hmtl 。set_flags() 办法是能够在实例化对象之后批改它的结构参数属性,也就是咱们在实例化时设置的那个参数信息,在这里咱们将它批改为 FILEINFO_EXTENSION ,也就是让 finfo 对象返回文件可能的扩展名。咱们应用一张图片进行测试,返回的可能扩展名就包含正文中展现的这些。 面向过程针对下面面向对象的代码,咱们也展现一下雷同的操作应用面向过程的函数是如何运行的。 $finfo = finfo_open(FILEINFO_MIME);echo finfo_file($finfo,"./1.PHP中的日期相干函数(三).php"), PHP_EOL;// text/x-php; charset=us-asciiecho finfo_buffer($finfo, file_get_contents("https://www.baidu.com")), PHP_EOL;// text/html; charset=utf-8finfo_set_flags($finfo, FILEINFO_EXTENSION);echo finfo_file($finfo, 'timg.jpeg') . "\n";// jpeg/jpg/jpe/jfiffinfo_close($finfo);能够看出,这里就是将 finfo 对象换成了 finfo_open() 办法来取得一个 finfo 操作句柄。之后应用相似的 finfo_file() 、 finfo_buffer() 、 finfo_set_flags() 函数来进行操作,实现的成果和下面的面向对象的后果是一样的。 ...

July 10, 2021 · 1 min · jiezi

关于php:从增删改查到事件溯源-PHP

本文转载自【何以解耦】:https://codedecoupled.com/php...增删改查如果你是一名 PHP 后端开发,增删改查(CRUD)对你来说,肯定不生疏。简略来说,它是指对数据库进行减少,删除,批改,查阅基本操作。增删改查是面向数据库的一种建模形式。PHP 几乎是为增删改查而生,它语法简略,无需编译,ORM 遍地开花,你能够疾速地将数据库表和网页买通,从而实现增删改查性能。这种快感给人一种错觉,仿佛这就是一个后端开发者的外围工作。 让咱们用增删改查的思路,设计一个简略购物车: 数据库设计增删改查的第一步必然是数据库设计。为便于演示,咱们设计从简,省去了很多细节,所以千万不要将这种设计用于你的产品中。咱们仅应用一个表 carts 来贮存购物车商品。 演示当产品 p-1(ID:1)被退出购物车时,在 carts 表中削减一条数据: 当产品 p-2(ID:2)被退出购物车时,在 carts 表中再次削减一条数据: 当产品 p-1(ID:1)被再次退出购物车时,更新 carts 表中相应数据: 当产品 p-2 被移除购物车时,删除 carts 表中对应数据: 购物车的内容被实时地记录在数据库中,这是增删改查的次要特色。 让咱们再来看看另一种截然不同的思维。 事件溯源事件溯源(Event Sourcing)是畛域驱动设计(Domain Driven Design)设计思维中的架构模式之一。畛域驱动设计是面向业务的一种建模形式。它帮忙咱们将留神点放回业务自身。 事件溯源的外围是事件,所有聚合(一种非凡的类)的状态源头来自于事件,所以它叫事件溯源。这里的事件叫做畛域事件,与咱们通常所讲的事件不同的是,畛域事件是指领域专家所关怀,业务过程中所产生的事件,它与业务非亲非故。 让咱们用事件溯源的思维来设计上文中的购物车。 应用畛域事件在购物车这个业务中,假如本人是一个用户的话,咱们最感兴趣的几件事件是将商品退出购物车,将商品移除购物车以及对购物车进行结算。于是咱们能够总结出几个畛域事件。值得注意的是,畛域事件都应该是过来式。 当产品 p-1(ID:1)被退出购物车时,在 events 表中削减一条事件数据: 当产品 p-2(ID:2)被退出购物车时,在 events 表中削减一条事件数据: 当产品 p-1 被再次退出购物车时,在 events 表中削减一条事件数据: 当产品 p-2 被移除购物车时,依然在 events 表中削减一条事件数据: 购物车的内容以事件的模式记录了下来,事件只可追加,不能够删除或者改变。 读取购物车商品当须要展现购物车内容时,重播 events 表中所贮存的事件即可: 拥抱事件溯源事件溯源要求开发者扭转本人的传统的,以数据库设计为源头的思维,从业务开始剖析问题。用其开发的零碎不仅仅自带日志,而且能够以畛域事件为核心来不便地排查问题,同时事件驱动建设的聚合模型也非常容易编写单元测试。 增删改查并非恶魔须要补充的是,增删改查并非一无是处,相同,在适宜它的畛域,它是十分弱小的。在一些畛域,增删改查就是以后的业务。比方一个简略的 CMS,比方 IoT 我的项目中对数据的存储。 ...

July 9, 2021 · 1 min · jiezi

关于php:使用-Go-defer-要小心这-2-个折腾人的雷区

微信搜寻【脑子进煎鱼了】关注这一只爆肝煎鱼。本文 GitHub github.com/eddycjy/blog 已收录,有我的系列文章、材料和开源 Go 图书。大家好,我是煎鱼。 在 Go 语言中 defer 是一个十分有意思的关键字个性。例子如下: package mainimport "fmt"func main() { defer fmt.Println("煎鱼了") fmt.Println("脑子进")}输入后果是: 脑子进煎鱼了在前几天我的读者群内有小伙伴探讨起了上面这个问题: 简略来讲,问题就是针对在 for 循环里搞 defer 关键字,是否会造成什么性能影响? 因为在 Go 语言的底层数据结构设计上 defer 是链表的数据结构: 大家放心如果循环过大 defer 链表会巨长,不够 “精益求精”。又或是猜测会不会 Go defer 的设计和 Redis 数据结构设计相似,本人做了优化,其实没啥大影响? 明天这篇文章,咱们就来摸索循环 Go defer,造成底层链表过长会不会带来什么问题,若有,具体有什么影响? 开始吸鱼之路。 defer 性能优化 30%在早年 Go1.13 时已经对 defer 进行了一轮性能优化,在大部分场景下 进步了 defer 30% 的性能: 咱们来回顾一下 Go1.13 的变更,看看 Go defer 优化在了哪里,这是问题的关键点。 以前和当初比照在 Go1.12 及以前,调用 Go defer 时汇编代码如下: ...

July 9, 2021 · 3 min · jiezi

关于php:PHP中DirectIO直操作文件扩展的使用

对于 PHP 的文件操作,咱们也将是通过一系列的文章来进行学习。明天咱们先学习的是一个很少人应用过,甚至很多人基本不晓得的扩大,它与咱们日常的文件操作有些许的不同。不过这些差异并不是咱们肉眼所能直观看到的,次要还是在于业务的需要与性能的均衡。 什么是Direct IODirect IO 其实是 Linux 操作系统中的一个概念。它的意思是间接操作文件流,为什么说是间接呢?其实在咱们的操作系统进行文件操作的时候,并不是马上间接就在磁盘上进行文件的读写,两头还有一层页缓存。既然是缓存,那么它当然是会带来肯定的性能晋升,但这也并不是齐全相对的。而间接操作就是疏忽掉这一层的缓存操作,间接对磁盘上的文件进行读写。咱们都晓得,磁盘,即便是固态硬盘,它和 CPU 以及内存的处理速度之间都是有着微小的落差的,默认的页缓存就是用来补救这种差距。然而页缓存会加大 CPU 的运算操作以及占用内存,而间接操作则不会有这种问题,然而相对来说,它的速度并不能和带缓存的文件读取操作相媲美。 以上是对于 Direct IO 的一个简略的了解,更详尽的解释大家能够参考文末参考文档中第二条链接的内容并进行深刻的学习。在 PHP 中,咱们间接在 PECL 下载 Direct IO 扩大就能够依照扩大的失常装置形式进行装置应用。 创立写入文件既然是文件操作,那么咱们首先还是来创立和写入一些文件数据。 $fd = dio_open("./test", O_RDWR | O_CREAT);echo dio_write($fd, "This is Test.I'm ZyBlog.Show me the money4i"), PHP_EOL;// 43print_r(dio_stat($fd));// Array// (// [device] => 64768// [inode] => 652548// [mode] => 35432// [nlink] => 1// [uid] => 0// [gid] => 0// [device_type] => 0// [size] => 43// [block_size] => 4096// [blocks] => 8// [atime] => 1602643459// [mtime] => 1602656963// [ctime] => 1602656963// )dio_close($fd);和 f 系列的函数相似,咱们须要应用一个 dio_open() 函数来关上一个文件,O_RDWR | O_CREAT 参数的意思是关上一个可读写文件,并且如果文件不存在的话,创立它。这两个常量是与 Linux 中相干的间接操作文件的常量对应的,在文末的链接中也能够看到对于这些常量的解释。 ...

July 9, 2021 · 2 min · jiezi

关于php:学习PHP中的高精度计时器HRTime扩展

不晓得大家还记得在学校的时候体育测试时老师带的秒表吗?当枪声想起时,咱们开始跑步,这时秒表启动,当咱们跑过起点后,老师会按下按扭记录咱们的问题,这就是一个典型的定时器的利用。明天咱们要学习的内容其实就是和这个体育测验的秒表相似的一个性能扩大,它就是 PHP 的 HRTime 扩大。 时钟节奏首先咱们要理解一下什么叫做零碎的时钟节奏。当 Linux 系统启动之后,会同时启动一个时钟节拍器,以纳秒为单位进行计时,而咱们的 HRTime 扩大的实在名称是 高精度工夫 扩大。也就是说,它正是基于操作系统的时钟节拍器,可能以纳秒为单位进行计时。 1秒=1000毫秒=1000000奥妙=1000000000纳秒,这是秒、毫秒、微秒和纳秒的关系,看进去它的精度有多高了吧。1秒等于10亿纳秒,这样咱们就能够取得一个十分准确的工夫距离计数。 HRTime 扩大间接在 PECL 进行下载安装就能够了,和其余的一般扩大没有什么区别。 获取零碎时钟节奏信息 Ticks咱们先来看看如何获取操作系统的时钟节奏,也就是这个 Ticks 。对于它的内容在学习操作系统的时候置信曾经有不少的同学接触过了,这里咱们看看应用 HRTime 扩大如何获取。 print_r(hrtime());// Array// (// [0] => 3758// [1] => 407409171// )echo hrtime(true), PHP_EOL;// 3758407428932hrtime() 这个函数在 PHP7 之后曾经集成在默认 PHP 环境中了。它不须要 HRTime 扩大就能够应用。这个函数在没有参数的状况下返回的是一个数组,第 0 项是系统启动到当初的秒数,第 1 项就是对应的纳秒计数。如果给它的参数设置一个 true 的话,它将间接返回将秒和纳秒拼接起来的理论纳秒工夫戳。 echo HRTime\PerformanceCounter::getFrequency(), PHP_EOL; // 1000000000echo HRTime\PerformanceCounter::getTicks(), PHP_EOL; // 3758428256236echo HRTime\PerformanceCounter::getTicksSince(1212), PHP_EOL; // 3758428257494$a = HRTime\PerformanceCounter::getTicks();echo HRTime\PerformanceCounter::getTicksSince($a), PHP_EOL; // 412接下来的这三个函数就是 HRTime 扩大中的 PerformanceCounter 对象的动态函数了。PerformanceCounter 对象的意思是性能计数器,getFrequency() 示意的是计时器频率(以滴答Ticks/秒为单位),能够看出,它返回的就是纳秒单位,也就是 10亿 。getTicks() 返回的是以后的时钟节奏工夫,能够看出它和 hrtime(true) 函数的后果是一样的,都是返回的系统启动后的时钟节奏工夫。getTicksSince() 办法则是依据指定的纳秒数返回工夫距离,相似于 date_diff() 的感觉,其实就像咱们的 time() - time() 这样的操作。通过这个办法就能够取得一段代码两次运行的工夫距离,而且是以纳秒为单位哦。 ...

July 8, 2021 · 2 min · jiezi

关于php:PHP-实现简单多路归并排序大文件

原文链接:何晓东 博客 算是一道常见的面试题引来的,有些大厂也喜爱把这个题当做面试题。 题目:例如有一个 1g 的文件,外面寄存这乱序不惟一的数字,如果利用 100m 实现整体排序? 思路就是:先将大文件逐行读取,每 10000 行为一组,而后排序后写入文件中,文件名称相似 t1.txt, t2.txt ... 这样的名称,直至读取和拆分结束整个文件,而后遍历所有文件,每个文件先读取第一行,放入长期排序数组,而后取其中最小值,放入长期存储数组,同时记录索引地位,从对应文件中取下一个数字,放入以后索引中,而后持续反复这样的操作,直到所有文件的所有内容读取结束,长期排序数组也读取结束,则整体文件从新排序结束。 以下是一个 PHP 多路归并排序 demo 代码,只是简略的骨架构造,例如 min 取最小值局部,能够扩大成定长最小堆实现,或者优先队列,能保留值和所在文件就行。 PHP 多路归并 demo 代码: function multiWaySort(){ // 读取所有的文件描述符 $fds = []; $dir = scandir('./runtime/txt/'); foreach ($dir as $file) { if ($file != '.' && $file != '..') { $fds[] = fopen('./runtime/txt/' . $file, 'rb'); } } // 读取每个文件的第一行内容,放入长期排序数组 $tmpNums = []; foreach ($fds as $fd) { $tmpNums[] = (int)fgets($fd); } $nums = []; $count = 0; while (true) { if (empty($tmpNums)) break; // 最小值放入长期存储数组 $value = min($tmpNums); $nums[] = $value; // 读取最小值所在索引,对应的文件下一行内容 $idx = array_search($value, $tmpNums); $next = fgets($fds[$idx]); if (!$next) { unset($tmpNums[$idx]); unset($fds[$idx]); } else { $tmpNums[$idx] = (int)$next; } // 长期存储数组达到肯定数量追加写入文件一次 if (count($nums) == 20) { foreach ($nums as $value) { $f = fopen('./runtime/result.txt', 'ab+'); fwrite($f, $value . PHP_EOL); } $nums = []; } if ($count == 4999999) { continue; } $count++; }}参考链接: ...

July 7, 2021 · 1 min · jiezi

关于php:学习PHP中的目录操作

对于编程语言来说,文件和目录的操作是其最最根底的性能。就像咱们日常中最常见的图片上传、文件上传之类的性能,都须要文件和目录操作的反对。明天咱们先来简略地学习一下 PHP 中对于目录操作的一些类和函数。 目录与门路分隔符首先来看看两个常量,它们别离是目录与门路的分隔符号。 echo DIRECTORY_SEPARATOR, PHP_EOL; // /echo PATH_SEPARATOR, PHP_EOL; // :DIRECTORY_SEPARATOR 常量在 Linux 零碎中输入的就是 / 这个斜杠,而在 Win 零碎中则是 \ 这样的反斜杠。也就是说,它是依据以后的操作系统来确定应用哪种目录分隔符号的。PATH_SEPARATOR 是环境门路的分隔符,在 Linux 零碎中输入的是 : ,其实就像是咱们定义的零碎环境变量一样,在 Linux 零碎中咱们查看或增加批改 PATH 环境变量就都都是应用 : 来分隔的。 Directory 对象操作既然有对象这个概念,那么也就阐明目录相干的操作其实也是有面向对象和面向过程两种模式的,咱们先来看看面向对象是如何操作的。 $directory = dir('../');while(($dir = $directory->read())!== false){ echo $dir, PHP_EOL;}// .// ..// 1.PHP中的日期相干函数(三).md// source咱们应用 dir() 函数来返回一个 Directory 对象,这里须要留神的是,Directory 对象是只能通过 dir() 函数来获取的,无奈通过 new 的形式来生成实例。在取得 Directory 对象之后,咱们就能够通过 read() 办法来读取目录中的所有内容信息了。展现的内容其实和咱们在操作系统中应用 ll -a 命令获取的后果是相似的,它会取得 . 、 .. 这两个目录信息,代表当前目录和下级目录。 echo $directory->read(), PHP_EOL;//$directory->rewind();while(($dir = $directory->read())!== false){ echo $dir, PHP_EOL;}// .// ..// 1.PHP中的日期相干函数(三).md// sourceread() 办法是游标操作,也就是遍历一次后游标就会挪动到最初一个地位,这时再调用 read() 就不会有任何信息了。这时咱们能够通过 rewind() 办法重置游标,而后就能够从新遍历目录内容。 ...

July 7, 2021 · 2 min · jiezi

关于php:laravel-Dcat-Admin-Class-name-must-be-a-valid-object-or-a-string

(1)问题:装置Laravel后盾零碎Dcat Admin 2.x报错:Class name must be a valid object or a string(2)解决: # step1.更新compoercomposer update# step2.再次运行命令公布资源php artisan admin:publish# step3.革除配置缓存(没成果再执行)php artisan config:cache

July 6, 2021 · 1 min · jiezi

关于php:PHP过滤数组中的空值

array_filter() 函数依据回调函数过滤数组中的值,省略回调函数则默认过滤空值。语法: array_filter( array[, function] )例子:$array = [ '管综我的项目', '', '2021年7月6日', '', '', '过滤空值'];// 输入过滤后果print_r(array_filter($array));Array( '管综我的项目', '2021年7月6日', '过滤空元素')应用回调函数过滤指定值例子: $array = [1, 2, 3, 4, 5, 6, 7, 8];// 大于5的元素print_r(array_filter($array, function($item) { return $item > 5;);Array( 6, 7, 8)

July 6, 2021 · 1 min · jiezi

关于php:static-静态变量引起-Laravel-中队列一个-Bug

环境PHP_VERSION=7.4laravel/framework: ^7.0动态变量很多编程语言对于动态变量的解释都是: 与程序有着雷同生命周期的变量, 只初始化一次不过因为PHP的罕用运行环境是php-fpm模式,每次申请完结过程就会被回收, 动态变量不会常驻内存(只会在此次申请失效)PHP 官网是这么介绍的变量范畴的另一个重要个性是动态变量(static variable)。动态变量仅在部分函数域中存在,但当程序执行来到此作用域时,其值并不失落。看看上面的例子:https://www.php.net/manual/zh/language.variables.scope.php前言我的项目中有以下伪代码逻辑: 因为数据库中的json_data是一个json字符串,所以不用每次获取都解析, 应用static变量修饰符使得下一次拜访不须要再次解析<?phpnamespace App\Models;use Illuminate\Database\Eloquent\Model;class AttributeRequestLog extends Model{ public function getJsonData($key) { static $jsonData; if (is_null($jsonData)) { $jsonData = json_decode($this->attributes['json_data'], true); } return $jsonData[$key] ?? null; }}因为之前没上队列解决异步工作, 程序始终没问题. 直到某一天上了队列之后, 有共事反馈, 有异样数据上报. 连忙排查了一下日志, 发现队列中的日志打点数据有问题,随后减少更多打点, 最初定位到了这个中央. 因为Laravel的队列采纳CLI运行模式, 这时候解决的工作都是后盾运行队列启动时载入代码, 直到队列过程被杀死, 否则代码也不会更新,剖析源码队列的启动命令: php artisan queue:work找到启动文件src\Illuminate\Queue\Console\WorkCommand.php是一个继承于Illuminate\Console\Command的类,运行artisan的时候, 会运行其的handle办法 实际上是拿到队列的驱动,而后转到worker去运行工作, 传递了一个参数once是否只运行一个工作,这里咱们间接查看daemon办法转到src\Illuminate\Queue\Worker.php的daemon办法后面三行代码去监听退出信号,而后被动退出过程下一行的$lastRestart是缓存中获取一个工夫戳,用于之后的被动退出过程,这个工夫戳只会被php artisan queue:restart重置所以能够用queue:restart这条命令去进行队列过程(并不会主动启动队列过程,能够配合Supervisor来主动重启)接下来是一个死循环,来达到过程不被杀死第一个逻辑判断死看程序是否曾经启动的保护模式,强制运行等等,就是队列工作是否能持续解决的前置判断所以咱们想长期暂停队列过程,能够向过程发送一个SIGUSR2信号,这时候队列过程解决完当前任务下一次就会进行,当想持续解决的时候,再发送一个SIGCONT信号而后到getNextJob这个办法去配置的队列驱动(redis, database 等等)里获取下一个待处理的工作如果反对异步扩大,registerTimeoutHandler对工作的超时做了一些解决, 如果工作超时了, 那么就结束任务下一步如果取出来的没工作, 那么就程序休眠, 否则就运行工作, 这里能够去看一下工作的理论运行代码这里咱们间接看fire办法即可, 而后找到对应的队列驱动类,继承了父级的fire办法实际上是反射了这个job类而后调用它对应的办法循环前的最初一个代码块就是stopIfNecessary, 看过程是否须要终止, 后面说的queue:restart也是在这里解决 所以当咱们应用动态变量的时候,尽管每次反射实例化了一个新的job,但实际上job去拿模型的属性的时候,static变量是始终没有发生变化的,这就导致了后面说的Bug原文链接https://www.shiguopeng.cn/archives/516

July 6, 2021 · 1 min · jiezi

关于php:laravelexceptionnotify-支持多种通道的-laravel-异常监控通知

laravel-exception-notify - 反对多种通道的 laravel 异样监控告诉(钉钉群机器人、飞书群机器人、Server 酱、企业微信群机器人、息知)。性能监控发送 laravel 利用异样反对多种通道(钉钉群机器人、飞书群机器人、Server 酱、企业微信群机器人、息知)自定义发送的异样信息数据源码https://github.com/guanguans/laravel-exception-notify相干我的项目https://github.com/guanguans/notifyhttps://github.com/guanguans/yii-log-target环境要求laravel >= 5.5装置$ composer require guanguans/laravel-exception-notify -vvv配置公布服务$ php artisan vendor:publish --provider="Guanguans\\LaravelExceptionNotify\\ExceptionNotifyServiceProvider"申请通道 token 等信息钉钉群机器人飞书群机器人Server 酱企业微信群机器人息知配置文件中配置 token 等信息config/exception-notify.php 应用批改 app/Exceptions/Handler.php 文件中的 report 办法public function report(Exception $exception){ // 增加的代码 $this->shouldReport($exception) and \ExceptionNotifier::report($exception); // // 或者 // $this->shouldReport($exception) and app('exception.notifier')->report($exception); // // 或者 // $this->shouldReport($exception) and \Guanguans\LaravelExceptionNotify\Facades\Notifier::report($exception); parent::report($exception);}告诉后果

July 6, 2021 · 1 min · jiezi

关于php:PHP中的日期相关函数三

之前咱们曾经介绍过了 PHP 的一些相干的日期操作对象,明天咱们就来学习剩下的那些面向过程的应用形式。当然,如果是和 DateTime 类中类似的办法咱们就不再进行介绍了。另外,Date() 和 time() 这两个十分罕用的函数也不会进行介绍,因为大家都曾经用滥了,所以咱们也就不节约贵重的学习资源了。 查看日期首先,咱们先学习一个函数,用来日期是否正确。 var_dump(checkdate(2, 29, 2020)); // bool(true)var_dump(checkdate(2, 29, 2021)); // bool(false)2020年是平年,所以有 2月29号 ,而 2021 年没有 2月29号 ,这个 checkdate() 函数就是用来检测给定的日期是否正确。它的参数程序是 月 、 日 、 年,都是必须的参数。 获取及设置时区对于时区内容的学习,咱们在 DateTimeZone 类的学习中曾经具体的解说过了,在面向过程的形式中,咱们也能够通过两个简略的函数来获取和设置以后零碎运行环境的时区信息。 var_dump(date_default_timezone_get()); // string(13) "Asia/Shanghai"var_dump(date("Y-m-d H:i:s")); // string(19) "2020-10-09 08:41:11"date_default_timezone_set("Asia/Tokyo");var_dump(date("Y-m-d H:i:s")); // string(19) "2020-10-09 09:41:11"应用 date_default_timezone_get() 就能够获取以后零碎环境中的时区信息,它是有优先程序的,最优先的是应用 date_default_timezone_set() 设置的时区,而后是 php.ini 文件中所设置的时区信息,最初如果都没有设置的话,就会依据操作系统的时区设置来确定最终咱们运行环境中的时区到底是哪里。 格式化转换日期这里的转换日期,其实就是将日期内容输入为一个具体的数组。 print_r(date_parse("2020-12-12 10:00:00.5"));// Array// (// [year] => 2020// [month] => 12// [day] => 12// [hour] => 10// [minute] => 0// [second] => 0// [fraction] => 0.5// [warning_count] => 0// [warnings] => Array// (// )// [error_count] => 0// [errors] => Array// (// )// [is_localtime] => // )$date = "6.1.2020 13:00+01:00";print_r(date_parse_from_format("j.n.Y H:iP", $date));// Array// (// [year] => 2020// [month] => 1// [day] => 6// [hour] => 13// [minute] => 0// [second] => 0// [fraction] => 0// [warning_count] => 0// [warnings] => Array// (// )// [error_count] => 0// [errors] => Array// (// )// [is_localtime] => 1// [zone_type] => 1// [zone] => 3600// [is_dst] => // )date_parse() 与 date_parse_from_format() 都是转换日期内容为具体数组的函数,它们的区别是 date_parse_from_format() 函数能够指定日期和格局,这样传递进来的日期内容就能够是各种格局类型的。它们生成的数组外面的内容字段名十分清晰,包含年、月、时、分、错误信息等内容。 ...

July 6, 2021 · 3 min · jiezi

关于php:PHP中的日期相关函数二

上回文章中咱们介绍了三个工夫日期相干的对象,不过它们的出镜频率并不是特地地高。明天学习的对象虽说可能不少人应用过,然而它的出镜频率也是非常低的。它们其实就是咱们十分罕用的那些面向过程的日期函数的面向对象式的封装。但,酒香不怕巷子深,好货色还是值得咱们去深刻的学习钻研的,当然更好的状况是能够在面对不同的业务场景时灵便地应用这些对象才是咱们学习的基本目标。 DateTime 对象没错,明天咱们学习的就是 DateTime 对象。从名字就能够看出,它就是一个规范的日期工夫类。 $date = new DateTime('now', new DateTimeZone('Asia/Tokyo'));echo $date->format('Y-m-d H:i:sP'), PHP_EOL;// 2020-09-29 09:47:57+09:00$date = new DateTime();echo $date->format('Y-m-d H:i:sP'), PHP_EOL;// 2020-09-29 10:22:45+08:00咱们能够为它指定工夫,指定时区。在第一行的测试代码中,咱们指定了工夫为 now ,也就是以后工夫,这里还能够传递字符串的工夫格局给这个参数。第二个参数就是指定时区,咱们传递了日本的区域时区,所以它的 P 格式化后输出的就是 +9:00 ,也就是东九区,比咱们的北京工夫东八区早 1 个小时。DateTime 实例化时不传递任何参数的话,默认状况就是以后的工夫以及 php.ini 中指定的时区。 还能够通过其它的形式来创立 DateTime 对象。 $date = DateTime::createFromFormat('Y年m月j日 H时i分s秒', '2020年09月22日 22时13分35秒');echo $date->format('Y-m-d H:i:sP'), PHP_EOL;// 2020-09-22 22:13:35+08:00$date = DateTime::createFromImmutable(new DateTimeImmutable("2020-09-22 11:45"));echo $date->format('Y-m-d H:i:sP'), PHP_EOL;// 2020-09-22 11:45:00+08:00createFromFormat() 静态方法是依照指定的格局来生成 DateTime 工夫对象。在这里咱们指定的格局是咱们中文罕用的格局,前面紧跟着具体的日期。createFromImmutable() 则是通过 DateTimeImmutable 对象来创立 DateTime 对象。 DateTime 与 DateTimeImmutableDateTimeImmutable 是日期示意对象,它与 DateTime 根本没什么区别,办法、属性都和 DateTime 是一样的,惟一的区别就是在前面介绍的操作方法中它不会批改本身,而是返回一个新的对象。在 DateTimeImmutable 对象中也有一个静态方法 createFromMutable() 是从 DateTime 对象创立一个 DateTimeImmutable 对象。 ...

July 6, 2021 · 2 min · jiezi

关于php:Swoole-v47-版本新特性预览之支持为每个端口设置不同的心跳检测时间

在之前的版本中,多端口监听的心跳检测性能只能配置在主服务上,无奈为每个端口独自设置心跳工夫。 例如须要在9501端口上设置 30 秒,而9502端口上设置 60 秒。从v4.7版本开始进行了反对,上面来具体理解一下。 配置项在 Server 中提供了两个配置项:heartbeat_check_interval 和 heartbeat_idle_time。 能够应用如下配置项减少心跳检测: $server->set([ 'heartbeat_check_interval' => 60, 'heartbeat_idle_time' => 120,]);heartbeat_check_interval 示意每隔多久轮循一次,单位为秒。如 heartbeat_check_interval => 60,示意每 60 秒遍历所有连贯。 如果该连贯在 120 秒内(heartbeat_idle_time 未设置时默认为 interval 的两倍),没有向服务器发送任何数据,此连贯将被强制敞开。 heartbeat_idle_time 示意连贯最大容许闲暇的工夫。 示例这里提供了一个多端口监听的代码用于测试,别离为不同的端口设置心跳检测: 为了不便测试将心跳检测时间设置为 1 秒use Swoole\Server;$server = new Server('127.0.0.1', 9501, SWOOLE_BASE);$server->set([ 'heartbeat_check_interval' => 1, 'heartbeat_idle_time' => 1,]);$server->on('connect', function ($server, $fd) { $time = date('Y-m-d H:i:s'); echo "[{$time}] Client#{$fd}: Connect.\n";});$server->on('receive', function ($server, $fd, $reactorId, $data) { $server->send($fd, 'ok');});$server->on('close', function ($server, $fd) { $time = date('Y-m-d H:i:s'); echo "[{$time}] Client#{$fd}: Close.\n";});$port2 = $server->listen('127.0.0.1', 9502, SWOOLE_SOCK_TCP);$port2->set([ 'heartbeat_idle_time' => 2,]);$port3 = $server->listen('127.0.0.1', 9503, SWOOLE_SOCK_TCP);$port3->set([ 'heartbeat_idle_time' => 10,]);$server->start();能够应用telnet或者 Swoole 的 TCP 户端进行测试。 ...

July 5, 2021 · 1 min · jiezi

关于php:Laravel-框架之路由基础

What 局部路由的概念(定义)、作用留神:Laravel 路由仅指 Web 中的后端路由。 概念:Laravel 中路由,是指外界拜访Laravel应用程序的通路。作用:定义外界拜访 Laravel 应用程序的资源或逻辑处理程序的匹配规定。也就是说,通过路由,咱们能够通过与路由匹配的 申请形式1 和 URI2 拜访到对应的资源或处理程序。 Laravel各版本路由配置的一些区别版本默认路由文件>= 5.3routes/web.app~5.1, ~5.2app/Http/routes.phpHow局部写在后面不要再路由中写逻辑代码,逻辑代码请放到controller解决路由缓存不会作用于基于闭包的路由。绝不 在路由配置文件里书写『闭包路由』或者其余业务逻辑代码,因为一旦应用将无奈应用 路由缓存 。路由器要放弃洁净整洁,绝不 搁置除路由配置以外的其余程序逻辑优先应用 Restful 路由(即资源路由)路由的形成、分类形成Laravel 路由最外围的三局部:申请形式(Method)、URI、解决形式(Action)。 按 Action 可分为:根本路由、控制器路由。 // 根本路由。只需一个 URI 和一个闭包函数Route::get('index', function () { return 'hello world';});// 控制器路由。只需一个 URI 和 一个控制器接口// 写法一Route::get('users', 'App\Http\Controllers\UsersController@index');// 写法二Route::get('users', ['App\Http\Controllers\UsersController', 'index']);// 写法三use App\Http\Controllers\UsersControllerRoute::get('users', [UsersController::class, 'index']);// 写法四Route::namespace('App\Http\Controllers')->group(function () { Route::get('users', 'UsersController@index');});按 Method 可分为:根本路由(同上)、视图路由、重定向路由、回进路由、资源路由。 // 视图路由Route::view( 'index', //uri,必填 'index', //视图名称,必填 ['name' => 'jack', 'gender' => '男'], //参数,选填);// 重定向路由Route::redirect('welcome', 'index');// 回进路由Route::fallback(function () { abort(404);});// 资源路由Route::resource('users', UsersController::class);资源路由应用php artisan route:list可查看已注册的路由。 ...

July 5, 2021 · 2 min · jiezi

关于php:多用户商城系统的运营模式有哪些

多用户商城零碎也称多用户网店零碎,可用来迅速搭建C2C(相似淘宝网)、B2B(相似阿里巴巴)等电子商务平台的网站零碎。是一种联合一个线上平台型商城+多个入驻商家+多个实体门店”多合一模式”。 一、自营模式 1、多用户商城平台企业通过建设自营网上商城,整合多渠道业务。 2、多用户商场管理系统,如会员、商品、订单、财务、仓储等,用于对线上线下多渠道服务的对立治理。 二、联营模式 1、多用户商城平台和合作伙伴供应商以不同的形式定期进行财务结算。 2、多商城系统集成多渠道供应商,以货物仓储、对立物流的形式进行入库联营。 3、多商户平台企业通过委托或直销等形式将合作伙伴供应商资源整合到平台自营零碎中,建设多个自营门店,实现商品和服务多元化,整合行业资源。 三、招商模式 1、多渠道供应商,以签约加盟形式,退出如B2B2C多用户商城零碎平台。 2、多用户商城零碎能够实现商品和服务多样化,整合行业资源,收取商户营销推广费、类别使用费、平台佣金。 3、多用户商场零碎企业通过网上购物中心的建设、多渠道供应商的签约,依照会员、交易、平台、财务等管理系统对平台进行经营和治理。 4、签约商家可自行治理商品、订单、仓储、物流、售后服务和营销推广服务,并定期与平台进行财务结算。签约商家能够通过大平台流量、资源、营销服务等行业劣势,加强品牌意识,促成交易成交。 四、混合模式 多商户商城零碎个别是自营+招商、自营+联营+招商等模式。通过建设自营在线商城,通过会员、商品、订单、金融和存储的管理系统,对线上线下多渠道服务进行对立治理 如果您想领有本人的多用户商城零碎,可抉择CRMEB,CRMEB专一于挪动互联网软件设计、研发、销售为一体的高新技术企业,咱们将竭诚为您服务。如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star:http://github.crmeb.net/u/fanfan 不胜感激 !

July 5, 2021 · 1 min · jiezi

关于php:PHP中的日期相关函数一

日期相干的操作函数是咱们在日常的工作开发中最常接触到的性能。当然,大部分同学可能最多用到的就是 date() 、 time() 这两个函数,咱们明天先不讲这两个函数,或者前面的文章也不太会讲它们,毕竟太罕用了。自身在对手册文档的学习中,就是要挖掘有意思的或者没有接触过的一些性能函数,所以咱们明天的学习的函数可能是大家都没怎么用过的,甚至可能很多大家都没见过的。 时区类相干函数首先就是时区类的一个对象。它能够帮忙咱们获取一些以后时区相干的信息。 $timezone = new DateTimeZone('Asia/Shanghai');var_dump($timezone);// object(DateTimeZone)#1 (2) {// ["timezone_type"]=>// int(3)// ["timezone"]=>// string(13) "Asia/Shanghai"// }在实例化这个 DateTimeZone 时区类时,须要传递一个时区参数。这里咱们给的就是通用的中国时区的设置,虽说咱们的国内标准时区是东八区的北京工夫,但在 PHP 中的时区格局中,咱们的时区是以上海为命名的。 这个时区类能够间接取得以后指定时区的定位信息,比方 Asia/Shanghai 的定位信息就是间接定位到上海市的。 // 时区相干的定位信息var_dump($timezone->getLocation());// array(4) {// ["country_code"]=>// string(2) "CN"// ["latitude"]=>// float(31.23333)// ["longitude"]=>// float(121.46666)// ["comments"]=>// string(12) "Beijing Time"// }通过 getLocation() 就能够获取到时区类的定位信息,经纬度的查问后果就是上海市核心,comments 字段也明确地指出了以后时区是北京工夫。 // 时区名称var_dump($timezone->getName());// string(13) "Asia/Shanghai"// 绝对于 GMT 的时差var_dump($timezone->getOffset(new DateTime('now', $timezone)));// int(28800)// 所有时区转换信息var_dump($timezone->getTransitions(time()));// array(1) {// [0]=>// array(5) {// ["ts"]=>// int(1601168813)// ["time"]=>// string(24) "2020-09-27T01:06:53+0000"// ["offset"]=>// int(28800)// ["isdst"]=>// bool(false)// ["abbr"]=>// string(3) "CST"// }// }getName() 办法获取的是以后时区的名称,这个就不必多说了。getOffset() 则是获取到与国内格林尼治工夫(GMT)的差值,也就是与子午线的工夫距离,这里返回的是秒,转换成小时后正好就是 8 小时。getTransitions() 函数返回的是所有时区转换的工夫,我测试的工夫是早上,返回的 time 字段内容是格林尼治工夫,offset 字段返回的也是与GMT工夫的差值。GMT工夫与UTC工夫是统一的,咱们在日常的学习和工作中如果接触到了这两个名词能够将它们看做是雷同的概念。 ...

July 4, 2021 · 3 min · jiezi

关于php:Deliverer-108-支持-PHP5-了

经验了两周的迭代,Deliverer 目前更新到了 1.0.8 https://github.com/zhoumengka... 因为是为了解决祖传代码的问题,也听到群友的一些声音,还是很有必要反对下 PHP5 的,所以这段时间始终在着力解决这个版本兼容问题,没想到问题比拟我预计的要难很多。 记录下开发中遇到的问题(次要是体力活)也想分享之后,有趣味的敌人能够fork一份之后,对代码不那么生疏,更期待各位个 PR。 在 PHP7 中,函数或者办法在执行的时候都在zend_execute_data构造体中的execute_data->call->fbc中,而 PHP5 中对应的字段拿到的却是调用该函数的函数,二者差距比拟大。 起初发现 PHP5 zend_execute_data的opline中查到了以后执行的函数信息,但在 PHP5.4 前后逻辑还有差别,须要区别对待(还好编译器提醒报错的字段) #if PHP_VERSION_ID < 50400#define OP1_FUNCTION_PTR(n) (&(n)->op1.u.constant)#else#define OP1_FUNCTION_PTR(n) ((n)->op1.zv)#endif首次调用解决了,发现内嵌的调用,又不在opline外面了,而且版本不一样,获得中央也不一样,并且和下面的 opline 的判断版本号还不一样,这就只能靠膂力来测了。 #if PHP_VERSION_ID < 50500 if (execute_data->fbc != NULL) { fbc = execute_data->fbc; }#else if (execute_data->call != NULL && execute_data->call->fbc != NULL) { fbc = execute_data->call->fbc; }#endif最终获取函数信息就是多层判断 zend_function *fbc;#if PHP_VERSION_ID < 70000#if PHP_VERSION_ID < 50500 if (execute_data->fbc != NULL) { fbc = execute_data->fbc; }#else if (execute_data->call != NULL && execute_data->call->fbc != NULL) { fbc = execute_data->call->fbc; }#endif if (fbc == NULL) { fbc = get_function_from_opline(execute_data->opline); }#else if (execute_data->call != NULL && execute_data->call->func != NULL) { fbc = execute_data->call->fbc; }#endif在从 opline 里查问到的只是函数的名字,须要再去全局函数表里找到对应的函数指针 ...

July 3, 2021 · 1 min · jiezi

关于php:使用-Docker-秒速搭建多版本-PHP-开发环境

文章中应用的软件: Mac:11.4(macOS Big Sur) ,处理器为:Intel Core。Docker:3.3.3 指标反对 PHP 5.6.x 环境反对 PHP 7.2.x 环境下载Docker 软件下载安装,不做过多解释,一步步装置即可。 下载地址:https://www.docker.com/produc... 代理设置"registry-mirrors" : [ "http://registry.docker-cn.com", "http://hub-mirror.c.163.com" ], 配置环境PHP 7.2.x,占用本地端口 8081启动 docker;下载压缩包:php7-2-x.zip 并进行解压;进入到 php7-2-x 目录,间接运行 docker-compose up 即可;浏览器输出:http://127.0.0.1:8081/; PHP 5.6.x,占用本地端口 8082启动 docker;下载压缩包:php5-6-x.zip 并进行解压;进入到 php5-6-x 目录,间接运行 docker-compose up 即可;浏览器输出:http://127.0.0.1:8082/; 端口映射local.php72.com -> 127.0.0.1:8081因为在 /etc/hosts 文件中不能做端口映射,须要借助其余工具。 我借助的工具为 Chrome 浏览器插件:Simple Proxy。 下载方式: Chrome 利用商店下载,搜寻 Simple Proxy。加载本地扩大程序,下载地址:chrome-simply-proxy看下装置好界面: 配置胜利后,拜访 http://local.php72.com/ local.php56.com -> 127.0.0.1:8082同上。 备注docker-compose 相干命令docker-compose up 构建容器 参数[-d]为后盾运行docker-compose start 启用容器docker-compose stop 进行容器docker-compose restart 重启容器docker-compose down 删除容器docker-compose ps 查看以后容器状态php7-2-x 目录介绍.├── docker-compose.yml├── log│   └── nginx│   └── local.php72.com_access.log├── phpdocker│   ├── README.html│   ├── README.md│   ├── nginx│   │   └── default.conf│   └── php-fpm│   ├── Dockerfile│   └── php-ini-overrides.ini└── web └── phpinfo └── index.php1、docker-compose.yml,容器编排的配置文件,文件无需更改。 ...

July 3, 2021 · 2 min · jiezi

关于php:CRMBE分销规则说明

1、CRMEB分销模式分销模式: 指定分销 指定分销: 用户默认无分销权限,须要后盾开明分销权限或在商城购买分销礼包商品后,才能够通过推广上级取得返佣; 2、分销等级CRMEB分销为二级分销;分销固定两级,后盾不能自己设置分销等级。 3、返佣规定A推广B,B推广了C;A购买商品后,本人没有返佣;B购买商品后,A取得一级返佣;C购买了商品,B取得一级返佣,A取得二级返佣注:不返佣金的状况(1)用户没有推广员身份(指定分销状况下)(2)产品售价为0时,不返佣(3)上级用户购买拼团、砍价、秒杀商品时,没有返佣(4)上级用户购买商品后,没有确认收货时,暂不返佣;确认收货之后才会返佣 4、商品返佣商品返佣分为 “默认返佣“ 和 “商品独自返佣“默认返佣商城对立设置商品的返佣比例(1)分销佣金仅和商品售价无关(2)分销佣金和订单、优惠券抵扣、积分抵扣、理论领取金额、会员优惠价等无关(3)商品佣金计算:一级佣金 = 产品售价 * 一级返佣比例二级佣金 = 产品售价 * 二级返佣比例商品独自返佣(1)每个商品可抉择独自设置返佣(2)每个商品规格设置一二级返佣(3)独自设置后,商品的返佣以固定佣金为准,不受其余因素影响(4)即便商品售价为0,用户购买该商品下级仍会收到固定金额的返佣5、佣金解冻佣金新增解冻期限,后盾可设置解冻期,解冻的佣金不可提现,达到冻结工夫前方可提现解冻期从用户取得返佣时(确认收货)开始计算解冻期设置为0时,则为无解冻期;解冻工夫单位为 “天“6、绑定推广关系公众号、小程序:商品详情页(分享链接形式),产品海报(二维码分享),分销推广海报(二维码分享);H5商城:产品海报,分销推广海报;阐明:用户通过这些形式进入商城后,必须受权或者注册(H5)之后才会绑定关系当用户已有下级、用户进入商城未受权或注册、用户曾经是推广员(指定分销模式),不能绑定推广关系用户之前拜访过商城,但没有下级时,能够绑定推广关系7、解除推广关系后盾分销员治理可解除用户的下级推广员,推广关系解除之后,推广员之前记录的推广订单仍然保留,之后上级生产的订单因推广关系已解除所以不再记录 如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star: http://github.crmeb.net/u/defu 不胜感激 !

July 3, 2021 · 1 min · jiezi

关于php:PHP中的国际化日历类

在 PHP 的国际化组件中,还有一个咱们并不是很罕用的日期操作类,它就是日历操作类。说是日历,其实大部分还是对日期工夫的操作,个别也是次要用于日期的格式化和比拟之类的。然而通常咱们间接应用 date 相干的函数或者 DateTime 相干的类操作日期相干的性能,反而比这套性能更不便灵便。当然,本着学习的目标,咱们还是来简略地理解一下。 格式化工夫首先还是从格式化工夫说起。 $cal = IntlCalendar::createInstance(IntlTimeZone::getGMT());var_dump(get_class($cal), IntlDateFormatter::formatObject($cal, IntlDateFormatter::FULL));// string(21) "IntlGregorianCalendar"// string(66) "2020年11月18日星期三 格林尼治规范工夫 上午12:58:14"$cal1 = IntlCalendar::fromDateTime('2013-02-28 00:01:02 Europe/Berlin');var_dump(get_class($cal1), IntlDateFormatter::formatObject($cal1, 'yyyy MMMM d HH:mm:ss VVVV', 'de_DE'));// string(21) "IntlGregorianCalendar"// string(41) "2013 Februar 28 00:01:02 Deutschland Zeit"IntlCalendar 类的 createInstance() 办法会返回一个 IntlCalendar 对象,它的参数是可选的,不过必须是 TimeZone 类型的参数。fromDateTime() 办法同样也是生成一个 IntlCalendar 对象,不过它能够设置一个 DateTime 对象或者日期类型的字符串为参数。 能够看到,咱们返回的对象应用 get_class() 办法后看到理论返回的是一个 IntlGregorianCalendar 格林格里日历对象。这时,就能够应用 IntlDateFormatter 类的 formatObject() 办法来格式化输入内容,它是能够指定地区的,不同的地区设置就会显示不同的格式化语言后果。 返回工夫戳echo IntlCalendar::getNow(), PHP_EOL; // 1605661094417不多做解释了,不过这个静态方法返的是带毫秒数的工夫戳。 时区相干设置只有是国际化相干的性能,都多少和时区 TimeZone 无关,日历类也不例外。 ini_set('intl.default_locale', 'de_DE');ini_set('date.timezone', 'Europe/Berlin');$cal = IntlCalendar::createInstance();print_r($cal->getTimeZone());// IntlTimeZone Object// (// [valid] => 1// [id] => Europe/Berlin// [rawOffset] => 3600000// [currentOffset] => 3600000// )echo $cal->getLocale(Locale::ACTUAL_LOCALE), PHP_EOL; // deecho $cal->getLocale(Locale::VALID_LOCALE), PHP_EOL; // de_DE应用 getTimeZone() 就能够取得以后的时区信息,getLocale() 和之前咱们文章中其它相干性能类的 getLocale() 办法没有什么区别,大家能够看下之前讲过的内容。当然,这个 TimeZone 属性除了通过 ini_set() 之外,也是能够间接通过对象的 setTimeZone() 办法进行批改的。 ...

July 3, 2021 · 3 min · jiezi

关于php:持续发烧聊聊Dart语言的静态编译能挑战Go不

前言前两天写了几篇文章,谈了谈Dart做后端开发的劣势,比方: 《Dart开发服务端,我是不是发烧(骚)了?》 《继续发烧,试试Dart语言的异步操作,效率晋升500%》 《继续发烧,聊聊Dart语言的并发解决,能挑战Go不?》 如果没有看过的同学,能够先看一下。 明天,咱们再来谈谈 Dart 的另外一大劣势,那就是动态编译。预计 php 和 python 间接认输, java 和 go 冷眼旁观? 提前预报,内容略干,请自带矿泉水。 Dart 语言反对哪些编译形式目前支流的开发语言,一般来说要么反对 JIT 模式,要么反对 AOT 模式,要么两种都反对。 关照小白, 稍稍解释下名词 JIT 即是 Just-In-Time, 实时编译,简称 解释型,简略的说就是代码运行后,边编译代码边运行代码,长处便于开发调试,毛病是执行效率不太行 AOT 即是 Ahead-Of-Time, 事后编译,简称 编译型, 简略说是代码运行前就编译代码,长处是执行效率高点,然而开发调试不敌对 支流的后端语言,从 理论应用 上来说: php, python 都是 解释型, 理论开发的时候,代码写的十分爽,但总是被埋怨性能低 java, go 都是 编译型, 总是被埋怨编译一次,出门打个架都还没完结,我说的是 java 面对这样的状况,机智的同学看进去了,那开发的时候应用 JIT模式, 运行的时候应用 AOT 模式不就好了吗,开发调试也不便了,执行效率也高了? 不错不错,小伙子你颇具慧根,你是对的,Dart 也是这样做的。 如何编译 Dart 编写的程序当你应用 Dart 编写好应用程序后,能够应用 dart compile 命令来编译成最终文件 比方应用如下命令间接编译成 exe 文件 dart compile exe bin/main.dart将失去 main.exe 文件,该文件能够在 win 平台间接运行, 然而它不能在 linux 下执行 ...

July 2, 2021 · 1 min · jiezi

关于php:浅析-DDD-一个-PHP-程序员的自述

DDD 是什么(首先它不是什么)DDD 是 Domain Driven Design 的缩写,在中文中常被翻译为畛域驱动设计。在咱们理解 DDD 是什么之前,首先探讨下它不是什么。 DDD 不是一个软件框架。然而基于 DDD 思维的框架是存在的,比方 Axon,它是以 DDD 为指导思想,应用 Java 实现的一个微服务软件框架。DDD 不是一种软件设计模式。它不是像工厂,单例这样子的设计模式。然而 DDD 思维中提出了诸如资源库(Repository)之类的设计模式。DDD 不是一种零碎架构模式。它不是像 MVC 之类的架构模式。然而 DDD 思维中提出了诸如事件溯源(Event Souring),读写隔离(Command Query Responsibility Segregation) 之类的架构模式。那么 DDD 到底是什么软件是服务于人类,为进步人类生产效率而产生的一种工具, 每一个软件都服务于某一个特定的畛域。比方一个 CRM,它是以治理客户数据为外围,帮忙商户与客户保持联系的工具。 而软件的本质是计算机中运行的代码,如何将形象的代码更精确地映射到人类所关怀的畛域中,这是软件开发者始终在探寻的话题,不论是函数式编程(FP)还是面向对象编程(OOP)也好,都是为了帮忙开发者开发出更贴近于畛域中的软件模型。 在传统的软件开发办法中,咱们经常会遇到一系列影响软件品质的技术以及非技术问题: 开发者热衷于技术,但不足设计和业务思考。开发人员在不齐全理解业务需要的状况下,闭门造车,即便性能上线也无人问津。代码输出而非业务输出。技术人员对技术实现情有独钟,呈现杀鸡焉用牛刀的状况。过于器重数据库。以数据库设计为核心,而非业务来进行开发,后果往往是,软件无奈适应始终在变动的业务逻辑。DDD 是一种设计思维,一种以畛域(业务)为出发点,以解决软件建模复杂度为目标设计思维,咱们也能够将其了解为一种建模的方法论。 DDD 的设计思维分为策略和战术两局部。 咱们能够将策略设计了解为宏观层面的设计,它的目标包含,剖析业务的复杂程度,拆分业务的畛域领域,领导业务整合形式等等 。咱们能够将战术设计了解为宏观层面(代码层面)的设计,它为咱们在实现业务逻辑提供一系列工具。 策略设计通用语言(Ubiquitous Language)语言本是人类沟通的根本工具,然而开发人员习惯了应用技术术语,领域专家(领域专家在此泛指精通业务的专家,比方用户,客户等等)对技术术语毫不关心,于是造成了不可避免的沟通问题,一旦沟通呈现问题,开发进去的软件便很难解决领域专家的真正痛点。 通用语言是 DDD 思维的基石,它是开发人员和领域专家独特创立一套沟通语言,一套在团队中风行的,通用的沟通语言,团队的组员之间可应用通用语言进行无障碍交换。 这要求开发人员摒弃技术味浓厚的技术术语,与领域专家单干,像领域专家一样关注业务问题,独特开掘并打磨业务中的术语,创立一套通用语言。 通用语言往往能够间接利用于代码中,它能够间接被写成一个类或者一个类的办法。 比方在开发一个购物车时,与其应用技术术语: Cart::create(): 创立一个购物车。Cart::updateStatus():更新购物车状态。Cart::remove():移除购物车。咱们无妨应用更贴近业务的通用语言: Cart::init(): 创立一个购物车。Cart::addItemToCart():增加商品。Cart::removeItemFromCart():移除商品。Cart::empty():清空购物车。在应用后者时,开发人员不必解释每一个类办法的意义,领域专家能够间接看懂每一个类办法的目标。开发人员甚至能够和领域专家坐在一起应用代码来打磨业务流程。 限界上下文(Bounded Context)在实现了通用语言自在当前,咱们须要应用限界上下文来规定每一套通用语言的应用边界。限界上下文是语义和语境的边界,在其内的每一个元素都有本人特定的含意,也就是说每一个概念在一个限界上下文中都是举世无双,不能够呈现一词多义的状况。 咱们能够用一个简略的例子来解释限界上下文。比方在一个购物车的限界上下文中,咱们能够用 User 一词来代表购买商品的客户。而在一个注册零碎中,咱们能够用 User 一词指的是带有用户名和明码的账号。尽管词汇一样,然而在不同的限界上下文中,它们的含意不同。 咱们应用限界上下文和通用语言,对业务进行语言层面的拆分。限界上下文为畛域中的每一个元素赋予清晰的概念,开发人员也就不会将不由自主的在脑海中闪现多个撑持一个元素的概念,防止写出“大泥球”(big ball of mud)代码。 子域(Subdomain)如果说限界上下文是对业务进行语言层面拆分的话,那么子域便是对业务进行商业价值的拆分。每一个商业都有本人的关注点,即使是看起来一样的电商平台,淘宝是开放平台模式,京东是价值链整合模式,一个显著的区别是,淘宝应用第三方物流而京东自建物流体系。 那么作为一个开发人员,为何要关怀看起来仿佛与本人无关的商业模式呢?恰恰相反,只有当咱们理解一个商业的构造时,能力开发出一个主次明显的零碎来撑持一个商业的飞速发展。 子域便是这样一个帮忙咱们划分主次的工具。 ...

July 2, 2021 · 1 min · jiezi

关于php:CRMEB-多商户系统单品运费模板说明

单品运费模板计费形式分为:按件数计费、按分量计费、按体积计费【增加商品需设置商品的体积或分量】指定区域配送:增加区域后需填写首件商品运费及续件商品的运费指定条件包邮:设置指定地点,满足(X件/kg/m³+金额)即可包邮运费计算形式:1、订单中的商品,应用同一运费模板计算逻辑: 订单中同一运费模板的商品,第二件商品依照续件计算运费;不同的商品若运费模板雷同,也对立计算运费举例:商品A和商品B应用同一运费模板O(首件10元,续件3件,续件5元)商品A(2件),商品B(1件),运费计算形式为:10 +[( 2 + 1 - 1)/ 3]x 5 = 10 +(2/3)x 5= 10 + 1 x 5= 15元 2、订单中不同的商品,应用不同的运费模板计算逻辑: 订单中首件/首重/首体积商品,应用所有模板中金额最高的运费模板;其余商品采纳各自的运费模板计算续件/续重/续体积举例:商品A(1件)应用模板O(首件10元,续件1件,续件5元),商品B(2kg)应用模板P(首重2kg,9元,续重2kg,4元),商品C(2m³)应用模板Q(首体积2m³,8元,续体积2m³,3元);订单中有商品A一件,商品B两件,商品C两件,则运费计算形式为:10 +(4 x 2)+(3 x 2)= 24元当不同运费模板的首件/重/体积的费用雷同时,这几种运费模板均计算之后取运费的最大值 3、指定条件包邮计算逻辑: 满足指定地点并且满足指定条件后,同一运费模板的商品免邮;其余运费模板的商品持续根据下面1、2的规定计算运费举例:商品A(1件,单价100元)应用模板O(首件10元,续件1件,续件5元),商品B(2件,单价50元)也应用模板O,商品C(2kg,单价30元)应用模板P(首重2kg,9元,续重2kg,4元),模板O设置了指定条件包邮,商品指定地点为浙江,商品数量大过2个,商品金额大于150元即可包邮;此商品的订单地址为浙江,商品A和商品B应用同一模板O,商品数量之和为3>2,商品金额为(100 x 1)+(50 x 2)= 200>150元,满足指定包邮条件,则商品A和商品B包邮;商品C独自计算运费,运费金额为:9 x 1 = 9元;订单运费金额为:0 + (0x2)+(9 x 1)= 9元。 4、商品如何按分量计费计算逻辑: 商品的运费不再以件数为单位计费,而是以kg为单位计费举例:商品A(2kg,4件)应用模板P(首重2kg,9元,续重3kg,4元),商品B(3kg,5件)应用模板P,运费计算:9 + {[(2x4)+(3x5)- 2 ]/ 3 x 4} = 9 +(21/3 x 4) = 9+28 = 37元阐明:商品分量有余续重的规格时,依照续重规格计算运费 5、指定不配送计算逻辑: 应用此运费模板的商品,在指定不配送的地区不能下单;此性能为最高优先级,指定不配送 > 指定包邮 > 指定区域配送 商品价格定义商品价格为用户下单时商品的价格 ...

July 2, 2021 · 1 min · jiezi

关于php:学习PHP中的信息格式化操作

在国际化组件的学习过程中,咱们曾经接触过了 NumberFormatter 这种数字的格式化操作,它能够让咱们将数字转换成规范格局、货币、本地语言等模式。明天咱们来学习的是另一种专门用于信息格式化的类 MessageFormatter ,它次要是针对字符串的操作。 MessageFormatter 也是遵循的 ICU 标准,底层是 C 中的 ICU 操作,所以和 C 相干代码的应用形式没有太大的区别。 格式化// 格式化$fmt = new MessageFormatter("zh_CN", "{0,number,integer} 只猴子在 {1,number,integer} 颗树上,每只树上有 {2,number} 只猴子");echo $fmt->format([4560, 123, 4560 / 123]), PHP_EOL;// 4,560 只猴子在 123 颗树上,每只树上有 37.073 只猴子$fmt = new MessageFormatter("de", "{0,number,integer} Affen auf {1,number,integer} Bäumen sind {2,number} Affen pro Baum");echo $fmt->format([4560, 123, 4560 / 123]), PHP_EOL;// 4.560 Affen auf 123 Bäumen sind 37,073 Affen pro Baumecho MessageFormatter::formatMessage("zh_CN", "{0,number,integer} 只猴子在 {1,number,integer} 颗树上,每只树上有 {2,number} 只猴子", [4560, 123, 4560 / 123]), PHP_EOL;// 4,560 只猴子在 123 颗树上,每只树上有 37.073 只猴子echo MessageFormatter::formatMessage("de", "{0,number,integer} Affen auf {1,number,integer} Bäumen sind {2,number} Affen pro Baum", [4560, 123, 4560 / 123]), PHP_EOL;// 4.560 Affen auf 123 Bäumen sind 37,073 Affen pro Baum看到了吗?相似于 PDO 里预编译操作的占位符。在调用 format() 办法后,就能够让这个办法外面的参数来替换占位符的内容。咱们能够指定占位的所应用的参数类型和地位,{参数下标,类型,扩大类型} 这就是这个信息数据格式化的占位符的规定定义。看起来貌似很简略呀,其实它还有更多的性能,咱们将在前面看到。不过须要留神的是,它只反对数字、日期、文本片段类型,文章最初的参考链接中有官网的文档能够查阅。 ...

July 2, 2021 · 4 min · jiezi

关于php:持续发烧聊聊Dart语言的并发处理能挑战Go不

前言貌似对于Dart的文章没流量啊,就算在小编关心上了首页,看得人还是很少的。 算了,明天继续发烧,再来写写如何应用 Dart 语言的并发操作。说起并发操作,玩 Go 的同学该笑了,这就是咱们的看家本领啊。玩 PHP 的同学持续看看,示意咱们光看不谈话。 代码演示之前,咱们先假如一个场景。假如我有一些漂亮妹妹,他们要出门旅行了,旅行的时候会发照片给我。在这里个过程中,代码须要做的事件: 接管申请安顿出行打算,同时出行哦,不能有先后之分他们各自出行,能够发照片给我返回后果这个过程中,我关怀的是他们能不能解决好本人的事件,因为我妹妹太多了,如果都让我帮他们,累死我也搞不定啊,我就干两件事,安顿好出行打算,最初收照片。 代码演示一下吧import 'dart:io';import 'dart:isolate';main() async { print(DateTime.now().toString() + ' 开始'); //这是一个接管端口,能够了解成我的手机 ReceivePort receivePort = new ReceivePort(); //安顿三个妹妹进来旅行,让她们牢记我的手机号 await Isolate.spawn(travelToBeijing, receivePort.sendPort); await Isolate.spawn(travelToShanghai, receivePort.sendPort); await Isolate.spawn(travelToGuangzhou, receivePort.sendPort); //我就在手机上,期待他们的音讯 receivePort.listen((message) { print(message); }); print(DateTime.now().toString() + ' 完结');}void travelToBeijing(SendPort sendPort) { sleep(Duration(seconds: 3)); sendPort.send(DateTime.now().toString() + ' 我是妹妹1,我在北京了');}void travelToShanghai(SendPort sendPort) { sleep(Duration(seconds: 3)); sendPort.send(DateTime.now().toString() + ' 我是妹妹2,我在上海了');}void travelToGuangzhou(SendPort sendPort) { sleep(Duration(seconds: 3)); sendPort.send(DateTime.now().toString() + ' 我是妹妹3,我在广州了');}下面写了那么多,都是啥意思呢,我本人略微解释下下面的代码。 ...

July 1, 2021 · 2 min · jiezi

关于php:CRMEB知识付费系统安装首页提示Undefined-index-host

首页提醒Undefined index: host解决办法:查看零碎后盾 设置->零碎设置->根底设置 中的网站地址域名是否带http或https,若是没有带须要增加;如图 如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star: http://github.crmeb.net/u/defu 不胜感激 !

July 1, 2021 · 1 min · jiezi

关于php:PHP中针对区域语言标记信息的操作

置信大家对 zh_CN 这个货色相对不会生疏,不论是 PHP 中,还是在咱们的网页上,都会见到它的身影。其实这就是指定咱们的显示编码是什么国家或者地区的,应用何种语言。对于这种区域语言的标记来说,PHP 中也有很多好玩的内容。明天,咱们要学习的 Locale 类就是操作区域语言相干内容的,它无奈被实例化,所有全副性能办法都是动态的。 获取及设置以后的区域语言信息首先就是咱们能够动静地获取和设置相应的区域语言信息。 // # echo $LANG;// en_US.UTF-8// php.ini// intl.default_locale => no value => no valueecho Locale::getDefault(), PHP_EOL; // en_US_POSIXini_set('intl.default_locale', 'zh_CN');echo Locale::getDefault(), PHP_EOL; // zh_CNLocale::setDefault('fr');echo Locale::getDefault(), PHP_EOL; // fr默认状况下,应用 getDefault() 办法取得的是 php.ini 文件中的 intl.default_locale 配置的内容。如果在 php.ini 中也没有配置的话,就会取操作系统的 $LANG 值外面的内容,也就是咱们下面例子中输入的 en_US_POSIX ,POSIX 示意的就是来自操作系统的配置。 应用 ini_set() 间接批改 ini 的配置或者应用 setDefault() 办法都是能够动静地批改以后的区域语言设置的。 对于语言标记的规定在持续学习上面的内容之前,咱们先来学习一下语言标记的标准。对于大多数人来说,可能只接触过 en_US 、 zh_CN 这类的标记,但其实它的残缺定义是很长的,只是咱们应用这种简写的形式时,很多内容会以默认的模式提供。残缺的标记规定是: language-extlang-script-region-variant-extension-privateuse语言文字品种-扩大语言文字品种-书写格局-国家和地区-变体-扩大-公有也就是说,咱们的 zh_CN 能够这样写: zh-cmn-Hans-CN-Latn-pinyin代表的是:zh 语言文字品种,Hans 书写格局为简体中文,cmn 普通话,CN 国家和地区,Latn 变体拉丁字母,pinyin 变体拼音。 ...

July 1, 2021 · 2 min · jiezi

关于php:PHP图片压缩代码

/** * desription 压缩图片 * @param string $imgsrc 图片门路 * @param string $imgdst 压缩后保留门路*/public function compressedImage($imgsrc, $imgdst) { list($width, $height, $type) = getimagesize($imgsrc); $new_width = $width;//压缩后的图片宽 $new_height = $height;//压缩后的图片高 if($width >= 600){ $per = 600 / $width;//计算比例 $new_width = $width * $per; $new_height = $height * $per; } $quality = 40; switch ($type) { case 1: $giftype = check_gifcartoon($imgsrc); if ($giftype) { header('Content-Type:image/gif'); $image_wp = imagecreatetruecolor($new_width, $new_height); $image = imagecreatefromgif($imgsrc); imagecopyresampled($image_wp, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height); //90代表的是品质、压缩图片容量大小 imagejpeg($image_wp, $imgdst, $quality); imagedestroy($image_wp); imagedestroy($image); } break; case 2: $image_wp = imagecreatetruecolor($new_width, $new_height); $image = imagecreatefromjpeg($imgsrc); imagecopyresampled($image_wp, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height); //90代表的是品质、压缩图片容量大小 imagejpeg($image_wp, $imgdst, $quality); imagedestroy($image_wp); imagedestroy($image); break; case 3: $image_wp = imagecreatetruecolor($new_width, $new_height); $image = imagecreatefrompng($imgsrc); imagecopyresampled($image_wp, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height); //90代表的是品质、压缩图片容量大小 imagejpeg($image_wp, $imgdst, $quality); imagedestroy($image_wp); imagedestroy($image); break; } }

July 1, 2021 · 1 min · jiezi

关于php:Swoole-v47-版本预览之支持-cares

c-ares 是什么? c-ares 是一个异步 DNS 解析库。 它实用于须要在不阻塞的状况下执行 DNS 查问或须要并行执行多个 DNS 查问的应用程序。 默认不开启,如需开启,须要在编译 Swoole 时减少 --enable-cares 参数 gethostbyname在之前的版本中 Coroutine\System::gethostbyname 是基于同步的线程池模仿实现,底层主动进行协程调度, 依赖操作系统和 AIO 线程池,导致并发能力较弱,而启用 c-ares 之后会变成纯异步 IO 的。 启用 c-ares 之后,所有的网络客户端在解析域名时都会应用 c-ares ,包含 Redis、MySQL、HttpClient ,以及 PHP 的 Hook stream、sockets 之类 dnsLookup函数原型: Swoole\Coroutine\System::dnsLookup(string $domain, float $timeout = 5): string|false与 Coroutine\System::gethostbyname 不同,Coroutine\System::dnsLookup 是基于 Co\Socket UDP 客户端自行实现的 DNS 协程客户端, 底层是异步 IO,而不是应用 libc 提供的 gethostbyname 函数。在开启 c-ares 之后也会被替换成 c-ares 实现。 此函数在 Swoole 版本 >= v4.4.3 时可用,底层会读取 /etc/resolve.conf 获取 DNS 服务器地址,之前版本中仅反对 AF_INET(IPv4) 域名解析,此版本中对于 IPv6 也减少了反对 ...

June 30, 2021 · 2 min · jiezi

关于php:PHP代码psysh调试代码片段工具

官网网址https://psysh.org/Github地址https://github.com/bobthecow/...装置应用wget装置 $ wget https://git.io/psysh$ chmod +x psysh$ ./psysh应用composer装置 $ composer g require psy/psysh:@stable $ psyshCommandwtf 打印最近的谬误提醒 history 显示执行命令 clear 革除命令 doc 显示函数应用文档 dump 打印变量 ls 显示变量 show 显示函数 常量 类 办法 doc命令应用的时候须要安装文件到本地 PsySH的文档寄存在~/.local/share/psysh/。(windows零碎寄存在C:\Users\{用户名}\AppData\Roaming\PsySH\) $ cd ~/.local/share $ mkdir psysh$ cd psydh$ wget http://psysh.org/manual/zh/php_manual.sqliteConfigurationOsx ~/.config/psysh/config.php (or C:\Users\{USER}\AppData\Roaming\PsySH\config.php on Windows). <?phpreturn [ 'commands' => [ new \Psy\Command\ParseCommand, ], 'defaultIncludes' => [ __DIR__ . '/include/bootstrap.php', //这里能够加载本人平时罕用的类库 ], 'startupMessage' => sprintf('<info>%s</info>', shell_exec('uptime')),];<img src='https://gitee.com/smallsha/upic/raw/master/uPic/下载 (2).png' alt='下载(2)' style="zoom:50%;" /> ...

June 30, 2021 · 1 min · jiezi

关于php:CRMEB-多商户系统运行环境要求说明

运行环境 LinuxPHP > 7.1 && <7.4Mysql >= 5.7Swoole4RedisSwoole-Loader PHP ExtensionPDO PHP ExtensionMBstring PHP ExtensionCURL PHP ExtensionMylsqi PHP ExtensionRedis PHP ExtensionCRMEB能够反对Unix服务器环境,须要PHP >7.1 版本反对, 可运行于包含Apache、nginx等多种WEB服务器和模式,反对Mysql数据库,引擎用InnoDB。框架自身没有什么特地模块要求,具体的利用零碎运行环境要求视开发所波及的模块。 CRMEB底层运行的内存耗费极低,而自身的文件大小也是轻量级的,因而不会呈现 空间和内存占用的瓶颈。对于刚刚接触PHP或者CRMEB的老手,咱们举荐应用集成开发环境 宝塔或者phpstudy(都是一个集成了Apache、PHP和MySQL的开发 套件,而且反对不同PHP版本、MySQL版本和Apache版本的切换)来应用CRMEB 进行本地开发和测试。 留神+域名必须备案+公众号必须应用80端口+小程序必须应用https协定 443端口+不反对二级目录装置 这里所说的装置其实就是把CRMEB零碎放入WEB运行环境(前提是你的WEB运行环境曾经OK)。 如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star: http://github.crmeb.net/u/defu 不胜感激 !

June 30, 2021 · 1 min · jiezi

关于php:学习PHP中的国际化功能来查看货币及日期信息

做为一门在世界范畴内宽泛应用的编程语言,国际化能力往往是掂量一个编程语言是否可能大范畴风行的重要内容。特地是对于 PHP 这种以 Web 页面编程为主战场的语言来说,国际化能力更是重中之重。在 PHP 中,曾经为咱们筹备好了很多国际化相干的扩大及函数库,明天咱们先来简略的学习一下,前面在学习到具体的 国际化与字符编码反对 相干的函数库时再进行深刻的解说学习。 获取以后浏览器用户的所在地首先,咱们来获取以后拜访用户的所在地信息,也就是咱们常见的 zh-cn 、 en-us 这类的地区语言编码信息。 // $_SERVER['HTTP_ACCEPT_LANGUAGE'] = zh-CN,zh;q=0.9;$browserLocale = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);print_r($browserLocale);echo '<br/>';// zh浏览器传递的这类区域信息是 zh-CN,zh;q=0.9; 这种模式的,咱们能够通过 Locale::acceptFromHttp() 取得具体的区域信息。不过须要留神的是,不论是 zh-cn 还是 zh-tw ,返回的都是 zh ,而英文则会返回具体的是 en-us 还是 en-gd 之类的内容,也就是说这个函数对于咱们中文语言的后果获取是有问题的。 $locale = ['en', 'fr-FR', 'da, en-gb;q=0.8, en;q=0.7', 'zh-cn', 'zh-tw', 'en-us', 'en-ca', 'ja-jp'];foreach($locale as $code){ print_r(Locale::acceptFromHttp($code)); echo '<br/>';}// en// fr_FR// da// zh// zh// en_US// en_CA// ja_JP咱们能够手动来指定区域信息,能够看出除了 zh 之外其它的都是能够获取到失常的具体区域信息的。这点是咱们应用这个函数时须要留神的中央。 获取指定地区所在地的规范数字信息对于咱们中国人来,数字比拟习惯的是百、千、万位,个别也不太须要辨别,而东方国家则喜爱三位一个逗号的分隔开来,也就是对应他们的英文数字习惯,比方 10000,在东方示意中是 10,000 ,英语是 ten thousand , 10000000 示意为 10,000,000 ,英语是 ten million 。因而,在 PHP 中,也是有绝对于这种状况的数字示意模式,也就是为一般数字加上逗号以示意东方数字规范格局。 ...

June 30, 2021 · 2 min · jiezi

关于php:持续发烧试试Dart语言的异步操作效率提升500

前言昨天发了篇文章《Dart开发服务端,我是不是发烧(骚)了》,承蒙小编看得起上了首页。 明天继续发烧,再来写写如何应用 Dart 语言的异步操作。说起异步操作,玩 NodeJS 的同学会心一笑,这就是咱们的看家本领啊。玩 PHP, JAVA 的同学也就看看,示意咱们光看不谈话。 代码演示之前,咱们先假如一个场景。假如我有一些漂亮妹妹,我别具匠心的想发电子邮件给他们,表白爱心。在这里个过程中,代码须要做的事件: 接管申请保留我的邮件内容到数据库还须要把邮件内容发送到她们的邮箱。返回后果这个过程中,我关怀的是发一封邮件须要多长时间,因为我妹妹太多了,一封邮件的工夫太长的话,我就没方法关照到其他人了。那下面4个步骤里,哪些步骤会耗时呢? 很显然,1 和 4 根本相对不耗时,2 须要点工夫,然而工夫很短,3 须要的工夫最长,因为波及到网络传输,不可控因素太多。 同步代码是什么样的咱们先用同步代码的形式来模仿下面的流程。 假如保存信息到数据库须要 1 秒,发送邮件到对方邮箱须要 5 秒,总体应该是 6 点多。 import 'dart:io';main() { acceptRequest(); //承受申请 saveToDb(); //保留到数据库,不太耗时, 假如须要1秒 sendLetter(); //发送邮件到对方邮箱,十分耗时, 假如须要5秒 returnRes(); //返回后果}void acceptRequest() { print(DateTime.now().toString() + ' 承受申请');}void saveToDb() { sleep(Duration(seconds: 1)); print(DateTime.now().toString() + ' 保留数据库胜利');}void sendLetter() { sleep(Duration(seconds: 5)); print(DateTime.now().toString() + ' 发送邮件胜利');}void returnRes() { print(DateTime.now().toString() + ' 返回后果');}执行它,失去打印的后果 2021-06-29 16:40:44.993785 承受申请2021-06-29 16:40:46.000240 保留数据库胜利2021-06-29 16:40:51.002400 发送邮件胜利2021-06-29 16:40:51.002400 返回后果简略计算一下,从承受申请到返回后果,总共耗时 6 秒左右,合乎预期。 ...

June 29, 2021 · 1 min · jiezi

关于php:PHP中非常好玩的Calendar扩展学习

为什么说这个 Calendar 扩大很好玩呢?因为你根本用不到它!这个扩大是一套对于日期历法的扩大,然而对于咱们来说,它没有农历的相干操作,所以对于咱们中国人来说这个扩大并没有什么理论的作用。不过这并不障碍咱们去理解学习它。 日期历法类型对于失常状况下的日期操作来说,PHP 默认应用的是 UTC 工夫,也就是国际标准工夫,对于咱们国家来说,须要在规范 UTC 的工夫上加 8 来示意北京工夫东八区。当然,也能够间接批改 php.ini 或者数据库中的时区相干参数来定义好日期时区。 标准时区对应的其实就是格里高利工夫历法 Gregorian 。也就是咱们当初最罕用的公历、阳历日期。Calendar 扩大中除了这个规范的公历历法之外,还反对 犹太历法 Jewish 、 法历 French 以及另一个十分闻名的 儒略历 Julian 。咱们的 Gregorian 历法就是从 Julian 历中演变而来的,它们的差距并不大,但 犹太历 和 法历 的差距就比拟大了,一会在上面的代码中咱们将看到各种历法之间的差异。 对于这些历法的具体内容大家能够自行查问一下相干的材料,也可能学习到一些乏味的历史常识,比方为什么废除了 儒略历 而将公历定为了 格里历 。还有 法历 为什么只有短短的那些年,犹太历 为什么年份记得这么大了。法历 和 犹太历 月份名字的起源等,都是很乏味的故事。 Calendar 扩大装置及历法信息查看Calendar 扩大曾经集成在 PHP 安装包中了,不须要特地的独自去装置。如果你无奈应用 Calendar 相干的函数,能够从新编译 PHP 并加上 --enable-calendar 参数即可。 接下来咱们看下指定历法的详细信息,这里咱们指定的是 犹太历 。 $info = cal_info(2);print_r($info);// Array// (// [months] => Array// (// [1] => Tishri// [2] => Heshvan// [3] => Kislev// [4] => Tevet// [5] => Shevat// [6] => Adar I// [7] => Adar II// [8] => Nisan// [9] => Iyyar// [10] => Sivan// [11] => Tammuz// [12] => Av// [13] => Elul// )// [abbrevmonths] => Array// (// [1] => Tishri// [2] => Heshvan// [3] => Kislev// [4] => Tevet// [5] => Shevat// [6] => Adar I// [7] => Adar II// [8] => Nisan// [9] => Iyyar// [10] => Sivan// [11] => Tammuz// [12] => Av// [13] => Elul// )// [maxdaysinmonth] => 30// [calname] => Jewish// [calsymbol] => CAL_JEWISH// )cal_info() 函数接管的参数是一个常量,别离是 CAL_GREGORIAN ,CAL_JULIAN ,CAL_JEWISH ,CAL_FRENCH ,它们对应的数字就是 0,1,2,3 。在这段代码中,咱们返回的就是 CAL_JEWISH 的信息。能够看出,犹太历 中的月份名称与公历中的英文名称都不一样,比方这里有 尼撒月 Nisan 、提市黎月 Tishri 。具体的内容就不深究了,毕竟咱们在日常生活中是齐全接触不到这种历法的。 ...

June 29, 2021 · 3 min · jiezi

关于php:COSC1076-Programming-Techniques

COSC1076Advanced Programming TechniquesAssignment 1Particle FilterWeight: 15% of the final course markDue Date: 11.59 pm, Sunday 7 April 2019 (Week 5)Learning Outcomes: This assignment contributes to CLOs: 1, 2, 3, 4, 6Change Log1.3 Added submission instructions Updated code description requirements for Milestone 4 Minor corrections in Background1.2 Updated references to classes Updated notes on Unit Tests to be clearer about the purpose of the sample unit tests. Updated parts of the Task descriptions to be clearer Added Section "Getting Started"1.1 Corrected positions on the worked example. Updated compilation command, removing -c from full code command.1.0 Initial Release1Contents1 Introduction 31.1 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.2 Relevant Lecture/Lab Material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.3 Start-up Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.4 Plagiarism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Background 42.1 Particle Filter Algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52.2 Worked Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 Task 73.1 Milestone 1: Unit Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73.2 Milestone 2: Particle Filter API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73.2.1 Particle Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83.2.2 ParticleList Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83.2.3 ParticleFilter Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93.2.4 Code Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103.2.5 Code Style . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103.2.6 Mandatory Requirements and Restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . . 103.3 Milestone 3: Unknown Orientation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103.4 Milestone 4: Efficient Memory Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113.4.1 Code Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 Starter Code 124.1 Running Unit Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124.2 Getting Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 Submission Instructions 135.1 Submitting Code Files (.h/.cpp) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135.2 Submitting Unit Tests (.maze/.obs/.pos) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1321 Introduction1.1 SummaryIn this assignment you will implement an algorithm known as a Particle Filter, and use it with a simplesimulated 2D robot moving around a room.In this assignment you will: Practice the programming skills covered throughout this course, such as:– Pointers– Dynamic Memory Management– Provided API Correctly Implement a pre-defined API Implement a medium size C++ program Use a prescribed set of C++11/14 language featuresThis assignment is divided into four Milestones: Milestone 1: Writing Unit Tests Milestone 2: Minimum required component for implementing the simple particle filter Milestone 3: Optional component to extend the particle filter for map rotations Milestone 4: Optional component for efficient memory management1.2 Relevant Lecture/Lab MaterialTo complete this assignment, you will requires skills and knowledge from lecture and lab material for Weeks 2 to4 (inclusive). You may find that you will be unable to complete some of the activities until you have completedthe relevant lab work. However, you will be able to commence work on some sections. Thus, do the work youcan initially, and continue to build in new features as you learn the relevant skills.1.3 Start-up CodeOn Canvas you will find starter code to help you get running with the assignment. This code includes: Header files, of the API (C++ classes) that you will implement Dummy (empty) code files, for you to implement Unit Testing code, to help you write and run tests on your implementation Example Unit Test cases1.4 Plagiarism!Plagiarism is a very serious offence.A core learning outcomes for this course is for you to: Demonstrate and Adhere to the standards and practiceof Professionalism and Ethics, such as described in the ACS Core Body of Knowledge (CBOK) for ICTProfessionals.The penalty for plagiarised assignments include zero marks for that assignment, or failure for this course.Please keep in mind that RMIT University uses plagiarism detection software to detect plagiarism and that allassignments will be tested using this software. See the RMIT website for more information about the universitypolicies on Plagiarism and Academic Misconduct.32 BackgroundOne challenge in robotics is called localisation. This is the process of the robot figuring out where it is withinsome environment. One algorithm for localising a robot is called a Particle Filter. In this assignment youwill implement a simple particle filter for a robot moving about a simple 2D maze.In this assignment, the simple 2D maze will be represented as a grid of ASCII characters. For example:Aspects of the maze are represented by different symbols:Symbol Meaning. (dot) Empty/Open Space. The robot can enter any open space.= (equal) Wall or Obstacle within the maze. The robot cannot pass obstacles~ (tilda) The edge of the maze. Every maze is always bounded by the edge symbolsEach location in the maze (including the maze edges) is indexed by a cartesian (x,y) co-ordinate. The top-leftcorner of the maze is always the co-ordinate (0,0), the x-coordinate increases right-wards, and the y-coordinateincreases down-wards. For the above maze, the four corners have the following co-ordinates:(0,0) . . (12,0)(0,6) . . (12,6)For the purposes of this assignment we will make two assumptions: ...

June 28, 2021 · 20 min · jiezi

关于php:PHP中的MySQLi扩展学习六MySQLIresult对象操作

在之前的文章中,咱们就曾经接触过 MYSQLI_result 相干的内容。它的作用其实就是一个查问的后果集。不过在 PDO 中,个别间接通过 query() 或者 PDOStatement 对象进行查问之后就会返回后果。但在 MySQLi 中,会把查问到的后果也放入一个对象中,这就是 MySQLI_result 对象。 MySQLI_result 对象属性首先,咱们要通过一段查问来取得一个 MySQLI_result 对象。 $stmt = $mysqli->prepare("select * from zyblog_test_user where username = 'kkk'");$stmt->execute(); // 执行语句$result = $stmt->get_result();var_dump($result);// object(mysqli_result)#3 (5) {// ["current_field"]=>// int(0)// ["field_count"]=>// int(4)// ["lengths"]=>// NULL// ["num_rows"]=>// int(7)// ["type"]=>// int(0)// }如果应用的 MYSQLI_STMT 的话,间接在 execute() 办法执行查问语句之后,就能够通过 get_result() 办法取得一个 MySQLI_result 对象。 在这个对象中,咱们能够看到有 current_field 以后字段 、 field_count 字段数量 、 lengths 字段长度 、 num_rows 行数 、 type 这些属性内容。不少同学会发现,current_field 和 lengths 如同并没有什么理论的内容,其实这两个属性是须要在特定操作下才会显示内容的,比方 lengths 是要在 fetch() 后果集之后才会有信息的。 ...

June 28, 2021 · 3 min · jiezi

关于php:PHP中的MySQLi扩展学习五MySQLISTMT对象操作

就像 PDO 中的 PDO_Statment 对象一样,MySQLI_STMT 对象也是一个预处理语句所造成的对象,专门用来操作 MySQLi 所生成的预处理语句的。其实操作形式之类也都比拟类似,不外乎以绑定参数为主的一些针对 SQL 语句和获取后果集的操作。 参数绑定及操作属性之前的文章中想必大家曾经见过咱们应用的 bind_param() 办法,它与 PDO 中的 bindParam() 办法有很大的不同。 $stmt = $mysqli->prepare("insert into zyblog_test_user(username, password, salt) values(?, ?, ?)");$username='mysqli_username';$password='mysqli_password';$salt = 'mysqli_salt';$stmt->bind_param('sss', $username, $password, $salt);var_dump($stmt->insert_id); // int(232)var_dump($stmt->affected_rows); // int(1)$stmt->execute();$stmt->close();首先就是之前提到过的,MySQLI_STMT 中绑定参数只能应用 ? 问号占位符,而后在应用 bind_param() 时,应用的是 's' 这种来按程序绑定参数,这个 's' 代表的就是字符串。另外还能够是 'i' 示意整型数字、'd' 示意浮点数字、 'b' 示意 blob 类型。 另外,从下面的测试代码中还能够看出,能够应用一个 bind_param() 办法绑定多个参数,'sss' 就是三个字符串,按程序进行绑定。 绑定参数之后,咱们就能够通过 execute() 办法来执行语句。同 PDO 一样,这个办法只返回成功失败的信息,也就是一个布尔值。所以,咱们须要通过 MySQLI_STMT 对象的 insert_id 来取得新减少数据的 ID ,或者通过 affected_rows 属性来取得以后语句执行后影响的行数,来确定语句是否真正地执行实现并达到咱们的冀望。 ...

June 26, 2021 · 2 min · jiezi

关于php:PHP中的MySQLi扩展学习四mysqli的事务与预处理语句

对于 MySQLi 来说,事务和预处理语句当然是它之所以可能淘汰 MySQL(原始) 扩大的资本。咱们之前也曾经学习过了 PDO 中对于事务和预处理语句相干的内容。所以在这里,咱们就不再多讲实践方面的货色了,间接上代码来看看 MySQLi 中这两大个性与 PDO 在应用上的区别。 事务处理首先,咱们还是要让 MySQLi 对于谬误的语句也报出异样来。对于这个性能就和 PDO 很不一样了。在 PDO 中,咱们间接指定连贯的报错属性就能够了。而在 MySQLi 中,咱们则须要指定 MySQLi_Driver 对象中的报错属性为抛出异样,很显著,MySQLi_Driver 就是 MySQLi 的驱动对象。 // 应用异样处理错误状况$driver = new mysqli_driver();$driver->report_mode = MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT;这样就指定了在应用 MySQLi 扩大时,所有的错误信息都会作为异样抛出。 接下来的内容,其实就和 PDO 很类似了。 try { // 开始事务 $mysqli->begin_transaction(); $mysqli->query("insert into tran_innodb (name, age) values ('Joe', 12)"); $mysqli->query("insert into tran_innodb2 (name, age) values ('Joe', 12)"); // 不存在的表 // 提交事务 $mysqli->commit();} catch (Exception $e) { // 回滚事务 $mysqli->rollback(); var_dump($e->getMessage()); // string(44) "Table 'blog_test.tran_innodb2' doesn't exist"}咱们同样是应用一个 begin_transaction() 来启动事务。而后通过 commint() 办法来提交事务。在这段测试代码中,第二条 SQL 语句是会报错的,于是进入了 catch 中,应用 rollback() 来回滚事务。 ...

June 25, 2021 · 1 min · jiezi

关于php:PHP-祖传代码拯救者-Deliverer-他来了

前几日有位群友接手一段祖传代码,排查很久没有解决,筹备提桶跑路,最终帮其解决,残缺的过程见 https://mengkang.net/1470.html 然而最初代码的定位我有一些基于集体教训,理论调用的链路和我预计的不一样,都是靠猜。没有看到残缺的调用链路,所以我想着须要一个工具来辅助明确查问到整个残缺的调用链。 所以搞了这么个工具,次要是用于一些不相熟的我的项目,而且日常环境不好复现的线上场景。 deliverer 祖传代码跑路援救者 https://github.com/zhoumengka... 如果你的我的项目不是那么蹩脚,日常环境都 ok,那么相熟一个我的项目最好的形式还是 xdebug,这个工具次要是排查线上问题。相似的工具有 360 的 phptrace 实现原理上略微有点不同性能点能够依据函数名、类名、办法名、路由来过滤输入能够在查问到指定过滤内容 n 次之后退出能够依据 request id 回放细看整个残缺的调用链过滤的内容会高亮显示调用栈比拟深的能够指定 -l 来暗藏深度调用的展现原理其实比较简单,分两步,第一步收集日志,第二步剖析日志。 第一步在PHP_MINIT阶段,通过zend_set_user_opcode_handler 来设置对 ZEND_DO_UCALL 、ZEND_DO_FCALL_BY_NAME、ZEND_DO_FCALL 三类 opcode 的解决剖析。 留神其中会涵盖一些内置函数和办法的调用,咱们能够通过类型进行过滤。而后在PHP_RINIT阶段新建日志文件,写入申请的信息 pid-ts sapi http_method http_url申请过程中在自定义的 handler 外面打印调用栈信息 最初在PHP_RSHUTDOWN敞开日志文件的写入 第二步对收集好的日志,利用bin/deliverer进行剖析和整顿,这块是 php 脚本,就不赘述了。 装置应用编译$ phpize$ ./configure --with-php-config=/usr/local/php/bin/php-config$ make && sudo make install配置 php.ini追加 [deliverer]extension=deliverer.so重启 php-fpmsudo service php-fpm restart应用剖析工具能够挪动./bin/deliverer到你感觉适合的目录,如果在当前目录 $ chmod +x deliverer用一段我本人很久之前的祖传代码(我的博客)来跑下 $ ./bin/deliverer -t这样会始终监控所有的 php 过程的执行 $ ./bin/deliverer -tAction::initUser -n3 -l5 ...

June 24, 2021 · 1 min · jiezi

关于php:经典面试题你觉得-Go-在什么时候会抢占-P

微信搜寻【脑子进煎鱼了】关注这一只爆肝煎鱼。本文 GitHub github.com/eddycjy/blog 已收录,有我的系列文章、材料和开源 Go 图书。大家好,我是煎鱼。 前几天咱们有聊到《单核 CPU,开两个 Goroutine,其中一个死循环,会怎么样?》的问题,咱们在一个细节局部有提到: 有新的小伙伴会产生更多的疑难,那就是在 Go 语言中,是如何抢占 P 的呢,这外面是怎么做的? 明天这篇文章咱们就来解密抢占 P。 调度器的发展史在 Go 语言中,Goroutine 晚期是没有设计成抢占式的,晚期 Goroutine 只有读写、被动让出、锁等操作时才会触发调度切换。 这样有一个重大的问题,就是垃圾回收器进行 STW 时,如果有一个 Goroutine 始终都在阻塞调用,垃圾回收器就会始终期待他,不晓得等到什么时候... 这种状况下就须要抢占式调度来解决问题。如果一个 Goroutine 运行工夫过久,就须要进行抢占来解决。 这块 Go 语言在 Go1.2 起开始实现抢占式调度器,不断完善直至今日: Go0.x:基于单线程的程调度器。Go1.0:基于多线程的调度器。Go1.1:基于工作窃取的调度器。Go1.2 - Go1.13:基于合作的抢占式调度器。Go1.14:基于信号的抢占式调度器。调度器的新提案:非平均存储器拜访调度(Non-uniform memory access,NUMA),但因为实现过于简单,优先级也不够高,因而迟迟未提上日程。 有趣味的小伙伴能够详见 Dmitry Vyukov, dvyukov 所提出的 NUMA-aware scheduler for Go。 为什么要抢占 P为什么会要想去抢占 P 呢,说白了就是不抢,就没机会运行,会 hang 死。又或是资源分配不均了, 这在调度器设计中显然是不合理的。 跟这个例子一样: // Main Goroutine func main() { // 模仿单核 CPU runtime.GOMAXPROCS(1) // 模仿 Goroutine 死循环 go func() { for { } }() time.Sleep(time.Millisecond) fmt.Println("脑子进煎鱼了")}这个例子在老版本的 Go 语言中,就会始终阻塞,没法重见天日,是一个须要做抢占的场景。 ...

June 24, 2021 · 3 min · jiezi

关于php:PHP中的MySQLi扩展学习三mysqli的基本操作

咱们持续 MySQLi 扩大的学习,上篇文章中提到过,MySQLi 的扩大绝对于 PDO 来说性能更加的丰盛,所以咱们仍然还会在学习过程中交叉各种 MySQLi 中好玩的办法函数。不过,明天的配角是 MySQLi 中如何执行 SQL 语句以及多条 SQL 语句的执行。 连贯与抉择数据库首先是一个小内容的学习分享,仍然还是连贯数据库,不过这次咱们用另外一种形式来进行连贯。 $mysqli = new mysqli();$mysqli->real_connect("localhost", "root", "", "blog_test");var_dump($mysqli); // ["thread_id"]=>// int(163)$mysqli->real_connect("localhost", "root2", "123", "blog_test");var_dump($mysqli);// ["thread_id"]=>// int(164)首先,咱们实例化了一个 mysqli 对象。在实例化过程中,咱们并没有给 mysqli 的构造函数传递任何的参数,而是应用 real_connect() 办法来传递数据库服务器信息并建设连贯。 置信不少敌人从代码中就能够看出,咱们应用 real_connect() 能够在一个 mysqli 实例下来切换不同的数据库连贯。通过打印 mysqli 对象的内容就能够看出,两个连贯的线程ID不同,也就是说,它们是不同的两个连贯,然而应用的都是最下面所初始化的那个 mysqli 对象。 连贯能够切换了,那么咱们要连贯的数据库呢?当然也能够不便地切换。 $mysqli->select_db('mysql');就是这样一个简略的 select_db() 办法,就能够帮忙咱们在代码执行过程中动静地批改所连贯的数据库。 执行 SQL 语句对于 PDO 来说,如果是查问语句,咱们须要应用 query() 办法,如果是增、删、改之类的其它语句,咱们要应用 exec() ,通过这两个办法别离执行不同的 SQL 语句。然而在 MySQLi 中,咱们对立只应用 query() 办法就能够了。 $mysqli->query("insert into zyblog_test_user(username, password, salt) values('3a', '3a', '3a')");var_dump($mysqli->affected_rows);var_dump($mysqli->insert_id);$mysqli->query("update zyblog_test_user set password='3aa' where username='3a'");var_dump($mysqli->affected_rows);$mysqli->query("delete from zyblog_test_user where id = 60");var_dump($mysqli->affected_rows);$res = $mysqli->query("select * from zyblog_test_user where username='3a'");print_r($res);// mysqli_result Object// (// [current_field] => 0// [field_count] => 4// [lengths] =>// [num_rows] => 3// [type] => 0// )print_r($res->fetch_assoc());// Array// (// [id] => 61// [username] => 3a// [password] => 3aa// [salt] => 3a// )while ($row = $res->fetch_assoc()) { print_r($row);}// Array// (// [id] => 62// [username] => 3a// [password] => 3aa// [salt] => 3a// )// Array// (// [id] => 63// [username] => 3a// [password] => 3aa// [salt] => 3a// )// ……对于增、删、改之类的语句,query() 办法只会返回一个布尔值,也就是语句是否执行胜利。记住,它返回的不是受影响的行数,这一点是须要留神的。咱们如果须要获取受影响的行数须要应用 MySQLi 的属性 affected_rows 。对于插入语句来说,获取最新插入的数据ID应用的是 insert_id 属性。 ...

June 24, 2021 · 3 min · jiezi

关于php:2021年Wordpress博客装修美化二

应用古腾堡来排版页面废话不多说,咱们间接开始吧,明天次要来聊聊如何应用Wordpress自带的可视化页面编辑器。我置信只有驾驭最根底的可视化排版,前面能力对高级版本的扩大可视化编辑器elementor有着更粗浅的了解。 图文排版1,登录WP后盾治理页,找到文章,去增加一个文章。如图(我把之前的示例清空了), 增加之后,列表会呈现在上面。 进入增加文章之后,先把题目增加上,固定链接,最好本人设置,不便SEO,分类的话,我这边先写个案例。以不便演示,前面会讲分类的设置。设置实现后,咱们能够先点击一下保留草稿。WP默认也会实时的保留。 上面为了防止版权问题,咱们先去找一个神器,[狗屁不通文章生成器],随机生成一篇文章。生成好文章后,依照上面的形式增加进去 也能够按左侧的增加板块,将须要的板块拖拽到内容区域。 咱们能够间接从左侧操作栏拖拽一个图片放在文档的结尾。图片能够来自URL,也能够媒体库。 如果咱们须要增加图片与文字的组合,咱们能够应用列, 在文章的任意中央,咱们能够增加一个列,依据须要,来进行对列的抉择。比方,咱们抉择7/3分。 咱们在第一列抉择图片,第二列抉择文字, 其实这样的多列看起来总是不足很多的违和感,咱们还能够用古腾堡提供的媒体图文块, 调整一些排版,就能够像这样。 就这样,看起来就像杂志的排版。上面,咱们来组多图插入,做一个画廊, 间接拖拽过去,从媒体库抉择一组图片。古腾堡会主动进行图片排版。 最初,咱们来为文章插一个封面, 公布一下,咱们回到博客主页看看, 好了,到当初为止,图文排版差不多就这样了。还有更多的板块,同学们能够自在去施展,比方插入视频,图表,子标题,链接到别的网站等内容。 Qubely古腾堡的神兵利器去插件下载一个qubely,实现装置激活。咱们只须要应用其收费性能即可。 激活后,咱们来增加一个主页,作为咱们关上博客页面的门面。如下图 此时,咱们关上主页进行编辑,发现很多高级块,能够随便拖拽到内容区体验下。 咱们当初能够拖拽一个图片过来,并更改页面模板,为全宽(Qubely Full Width),如下, 咱们选中图片区块,在右侧的操作栏,能够看到区块的款式,并从此处去抉择媒体库中的图片, 这里只是一个示例,当初咱们能够把图片删掉,增加一个行块,来减少更简单的组块。如下图, 咱们能够在高级你们设置内边距,外边距等。咱们也能够为行块增加一个背景图片,使其更有层次感。照着本人的感觉去调整。 调整实现后,咱们能够间接把咱们方才的文章,增加到咱们的首页, 依据本人的须要,实现一些调整设置后,咱们点击公布。公布实现后,咱们能够去自定义网站,将该页面设置为咱们的网站首页。步骤如下, 确认无误后,点击公布,即发现,当初的首页曾经是咱们设计的啦。(如果感觉本人做的首页不难看,不设置,也没有关系,咱们前面有机会还会讲更弱小的网页编辑器,只须要简略的拖拽,就能够实现得心应手的页面) 我做的页面感觉切实不难看,我给删了,用默认的页面 分类和标签分类,即是把文章依照树形构造进行排列分组。能够对分类进行父子关系的组合。而标签,次要的目标是提取文章的外围关键词,以便搜索引擎索引。一篇文章的外围关键词不倡议超过五个。 设置分类,倡议别名应用英文,不便SEO 我这边依照我的编程打算,设置一些内容。实现类别的设置后,咱们去自定义菜单,将分类作为菜单。 咱们先创立一个主菜单。 在治理地位中,将菜单增加至页眉的菜单 这样,咱们回到首页,便能够看见菜单曾经配置到咱们的主页面头部了。 我曾经在菜单中,调整过想要展现菜单的程序了。 页眉和页脚设置简介对于页眉与页脚,这期只简要提到一下,不做深刻解说。我贴几张图,从左往右,大家去操作一下,即刻能明确其中的意思。比方页头, 页脚也这样, ...

June 23, 2021 · 1 min · jiezi

关于php:web-hooks服务器自动拉取代码php-thinkphp6

Github 筹备事项1.在仓库settings里增加webhooks以私人仓库为例: 1.创立完仓库之后,点击settings。设置webhooks拜访门路: 以我本人我的项目为例 ,框架应用的是tp6。在public/下创立一个名为basic.php的文件,目标在于当代码推送至服务器上时,github能够拜访到并且能够执行的一个文件。该文件用于执行shell 命令,在触发该链接时主动执行该文件里的命令,从而实现git 主动拉取。2.测试链接是否失效,文件是否有被拜访到 如上图所示,当呈现绿色✅时示意此链接被拜访到,当呈现红色⚠️标记则示意文件没有被拜访。以此排查链接问题还是代码问题。[x] 至此Github方面实现。 PHP代码部署1.增加钩子文件 执行shell命令上面展现一些 内联代码片。 <?php //git webhook 主动部署脚本 $requestBody = file_get_contents("php://input"); //接收数据 if (empty($requestBody)) { //判断数据是不是空 die('send fail'); } $content = json_decode($requestBody, true); //数据转换 //若是主分支且提交数大于0 if ($content['ref']=='refs/heads/main') { //或将命令退出 shell里,看集体需要 git reset --hard origin/master && git clean -f $res = shell_exec('cd /www/wwwroot/xxxx/ && echo `sudo git pull` >> b.log');//PHP函数执行git命令 $res_log = '-------------------------'.PHP_EOL; $res_log .= ' 在' . date('Y-m-d H:i:s') . '向' . $content['repository']['name'] . '我的项目的' . $content['ref'] . '分支push'.$res; file_put_contents("git-webhook.txt", $res_log, FILE_APPEND);//将每次拉取信息追加写入到日志里 }?>[x] 至此命令 php shell局部已实现,可依据不同我的项目需要自行调试。 ...

June 23, 2021 · 1 min · jiezi

关于php:PHP中的MySQLi扩展学习二mysqli类的一些少见的属性方法

虽说是少见的一些属性办法,然而可能还是有不少同学在日常的开发中应用过,这里只是学习了可能相对来说咱们用得比拟少的一些 mysqli 的属性或办法。就当是扩大一下本人的常识体系。 切换用户首先就是切换一下以后连贯数据库的用户。 // 切换用户$mysqli->change_user('root2', "123", 'blog_test');// 错误信息$res = $mysqli->query( "SELECT * FROM zyblog_test_user");var_dump($res); // bool(false)var_dump($mysqli->error_list);// array(1) {// [0]=>// array(3) {// ["errno"]=>// int(1142)// ["sqlstate"]=>// string(5) "42000"// ["error"]=>// string(78) "SELECT command denied to user 'root2'@'localhost' for table 'zyblog_test_user'"// }// }应用 change_user() 办法就可能不便地在 mysqli 对象曾经实例化之后再来进行用户的切换。在这段代码中,咱们的 root2 用户没有 blog_test 表的 SELECT 权限,所以返回的 query() 查问后果是空的。通过打印 mysqli 的 error_list 属性就能够看到以后的错误信息。 错误信息紧接着上一段,对于执行语句的错误信息,咱们能够通过几个 mysqli 中的属性来取得。比方上文中的 error_list 。它外面蕴含的就是所有的错误信息列表,并且是十分具体的谬误信息内容。不过咱们还能够通过另外两个属性来取得独自的谬误号和错误信息的字符串。 var_dump($mysqli->errno); // int(1142)var_dump($mysqli->error); // string(78) "SELECT command denied to user 'root2'@'localhost' for table 'zyblog_test_user'"errno 属性外面保留的就是数据库的谬误号,error 属性中保留的是错误信息的具体文本阐明。这两个谬误信息内容都是在执行 SQL 语句之后数据库返回的内容。 ...

June 23, 2021 · 3 min · jiezi

关于php:go语言-实战导出excel并且上传到阿里云OSS

蒽~ 间接上代码吧 //数据格式以json为根底 如果复制此段代码进行运行请间接通过编译器提醒装置所需类库/********这部分代码不必写的哦--间接依据定义好的json数据格式在线生成,在线工具网址在代码上面******************/type AutoGenerated struct { URL []URL `json:"url"` Label Label `json:"label"`}type URL struct { StoreName string `json:"store_name"` ProductID string `json:"product_id"`}type Label struct { StoreName string `json:"store_name"` ProductID string `json:"product_id"`}/************************.这部分代码不必写的哦*******************/func init() { //data 为导出数据 //label 定义为导出 jsonData := []byte(` { "data":[ { "store_name":"watotomama", "product_id":"5942170910885" } ], "label":{ "store_name":"商户名称", "product_id":"没有sku的shopify商品ID" } }`) var basket AutoGenerated err := json.Unmarshal(jsonData, &basket) if err != nil { fmt.Println(err) } result := ExcelData(basket) fmt.Printf("%# v\n", pretty.Formatter(result)) f := excelize.NewFile() // Create a new sheet. index := f.NewSheet("Sheet1") for i, i2 := range result { // Set value of a cell. f.SetCellValue("Sheet1", i, i2) } // Set active sheet of the workbook. f.SetActiveSheet(index) // Save spreadsheet by the given path. if err := f.SaveAs("Book1.xlsx"); err != nil { fmt.Println(err) }}//解决并且组装数据func ExcelData(data AutoGenerated) map[string]interface{} { url := data.URL label := data.Label labelT := reflect.TypeOf(label) tempData := make(map[string]interface{}) labelV := reflect.ValueOf(label) for i := 0; i < len(url); i++ { col := 65 for k := 0; k < labelT.NumField(); k++ { key1 := labelT.Field(k).Name if i == 0 { ch := HandleChr(col)+strconv.Itoa(i+1) ch1 := HandleChr(col)+strconv.Itoa(i+2) tempData[ch] = labelV.Field(k).Interface() tempData[ch1] = reflect.ValueOf(url[i]).FieldByName(key1) } else { ch := HandleChr(col)+strconv.Itoa(i+2) tempData[ch] = reflect.ValueOf(url[i]).FieldByName(key1) } col++ //key := t.Field(k).Name //value := v.Field(k).Interface() } } fmt.Printf("%s\n", pretty.Formatter(tempData)) return tempData}//返回ASICC码func HandleChr(num int) string { ch1 := fmt.Sprintf("%c", rune(num)) return strings.ToUpper(ch1)} ...

June 22, 2021 · 2 min · jiezi

关于php:PHP中的MySQLi扩展学习一MySQLi介绍

对于 PDO 的学习咱们告一段落,从这篇文章开始,咱们持续学习另外一个 MySQL 扩大,也就是除了 PDO 之外的最外围的 MySQLi 扩大。能够说它的先人,也就是 MySQL(原始) 扩大是咱们很多人刚开始学习 PHP 时连贯数据库的入门导师。不过随着时代的变迁,MySQL(原始) 扩大在 PHP7 中曾经被彻底废除了。当初如果想要应用过程式的代码来操作数据库,只能应用 mysqli 扩大了。当然,mysqli 扩大也是反对面向对象式的写法的。 什么是 MySQLiMySQLi 扩大容许咱们拜访 MySQL4.1 及以上版本的数据库所提供的性能。它是专门针对于 MySQL 数据库的,不像 PDO 能够通过不同的 dns 来连贯不同的数据库。 与 MySQL 和 PDO 的区别与分割首先,咱们还是回顾一下最早的 MySQL 扩大。 只面向过程不反对 存储过程 、 多语句执行 、 预处理语句PHP7 中曾经删除了并且齐全不反对而后是 PDO 。 仅反对面向对象形式应用能够连贯多种数据库,切换数据库带来的变更少,甚至可能不必批改代码反对 存储过程 、 多语句执行 、 预处理语句最初就是 MySQLi 。 反对面向对象和面向过程两种写法仅反对 MySQL 数据库反对 存储过程 、 多语句执行 、 预处理语句追随 PHP 及 MySQL 的版本更新,能够更疾速地反对更多的 MySQL 高级个性从它们三个的这些特点来看,MySQL(原始)扩大必定是不举荐了,就算是老的我的项目,只有是反对 PDO 或 MySQLi 的 PHP 版本,都应该思考将数据库的连贯转换成这两种形式之一。如果你还在 PHP5 的环境中学习 MySQL(原始)扩大的应用的话,也能够放下了。 ...

June 22, 2021 · 1 min · jiezi

关于php:多商户页面目录结构说明

页面阐明└─view uni-app寄存根目录 ├─api 接口对立寄存目录 │ ├─activity.js 流动接口 │ ├─admin.js 后盾订单治理接口 │ ├─api.js 公共接口 │ ├─order.js 订单接口 │ ├─public.js 受权分享接口 │ ├─store.js 产品接口 │ └─user.js 用户接口 ├─components 组件目录 │ ├─addressWindow 地址组件 │ ├─countDown 倒计时组件 │ ├─couponListWindow 优惠券列表弹框组件(商品详情、提交订单) │ ├─couponWindow 优惠券弹出框组件(首页) │ ├─goodList 商品展现组件 │ ├─home 悬浮导航组件 │ ├─jyf-parser 富文本框组件 │ ├─Loading 正在加载组件 │ ├─orderGoods 订单产品展现组件 │ ├─payment 领取弹出框组件 │ ├─PriceChange 后盾更改价格组件 │ ├─productConSwiper Swiper产品轮播图组件 │ ├─productWindow 产品属性组件 │ ├─promotionGood 促销产品组件 │ ├─recommend 热门举荐组件 │ ├─shareInfo 分享组件 │ ├─shareRedPackets 产品页分享组件 │ ├─swipers swipers轮播组件 │ ├─ucharts 图表组件 │ ├─uni-calendar 日期组件 │ ├─userEvaluation 产品页评论列表组件 │ ├─Authorize.vue 受权组件 │ ├─emptyPage.vue 空页面组件 │ └─tabNav.vue 导航组件 ├─config 配置目录 │ ├─app.js 接口配置 │ ├─cache.js 缓存配置 │ └─socket.js 长链接配置 ├─libs │ ├─chat.js 聊天 │ ├─login.js 是否登录 │ ├─order.js 流动页面的跳转 │ ├─routine.js 小程序受权 │ └─wechat.js 公众号受权 ├─mixins 验证码目录 │ └─SendVerifyCode.js 验证码倒计时 ├─pages 页面目录 │ ├─activity 流动 │ │ ├─poster-poster 海报页面 │ ├─admin 订单治理 │ │ ├─delivery 订单发货 │ │ ├─order 订单统计 │ │ ├─order_cancellation 订单核销 │ │ ├─orderDetail 订单详情 │ │ ├─orderList 订单列表 │ │ └─statistics 营业额统计 │ ├─chat 聊天 │ │ ├─customer_list/chat 聊天内容页 │ │ ├─customer_list/index 音讯列表 │ ├─auth 受权 │ ├─columnGoods │ │ ├─goods_search/index 搜寻商品 │ │ ├─goods_search_con/index 搜寻商品后果页 │ │ ├─goods_list/index 三级分类列表页 │ │ ├─HotNewGoods/index 精品举荐,热门榜单,首发新品,促销单品 │ ├─goods_cate 商品分类 │ ├─goods_details 商品详情 │ ├─goods_list 商品列表 │ ├─index 首页 │ ├─news_details 新闻详情 │ ├─news_list 新闻列表 │ ├─order_addcart 购物车 │ ├─order_details 订单详情 │ ├─order_pay_status 订单领取状态 │ ├─retrieve_password 找回明码 │ ├─order_addcart 购物车 │ ├─user 集体核心 │ ├─users 我的页面 │ │ ├─commission_rank 佣金排行 │ │ ├─goods_comment_con 商品评估 │ │ ├─goods_comment_list 评估列表 │ │ ├─goods_details_store 商品提货点 │ │ ├─goods_logistics 物流信息 │ │ ├─goods_return 商品退货 │ │ ├─login 登录 │ │ ├─order_confirm 订单确认 │ │ ├─order_list 订单列表 │ │ ├─promoter_rank 推广人排行 │ │ ├─promoter-list 推广人列表 │ │ ├─promoter-order 推广人订单 │ │ ├─retrievePassword 找回明码 │ │ ├─user_address 增加地址 │ │ ├─user_address_list 地址列表 │ │ ├─user_bill 账单明细 │ │ ├─user_cash 提现 │ │ ├─user_coupon 我的优惠卷 │ │ ├─user_get_coupon 支付优惠卷 │ │ ├─user_goods_collection 珍藏产品 │ │ ├─user_info 个人资料 │ │ ├─user_integral 积分明细 │ │ ├─user_money 我的账户 │ │ ├─user_payment 充值 │ │ ├─user_phone 手机号绑定 │ │ ├─user_pwd_edit 批改明码 │ │ ├─user_return_list 退款列表 │ │ ├─user_sgin 签到 │ │ ├─user_sgin_list 签到记录 │ │ ├─user_spread_code 分销海报 │ │ ├─user_spread_money 佣金明细 │ │ ├─user_spread_user 我的推广 │ │ └─user_vip 会员页面 ├─static 动态文件 │ ├─css 款式文件 │ ├─iconfont 小图标字体包 │ ├─images 图片包 ├─store Vuex目录 ├─utils 工具类目录 │ ├─cache.js 缓存 │ ├─emoji.js 表情图标 │ ├─index.js 用户受权 │ ├─permission.js 权限 │ ├─request.js 申请基类 │ ├─SubscribeMessage.js 音讯 │ ├─util.js 工具函数 │ └─validate.js 验证码 ├─App.vue ├─main.js ...

June 21, 2021 · 2 min · jiezi

关于php:在PHP中使用SPL库中的对象方法进行XML与数组的转换

虽说当初很多的服务提供商都会提供 JSON 接口供咱们应用,然而,还是有不少的服务仍然必须应用 XML 作为接口格局,这就须要咱们来对 XML 格局的数据进行解析转换。而 PHP 中并没有像 json_encode() 、 json_decode() 这样的函数可能让咱们不便地进行转换,所以在操作 XML 数据时,大家往往都须要本人写代码来实现。 明天,咱们介绍的是应用 SPL 扩大库中的一些对象办法来解决 XML 数据格式的转换。首先,咱们定义一个类,就相当于封装一个操作 XML 数据转换的类,不便咱们未来应用。如果只是测试成果的话,间接写上面的函数也是能够的。 class ConvertXml{ // ....}XML 转换为 PHP 数组class ConvertXml{ public function xmlToArray(SimpleXMLIterator $xml): array { $res = []; for ($xml->rewind(); $xml->valid(); $xml->next()) { $a = []; if (!array_key_exists($xml->key(), $a)) { $a[$xml->key()] = []; } if ($xml->hasChildren()) { $a[$xml->key()][] = $this->xmlToArray($xml->current()); } else { $a[$xml->key()] = (array) $xml->current()->attributes(); $a[$xml->key()]['value'] = strval($xml->current()); } $res[] = $a; } return $res; } // .....}$wsdl = 'http://flash.weather.com.cn/wmaps/xml/china.xml';$xml = new SimpleXMLIterator($wsdl, 0, true);$convert = new ConvertXml();// var_dump($convert->xmlToArray($xml));// array(37) {// [0]=>// array(1) {// ["city"]=>// array(2) {// ["@attributes"]=>// array(9) {// ["quName"]=>// string(9) "黑龙江"// ["pyName"]=>// string(12) "heilongjiang"// ["cityname"]=>// string(9) "哈尔滨"// ["state1"]=>// string(1) "7"// ["state2"]=>// string(1) "3"// ["stateDetailed"]=>// string(15) "小雨转阵雨"// ["tem1"]=>// string(2) "21"// ["tem2"]=>// string(2) "16"// ["windState"]=>// string(21) "南风6-7级转4-5级"// }// ["value"]=>// string(0) ""// }// }// [1]=>// array(1) {// ["city"]=>// array(2) {在这里,咱们应用的是 SimpleXMLIterator 对象。从名称中就能够看出,它的作用是生成能够遍历的 SimpleXMLElement 对象。第一个参数是格局正确的 XML 文本或者链接地址。第二个参数是一些选项参数,这里咱们间接给 0 就能够了。第三个参数则是指明第一个参数是否是链接地址,这里咱们给 true 。 ...

June 21, 2021 · 2 min · jiezi

关于php:PHP中PDO关闭连接的问题

在之前咱们手写 mysql 的连贯操作时,个别都会应用 mysql_close() 来进行敞开数据库连贯的操作。不过在现代化的开发中,个别应用框架都会让咱们漠视了底层的这些封装,而且大部分框架都曾经默认是应用 PDO 来进行数据库的操作,那么,大家晓得 PDO 是如何敞开数据的连贯的吗? 官网阐明要想敞开连贯,须要销毁对象以确保所有残余到它的援用都被删除,能够赋一个 NULL 值给对象变量。如果不明确地这么做,PHP 在脚本完结时会主动敞开连贯。$pdo = new PDO('mysql:host=127.0.0.1;port=3306;dbname=blog_test', 'root', '');$pdo = null;官网文档中说得很明确,那就是给 PDO 对象赋值为 NULL 即可。然而事件真的有那么简略吗? 理论测试咱们来这样进行一下测试,失常状况下,咱们关上数据库连贯后都不会间接就敞开,而是要进行一些操作。 $pdo = new PDO('mysql:host=127.0.0.1;port=3306;dbname=blog_test', 'root', '');$stmt = $pdo->prepare('SELECT * FROM zyblog_test_user');$stmt->execute();$pdo = null;sleep(60);运行上述代码后,咱们在数据库应用 show full processlist; 查看连贯过程,会发现以后的连贯并没有马上敞开,而是等到 60 秒之后,也就是页面执行实现之后才会敞开。仿佛 $pdo = null; 这句并没有执行胜利。 其实,在官网文档中曾经阐明了这个状况,只是大家可能不太会留神。【须要销毁对象以确保所有残余到它的援用都被删除】,在下面的代码中,\$stmt 预编译 SQL 语句的性能调用的是 $pdo 对象中的办法,它们之间产生了援用依赖的关系,这样的状况下,间接给 $pdo = null; 是没有成果的,咱们须要将 $stmt 也赋值为 null 。 $pdo = new PDO('mysql:host=127.0.0.1;port=3306;dbname=blog_test', 'root', '');$stmt = $pdo->prepare('SELECT * FROM zyblog_test_user');$stmt->execute();$stmt = null;$pdo = null;sleep(60);mysqli测试那么应用 mysqli 的默认扩大组件,也就是应用 mysqli 对象中的 close() 来敞开数据库连贯会有这个问题吗?还是间接用代码来测试测试。( mysql 扩大曾经过期不举荐应用了,大家如果要本人封装数据库操作类或者写小 Demo 的话还是要用 mysqli 更好一些 ) ...

June 20, 2021 · 1 min · jiezi

关于php:2021年WordPress博客装修美化一

2021年Wordpress博客装修丑化(一) 2021年WP博客Blocksy主题装置和根底配置 接上篇,2021年Wordpress博客搭建 ,对于搭建WP的步骤,基本上都曾经讲了。看完后,照着操作能够疾速的搭建一个高可维护性的属于本人的博客。万里长征,咱们才实现一小小步,仍然是微不足道的一步,前面对博客的平安治理,内容治理,图文排版,才是咱们的重头戏。 前言一切照旧,在教程的开始,容我先废话几句。WP的性能,远不止记录一个博客那么简略,通过肯定的优化,能够撑持数千万流量的订单流水。也能够做一个简单商业网站,甚至不须要写一行代码。只须要对主题插件页面进行元素的拖拽和款式的微调就能够实现。如果对自建站感兴趣的同学,能够认真来看下我接下来的内容,搭建一个小小的博客,对WP来说,倒退到当初,真的是有点大材小用是也。 长时间以来,我始终认为从百度上搜寻进去的WP集体网站,是WP的平均水平。直到我发现国内上的WP曾经倒退成了一个新高度,我才释然明确,是我错了,没能跟上时代,为了把最新的WP科技展示给大家,我信心写一个WP系列相干的文章,将来还会出相干视频。我一口气开明近二十家各类媒体平台,打算将所有我晓得的常识进行收费分享,写的好的文章,心愿大家能多多转载。写的不好的中央,心愿大家能在评论中指出,一起提高。 好了,言归正卷。这篇文章次要讲述WP的一些根本须要留神到的配置,和Blocksy主题的根本装置配置,以及过程中波及到的插件装置及应用。 Blocksy主题装置为什么要用Blocksy主题? 在主题森林中,售卖着数万套主题计划,他们有开发人员开发的,有设计人员开发,有业余公司开发的,也有WP爱好者开发的。他们模式大体雷同,然而在应用细节上却又有着多多少少的缺点,要么用起来不爽,要么费用昂扬。联合着咱们的选题,只须要一个博客内容的丑化展现,所以就不那么费周折了。Blocksy主题的收费版本曾经足够应用了。装置主题 进入咱们的博客后盾治理页面,如图, 点击装置主题后,搜寻 Blocksy ,只有一个后果, 装置实现后,即可立刻启用。 回到后盾主页,会有一条提醒: 点击 Install Blocksy Companion,人家插件强烈推荐了,咱们还是装置一下的好,尽管说不装置也能用。 装置实现后,刷新一下页面,点击激活。如下, 间接跳过就行了。好奇的话,也能够轻易看看。 至此,主题就装置实现了。此时间接关上主域名页面,即可看到, 当初页面上一下子洁净啦。先让咱们回到后盾治理页面,检查和设置一些必要的配置。 根底配置查看1,工夫配置,防止时区问题导致文章公布的工夫不对。做外贸SEO的同学,能够依据当地工夫进行调整。 2,固定链接是必须要设置的。对SEO影响甚大。 3,拜访404的配置。如果不出意外,当初拜访任何页面都是404,是因为Nginx中的确对php的定向配置。当初,咱们去解决这个问题。 登录宝塔面板,依照如下4个步骤。 代码为, if (-f $request\_filename/index.php){ rewrite (.*) $1/index.php; } if (!-f $request\_filename){ rewrite (.*) /index.php; } 保留实现后,即可看到页面, 等等,咱们貌似又发现一个小细节,浏览器的icon还是默认的,棘手配置一下呗。 4,设置头像与网站icon 在个人资料中,他当初只有一个必须从Gravatar中增加头像,不能从媒体题库中抉择。是不是感觉很厌恶,很不人性化,我要谋求个性化,不须要搞神马头像认证的。 当初,咱们就装置一款插件,让他能够媒体库加载图片。去插件选项中,搜寻User Profile Picture,如图: 应用图中指向的哪一款。点击装置后激活。再回到头像,就能够看到,当初多了一个选项,咱们去抉择上传图片即可。 当初能够从媒体库增加头像了。如果你在编辑头像的时候,向上面这样,遇到裁剪无奈保留的话,请不要放心。 我查阅了他们的官网文档,找到了一个issue,图片裁剪问题,他们不认为这是个问题,解决办法是再按一次裁剪,。 ...

June 19, 2021 · 1 min · jiezi

关于php:PHP中使用PDO操作事务的一些小测试

对于事务的问题,咱们就不多解释了,当前在学习 MySQL 的相干内容时再深刻的理解。明天咱们次要是对 PDO 中操作事务的一些小测试,或者能发现一些比拟好玩的内容。 在 MyISAM 上应用事务会怎么样?首先,置信只有是学过一点点的 MySQL 相干常识的人都晓得,在 MySQL 中罕用的两种表类型就是 InnoDB 和 MyISAM 这两种类型。当然,咱们明天也不讲它们全副的区别,但有一个区别是最显著的,那就是 MyISAM 不反对事务。那么,如果咱们在 PDO 操作中对 MyISAM 进行事务操作会怎么样呢? // myisamtry { $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->beginTransaction(); $pdo->exec("insert into tran_myisam (name, age) values ('Joe', 12)"); $pdo->exec("insert into tran_myisam2 (name, age) values ('Joe', 12, 33)"); // sleep(30); $pdo->commit();} catch (Exception $e) { $pdo->rollBack(); echo "Failed: " . $e->getMessage(), PHP_EOL;}tran_myisam 和 tran_myisam2 表都是 MyISAM 类型的表,在这段代码中,咱们成心写错了 tran_myisam2 的插入语句,让它走到 catch 中。理论执行的后果是,报错信息失常输入,tran_myisam 表的数据也被插入了。也就是说,针对 MyISAM 表的事务操作是没有成果的。当然,PDO 也不会被动报错,如果咱们让第二条 SQL 语句也是失常语句的话,PDO 只会失常执行完结,不会有任何的谬误或者提示信息。 ...

June 19, 2021 · 2 min · jiezi

关于php:CRMEB知识付费系统安装搭建常见问题13redis密码

redis明码没有设置如图:目录切换到常识付费我的项目根目录,点击终端关上终端后切到常识付费根目录第一步:查看redis是否启动命令:redis-cli第二步:查看redis明码命令:keys *第三步:明码这是没有设置redis明码,我的项目中也可不必设置明码第四步:设置redis明码如 将redis明码设置成1234567命令:config set requirepass 1234567第五步:查看明码是否设置胜利第六步:我的项目配置文件设置redis明码更改成redis明码 如:1234567 redis认证报错Redis (error) NOAUTH Authentication required解决办法如呈现这种问题则redis的明码已设置办法一:找到redis配置文件找到requirepass在常识付费我的项目中如图填入requirepass 前面的值办法二:找到redis配置文件找到requirepass,而后正文掉后。实现后如图:最初在我的项目中关上终端目录切换到常识付费我的项目根目录,点击终端关上终端后切到常识付费根目录查看redis是否启动命令:redis-cli设置redis明码如 将redis明码设置成1234567命令:config set requirepass 123456 明码有误首页提醒:WRONGPASS invalid username-password pair或WRONGPASS invalid username-password pair or user is disabled我的项目中设置的redis明码和服务器中redis软件里设置的明码不匹配 如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star: http://github.crmeb.net/u/defu 不胜感激 !

June 18, 2021 · 1 min · jiezi

关于php:使用phpimap查询操作邮件收件箱

最近在业务场景里有接管解析用户被动发送的邮件,应用php-imap实现了这一需要,记录一下。 确定实现形式读取邮件的协定有POP3和IMAP两种,区别:POP3协定容许电子邮件客户端下载服务器上的邮件,然而在客户端的操作,不会反馈到服务器上。IMAP提供webmail与电子邮件客户端之间的双向通信,客户端的操作都会反馈到服务器上,对邮件进行的操作,服务器上的邮件也会做相应的动作。 需要要求解决完用户的邮件当前,将邮件标记为已解决,因而选用IMAP协定。 装置依赖本地、服务器php均须要装置imap扩大。在我的项目的composer.json中增加php-imap扩大如下: "require": { "php-imap/php-imap": "^3.1",},配置相干服务namespace app\library\service\mail;use PhpImap\Exceptions\ConnectionException;use PhpImap\Mailbox;/** * 收邮件服务邮件API接口 * Class PlayService * @package app\library\service */class ImapService{ public $path = '{imap.263.net:993/imap/ssl}INBOX'; // IMAP server and mailbox folder public $login = 'user@263.cn'; // Username for the before configured mailbox public $password = 'pwd'; // Password for the before configured username public $dir = null; // Directory, where attachments will be saved (optional) public $encoding = 'UTF-8'; // Server encoding (optional) public $mailbox; public function __construct() { $this->mailbox = new Mailbox( $this->path, $this->login, $this->password, $this->dir, $this->encoding ); }获取所有未读邮件列表public function unSeenList(){ try { $mail_ids = $this->mailbox->searchMailbox('UNSEEN'); } catch (ConnectionException $ex) { die('IMAP connection failed: ' . $ex->getMessage()); } catch (\Exception $ex) { die('An error occured: ' . $ex->getMessage()); } // If $mailsIds is empty, no emails could be found if (!$mail_ids) { die('Mailbox is empty'); } try { $info = $this->mailbox->getMailsInfo($mail_ids); } catch (ConnectionException $ex) { echo "IMAP connection failed: " . $ex; die(); } return ['ids' => $mail_ids, 'list' => $info];}将某些邮件标记为已读/** * @param array $mail_ids * @return mixed */public function markRead($mail_ids){ return $this->mailbox->markMailsAsRead($mail_ids);}搜寻指定主题的邮件并标记为已读$imap = new ImapService();$condition = 'UNSEEN SUBJECT "' . $title . '" SINCE "' . date('Y-m-d', strtotime('-1 days')) . '" FROM ' . $mail;$data['mail'] = $imap->mailbox->searchMailbox($condition);if (!empty($data['mail'])) { $data['info'] = $imap->mailbox->getMailsInfo($data['mail']); if ($params['mark'] == 1) { $data['mark'] = $imap->markRead(array_column($data['info'], 'uid')); }}

June 17, 2021 · 2 min · jiezi

关于php:LinkLayer-Frames-Analysis

F. Task(s)Task 1. Link-Layer Frames AnalysisPart 1:Figure 1Consider the simplified building network (as shown in Figure 1) which consists of two aggregationswitches (SW1 and SW2) and two edge switches (SW3 and SW4). Each aggregation switch servesas an aggregation point for all the edge switches. Edge switches serve the PCs of end users. Theswitches have been configured to support for multiple VLANs. The IP addresses of PC C, D, andY are shown in Figure 1. The MAC address of PC W is 54:89:98:82:2c:21.Download packet traces from Moodle. There are four packet traces collected using Wiresharkrunning on the network simulated with eNSP software. The descriptions of the packet traces arelisted in Table 1. Once you have downloaded the trace, you can load it into Wireshark and viewthe trace using the File pull down menu, choosing Open, and then selecting the respective packettrace file.Table 1File Name of Packet Trace DescriptionPCA-SW3.pcap Packet trace on the link between PC A and SW3. ...

June 17, 2021 · 3 min · jiezi

关于php:PHP中的PDO操作学习三预处理类及绑定数据

要说 PDO 中最弱小的性能,除了为不同的数据库提供了对立的接口之外,更重要的就是它的预处理能力,也就是 PDOStatement 所提供的性能。因为它的存在,才让咱们能够安心地去应用而不必操心 SQL 语句的拼接不好所带来的平安危险问题。当然,预处理也为咱们晋升了语句的执行效率,能够说是 PDO 的另一大杀器。 PDOStatement 类PDOStatement 类其实就是代表一条预处理语句,并在该语句被执行后代表一个相干的后果集。它提供一些办法,让咱们可能对这条预处理语句进行操作。 $dns = 'mysql:host=localhost;dbname=blog_test;port=3306;charset=utf8';$pdo = new PDO($dns, 'root', '', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);$stmt = $pdo->prepare("select * from zyblog_test_user");// PDOStatement 对象的内容var_dump($stmt);// object(PDOStatement)#2 (1) {// ["queryString"]=>// string(57) "select * from zyblog_test_user where username = :username"// }PDOStatement 对象是通过 PDO 对象的 prepare() 办法返回的一个对象。它没有构造函数,也就是说咱们不能间接实例化一个 PDOStatement 对象。它蕴含一个只读属性,也就是咱们要执行的 SQL 语句,保留在 queryString 中。 PDOStatement 错误处理接下来咱们先看看 PDOStatement 的两个错误信息办法。 // 没有指定异样解决状态下的错误信息函数 $pdo_no_exception = new PDO($dns, 'root', '');$errStmt = $pdo_no_exception->prepare("select * from errtable");$errStmt->execute();var_dump($errStmt->errorCode()); // string(5) "42S02"var_dump($errStmt->errorInfo());// array(3) {// [0]=>// string(5) "42S02"// [1]=>// int(1146)// [2]=>// string(40) "Table 'blog_test.errtable' doesn't exist"// }在之前的文章中,咱们学习过,如果不给 PDO 对象指定错误处理格局的话。它会应用返回错误码和错误信息的形式处理错误。在这种状况下,如果预处理的语句有问题,咱们就能够通过 errorCode() 和 errorInfo() 办法来取得谬误的代码和谬误的详细信息。不过,还是更加举荐指定 PDO 的错误处理形式为抛出异样,就像最下面咱们定义的 PDO 对象那样。这样咱们就能够通过 try...catch 来处理错误异样了。 ...

June 17, 2021 · 4 min · jiezi

关于php:PHP中的PDO操作学习二预处理语句及事务

明天这篇文章,咱们来简略的学习一下 PDO 中的预处理语句以及事务的应用,它们都是在 PDO 对象下的操作,而且并不简单,简略的利用都能很容易地实现。只不过大部分状况下,大家都在应用框架,手写的机会非常少。 预处理语句性能预处理语句就是筹备好一个要执行的语句,而后返回一个 PDOStatement 对象。个别咱们会应用 PDOStatement 对象的 execute() 办法来执行这条语句。为什么叫预处理呢?因为它能够让咱们屡次调用这条语句,并且能够通过占位符来替换语句中的字段条件。相比间接应用 PDO 对象的 query() 或者 exec() 来说,预处理的效率更高,它能够让客户端/服务器缓存查问和元信息。当然,更加重要的一点是,占位符的利用能够无效的避免根本的 SQL 注入攻打,咱们不须要手动地给 SQL 语句增加引号,间接让预处理来解决这个问题,置信这一点是大家都学习过的常识,也是咱们在面试时最常见到的问题之一。 // 应用 :name 模式创立一个只进游标的 PDOStatement 对象$stmt = $pdo->prepare("select * from zyblog_test_user where username = :username", [PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY]);var_dump($stmt);// object(PDOStatement)#2 (1) {// ["queryString"]=>// string(57) "select * from zyblog_test_user where username = :username"// }$stmt->execute([':username' => 'aaa']);$aUser = $stmt->fetchAll();$stmt->execute([':username' => 'bbb']);$bUser = $stmt->fetchAll();var_dump($aUser);// array(1) {// [0]=>// array(8) {// ["id"]=>// string(1) "1"// [0]=>// string(1) "1"// ["username"]=>// string(3) "aaa"// ……var_dump($bUser);// array(1) {// [0]=>// array(8) {// ["id"]=>// string(1) "2"// [0]=>// string(1) "2"// ["username"]=>// string(3) "bbb"// ……prepare() 办法的第一个参数就是咱们须要执行的 SQL 语句,在这段代码中,咱们应用的是 :xxx 模式的占位符,所以在调用 prepare() 办法返回的 PDOStatement 对象的 execute() 办法时,咱们须要指定占位符的值。在代码中,咱们应用这一条 SQL 语句,通过替换不同的占位符内容,实现了两次查问。 ...

June 16, 2021 · 2 min · jiezi