php 题
1. php如何校验IP地址
filter_var() 函数
通过指定的过滤器过滤一个变量。如果成功,则返回被过滤的数据。如果失败,则返回false。
FILTER_VALIDATE_IP过滤器
过滤器把值作为ip地址来验证。
$ip = "192.168.0.1";
if (!filter_var($ip, FILTER_VALIDATE_IP)) {
echo "IP is not valid";
} else {
echo "IP is valid";
}
注:过滤器也可以校验邮箱,url,正则,布尔选项,字符,去除标签等。参考链接
2. 计算两个地址的相对路径
$a = '/a/b/c/d/a.php';
$b = '/a/b/1/2/b.php';
$arr_a = explode('/', $a);
$arr_b = explode('/', $b);
$arr_diff = array_diff_assoc($arr_a, $arr_b);
//array_diff_assoc()用于获取A数组与B数组之间元素的差集,Key和Value都不相同视为不同元素,此处返回在A数组中且与B数组不相同的元素
$count = count($arr_diff);
$path = '';
for($i=0; $i<$count-1; $i++){
$path .= '../';
}
$path .= implode('/', $arr_diff);
//implode()用于使用指定字符串连接数组元素,此处返回用'/'连接数组元素后的字符串
3. 获取相邻两个值相同的个数
$key = 0;
$a = [];
$arr = [1,1,1,0,1,1,0,1,1,1,1,1,1,1,1];
foreach($arr as $k =>$v) {
if($v == 1) {
$key++;
}
if($v == 0) {
array_push($a, $key);
$key = 0;
}
}
$pop = array_pop($arr);
if ($pop == 1) {
array_push($a, $key);
}
print_r($a);
4. php中的自动加载
PHP 5.2版本更新了自动加载需要的一个魔术方法 __autoload()
自动加载的原理,就是在我们 new 一个类的时候,php 系统如果找不到你这个类,就会去自动调用本文件中的 __autoload() 方法
项目中仅能有一个这样的 __autoload() 函数
spl_autoload_register() 需要不同的自动加载来加载不同路径的文件
5. 生成随机数
function random($length, $numeric = 0) {
PHP_VERSION < '4.2.0' ? mt_srand((double)microtime() * 1000000) : mt_srand();
$seed = base_convert(md5(print_r($_SERVER, 1) . microtime()), 16, $numeric ? 10 : 35);
$seed = $numeric ? (str_replace('0', '', $seed) . '012340567890') : ($seed . 'zZ' . strtoupper($seed));
$hash = '';
$max = strlen($seed) - 1;
for ($i = 0; $i < $length; $i++) {
$hash .= $seed[mt_rand(0, $max)];
}
return $hash;
}
6. 逻辑推演,根据5个已知条件,推断出正确密码
7. 不同的路径
一个机器人位于一个 m x n 网格的左上角(Start),机器人每次只能向下或者向右移动一步。试图达到网格的右下角(Finish)
问总共有多少条不同的路径? 题目连接
int uniquePaths(int m, int n){
if (m == 1 || n == 1) {
return 1;
}
int i, j;
int v[m][n];
for (i = 1; i < m; i++) {
v[i][0] = 1;
for (j = 1; j < n; j++) {
v[0][j] = 1;
v[i][j] = v[i][j-1] + v[i-1][j];
}
}
return v[m-1][n-1];
}
8. cgi php-cgi fastcgi php-fpm
cgi 每次来一个请求都会新创建一个进程
php-cgi 专门解析cgi传递过来的php代码,只处理业务
fastcgi 常驻型协议,不会重新生成进程
php-fpm 进程管理器,管理php-cgi、fastcgi
9. 攻击
-
XSS攻击:利用 js 和 DOM 攻击。
过滤,转义关键词,采用post提交表单
-
CSRF 跨站请求伪造:攻击者盗用了你的身份,以你的名义发送恶意请求
在请求地址中增加token验证,每次请求把token从session中取出来,与请求的token进行对比
-
DDOS攻击:利用合理的请求造成资源过载,导致服务不可用
验证码
10. php7 新功能
-
声明变量类型
可以使用字符串(string)、整数(int)、浮点数(float)、布尔值(bool)来 声明变量返回类型
标量类型声明 有两种模式: 强制 (默认) 和 严格模式。
declare(strict_types=1)必须放在文件的第一行执行代码,当前文件有效!
-
set_exception_handler() 不再保证收到的一定是 Exception 对象
致命错误可以转换为异常来处理
-
新增操作符 "<=>"
语法:$c = $a <=> $b。
如果$a > $b, $c 的值为1,$a == $b, $c 的值为0,如果$a < $b, $c 的值为-1
-
新增操作符 "??"
如果变量存在且值不为NULL, 它就会返回自身的值,否则返回它的第二个操作数。
-
define() 定义常量数组
define('ARR',['a','b']);
echo ARR[1];// a
-
AST: Abstract Syntax Tree, 抽象语法树
AST 在PHP编译过程作为一个中间件的角色, 解释器(parser)和编译器(compliler)解耦,让实现更容易理解和可维护
PHP5 : PHP代码 -> Parser语法解析 -> OPCODE -> 执行
PHP7 : PHP代码 -> Parser语法解析 -> AST -> OPCODE -> 执行 -
Unserialize 提供过滤特性
防止非法数据进行代码注入,提供了更安全的反序列化数据。
-
命名空间引用优化
// PHP7以前语法的写法
use FooLibrary\Bar\Baz\ClassA;
use FooLibrary\Bar\Baz\ClassB;
// PHP7新语法写法
use FooLibrary\Bar\Baz\{ ClassA, ClassB};
11. php 垃圾回收机制
每次将常量赋值给一个变量时,都会产生一个变量容器
$a = '测试数据';
xdebug_debug_zval('a')
// 结果
a: (refcount=1, is_ref=0)='许铮的技术成长之路'
当变量容器的ref_count计数清0时,表示该变量容器就会被销毁 ,实现了内存回收
-
循环引用引发的内存泄露问题
php5.3之前存在一个漏洞,即 当数组或对象内部子元素引用其父元素,而此时如果发生了删除其父元素的情况,此变量容器并不会被删除,因为 其子元素还在指向该变量容器 ,但是由于所有作用域内都没有指向该变量容器的符号,所以无法被清除,因此会发生内存泄漏,直到该脚本执行结束
-
新的垃圾回收机制
php5.3版本之后引入根缓冲机制,即php启动时默认设置指定zval数量的根缓冲区(默认是10000),当php发现有存在循环引用的zval时,就会把其投入到根缓冲区,当根缓冲区达到配置文件中的指定数量(默认是10000)后,就会进行垃圾回收,以此解决循环引用导致的内存泄漏问题
-
确认为垃圾的准则
1、如果引用计数减少到零,所在变量容器将被清除(free),不属于垃圾
2、如果一个zval 的引用计数减少后还大于0,那么它会进入垃圾周期。其次,在一个垃圾周期中,通过检查引用计数是否减1,并且检查哪些变量容器的引用次数是零,来发现哪部分是垃圾。
12. echo(),print(),print_r()的区别
echo 是PHP语句
print() 只能打印出简单类型变量的值
print_r() 可以打印出复杂类型变量的值
13. 数组[‘a’, ‘b’, ‘c’] 转换成字符串 ‘abc’
echo implode(‘’,[‘a’, ‘b’, ‘c’]);
echo join([‘a’, ‘b’, ‘c’],'');
14. 获取字符串’aAbB’中A首次出现的位置
$str=‘aAbB’;
echo strpos($str,"A");
15. 编写一段用最小代价实现将字符串完全反序, e.g. 将 “1234567890” 转换成 “0987654321”.
$s = '1234567890';
$o = '';
$i = 0;
while(isset($s[$i]) && $s[$i] != null) {
$o = $s[$i++].$o;
}
echo $o;
16. 请用递归实现一个阶乘求值算法 F(n): n=5;F(n)=5!=54321=120置
function F($n) {
if($n==0) {
return 1;
}else{
return $n* F($n-1);
}
}
var_dump(F(5));
17. sql语句应该考虑哪些安全性
-
防止sql注入,对特殊字符进行转义,过滤或者使用预编译sql语句绑定
-
使用最小权限原则,特别是不要使用root账户,微不同的动作或者操作建立不同的账户
-
当sql出错时,不要把数据库出错的信息暴露到客户端
18. 商品下单流程
- 点击下单按钮
- 判断库存 判断上下架状态:合适允许继续 否则报警
- 商品减库存 增加销量 生成订单状态
- 点击支付 进行支付
- 如未支付,库存还原,修改订单状态,其它状态还原,终止流程
- 更改订单状态、发货、物流状态、确认收货、完成订单
- 评论 追加评论
20. phpExcel导出
下载地址 PHPOffice/PHPExcel
找到classes目录下的PHPExcel.php和PHPExcel\IOFactory.php文件引出并使用
require_once('PHPExcel.php');
require_once('PHPExcel/IOFactory.php');
$objPHPExcel=new PHPExcel();
$iofactory=new PHPExcel_IOFactory();
$data = [];
//设置excel列名
$objPHPExcel->setActiveSheetIndex(0)->setCellValue('A1','地区');
$objPHPExcel->setActiveSheetIndex(0)->setCellValue('B1','学院名称');
foreach($data as $key => $value){
$key+=2;
$objPHPExcel->setActiveSheetIndex(0)->setCellValue('A'.$key,$value['province']);
$objPHPExcel->setActiveSheetIndex(0)->setCellValue('B'.$key,$value['school']);
}
// 使用命令导出
$objPHPExcel->getActiveSheet() -> setTitle('SetExcelName');
$objPHPExcel-> setActiveSheetIndex(0);
$objWriter = $iofactory -> createWriter($objPHPExcel, 'Excel2007');
$objWriter -> save('学校名称.xlsx');
// 使用浏览器导出代码
// $objPHPExcel->getActiveSheet() -> setTitle('SetExcelName');
// $objPHPExcel-> setActiveSheetIndex(0);
// $objWriter = $iofactory -> createWriter($objPHPExcel, 'Excel2007');
// $filename = 'SetExcelName.xlsx';
// header('Content-Type: application/vnd.ms-excel');
// header('Content-Type: application/octet-stream');
// header('Content-Disposition: attachment; filename="' . $filename . '"');
// header('Cache-Control: max-age=0');
// $objWriter -> save('php://output');
19. ip2Long 与 long2ip
// ip2long 将ip转换整形
$ip = '221.176.238.50';
list($ip1, $ip2, $ip3, $ip4) = explode(".", $ip);
$ip1*pow(256,3) + $ip2*pow(256,2) + $ip3*256 + $ip4;
// long2ip
for ($i=3;$i>=0;$i--) {
$ip .= (int)($long / pow(256,$i));
$long -= (int)($long / pow(256,$i))*pow(256,$i);
if ($i>0) $ip .= ".";
}