1. 何为OPCode
在面向对象的设计中,如何通过很少的设计改变就可以应对设计需求变化,这是设计者极为要关注的问题。为此,我们需要掌握面向对象设计的5大设计原则。
面向对象设计的5大设计原则分别是:
单一职责原则(Single Responsibility Principle,SRP)
一个类被改变的原因不能超过一个,也就是说,一个类只有一个职责,如果职责过多,代码就会臃肿,可读性更差,也更难以维护。
1、提高类的可维护性和可读写性
一个类的职责少了,复杂度降低了,代码就少了,可读性也就好了,可维护性自然就高了
2、提高系统的可维护性
系统是由类组成的,每个类的可维护性高,相对来讲整个系统的可维护性就高。当然,前提是系统的架构没有问题。
3、降低变更的风险
一个类的职责越多,变更的可能性就更大,变更带来的风险也就越大
合理的职责分解相同的职责放到一起,不同的职责分解到不同的接口和实现中去
在实际工作中,有一个经常会用到的设计模式,DAO模式,又叫数据访问对象,里面定义了数据库中表的增、删、改、查操作.
按照单一职责原则,为什么不把增、删、改、查分别定义成四种接口?这是因为数据库的表操作,基本上就是这四种类型,不可能变化,所以没有必要分开定义。
反而经常变化的是数据库的表结构,表结构一变,这四种操作都要跟着变。所以通常我们会针对一张表实现一个DAO,一张表就代表一种类型的职责。
接口隔离原则(Interface Segregation Principle,ISP)
1.客户端不应该依赖它不需要的接口
2.类间的依赖关系应该建立在最小的接口上
通俗来讲:使用多个专门的接口比使用单一的总接口要好。
接口如果能够保持粒度够小,就能保证它足够稳定
换而言之,从一个客户类的角度来讲:一个类对另外一个类的依赖性应当是建立在最小接口上的。
过于臃肿的接口是对接口的污染。不应该强迫客户依赖于它们不用的方法。
接口隔离原则和单一职责原则非常类似。
单一职责原则要求接口的职责是单一的,而接口隔离原则要求接口尽量细化,它们有异曲同工之妙,都是要让我们的接口功能尽量单一,尽量小。
但是,单一职责原则的着重点是在“职
1. 何为OPCode
PHP是一种适用于web开发的动态语言。具体点说,就是一个用C语言实现包含大量组件模块的软件框架。是一个强大的UI框架。
简言之;PHP动态语言执行过程:拿到一段代码后,经过词法解析、语法解析等阶段后,源程序会被翻译成一个个指令(opcodes),然后ZEND虚拟机顺次执行这些指令完成操作。PHP本身是用C实现的,因此最终调用的也是C的函数,实际上,我们可以把PHP看做一个C开发的软件。
一.PHP的设计理念及特点
1、多进程模型:由于PHP是多进程模型,不同请求间互不干涉,这样保证了一个请求挂掉不会对全盘服务造成影响,目前PHP也早支持多线程模型。
2、弱类型语言:和C/C++、JAVA、C#等语言不同,PHP是一种弱类型的语言。一个变量的类型并不是一开始就确定不变的,运行中才会确定并可能发生隐式或显示的类型转换,这种机制的灵活性在web开发中非常方便、高效,具体会在后面PHP变量中详述。
3、引擎(Zend)+组件(ext)的模式降低内部耦合。
4、中间层(sapi )Sapi全称是Server Application Programming Interface 隔绝web server和PHP。
5、语法简单灵活,没有太多规范。缺点导致风格混杂。
二、PHP的四层体系
PHP的核心架构如下图:(我自己根据网上的图有PS了下;比较形象了;www.daokr.com 是我的个人网站;准备运营一个PHP开源项目;之前的www.ikphp.com我是网站长)
PHP从下倒上是一个4层体系:
1、Zend引擎:Zend整体用纯C实现,是PHP的内核部分,他将PHP代码翻译(词法、语法解析等一系列编译过程)为可执行opcode的处理并实现相应的处理方法、实现了基本的数据结构(如:hashtable、OO)、内存分配机制及管理、提供了相应的api方法供外部调用,是一切的核心,所有的外围功能均围绕Zend实现。
2、Extensions:围绕着Zend引擎,extensions通过组件式的方式提供各种基础服务,我们常见的各种内置函数(array系列)、标准库等都是通过extension来实现,用户也可以根据需要实现自己的extension的典型应用)。
3、Sapi:Sapi全称Server Application Programming Interface,也就是服务端应用编程接口,Sapi通过一系
计算两个日期间的差值:
<?php $date1=date_create("1984-01-28"); $date2=date_create("1980-10-15"); $diff=date_diff($date1,$date2); ?>
date_diff() 函数返回两个 DateTime 对象间的差值。
date_diff(datetime1,datetime2,absolute);
参数 | 描述 |
---|---|
datetime1 | 必需。规定 DateTime 对象。 |
datetime2 | 必需。规定 DateTime 对象。 |
absolute | 可选。规定布尔值。TRUE 表示间隔/差值必须是正的。默认是 FALSE。 |
返回值: | 如果成功则返回一个 DateInterval 对象,表示两个日期间的差值。如果失败则返回 FALSE。 |
---|---|
PHP 版本: | 5.3+ |
1、冒泡排序
在要排序的一组数中,对当前还未排好的序列,从前往后对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即,每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
// 升序 $arr=[1,43,54,62,21,66,32,78,36,76,39]; function bubbleSort($arr) { $len=count($arr); //该层循环控制 需要冒泡的轮数 for($i=1;$i<$len;$i++) { //该层循环用来控制每轮 冒出一个数 需要比较的次数 for($k=0;$k<$len-$i;$k++) { if($arr[$k]>$arr[$k+1]) { $tmp=$arr[$k+1]; $arr[$k+1]=$arr[$k]; $arr[$k]=$tmp; } } } return $arr; } // 降序 function bubbleSort($arr) { $len=count($arr); for($i=1;$i<$len;$i++) { for($k=0;$k<$len-$i;$k++) { // 只需要此处大小比较进行替换即可 if($arr[$k]<$arr[$k+1]) { $tmp=$arr[$k+1]; $arr[$k+1]=$arr[$k]; $arr[$k]=$tmp; } } } return $arr; }
2、快速排序
选择一个基准元素,通常选择第一个元素或者最后一个元素。通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素。此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。
function quickSort($arr) { //先判断是否需要继续进行 $length = count($arr); if($length <= 1) {
xlswriter 是一个 PHP C 扩展,可用于在 Excel 2007+ XLSX 文件中读取数据,插入多个工作表,写入文本、数字、公式、日期、图表、图片和超链接。
请参考下方对比图;由于内存原因,PHPExcel
与 PHPSpreadSheet
在数据量 相对较大
的情况下无法正常工作,虽然可以通过 修改memory_limit
配置来解决内存问题,但完成工作的时间可能会更长;
$config = [ 'path' => './tests' ]; $fileObject = new \Vtiful\Kernel\Excel($config); $fileObject = $fileObject->fileName('tutorial.xlsx'); $filePath = $fileObject->header(['date']) ->insertDate(1, 0, time(), 'mmm d yyyy hh:mm AM/PM') ->output();
$config = [ 'path' => './tests', ]; $fileObject = new \Vtiful\Kernel\Excel($config); $fileObject->openFile('tutorial.xlsx') ->openSheet(); var_dump($fileObject->nextRow([ \Vtiful\Kernel\Excel::TYPE_STRING, \Vtiful\Kernel\Excel::TYPE_TIMESTAMP, ]));
测试环境:
1、一群猴子排成一圈,按1,2,…,n依次编号。然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,在把它踢出去…,如此不停的进行下去,直到最后只剩下一只猴子为止,那只猴子就叫做大王。要求编程模拟此过程,输入m、n, 输出最后那个大王的编号。
function king($n, $m){
$monkeys = range(1, $n); //创建1到n数组
$i=0;
while (count($monkeys)>1) { //循环条件为猴子数量大于1
if(($i+1)%$m==0) { //$i为数组下标;$i+1为猴子标号
unset($monkeys[$i]); //余数等于0表示正好第m个,删除,用unset删除保持下标关系
} else {
array_push($monkeys,$monkeys[$i]); //如果余数不等于0,则把数组下标为$i的放最后,形成一个圆形结构
unset($monkeys[$i]);
}
$i++;//$i 循环+1,不断把猴子删除,或 push到数组
}
return current($monkeys); //猴子数量等于1时输出猴子标号,得出猴王
}
echo king(6,3);
2、有一母牛,到4岁可生育,每年一头,所生均是一样的母牛,到15岁绝育,不再能生,20岁死亡,问n年后有多少头牛。
function niu($y){
static $num= 1; //定义静态变量;初始化牛的数量为1
for ($i=1; $i <=$y ; $i++) {
if($i>=4 && $i<15){ //每年递增来算,4岁开始+1,15岁不能生育
$num++;
niu($y-$i); //递归方法计算小牛$num,小牛生长年数为$y-$i
}else if($i==20){
$num--; //20岁死亡减一
}
return $num;
}
3、杨辉三角
<?php
/* 默认输出十行,
当本地curl需要访问https时,出现SSL certificate: unable to get local issuer certificate错误信息
解决办法:
到http://curl.haxx.se/ca/cacert.pem
下载pem文件,并将文件拷贝到PHP目录在php.ini
增加curl.cainfo = "PHP目录\cacert.pem"
本地下载:cacert.pem
php有一款插件叫做imagemagick,功能很强大,提供了图片的很多操作,图片剪切、压缩、合并、插入文本、背景色透明等。并且有api方法调用和命令行操作两种方式,如果只是简单处理的话建议api方法调用,如果是很复杂的操作建议服务器端搭shell命令行操作,因为api方法调用同操作对比命令行他更吃内存,并且效率没有命令行那么高。
本文章就对于这些常见操作进行介绍说明
首先要提一声的时候每次通过imageMagic处理图片都会new一个对象出来,当图片处理好之后最好是把这个对象给销毁,它会占用cpu和内存,如果你不在乎这些小细节的话就当做我没有说,接下来进入正题。
图片宽高压缩:通过调用api中的 thumbnailImage 方法,可以实现图片宽高设置,这个操作不会影响图片的质量,是同大小压缩。
代码如下
1 $codeLogo = new \Imagick( '图片路径' );2 $codeLogo->thumbnailImage( '图片高','图片宽'); 3 header("Content-Type: image/{$image->getImageFormat()}"); 4 echo codeLogo; 5 exit;
图片存储大小压缩:通过调用api中的 setImageCompressionQuality 方法,可以实现图片存储大小设置,但是后带参数越小那么图片清晰度越差,但是图片存储大小会越小那么web加载的时候就越快,压缩率请根据实际情况进行调整。
代码如下
code = new \Imagick( '图片路径' ); $code->setImageCompressionQuality('缩放比例'); header("Content-Type: image/{$image->getImageFormat()}"); echo $image->getImageBlob( );
图片合并: 通过imageMagick可以实现多个图片合并到一张图片中,但是在合并的时候需要根据被覆盖图片的高和宽来确定覆盖图片的xy坐标,获取被覆盖图片的高和宽可以通过方法getImageGeometry来获取图片属性,然后得到高和宽,然后进行定位计算,下边的代码是将覆盖图片水平、垂直居中。
代码如下
$code = new \Imagick( '被覆盖图片路径'); $codePro
给图片添加水印,是一个很常见的需求。但是该需求的实现却不简单。
通常添加文字水印,是gd库的imagefttext方法。但是尝试之后,发现图片变成静态了。不符合需求。
利用搜索引擎,查询无数,发现gd扩展不合适解决这个问题。此时需要使用一个新的扩展
imagick
该扩展除了在gif图片过大的情况,存在速度问题,其他情况下表现良好。
在尝试了很多教程,失败无数次。于是忍痛去阅读英文文档,写出正确的代码。
代码如下:
$im = new Imagick("2.gif"); $draw = new ImagickDraw(); $draw->setFont('LOKICOLA.TTF'); $draw->setFontSize( 50 ); $draw->setFillColor(new ImagickPixel("red")); $text = "wuwenfu"; foreach ($im as $frame) { $frame->annotateImage($draw, 100, 120, 0, $text); } //写入到文件 //$im->writeImages("2_small.gif", true); //输出到浏览器。 header( "Content-Type: image/gif" ); echo $im->getImagesBlob();
原图: