php杂谈

1:什么是队列?
队列是先进先出的线性表,队列只允许在后端进行插入操作,在前端进行删除操作。一般情况下,在并发请求又要保证事务的完整性的时候就会用到队列。

2:对于一些存在阻塞的io密集操作,比如上传操作,可以设立单独的upload进程池,利用php-fpm提供的池的隔离性,来分离计算密集行操作。可以减少阻塞对整个php应用的影响。
如:
nginx.conf
location = /curl.php{
include fastcgi_params;
fastcgi_pass 127.0.0.1:9001
}

php-fpm.conf
[upload]
listen = 127.0.0.1:9001
pm = static
pm.max_children = 4;
这样,就可以把上传操作转发到upload进程池里进行处理。

3:nginx跟php-fpm分开,其实是很好的解耦,php-fpm专门负责处理php中动态的请求,而静态资源请求则由nginx去处理。

4:当执行echo、print的时候,输出并没有立即通过tcp传给客户端浏览器显示,而是将数据写入到php buffer中,php执行结束或者buffer被写满的时候才会输出到浏览器上显示。

5:页面创建的变量和其他对象都只在当前页面的内部可见,无法跨越页面进行访问,在终止运行后,页面中申请的所有资源都会被释放,也就是说php无法在语言级别上实现直接访问跨越页面的变量,也无法创建驻留内存的对象。

6:urlencode和rawurlencode的区别:
两种唯一的区别在于对于空格的处理不同,urlencode会把空格编码为+,而rawurlencode会把空格编码为%20.

7:is_int:判断一个变量是否是整数型,is_numeric:判断一个变量是否是整数或者数字字符串。

8:什么是socket:socket是应用层与TCP/IP通信的中间抽象层,它是一组接口,它把复杂的tcp/ip协议隐藏在socket接口里。对于调用者来说,我们只需要去调用socket提供的接口就可以获取我们需要的数据。

9:ssl网站安全协议采用了非对称与对称混合的加密机制,在建立ssl连接时,网站会把自己的数字证书发送给客户端,客户端首先检验证书的有效性,检验通过后,客户端使用本地随机数产生器产生一个称为会话密钥的对称加密密钥,使用服务器证书中的公钥加密后,发给服务器,此后,客户端与服务器之间交换的数据包都会使用会话加密予以保护。存在中间人攻击时,客户端与服务器的通信实际上是由两段ssl安全连接串起来的,客户端实际上是与中间人建立了ssl连接,一切收发信息都经过了中间人,但是在客户端浏览器上,看上去确是一个安全的连接,然而,所有的通信内容,无论是用户在浏览器窗口中的输入,还是服务器发送给用户的网页内容,都在实施攻击的中间人的掌控之中。

10:php处理模块在解析.php文件的时候,遇到需要发送回客户端的信息,不会立刻返回给web服务器,而是会根据header生成http头信息先把数据放进程序缓存里面,等待php处理模块继续解析程序,等整个程序解析完之后才会把程序缓存里的数据发送给web服务器,在由web服务器把数据组装在http的响应中发送给客户端,也就是说客户端的一次页面请求,服务端在这个页面不管要解析多少信息,它都只是向客户端响应一次。

11:资源是REST中最关键的抽象概念,它是能够被远程访问的应用程序对象,一个资源就是一个标识单位,任何可以被访问或被远程操纵的东西都可能是一个资源,REST是一种架构风格,其核心就是面向资源。REST可以简化开发,其架构遵循CRUD原则。是否使用资源就需要考虑资源本身的抽象识别是否困难,如果本身就是简单的类似增删改查的操作,那么抽象资源就比较容易,而对于复杂的业务活动抽象资源并不是一个简单的事情,比如校验用户等级、转账等操作。
REST的准则:
a:网络上的所有事务都可以被抽象为资源。
b:每一个资源都有一个唯一的标识。
c:所有的操作都是无状态的。

12:php-fpm这种模式是典型的多进程同步模型,意味着一个请求对应一个进程,并且io是同步阻塞的。和js不一样,php进程本身并不存在内存泄漏的问题,每个进程完成请求处理后会回收内存,但是并不会释放给操作系统,这就导致大量内存被php-fpm占用而无法释放,请求量升高时性能降低。所以php-fpm需要控制单个进程请求次数的阈值,表示这个进程在接收多少请求后会自动重启,用于回收内存。

13:isset用来表示变量释放初始化,但是当变量的值为null时,isset会返回false。

14:$a = b + 0 ; 请 问 这 里 的 加 0 是 什 么 意 思 ? 加 0 表 示 转 为 数 值 类 型 。 作 用 类 似 于 类 型 强 转 , 可 以 防 止 s q l 注 入 。 那 为 什 么 不 用 i n t 或 i n t v a l 呢 ? 因 为 用 + 0 我 不 需 要 关 心 b + 0;请问这里的加0是什么意思? 加0表示转为数值类型。作用类似于类型强转,可以防止sql注入。那为什么不用int或intval呢?因为用+0我不需要关心 b+0;00sqlintintval+0b是整形还是浮点型,还是数值特长的长整形,+0都能适应,对于特长的长整形,用强转,则会发生溢出。当然你会说,对于float类型,我可以用float来转啊,但,那不得分情况吗?

15:正则表达式:
: 匹 配 字 符 串 的 结 尾 位 置 , 要 匹 配 :匹配字符串的结尾位置,要匹配 请使用$;
():标记一个子表达式的开始和结束位置;
*:匹配前面的子表达式零次或多次
+:匹配前面的子表达式一次或多次
?:匹配前面的子表达式零次或一次
.:匹配除换行符之外的任何单字符
^:匹配输入字符串的开始位置
{n}:匹配前面的子表达式n次
{n,}:匹配前面的字符至少n次
(patten):匹配patten并获取这一匹配,可以通过$0-$9获取匹配的结果。
[xyz]:匹配xyz中任意一个字符
[^xyz]:匹配不包含xyz的任意字符
[a-z]:匹配a到z之间的任意字符。
\d:匹配一个数字字符,等价于[0-9]
\D:匹配任意一个非数字字符
\n:匹配一个换行符
\s:匹配任何空白字符
\w:匹配包括下划线的任何单词字符,等价于:[A-Za-z0-9_]

16:xss攻击:跨站点脚本攻击,就是篡改网页,注入恶意的html、js脚本,在用户访问网页时控制用户浏览器进行恶意操作的一种攻击方式。
解决方法:对某些html字符进行转义。

17:CSRF攻击:跨站点请求伪造,它主要利用浏览器的cookie或者服务器的session来盗取用户的身份。

18:GC进程启动后会遍历session文件列表,对比文件的修改时间和服务端的当前时间,如果当前时间大于修改时间加上设置的过期时间戳,则删除文件。

19:301重定向和302重定向的区别:
302重定向是临时重定向,搜索引擎会抓取新的内容而保留旧的网址。
301重定向是永久重定向,搜索引擎在抓取新内容的同时也将旧的网址替换为重定向之后的网址。

302重定向有可能造成网址劫持现象的发生,比如,某个人在它自己的网址A做了一个302重定向到你的网址B上,这时搜索结果所显示的网址仍然是A,但是所用的网页内容却是你的网址B上的内容,这种情况就叫做网址url劫持,这样你辛辛苦苦写的内容就被别人偷走了。

19:回调函数就相当于一个中断处理函数,由系统在符合你设定的条件时自动调用。所谓回调函数就是按照一定的形式,由你定义并编写实现内容,当发生某种事件时,而由系统或其他函数来调用的函数。使用回调函数实际上就是在调用某个函数时,将自己编写的一个函数的地址作为参数传递给那个函数,而那个函数在需要的时候,也就是某种事件发生时,来调用回调函数。

20:面向对象和面向过程有什么不同?
类的出现并不能说明是面向对象设计,其核心的区别是如何分配职责,过程式编程表象为一系列命令和方法的连续调用,这种置顶向下的控制方式导致了重复和相互依赖的代码遍布于整个项目,而面向对象编程则将职责从客户端代码中移动到专门的对象中,尽量减少相互依赖。

21:使用update时,更改成功返回true,更新失败返回false,如果值和数据库中已有的值相等,则不更新,返回0.

22:php的unset确实会释放内存,但是这个释放不是c编程意义上的释放,不会交回给操作系统,当我们释放内存时,php会把这块内存归入自己维护的空闲内存列表中。

23:当使用变量复制的时候,php内部并不是真正的复制,而是采用指向相同的结构来尽量节约开销。这就是php的写时复制。

24:ob_*系列函数是操作php本身的输出缓冲区,所以ob_flush是刷新php自身的缓冲区,而flush,严格来讲,这个只有在php作为apache的module安装的时候才有实际的作用,它是刷新apache的缓冲区。

25:php5.3之后调用函数时不允许采用引用的方式,否则会被错。

26:传统的B/S结构的应用程序,都是采用客户端拉的方式来实现客户端和服务端的数据交换。有时候用set_cookie、header会遇到Warning:Can’t modify header information - headers already sent by…等错误。出现这种错误提示,是因为通过http通信,数据包会包含两部分数据,一个是header,一个是data,会在header里指明data数据的长度,当我们有任何输出的时候,header部分就发送了,这个时候,你再想用header函数来改变一些header部分的信息,就会报错。一个简单的办法就是使用output_buffering,让它来缓存服务器的输出,不要太早的将header部分发给客户端。

27:MVC是一种面向对象的设计模式,它主要是将程序的输入、处理、输出相分离,使代码更简洁和便于以后的维护和扩展。其中M是model,它主要是根据业务逻辑获取数据,并进行处理,然后返回。V是view(视图),它主要是用来显示model返回的数据,也就是与用户进行交互的界面。C是控制器,它其实不做任何的数据处理,也不做数据显示,它只是根据业务逻辑去调用模型和视图。

28:http协议是应用层面向对象的协议,它的主要特点是:
a:简单快速:客户端向服务器请求服务时只需传送请求方法和路径,因此,速度很快。
b:比较灵活:允许传输任何类型的数据。
c:服务器处理完客户端的请求并收到客户端的应答就断开连接,这样减少连接的持续时间。
d:它是无状态的协议,就是说不会记住前一次传送的数据。

29:php5新增了一个final关键字,如果父类中的方法被声明为final,则子类无法覆盖该方法,如果一个类被声明为final,则不能被继承。属性不能被定义为final,只有类和方法才能被定义为final。

30:类中属性的值必须是直接的值,不能赋给它函数,或让它自己计算。
如:
class Man{
public $time = 3-1;//会报错
public $time1 = time();//会报错
}

31:phpize是用来扩展php模块的,通过phpize可以建立php的外挂模块,比如你想在原来编译好的php中加入memcache等扩展,就可以使用phpize。那么如何使用phpize呢?
当php编译完成后,php的bin目录下会有phpize这个脚本文件,在编译你要添加的扩展模块之前,执行phpize即可。比如你现在想在php中加入memcache扩展,我们只需做好以下几步即可:
a:tar zxvf memcache-2.2.taz cd memcache-2.2
b:进入到php安装源文件目录,如果已删除,重新下一个即可,cd php/bin/phpize ./configure
c:./configure with-php-config=/usr/local/php/bin/php-config make make install
d:在编译完成后,在php.ini文件中加入extension=memcache.so

32:面向对象编程的基本原则:
a:单一职责:一个类只需要做好一件事。
b:开放封闭:一个类应该是可扩展而不可修改的。
c:依赖倒置:一个类不应该强依赖另外一个类,每一个类对于另外一个类都是可替换的。
d:配置化:尽可能的使用配置,而不是硬编码。
e:面向接口编程:只需要关心接口,不需要关心实现。

33:一直以来都有个疑问?yii2框架中,有必要在分离service层吗?
在简单的系统里,分层是这样的controller<->model<->storage(sql、cache),所有的业务逻辑都在model上。现在讨论一个常见的场景,用户下单要买点东西,这个业务逻辑涉及到的model类有User、Order、Goods等,那么下订单这个事情是放到User还是Order上呢?不管你放到哪里,这个业务逻辑都需要多个model类的参与,当这种需求在系统里越来越多,你就会发现总有那么几个model在不断的膨胀,这些model之间甚至产生了网状的相互依赖的关系,需求越复杂,局面就会越混乱。service层的第一个目的其实就是对model层进行解耦。前面那种不断膨胀的model被称为充血模型。起初,对充血模型的解决方案是贫血模型,就是在model里尽量少放点逻辑,把这些逻辑移到controller层去处理,在controller里面调用多个model去完成业务逻辑,也达到了model间的解耦作用,但是业务放到了层里面,如果其他controller也需要相同的业务逻辑时,只能在controller里面去调用其他的controller,这样就很麻烦了。所以,后来还是把解耦单独放一层,现在分层就变成这样了:controller<->service<->model<->stroge。service层的第二个作用就是重用。

34:根据网站的分层架构,可以分为web前端性能优化、应用服务器性能优化、存储服务器性能优化。
web前端性能优化:一般来说web前端指网站业务逻辑之前的部分,包括浏览器加载、网站视图模型、图片服务、CDN服务等。
a:减少http请求,可以把多个css、js文件压缩成一个。
b:使用浏览器缓存。
c:压缩图片、css、js等。
d:减少cookie传输的数据量,因为cookie包含在每次请求和响应中。
e:使用cdn、反向代理加速等。
f:并行下载,默认情况下浏览器一次会向一个主机名并行执行两条http请求,因此,我们可以把样式表文件、脚本文件放到多个主机上。

35:php中的number_format()函数,当数值大于等于1000时,就会出现逗号,如:
echo number_format(999,2); //输出:999.00
echo number_format(1000,2); //输出:1,000.00
解决方法:echo number_format(1000,2,’.’,’’); //输出:1000.00

36:Json中字符串类型:使用双引号来包裹字符串,而不能使用单引号,如:{name:“lbj”}
Json中数字类型:{number:33}
Json中布尔类型:{isBool:true}
Json中的null类型:null代表着空、无的意思,不要和undefined混淆了,json中是没有undefined类型的。{name:null}

37:对于用json传递数据,会根据传递方写法的不同,接收方接收到的值得类型也不同。如:
a: s t r = ′ n a m e : 12121212121212121212121212121212 ′ ; str = '{name:12121212121212121212121212121212}'; str=name:12121212121212121212121212121212;arr = json_decode( s t r , t r u e ) ; v a r d u m p ( str,true);var_dump( str,true);vardump(arr);
会输出:float 1.2121212121212E+20,传递时name的值是整形,接收时已经被转成整形了。
b: s t r = ′ n a m e : " 12121212121212121212121212121212 " ′ ; str = '{name:"12121212121212121212121212121212"}'; str=name:"12121212121212121212121212121212";arr = json_decode( s t r , t r u e ) ; v a r d u m p ( str,true);var_dump( str,true);vardump(arr);
会输出:string ‘121212121212121212121212121212’;传递时name的值是字符串,接收时name的值还是字符串,这样的好处是不会溢出,在签名时能保证签名串一致。

38:
if(0 == ‘aa’){
echo ‘yes’;
}else{
echo ‘no’;
}
输出:yes,为什么会输出yes呢?这里涉及到了php的类型转换规则:
a:如果一个数字与一个字符串进行比较,那么会把字符串转换为数字在进行比较。
b:字符串的转换规则:若字符串以数字开头,则开头数字作为转换的结果,若无,则0作为转换的结果。

39:搭建好php环境后,环境是lnmp的,访问php文件时直接把源文件内容输出了,一开始以为是php和nginx之间没通,最后发现是php配置文件的短标签没开,而我的php文件格式是:,因为没开短标签,这里却用了短标签格式,所以php没有解析。

40:php -m 列出已安装的php模块。php -i 调用phpinfo()函数。php -v php的版本。php -r 运行php代码。

41:在装php多进程扩展pcntl时,先下载好对应的php版本,然而并没有进入到/soft/php5.3/ext/pcntl这个目录里去执行/usr/bin/phpize,我是直接在别的目录执行/usr/bin/phpize的,然后就报Cannot find config.m4这个错误,最后发现一定要到对应扩展目录里去执行/usr/bin/phpize才行。到/soft/php5.3/ext/pcntl/里去执行/usr/bin/phpize一下就好了。

42:在写while死循环时,最好加上一个sleep,以免cpu被100%的占用。

43:怎么把session存储到redis里?
先安装好redis,并且安装好php的redis扩展,然后配置php.ini:
session.save_handler = redis;
session.save_path = “tcp://127.0.0.1:6379”;

44:表的主键如果没有设置自增,即使数据插入成功也不会返回主键id,而是返回0。
所以正确的代码应该是:if( r e s = = = f a l s e ) e c h o ′ 插 入 失 败 ′ , 而 不 是 i f ( ! res === false){echo '插入失败'},而不是if(! res===false)echoif(!res){echo ‘插入失败’}

45:composer是php5.3及以上的一个依赖管理工具,它允许你申明项目所依赖的代码库,它会在你的项目中安装他们。

46:如果用unset删除一个通过引用传递或静态变量,则只是局部变量被销毁。

47:APP接口防CC攻击的方法:
a:一个接口用两次请求,比如一个支付接口,app先请求一个预支付接口,这个预支付接口可以返回time、用户ip和一个随机数给客户端,客户端请求支付接口时把这三个参数带上,在服务端对随机数和用户ip进行校验,然后对time进行过滤,比如10秒有效,在服务端做个逻辑检查,比如随机数只能使用1次。
b:该用户第一次请求过来时生成一个随机数并存储到redis里,过期时间为1秒,每次请求之前都先查询redis里是否有该随机数,如果有说明是cc攻击。

48:自php5.3开始,php增加了一个叫做后期静态绑定的功能,用于在继承范围内引用静态调用的类,也就是说类和方法是在运行时绑定的。
class A{
public static function who(){
echo CLASS;
}
public static function test(){
static::who();
}
}

class B extends A{
public static function who(){
echo CLASS;
}
}

B::test();//输出:B
如上代码:B调用test方法,test方法调用who方法,而B类中重写了who方法,则实际调用的是B中的who方法,所以输出__CLASS__是B,这就是说static调用的静态方法会在运行时自动判断调用谁的方法,而self则只会调用定义它所在的类中的方法。

49:今天用php的curl请求接口数据时一直报302,但是把这个url用浏览器打开是能正常的获取到数据的,但是发现跳转到了一个新的地址并把参数传递过去了,查了一下php的curl,发现有CURLOPT_FOLLOWLOCATION这个参数,它表示如果在请求的过程中,url发生了跳转,它会继续请求跳转后的地址。

50:time()是获取系统当前时间的时间戳。$_SERVER[‘REQUEST_TIME’]是获取请求开始时的时间戳。

51:Xphrof是一个分层的php性能分析工具,它报告函数级别的请求次数和各种指标,包括阻塞时间、cpu时间和内存使用情况等。一个函数的开销可细分成调用者和被调用者的开销。

52:htmlspecialchars:把一些预定义的字符转换为html实体,如:<转换成<,可以防止一些xss攻击。

53:http_build_query:把数组转换为url。FILE:返回当前执行程序的绝对路径。

54:php支持8种数据类型:
a:四种标量类型:字符串、整形、浮点型和布尔型。
b:两种复合类型:数组、对象。
c:两种特殊类型:资源、null

55:当解析一个文件时,php会寻找起始和结束标记,它告诉php开始和停止解析二者之间的代码。这种解析方式,使得php可以被嵌入到各种不同的文档中去。

56:php的变量名区分大小写。定义常量有2种方式,define和const,使用const定义常量必须处于最顶端的作用域,因为此方法是在编译时定义的,这就意味着不能在if语句内用const定义常量。

57:如果字符串和数值进行比较,则字符串会被转换成数值,然后在进行比较。但是,当使用全等于进行比较时,则不进行类型转换。null与其他类型进行比较时会被转换为空。

58:给函数传参时,任何默认参数必须放在非默认参数的右侧。

59:php支持可变函数的概念,如果一个变量名后有圆括号,php将寻找与变量的值同名的函数,并且尝试执行它。
如:
function foo()
{
echo ‘1’;
}
$func = ‘foo’;
$func();//输出:1

60:标准的range函数需要在内存中生成一个数组,包含每一个在它范围内的值,然后返回该数组,造成的结果就是会产生多个很大的数组,比如,调用rage(0,1000000)将会导致内存占用100M.

61:php的错误级别:
E_ERROR:致命错误,会在页面显示Fatal Error,当出现这种错误的时候,程序就无法继续下去。如:调用一个不存在的函数或有未被捕获的异常。
E_WARNING:警告错误,它不会终止脚本,程序还会继续执行,比如include一个不存在的文件。
E_NOTICE:错误提示,它不会终止脚本,程序还会继续执行。比如调用一个不存在的变量。
E_PARSE:这个错误是编译时发生的,在编译期发生语法错误,不能进行语法分析。

62:请问MVC中的model是什么抽象?
model应该是业务逻辑上的抽象,而不是数据结构的抽象,也就是说model层应该是触及到了具体的业务逻辑,它把业务逻辑封装一下给controller调用。

63:请问业务代码中胖model好还是瘦model好呢?
对于前台尽可能的胖model,就是把业务逻辑都放在model里,以提高代码的复用性。对于后台,因为自己用,就无所谓了。

64:工作中的坑:用php生成一个html页面,并且把html中的css、图片都缓存在cdn,缓存时间是60秒,该页面可以通过http或https上来访问,现在遇到的问题是部分用户访问页面时图片是可以正常访问的,但css却加载不了,发现访问不了页面的用户都是通过https来访问的,那问题就已经很明显了,肯定是https页面中引入的css文件是http的,那为什么会这样呢?可能是生成缓存时只生成了了一份,也就是说当http用户来访问时生成了http形式的css文件,然后https的用户来访问时自然就加载不了http的css文件,提交工单给阿里云,询问在生成缓存时是否只生成了一份,得到的答案是只生成了一份。。。。。解决办法:因为只生成了一份的css,就没办法通过判断url来加载css文件,只有在加载css时把前面的服务器名去掉,如://www.alicdn.com/a.css。

65:工作中的坑:与app传递数据时是通过xxtea加密的,客户端传输过来的数据始终无法解密,但是直接把密文写死却可以解密,最后发现是密文中有+号,被转义了,因此传递数据时最好通过urlencode一下。

66:php中的session有效期默认是24分钟,也就是说客户端超过24分钟没有刷新,当前session就会失效,解决方法是使用session_set_save_handler接管session的管理工作,一般是把sessoin存储到数据库或redis中。session是存储在服务器端,根据客户端提供的sessionId来得到这个用户的文件,然后读取文件,sessionId可以通过cookie或者以url来传递。
php.ini里有关session的设置:
session_use_cookie:默认值是1,代表用cookie来传递sessionId。
session_name:sessionId存储的变量名,默认是PHPSESSIONID。
session_cookie_lifetime:sessionId在客户端存储的时间,默认是0,表示浏览器一关闭SESSIONID就作废。
session_gc_maxlifetime:session数据在服务端存储的时间,如果超过这个时间,那么session数据就有可能被删除,对于过期的session数据会被php视为垃圾数据,一旦触发了php的垃圾回收机制,就会把此session数据删除。

67:为什么不能memcache来存储session?
a:memcache不能持久化,有可能造成session数据的丢失。
b:如果所有session的大小大致相同,那么它们会被分成两三个slab类,所有其他大小大致相同的数据也会被放入同一个slab,会与session争用存储空间,一旦slab满了,即使更大的slab中还有空间,数据也会被回收,而不是放入更大的slab中,所以,session的数据有可能会被清除掉,造成的结果是用户可能会随机掉线。

68:time_sleep_unit(timestamp):延迟代码执行,直到指定的时间。substr_count():计算子串在字符串中出现的次数。

69:php高效率的写法:
a:如果一个方法能被静态,那就声明为静态方法,速度可以提升很多。静态方法在程序开始时生成内存,实例方法在程序运行中生成内存,所以静态方法可以直接调用,实例方法要先生成实例,通过实例调用方法,静态方法速度快,但是会多占内存。任何语言都是对内存和磁盘的操作,至于是否面向对象,只是软件层的问题,底层都是一样的,只是实现方法不同,静态内存是连续的,因为是在程序开始时就生成,而实例申请的是离散的空间,所以就没有静态方法快。

你可能感兴趣的:(PHP)