>  기사  >  백엔드 개발  >  PHP 면접 질문 정리 및 공유

PHP 면접 질문 정리 및 공유

小云云
小云云원래의
2018-03-27 11:14:284308검색

이 기사에서는 모든 사람이 보다 원활한 인터뷰를 할 수 있도록 돕기 위해 주로 PHP 인터뷰 질문 수집 및 공유를 공유합니다.

서버 측면

1. nginx 원활한 재시작

nginx는 새로운 작업자 프로세스를 실행하고 이전 작업자 프로세스를 조용히 종료하고 작업자 프로세스에 청취 소켓을 닫으라고 알리지만 현재 연결된 고객에게는 계속 서비스를 제공합니다. 모든 클라이언트 서비스가 완료되면 이전 작업자 프로세스가
닫힙니다. 새 구성 파일 적용이 실패하면 nginx는 이전 구성 파일을 사용하여 계속 작동합니다.
간단히 말해서 nginx는 이전 요청을 계속 처리하고 새 요청을 처리하기 위해 새 프로세스를 시작합니다. 이전 프로세스는 처리가 완료된 후 종료됩니다.

2. 파일의 마지막 10줄을 가져옵니다.
tail -10 a.log

3. 시스템 리소스를 더 많이 차지하는 프로세스를 확인하세요
Top -n '내가 찾고 싶은 키워드입니다' a.txt | cut -d ":" - f1

줄 수 세기 파일에 나타나는 키워드:
grep -n "keyword" "file path" | cut -d ":" -f1
통계 파일에 키워드가 나타나는 마지막 줄 번호:
grep -n "keyword" " File path" | tail -n 1 | cut -d ":" -f1


4 , /root/ 디렉터리에서 키워드 "www"가 있는 파일을 검색하고 터미널에서
find /root 명령을 실행하세요. / –type f | xargs grep “www

5. 파일 줄 수 계산
wc -l a .txt

데모 디렉터리에 있는 js 파일 수 계산:
find deco/ -name "*.js" | wc -l
데모 디렉터리에 있는 모든 js 파일의 코드 줄 수를 셉니다.
find deco/ -name "*.js " |xargs cat|wc -l
wc -l `find ./ -name "*. js"`|tail -n1
데모 디렉터리에 있는 모든 js 파일의 코드 줄 수를 계산하고 빈 줄을 필터링합니다.
find /demo - name "*.js" |xargs cat|grep -v ^$|wc -l

6. 파일 실시간 모니터링
tail -f a.log

7. nginx 로그에 가장 많이 방문한 100개의 IP와 방문 횟수
가장 많이 방문한 100개의 IP와 방문 횟수 nginx log
awk '{print $1}' /opt/software/nginx/logs/access.log| sort | uniq -c | sort -n -k 1 -r | head -n 100

8. 컴파일된 php
-------------------------------- --------------- --------------- 소스코드 설치
1. php의 소스 코드 디렉터리 찾기
2. EXT 디렉터리로 점프
3. phpize를 실행하여 구성 파일 생성
4. ./configure --with-php-config =/usr/local/php/bin/ php-config
5. make
컴파일 6. make install
컴파일 및 설치 7. php.ini 확장자=/usr/local/***.so
수정 8. php-fpm

YUM 설치 다시 시작:
1. PHP 공식 홈페이지(htpp://pecl.php.net)에 접속하여 소스코드를 다운로드 받으세요
2. 파일의 압축을 푼다
3. phpize를 실행해 설정 파일을 생성합니다
4. ./configure --with-php -config =/usr/local/php/bin/php-config
5. make
컴파일 6. make install
컴파일 및 설치 7. php.ini 확장명=/usr/local/***.so
수정 8. PHP 다시 시작 -fpm
------------
php 최적화 nginx 최적화 mysql 최적화

php 최적화:
1. 클래스 메서드를 정적으로 정의합니다.
2. 작은따옴표를 사용해 보세요.
3. php-fpm 프로세스 수를 수정합니다.
4. 단일 스크립트의 최대 사용 가능한 메모리를 수정합니다.
5. 대형 어레이는 사용 후 즉시 반출해야 합니다.
6. 루프 시 최대 루프 수를 설정하세요.
7. 오류를 방지하기 위해 @를 사용하지 마세요.
8. 많은 수의 PHP 내장 함수를 사용해 보세요.
9. require_once 대신에 require를 사용하세요.
1. nginx 하위 프로세스 수를 수정합니다. [최대 65535]
2. 정적 캐시 활성화
3. 주요 프로세스 수를 수정합니다. CPU 수에 따라 지정하는 것이 좋습니다. 일반적으로 배수입니다(예: 쿼드 코어 CPU 2개는 8로 계산됩니다).
4. gzip 출력 켜기 [gzip을 켜면 ob 기능을 사용할 수 없습니다.]
5. keepalive_timeout은 연결 시간 초과를 설정합니다.
1. 하위 쿼리 방지
2. 연속 읽기 방지
4. 선택 * 사용 방지
6. 필드 유형을 합리적으로
7, 읽기 및 쓰기 분리
9. 적절한 인덱스 생성
10. 리소스를 소모하는 작업 방지
11. 사용하지 마세요. 또는 쿼리
13. 데이터 조각 추가 LIMIT 1
14. 쿼리 캐시 켜기
15. 초기 단계에서 데이터에 대한 합리적인 평가를 수행하고 이를 테이블화합니다.
16.
17. mysql에 내장된 기능을 사용하지 마세요.
18. 여러 개의 슬레이브를 사용하여 쿼리 속도가 느린 문제를 해결하세요.

플래시 세일을 구현하는 방법은 무엇인가요?

저희가 만드는 동시 플래시 판매 수는 수십만개이며, 아래 버전은 수십만개입니다.

1 특히 플래시 판매 서버의 경우 [ps: 볼륨이 크면 작으면 필요하지 않습니다. ]
2. 정적 페이지를 생성합니다. [ ps: 그래도 용량이 크다면 이 파일을 CDN에 넣어도 됩니다 ]
3. 카운트다운 및 인벤토리는 서버에서 가져옵니다. [일정 기간 내에 한 번만 가져옵니다. 카운트다운이 끝난 후 서버는 시작되었는지 확인하도록 요청합니다.] 4. 판매할 데이터베이스를 Redis에 저장합니다. 키 값] stock=10
5. redis 큐 설정 [목록을 큐로 사용] lpop rpush
6. 사용자가 요청하면 플래시 세일에 참여했는지 여부를 판단합니다. , 사용자 데이터가 대기열에 기록됩니다. 동시에 인벤토리가 1만큼 감소합니다. 그가 참여한 경우 이미 참여했음을 묻는 메시지가 표시됩니다
PS: 이 섹션에서는 redid의 원자적 연산과 트랜잭션 다중 및 watch
redis 낙관적 잠금 cas ==== 설정하기 전에 값이 변경되었는지 판단하는 것입니다
7. 재고가 0으로 줄어들면 플래시 세일을 진행할 수 없습니다
8. + php 파일]

10,000~30,000이라고 하면 따로 서버를 빌릴 필요가 없어요

비즈니스 관련 질문을 받으면 상황에 맞게 대처하면 됩니다! ! ! !

예: 10명의 사용자가 구매했지만 비용을 지불하지 않으면 어떻게 해야 하나요?
첫 번째 진술:
당시 해당 상품에 대한 수요는 결제 없이는 문제가 없었고, 다른 유저들은 구매할 수 없었다고 합니다. 당시 상품과 논의를 했고, 그 상품이 맞는지. 일반적으로 사용자는 더 저렴하기 때문에 비용을 지불할 것입니다.
두 가지 설명:
다음 플래시 세일을 시작합니다. 예를 들어 Xiaomi에서는 2시간 후에도 계속 구매할 수 있습니다! !
세 번째 정거장:
네. . . .

과매수 상태가 아닌지 확인하는 방법은 무엇인가요?
재고를 줄일 때 원자적 작업이며 CAS 낙관적 잠금을 사용합니다. 테스트때는 과매수 현상이 없었습니다

그리고 플래시세일때 장바구니도 필요 없고, 클릭시 대기열이 발생합니다


Q1: 양치질 방지 방법은? 일반적으로 급한 세일 기간에는 큰 할인 혜택이 있습니다. 누군가 악의적으로 부정 행위를 하면 일반 사용자는 구매할 기회를 잃게 됩니다. 예를 들어, 낚아채는 상품 수가 1,000개인데 누군가 악의적으로 900개를 스와이프했다면 일반 사용자는 100개만 낚아채게 됩니다.
추후 결제 과정에서 악의적으로 포획한 900개가 확인된 후, 스냅업 시간이 지났을 수 있습니다. 악의적으로 빼앗은 900개를 모두 성공적으로 지급했다고 하더라도 일반 유저들에게는 여전히 불공평한 일이 될 것입니다.
이 비즈니스 시나리오에서 우리가 하는 일은 제품을 진열하고 제품을 구매할 권리를 발급하는 것입니다. 실제 소비는 제3자에 의해 이루어집니다. 그런 다음 사용자 사기 문제는 당사와 제3자 결제 페이지에서 통제해야 합니다. 사용자가 대기열 메커니즘을 통해 구매 할당량을 획득하고 제3자로 이동한 후, 제3자는 제3자와 합의한 암호화 방법에 따라 암호화된 정보를 성공적으로 해독한 후에만 사용자가 결제할 수 있도록 허용합니다. 합의된 암호 해독 방법에 따라 암호화 암호 해독 프로세스에는 수명 주기가 있는 콘텐츠가 포함될 수 있습니다. 이러한 방식으로 사용자가 고주파 요청 결제 페이지에서 제품을 얻을 때 실제로는 1) 암호화된 쌍 2) 처음으로만 얻을 수 있습니다. 그러나 제3자는 상품 판매가 전부이기 때문에 이러한 유형의 협력은 성공률이 낮습니다. 악의적인 브러싱은 실제로 당사 비즈니스 수준에서 해당 제품의 재고가 없음을 나타냅니다. 결과적으로 구매를 원하는 사용자는 기회를 잃게 되지만 제3자에게 피해가 가지 않도록 보장할 수 있습니다. 비즈니스 계층에서 이러한 브러싱 상황을 피하려면 이것이 일반적인 스팸 방지 문제라고 생각합니다. 나는 이것에 대해 잘 모른다.

Q2: 브러쉬를 정확하게 배치하기 위해서는 판단의 차원이 다양하고 논리도 복잡합니다. 이에 반해 급하게 구매하려면 빠른 대응이 필요합니다.
네, 인기 상품에 대한 높은 요청 압력과 높은 동시 구매로 인해 긴급 구매 비즈니스는 너무 많은 논리를 추가하거나 백엔드에 너무 많이 의존해서는 안 됩니다. 시스템을 설계할 때 시스템만으로는 처리할 수 없는 것들이 많이 있습니다. 시스템이 제대로 실행되기 위해서는 몇 가지 사전 요구 사항 모듈과 기능을 준비해야 합니다. 계정 시스템과 사용자 소비 기록을 구축하는 것이 좋습니다.
Q3: 조정은 단순히 제3자와 상품의 재고를 비교하는 것인가요?
화해는 사실 소비 데이터의 비교입니다. 우리 통계가 오늘 총 가치가 Y인 X 품목의 소비를 표시하는 상황을 피하기 위해 제3자는 총 가치가 M인 N 품목의 소비를 제공합니다. 금액의 불일치로 인해 정산, 공유 등의 문제가 발생하지 않도록 하세요.
귀하의 질문에 있는 재고 차이 문제로 인해 제3자가 당사 데이터 계층의 인터페이스를 통해 제공하는 제품을 정기적으로 업데이트해야 한다고 생각합니다. 실제로 당사 제품 라이브러리에서는 반드시 제3자에 의한 제품 제공만 허용되는 것은 아닙니다. 예를 들어, 과일을 판매하는 제3자와 협력하는 경우 제3자가 제품을 축소하도록 허용할 수도 있습니다. 제3자는 지난주에 100개의 항목이 있다고 발표했지만 이번 주에는 오프라인이 뜨거워서 20개만 남았습니다. 또한 제3자가 더 낮은 값으로 업데이트할 수 있도록 허용해야 합니다. 하지만 이렇게 하면 우리 시스템이 상당히 복잡해질 것입니다.

Q4: 원하는 결과를 얻지 못하는 제3자 프로모션으로 인한 문제를 방지하기 위한 브러싱 방지.
네, 사용자 ID 차원과 IP 차원 모두 효과적인 방법입니다. 구체적인 시나리오를 살펴보세요. 계정 시스템을 갖춘 기업의 경우 사용자 ID 차원을 사용하는 것이 가장 좋습니다. 스토리지를 사용하여 각 사용자의 구매 기록을 기록하면 됩니다. 시중에 나와 있는 전자상거래 사이트들은 급매업무를 위해 기본적으로 로그인을 요구하고 있으며, 품목별 1인 구매횟수를 제한하고 있으며, 실제로는 사용자의 소비를 저장하고 기록하며, 소비 전 쿼리를 다시 생성하여 추가하고 있다. 그것을 제어하는 ​​코드 로직.

Q5: 각 급매 이벤트마다 새로운 인증 코드가 필요합니까?
인증 코드는 튜링 테스트 방식이고, 매번 생성되는 인증 정보가 절대 나타나지 않고 불규칙하다면 좋은 인증 코드입니다.

대량 데이터에서 가장 많이 반복되는 IP를 찾는 방법

사용자의 IP는 웹사이트 로그에 기록되고, 가장 많이 방문하는 IP를 찾는다

1kw의 ID번호와 그에 상응하는 데이터가 있다고 가정해보자. ID번호는 중복될 수 있으므로, 가장 많이 나타나는 ID번호를 찾으셔야 합니다.

1G 크기의 파일이 있는데, 그 안에 있는 각 줄은 워드이고, 워드 크기는 16바이트를 초과하지 않으며, 메모리 제한은 1M입니다. 가장 자주 사용되는 단어 100개를 반환합니다.

파일은 10개이며 각 파일의 각 줄은 사용자의 쿼리를 저장합니다. 쿼리 빈도별로 정렬하라는 메시지가 표시됩니다.

버블 정렬:
원리:
첫 번째 숫자를 모든 숫자와 비교한 후 큰 교환 위치에 직면하여 가장 큰 숫자가 처음에 끝에 배치되고 두 번째로 계속 비교됩니다. 이 비교에서는 마지막 숫자가 가장 큰 것으로 판별되었기 때문에 비교되지 않습니다.

1. 버블 정렬 방법

 *     思路分析:法如其名,就是像冒泡一样,每次从数组当中 冒一个最大的数出来。 
 *     比如:2,4,1    // 第一次 冒出的泡是4 
 *                2,1,4   // 第二次 冒出的泡是 2 
 *                1,2,4   // 最后就变成这样

시간 복잡도:
버블 정렬은 시간을 공간과 맞바꾸는 정렬 방법입니다. 최악의 시나리오는 순서를 역순으로 바꾸거나, 역순을 순서로 바꾸는 것입니다.


$arr=array(1,43,54,62,21,66,32,78,36,76,39);  
function getpao($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. 선택 정렬:


http://jingyan.baidu.com/article/f3ad7d0f07516d09c3345b19.html
http://mmm2010.blog.163.com/blog/static/174230348201292273310140/
function select_sort($arr) {
//实现思路 双重循环完成,外层控制轮数,当前的最小值。内层 控制的比较次数
    //$i 当前最小值的位置, 需要参与比较的元素
    for($i=0, $len=count($arr); $i<$len-1; $i++) {
        //先假设最小的值的位置
        $p = $i;
        //$j 当前都需要和哪些元素比较,$i 后边的。
        for($j=$i+1; $j<$len; $j++) {
            //$arr[$p] 是 当前已知的最小值
            if($arr[$p] > $arr[$j]) {
     //比较,发现更小的,记录下最小值的位置;并且在下次比较时,
 // 应该采用已知的最小值进行比较。
                $p = $j;
            }
        }
        //已经确定了当前的最小值的位置,保存到$p中。
 //如果发现 最小值的位置与当前假设的位置$i不同,则位置互换即可
        if($p != $i) {
            $tmp = $arr[$p];
            $arr[$p] = $arr[$i];
            $arr[$i] = $tmp;
        }
    }
    //返回最终结果
    return $arr;
}
3.快速排序法  
function quick_sort($arr) {
    //先判断是否需要继续进行
    $length = count($arr);
    if($length <= 1) {
        return $arr;
    }
    //如果没有返回,说明数组内的元素个数 多余1个,需要排序
    //选择一个标尺
    //选择第一个元素
    $base_num = $arr[0];
    //遍历 除了标尺外的所有元素,按照大小关系放入两个数组内
    //初始化两个数组
    $left_array = array();//小于标尺的
    $right_array = array();//大于标尺的
    for($i=1; $i<$length; $i++) {
        if($base_num > $arr[$i]) {
            //放入左边数组
            $left_array[] = $arr[$i];
        } else {
            //放入右边
            $right_array[] = $arr[$i];
        }
    }
    //再分别对 左边 和 右边的数组进行相同的排序处理方式
    //递归调用这个函数,并记录结果
    $left_array = quick_sort($left_array);
    $right_array = quick_sort($right_array);
    //合并左边 标尺 右边
    return array_merge($left_array, array($base_num), $right_array);
}

4. 삽입 정렬 방법

시나리오 설명:
학생들이 시도하고 실패할 때마다 교사는 계속해서 다음과 같은 결과를 얻었습니다. 정렬 팀을 마친 후 저는 대부분의 수업 시간이 늦어져서 이렇게 말했습니다. "더 이상 거품을 낼 필요가 없습니다. 시간이 좀 지났으니 오늘 정렬을 삽입합시다."
이때 체육교사는 수학교사의 역할을 맡아 학생들에게 줄서기-삽입정렬을 가르쳤다.
1. 첫 번째 동급생을 기준으로 시작하고 두 번째 동급생이 앞으로 나아가면서 첫 번째 동급생과 비교합니다. 키가 크면 가만히 있고, 낮으면 자세를 바꿔보세요
2. 앞에 있는 학생과 비교하여 두 번째 학생과 비교하여 더 낮으면 두 번째 학생으로 전환한 다음 첫 번째 학생과 비교하고, 낮으면 다시 전환하고, 그렇지 않으면 차단하고 더 이상 비교하지 않습니다.
3. 2단계를 앞에서 뒤로 수행한 후 순서대로 나옵니다. 각 학생은 앞에 있는 동급생과 비교하여 삽입할 적절한 위치를 찾고, 다른 학생들은 다시 적절한 위치로 이동합니다. 이전 동급생은 동일하거나 동일합니다. 자신의 키보다 낮고, 다음 반 친구는 자신의 키보다 높습니다
 에 따라 학생들은 하나씩 올바른 위치를 찾을 수 있으므로 더 이상 매번 인접한 위치를 비교할 필요가 없으며 위치를 찾은 후에는 앞면과 비교할 필요가 없습니다...

삽입 정렬 방법 아이디어: 정렬할 항목을 정렬합니다. 배열의 정렬 번호가 가정된 지정된 위치에 요소가 삽입됩니다.

function insert_sort($arr) {
    //区分 哪部分是已经排序好的
    //哪部分是没有排序的
    //找到其中一个需要排序的元素
    //这个元素 就是从第二个元素开始,到最后一个元素都是这个需要排序的元素
    //利用循环就可以标志出来
    //i循环控制 每次需要插入的元素,一旦需要插入的元素控制好了,
    //间接已经将数组分成了2部分,下标小于当前的(左边的),是排序好的序列
    for($i=1, $len=count($arr); $i<$len; $i++) {
        //获得当前需要比较的元素值。
        $tmp = $arr[$i];
        //内层循环控制 比较 并 插入
        for($j=$i-1;$j>=0;$j--) {
   //$arr[$i];//需要插入的元素; $arr[$j];//需要比较的元素
            if($tmp < $arr[$j]) {
                //发现插入的元素要小,交换位置
                //将后边的元素与前面的元素互换
                $arr[$j+1] = $arr[$j];
                //将前面的数设置为 当前需要交换的数
                $arr[$j] = $tmp;
            } else {
                //如果碰到不需要移动的元素
           //由于是已经排序好是数组,则前面的就不需要再次比较了。
                break;
            }
        }
    }
    //将这个元素 插入到已经排序好的序列内。
    //返回
    return $arr;
}
/**
     * 插入排序,默认第一位已经排好序,从第二位开始依次向前比较,确定自己的位置后插入,即前一位小余或等于当前,且后一位大于当前。
     * 插入后,自己新位置后面的元素依次向后移位, 完成一轮插入排序
     * @param arr
     * @return
     */
    public static int[] insertSort(int[] arr) {
        int len = arr.length;
        for (int i = 1; i < len; i++) {
            if (arr[i - 1] > arr[i]) {
                int k = arr[i];
                int j = i;
                while (j > 0 && arr[j - 1] > k) {
                    arr[j] = arr[j - 1];
                    j--;
                }
                arr[j] = k;
            }
        }
        return arr;
    }

1,2,3,4,5,6,7

지금 7을 찾고 싶어요
먼저 가운데 숫자 4
를 꺼내서 제가 찾는 숫자인지 판단합니다. 더 작다
그런 다음 오른쪽으로 가서 검색
그런 다음 오른쪽에 있는 숫자를 모두 꺼내세요
가운데 숫자 6을 빼세요
아직 작다는 걸 발견했어요
계속해서 오른쪽 배열을 찾아보세요
찾았어요 7, 알았어! ! !

최악의 시나리오는 이 번호가 존재하지 않는다는 것입니다 =====

 1 <?php
 2     #二分查找
 3     function binarySearch(Array $arr, $target) {
 4         $low = 0;
 5         $high = count($arr) - 1;
 6         
 7         while($low <= $high) {
 8             $mid = floor(($low + $high) / 2);
 9             #找到元素
10             if($arr[$mid] == $target) return $mid;
11             #中元素比目标大,查找左部
12             if($arr[$mid] > $target) $high = $mid - 1;
13             #重元素比目标小,查找右部
14             if($arr[$mid] < $target) $low = $mid + 1;
15         }
16         
17         #查找失败
18         return false;
19     }
20     
21     $arr = array(1, 3, 5, 7, 9, 11);
22     $inx = binarySearch($arr, 1);
23     var_dump($inx);
24 ?>

安全方面:
xss :跨站脚本攻击
csrf :  跨站请求伪造
Ddos:用很多机器对网址进行请求,把服务器某方面搞挂。
sql注入: 通过关键字或者非法字符的注入,实现一些对数据库一些非正常的操作

最简单的demo :
在用户登陆的时候,用户名和密码的判断,密码后加上 or 1=1

如何防止sql注入:
关键字的过滤
pdo预处理
php 配置文件 php.ini 中的 magic_quotes_gpc选项没有打开,被置为 off
addslashes stripslashes
mysql_real_escape_string
对一些数据类型做强制的校验

如何防止xss攻击?
xss攻击最简单的方式就是通过地址栏输入3f1c4e4b6b16bbbd69b2ee476dc4f83a2cacc6d41bbb37262a98f745aa00fbf0,最简单的列子我们在php在使用一个get的a参数的时候,如何客户端传过来是3f1c4e4b6b16bbbd69b2ee476dc4f83aalert(1)2cacc6d41bbb37262a98f745aa00fbf0,
这样的话就会在我们的浏览器弹出来1,如果是页面的跳转,或者是一些其它脚本、病毒的话,可能对我们网站的安全造成很大的隐患。

最简单的解决办法
不要相信客户端的任何输入,在程序做严格的判断以及处理
htmlspecialchars进行过滤

csrf :
这个我们在学curl的时候做的模拟登陆就是跨站请求伪造!!!!
最简单的大白话就是:
a网站往b网站请求数据。
加个token防止下就行了,简单,粗暴,有效

Dos和Ddos防止:
阿里云 高防ip
idc机房
放弃一部分请求不处理。


正则方面的问题:

贪婪模式和非贪婪模式的区别:
贪婪模式匹配到内容之后会继续向后匹配
非贪婪模式则不回继续匹配


匹配中文字符的正则表达式: [\u4e00-\u9fa5]
评注:匹配中文还真是个头疼的事,有了这个表达式就好办了
匹配双字节字符(包括汉字在内):[^\x00-\xff]
评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
匹配空白行的正则表达式:\n\s*\r
评注:可以用来删除空白行
匹配HTML标记的正则表达式:706b83c79d2c696ac46a98098db7b11b]*>.*?c0f8603dd44f0db5dcc943cf687721b3|7ced4b295831648a0fce6ecb53f5fd4b
评注:网上流传的版本太糟糕,上面这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力
匹配首尾空白字符的正则表达式:^\s*|\s*$
评注:可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式
匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
评注:表单验证时很实用
匹配网址URL的正则表达式:[a-zA-z]+://[^\s]*
评注:网上流传的版本功能很有限,上面这个基本可以满足需求
匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
评注:表单验证时很实用
匹配国内电话号码:\d{3}-\d{8}|\d{4}-\d{7}
评注:匹配形式如 0511-4405222 或 021-87888822
匹配腾讯QQ号:[1-9][0-9]{4,}
评注:腾讯QQ号从10000开始
匹配中国邮政编码:[1-9]\d{5}(?!\d)
评注:中国邮政编码为6位数字
匹配身份证:\d{15}|\d{18}
评注:中国的身份证为15位或18位
匹配ip地址:\d+\.\d+\.\d+\.\d+
评注:提取ip地址时有用
匹配特定数字:
^[1-9]\d*$    //匹配正整数
^-[1-9]\d*$   //匹配负整数
^-?[1-9]\d*$   //匹配整数
^[1-9]\d*|0$  //匹配非负整数(正整数 + 0)
^-[1-9]\d*|0$   //匹配非正整数(负整数 + 0)
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$   //匹配正浮点数
^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$  //匹配负浮点数
^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$  //匹配浮点数
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$   //匹配非负浮点数(正浮点数 + 0)
^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$  //匹配非正浮点数(负浮点数 + 0)
评注:处理大量数据时有用,具体应用时注意修正
匹配特定字符串:
^[A-Za-z]+$  //匹配由26个英文字母组成的字符串
^[A-Z]+$  //匹配由26个英文字母的大写组成的字符串
^[a-z]+$  //匹配由26个英文字母的小写组成的字符串
^[A-Za-z0-9]+$  //匹配由数字和26个英文字母组成的字符串
^\w+$  //匹配由数字、26个英文字母或者下划线组成的字符串

下面是一些特殊字符:
正则表达式中的特殊字符: (学习参考书-<<精通正则表达式>>)
字符
의미: 문자의 경우 일반적으로 문자 그대로의 의미를 의미하며, 다음 문자는 설명이 없는 특수 문자임을 나타냅니다.
예: /b/는 문자 'b'와 일치합니다. b 앞에 백슬래시를 추가하면, 즉 /b/는 문자가 특수 문자가 되어
가 단어의 구분선과 일치함을 나타냅니다.
또는:
여러 문자의 경우 일반적으로 특수 문자라고 명시되어 있으며, 이는 다음 문자가 특수 문자가 아니므로 문자 그대로 해석해야 함을 나타냅니다.
예를 들어 *는 임의의 수의 문자(0자 포함)와 일치하는 특수 문자입니다. 예를 들어 /a*/는 0개 이상의 a와 일치함을 의미합니다.
리터럴 *와 일치하려면 a 앞에 백슬래시를 추가하세요. 예를 들어 /a*/는 'a*'와 일치합니다.

Character^
의미: 일치하는 문자가 앞에 와야 함을 나타냅니다.
예: /^A/는 "an A"의 'A'와 일치하지 않지만 "An A."의 첫 번째 'A'와 일치합니다.

문자 $
의미: ^와 유사하며 마지막 문자와 일치합니다.
예: /t$/는 "eater"의 't'와 일치하지 않지만 "eat"의 't'와 일치합니다.

Character *
의미: * 0 또는 n번 앞의 문자를 일치시킵니다.
예: /bo*/는 "A ghost booooed"의 'boooo' 또는 "A Bird Warbled"의 'b'와 일치하지만 "A sheep g
runted"의 어떤 문자와도 일치하지 않습니다.

문자 +
의미: + 기호 앞의 문자를 1번 또는 n번 일치시킵니다. {1,}과 동일합니다.
예: /a+/는 "candy"의 'a'와 "caaaaaaandy"의 모든 'a'와 일치합니다.

문자?
의미: ? 이전의 문자를 일치시킵니다.
예: /e?le?/는 "angel"의 'el' 및 "angle."의 'le'과 일치합니다.

문자.
의미: (소수점)은 개행 문자를 제외한 모든 단일 문자와 일치합니다.
예: /.n/은 "nay, an apple is on the tree"의 'an' 및 'on'과 일치하지만 'nay'와는 일치하지 않습니다.


문자(x)
의미: 'x'를 일치시키고 일치하는 값을 기록합니다.
예: /(foo)/는 "foo bar"에서 'foo'를 일치시키고 기록합니다. 일치하는 하위 문자열은 결과 배열의 요소 [1], ..., [n] 또는 RegExp 개체의 $1, ..., $9 속성에 의해 반환될 수 있습니다.

문자 x|y
의미: 'x' 또는 'y'와 일치합니다.
예: /green|red/는 "green apple"의 'green' 및 "red apple"의 'red'와 일치합니다.

문자 {n}
의미: n은 양의 정수입니다. 처음 n개 문자와 일치합니다.
예: /a{2}/는 "candy"의 'a'와 일치하지 않지만 "caandy"의 모든 'a' 및 "caaandy."의 처음 두 개의
'a와 일치합니다.

문자 {n,}
의미: n은 양의 정수입니다. 최소한 n개의 이전 문자와 일치합니다.
예: /a{2,}는 "candy"의 'a'와 일치하지 않지만 "caandy"의 모든 'a' 및 "caaaaaaandy"의 모든 'a'와 일치합니다.

문자 {n,m}
의미: 여기서 n과 m은 모두 양의 정수입니다. 최소 n개, 최대 m개의 이전 문자와 일치합니다.
예: /a{1,3}/는 "cndy"의 어떤 문자와도 일치하지 않지만 "candy"의 'a', "caandy"의 처음 두
'a' 및 "caaaaaaandy"와 일치합니다. 그 안에 처음 세 개의 'a'가 있습니다. 참고: "caaaaaaandy"에 'a'가 많더라도 처음 세 개의 'a', 즉 "aaa"만 일치합니다.

문자 [xyz]
의미: 목록의 모든 문자와 일치하는 문자 목록입니다. 하이픈 -을 사용하여 문자 범위를 지정할 수 있습니다.
예: [abcd]는 [a-c]와 동일합니다. 이는 "brisket"의 'b'와 "ache"의 'c'와 일치합니다.

Character[^xyz]
의미: 한 문자 보완, 즉 나열된 문자를 제외한 모든 문자와 일치합니다. 하이픈을 사용하여
문자 범위를 나타낼 수 있습니다.
예: [^abc]와 [^a-c]는 동일합니다. 먼저 "brisket"의 'r'과 "chop."의 'h'와 일치합니다.

Character
의미: 공백과 일치(b와 혼동하지 마세요)

문자 b
의미: 공백 등 단어의 구분선과 일치(헷갈리지 마세요)
예: /bnw/ "noonday" no'의 '와 일치합니다. /wyb/는 "아마도 어제"의 'ly'와 일치합니다.

문자 B
의미: 단어의 줄바꿈 ​​없는 행과 일치합니다.
예: /wBn/은 "noonday"의 'on'과 일치하고, /yBw/는 "posseverly Tuesday"의 'ye'와 일치합니다.

Character cX
의미: 여기서 X는 제어 문자입니다. 제어 문자 문자열과 일치합니다.
예: /cM/은 문자열의 control-M과 일치합니다.

문자 d
의미: [0-9]에 해당하는 숫자와 일치합니다.
예: /d/ 또는 /[0-9]/는 "B2가 모음 번호입니다."에서 '2'와 일치합니다.

문자 D
의미: 숫자가 아닌 모든 것과 일치하며 [^0-9]와 동일합니다.
예: /D/ 또는 /[^0-9]/는 "B2는 모음 번호입니다."의 'B'와 일치합니다.

Character f
의미: 형식 문자 일치

Character n
의미: 개행 문자

문자 r
의미: 캐리지 리턴 문자

문자 s
의미: [fnrtv]에 해당하는 공백, 탭, 폼 피드, 개행 문자를 포함하여 단일 공백 ​​문자와 일치합니다.
예: /sw*/는 "foo bar"의 'bar'와 일치합니다.

문자 S
의미: 공백을 제외하고 단일 문자와 일치하며 [^ fnrtv]와 동일합니다.
예: /S/w*는 "foo bar."의 'foo'와 일치합니다.

문자 t
의미: 탭 문자 일치

문자 v
의미: 선행 탭 문자 일치

문자 w
의미: 모든 숫자, 문자 및 밑줄 일치([A-Za-z0 -9_]와 동일).
예를 들어 /w/는 'apple'의 'a', '$5.28'의 '5', '3D'의 '3'과 일치합니다.

문자 W
의미: 숫자, 문자, 밑줄을 제외한 다른 문자와 일치하며 [^A-Za-z0-9_]와 동일합니다.
예: /W/ 또는 /[^$A-Za-z0-9_]/는 "50%"의 '%'와 일치합니다.

문자 n
의미: n은 양의 정수입니다. 정규식의 마지막 하위 문자열과 일치하는 n 값(왼쪽 괄호 수 계산)


PHP 함수에 대한 질문:

1. 배열 함수

array_key_exists는 키가 있는지 확인합니다.
is_array는 배열인지 확인합니다.
in_array는 주어진 값이 데이터에 나타나는지 확인합니다.
array_count_values는 횟수를 결정합니다. 값이 나타납니다
array_search array 찾기
array_merge 배열 병합
array_map 배열의 각 요소에 대해 사용자 정의 함수 사용
array_change_case 배열 키의 대소문자 변경
sort 배열 정렬
array_push 배열 끝에 하나 이상의 요소 삽입
array_pop 배열의 마지막 요소를 팝합니다
array_unshift 배열의 시작 부분에 여러 요소를 삽입합니다
array_shift는 배열의 첫 번째 요소를 팝합니다
implode 배열을 문자열로 변환
shuffle 배열의 순서를 뒤집습니다
array_rand 여러 요소를 무작위로 제거 배열에서
array_chunk 배열을 새 배열로 나누기
array_diff 차이점
array_inestsert 교차점
array_flip 키 값 교환 ​​
array_keys 배열의 모든 키 반환
count 배열 길이 계산

2 문자열 함수
addcslashes — 문자열의 일부 문자에 백슬래시 이스케이프 문자 추가
addslashes — 지정된 방법을 사용하여 문자 수정 문자열의 문자 이스케이프
bin2hex — 이진 데이터를 16진수 표현으로 변환
chop — rtrim()의 별칭 ​​함수
chr — 반환 문자의 ASCII 코드
chunk_split — 특정 문자 길이에 따라 문자열을 작은 조각으로 분할
convert_cyr_string — 키릴 문자를 다른 문자로 변환
convert_uudecode — 문자열 암호 해독
convert_uuencode — 문자열 암호화
count_chars — 문자 사용 정보 반환 문자열
crc32 — 문자열의 crc32 계산 다항식
crypt — 단방향 해시 암호화 기능
echo — 일부 콘텐츠를 표시하는 데 사용
explode — 구분 기호를 사용하여 문자열을 배열로 변환
fprintf — 필요에 따라 데이터를 반환하고 쓰기
get_html_translation_table — 변환할 수 있는 HTML 엔터티를 반환합니다.
hebrev — 히브리어로 인코딩된 문자열을 시각적 텍스트로 변환합니다.
hebrevc — 히브리어로 인코딩된 문자열을 시각적 텍스트로 변환합니다.
html_entity_decode — htmlentities ()의 역수 함수, 변환 HTML 엔터티를 문자로 변환
htmlentities — 문자열의 일부 문자를 HTML 엔터티로 변환
htmlspecialchars_decode — htmlspecialchars() 함수의 역함수, HTML 엔터티를 문자로 변환
htmlspecialchars — 문자열의 일부 문자를 HTML 엔터티로 변환
implode — 특정 구분 기호를 사용하여 배열을 문자열로 변환
join — 배열을 implode() 함수의 별칭인 문자열로 변환
levenshtein — 두 단어 간의 차이 계산
localeconv — 숫자 관련 형식 정의 가져오기
ltrim — 문자열 왼쪽의 공백이나 지정된 문자를 제거합니다
md5_file — MD5 알고리즘으로 파일 암호화
md5 — MD5 알고리즘으로 문자열 암호화
metaphone — 문자열의 발음 규칙 결정
money_format — 다음에 따라 숫자 암호화 매개변수 형식화된 출력
nl_langinfo — 언어 및 로케일 정보 쿼리
nl2br — 문자열의 개행 문자 "n"을 "076402276aae5dbec7f672f8f4e5cc81"로 대체
number_format — 매개변수에 따라 형식화된 숫자 출력
ord — ASCII 코드를 문자
parse_str — 특정 형식의 문자열을 변수와 값으로 변환 ​​
print — 단일 값을 출력하는 데 사용
printf — 필요에 따라 데이터 표시
quoted_printable_decode — 문자열을 8비트 이진 문자열로 암호화
quotemeta — 이스케이프 여러 특정 문자
rtrim — 문자열 오른쪽의 공백이나 지정된 문자를 제거합니다.
setlocale — 숫자, 날짜 등의 로컬 형식을 설정합니다.
sha1_file — 변환 파일은 SHA1 알고리즘으로 암호화됩니다
sha1 — 암호화 SHA1 알고리즘을 사용한 문자열
similar_text — 두 문자열을 비교하고 시스템에서 고려한 유사한 문자 수를 반환합니다
soundex — 문자열의 발음 규칙 결정
sprintf — 필요에 따라 데이터를 반환하지만 출력하지 않음
sscanf — 문자열 형식을 지정할 수 있음
str_ireplace — str_replace() 함수와 같은 문자열을 일치시키고 바꾸지만 대문자와 소문자를 구분하지 않음
str_pad — 문자열 양쪽 패딩
str_repeat — 반복되는 문자열 조합
str_replace — 문자열 일치 및 바꾸기
str_rot13 — 문자열의 ROT13 암호화
str_shuffle — 문자열의 문자 무작위 정렬 수행
str_split — 문자열을 배열로 분할 문자 간격에 따라
str_word_count — 문자열에서 영어 단어 정보 가져오기
strcasecmp — 대소문자를 구분하지 않고 문자열 크기 비교
strchr — 비교를 통해 문자 반환 문자열의 strstr() 함수의 부분 별칭
strcmp — 문자열 크기를 비교합니다.
strcoll — 로컬 설정에 따라 문자열 크기를 비교합니다.
strcspn — 연속적으로 일치하지 않는 문자 길이의 값을 반환합니다.
strip_tags — 문자열 HTML 및 PHP 코드에서 문자를 제거합니다.
stripcslashes — 처리된 문자열을 이스케이프 처리하기 위해 addedcslashes() 함수를 이스케이프 해제합니다.
stripos — 첫 번째 일치 항목의 위치를 ​​찾아 반환합니다. 일치는 대소문자를 구분하지 않습니다.
stripslashes — addslashes() 함수를 이스케이프 해제합니다. 의미 처리된 문자열
stristr — 문자열의 일부를 반환합니다. 비교를 통해 문자열을 비교합니다. 비교는 대소문자를 구분하지 않습니다.
strlen — 문자열의 인코딩된 길이를 가져옵니다.
strnatcasecmp — 자연 정렬을 사용하여 문자열 크기를 비교합니다. 대소문자를 구분하지 않습니다. 대소문자
strnatcmp — 자연 정렬을 사용하여 문자열을 비교합니다.
strncasecmp — 첫 번째 N을 비교합니다. 문자열의 문자, 대소문자 구분 안 함
strncmp — 문자열의 처음 N자를 비교합니다.
strpbrk — 비교하여 문자열의 일부를 반환합니다.
strpos — 첫 번째 일치 위치를 찾아서 반환합니다.
strrchr — 문자열의 일부를 반환합니다. 뒤에서 앞으로 비교하는 문자열
strrev — 문자열의 모든 문자를 반대로 합니다.
strripos — 뒤에서 앞으로 검색하고 일치하는 첫 번째 위치를 반환합니다.
strrpos — 뒤에서 앞으로 검색합니다. 첫 번째 일치 위치를 반환합니다.
strspn — 연속된 문자의 길이 값을 일치시키고 반환합니다.
strstr — 비교를 통해 문자열의 일부를 반환합니다.
strtok — 지정된 문자 수로 문자열을 분할합니다.
strtolower — 문자열을 소문자로 변환
strtoupper — 문자열을 대문자로 변환
strtr — 문자열 비교 및 ​​바꾸기
substr_compare — 문자열을 가로채서 비교
substr_count — 문자열에서 특정 문자 세그먼트의 발생 횟수 계산
substr_replace — 일부 문자 바꾸기 문자열에서
substr — 문자열 가로채기
trim — 문자열의 양쪽 측면 제거 공백 또는 지정된 문자
ucfirst — 주어진 문자열의 첫 글자를 대문자로 변환
ucwords — 주어진 문자열에 있는 각 영어 단어의 첫 글자를 변환 대문자로
vfprintf — 필요에 따라 데이터 변환 반환하여 문서 스트림에 직접 쓰기
vprintf — 필요에 따라 데이터 표시
vsprintf — 필요에 따라 데이터를 반환하지만 출력하지 않음
wordwrap — 특정 문자에 따라 문자열 분할 길이



코드 사양은 어떻게 되나요?

인터페이스 작성 시 통합 검증 및 반환을 작성했습니다.

각 파일에는 고유한 주석이 있어야 하고, 각 클래스에는 고유한 주석이 있어야 하며, 각 메서드에는 주석이 있어야 합니다. 불확실한 요구 사항 또는 나중에 발생할 수 있는 문제. todo에 추가해야 합니다

주요 로직은 주석으로 작성해야 합니다

외부 인터페이스 호출 시 프로그램에 하드 코딩할 수 없습니다. 나중에 수정하기 쉽도록 구성 파일을 별도로 제안해야 합니다.

데이터베이스 작업은 다음과 같이 작성해야 합니다. 모델 내부에서는 데이터베이스 작업을 C 계층에 작성할 수 없습니다.

변수 이름은 의미를 명확하게 표현할 수 있어야 합니다.

인터페이스를 작성하기 전에 인터페이스 문서를 받아야 합니다.

Private 메소드를 추가해야 합니다_ [중요, 저는 드라이버 경험이 있는 것 같습니다]



클래스 파일에는 모두 .class.php가 붙습니다. (이것은 ThinkPHP에서 내부적으로 사용하는 클래스 라이브러리 파일을 의미하며, 그렇다고 의미하는 것은 아닙니다. 외부 로딩) 클래스 라이브러리 파일), Camel Case 명명을 사용하고 첫 글자는 대문자로 표시합니다(예: DbMysql.class.php).

클래스의 네임스페이스 주소는 해당 클래스가 위치한 경로 주소와 일치합니다. HomeControllerUserController 클래스가 있는 경로는 Application/Home/Controller /UserController.class.php여야 합니다.
Unix 계열 시스템은 대소문자를 구분하므로 파일 이름 지정 및 호출 대소문자가 일치하는지 확인하세요. Windows 플랫폼에서도 디버그 모드) );
클래스 이름은 파일 이름(위에서 언급한 대문자 및 소문자 포함)과 일치합니다. 예를 들어 UserController 클래스의 파일 이름은 UserController.class.php입니다. InfoModel 클래스의 이름은 InfoModel.class.php입니다.
그리고 다양한 클래스 라이브러리 클래스 이름 지정에 대한 특정 표준이 있습니다.

함수, 구성 파일 및 기타 클래스 라이브러리 파일에는 일반적으로 .php라는 접미사가 붙습니다(제3자가 도입한 파일은 그렇지 않습니다). 필수);

函数的命名使用小写字母和下划线的方式,例如 get_client_ip;

方法的命名使用驼峰法,并且首字母小写或者使用下划线“_”,例如 getUserName,_parseType,通常下划线开头的方法属于私有方法;
属性的命名使用驼峰法,并且首字母小写或者使用下划线“_”,例如 tableName、_instance,通常下划线开头的属性属于私有属性;
以双下划线“__”打头的函数或方法作为魔法方法,例如 __call 和 __autoload;

常量以大写字母和下划线命名,例如 HAS_ONE和 MANY_TO_MANY;

配置参数以大写字母和下划线命名,例如HTML_CACHE_ON;

语言变量以大写字母和下划线命名,例如MY_LANG,以下划线打头的语言变量
通常用于系统语言变量,例如 _CLASS_NOT_EXIST_;

对变量的命名没有强制的规范,可以根据团队规范来进行;

ThinkPHP的模板文件默认是以.html 为后缀(可以通过配置修改);

数据表和字段采用小写加下划线方式命名,并注意字段名不要以下划线开头,例
如 think_user 表和 user_name字段是正确写法,类似 _username 这样的数据表字段可能会被过滤。


tp底层看过没有?


1、看过框架的底层没有?
    看过tp的数据库驱动相关。 关于配置数据库方面的,在配置文件配置就直接可以使用各种数据库类型,自己简单看了下,主要就是通过一个driver(驱动类)来判断当前连接类
型,然后调用对于的数据库操作类。
    ps:如果是要我们自己实现的话,可以借助接口,每个数据库的操作类都需要集成一个接口,然后根据具体的配置去调用每个操作类。 就算后期我修改了数据库的类型,也不
会导致程序需要改动。

2、看过tp的cache类,和数据库类似,修改过redis的cache类,因为tp的redis操作类不支持认证。
  主要就是在redis操作类添加了个认证

$this->handler  = new \Redis;
        $options[&#39;timeout&#39;] === false ?
            $this->handler->$func($options[&#39;host&#39;], $options[&#39;port&#39;]) :
            $this->handler->$func($options[&#39;host&#39;], $options[&#39;port&#39;], $options[&#39;timeout&#39;]);
            $this -> handler->auth( C(‘REDIS_AUTH_KEY’) );

3、看过tp的处理异常类
路径  ThinkPHP/library/Think/Think.class.php

主要使用的是php自带的错误处理相关函数

register_shutdown_function 定义PHP程序执行完成后执行的函数
set_error_handler    设置用户自定义的错误处理程序
set_exception_handler 设置自己的异常处理机制

借助 get_last_error获取最后一次报错的信息
根据报错级别可以自定义写日志
这个地方我们在做接口的时候纪录了一些错误日志,帮助我们排查一些问题。
如果要看文件加载以及调用关系可以借助 print_debug_backtrace获取文件加载的顺序

     // 注册AUTOLOAD方法
      spl_autoload_register(&#39;Think\Think::autoload&#39;);      
      // 设定错误和异常处理
      register_shutdown_function(&#39;Think\Think::fatalError&#39;);
      set_error_handler(&#39;Think\Think::appError&#39;);
      set_exception_handler(&#39;Think\Think::appException&#39;);

4、简单看了下tp的命名空间自动记载
框架下的核心类都包含进来了,其他的事借助 spl_register_autoload实现。

위 내용은 PHP 면접 질문 정리 및 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.