>  Q&A  >  본문

require 메소드는 PHP에서 불가능할 때 int를 반환합니다.

<p>일부 PHP 코드를 파일에 저장한 다음 로드하고 다시 실행하는 다음 코드가 있는데 때로는 require 메소드가 int를 반환하는데, 왜 이런 일이 발생합니까? </p> <h1>demo.php</h1> <pre class="brush:php;toolbar:false;"><?php $f = 함수() 사용($a){ $cachePath = '/tmp/t.php'; $code = '<?php'; $code .= "nn";; $code .= '반환' . var_export([], true) ';'; file_put_contents($cachePath, $code, LOCK_EX); if (file_exists($cachePath)) { // 다음 줄이 int를 반환하는 경우가 있습니다. 이유는 무엇입니까? $결과 = 요구($cachePath); if (!is_array($result)) { var_dump($result, $cachePath, file_get_contents($cachePath)); 종료("확인"); } var_dump($result); } }; for($i=0;$i<1000000;$i++) { $f(); }</pre>

어떻게 재현하나요? </h1> <p>두 개의 PHP 프로세스를 사용하여 위 코드를 실행합니다</p> <pre class="brush:php;toolbar:false;">php 데모.php</pre></p>

P粉883223328P粉883223328383일 전536

모든 응답(2)나는 대답할 것이다

  • P粉351138462

    P粉3511384622023-09-03 09:03:54

    이것은 require 的标准行为,与 include에 대한 문서입니다. 둘 사이의 동작은 동일합니다.

    보시다시피 반환 값을 덮어쓰지 않으면 해피 경로에 정수(1)가 반환됩니다.

    지금까지는 파일이 존재했지만(치명적인 오류는 없음), 파일이 방금 생성되었기 때문에 잘릴 수도 있습니다. 즉, 비어 있을 수 있습니다.

    그래서 반환 값은 덮어쓰이지 않고 int(1)을 볼 수 있습니다.

    또 다른 설명은 당연히 정수로 덮어썼다는 것입니다. 이는 여러 프로세스가 동일한 파일에 쓸 수 있기 때문에 가능하지만 예제를 작성한 방식으로는 그럴 가능성이 적습니다. 나는 그것이 또 다른 유효한 설명이기 때문에 언급합니다.

    있는 경우 포함

    파일이 존재할 때만 (만) 대신 $result을 찾을 때 경쟁 조건을 일시 중단하는 방법의 예:

    으아악

    그 뒤에 있는 아이디어는 파일이 존재하는지 확인하는 것과 같은 오류 처리를 거의 수행하지 않는다는 것입니다. 그렇지 않으면 파일을 포함할 수 없습니다(include()는 경고를 내보내고 $result = false로 전달합니다). 결과가 로드되면 is_array() 테스트에 적용됩니다.

    이것은 오류에 대한 것이지만 우리가 찾고 있는 것이 무엇인지 알고 있습니다. 즉, $result는 배열입니다.

    이를 흔히 거래 또는 거래 작업이라고 합니다.

    이 새로운 예에서는 $result 배열이 비어 있을 때, 즉 데이터가 포함되어 있지 않을 때 if-body도 입력하지 않습니다.

    우리가 관심을 가질 수 있는 프로그램 처리 수준에서 파일 존재 또는 존재하지 않음, 비어 있음 또는 비어 있지 않음, 심지어 쓰기 오류는 모두 "먹혀서" $결과를 무효화해야 하는 오류 조건입니다.

    정의 오류가 존재하지 않습니다.

    구문 분석 오류 처리(Include-If-Exists의 경우)

    PHP 7.0부터 include()를 사용할 수 있으며 불행하게도 반환된 포함 파일이 절반만 작성된 경우 잡을 수 있는:

    PHP 구문 분석 오류가 표시됩니다. 으아악

    예외 발생/예외 처리 작업에 대한 자세한 내용은 PHP try-catch-finally를 참조하세요. 예제에서 입력 매개 변수 $cachePath의 의미를 기록하는 데 Assert()가 사용됩니다.

    두 번째 예에서는 억제 작업 "@"을 사용하지 않습니다. 그 이유는 이전 예와 같이 사용하면 포함할 파일에 실제 치명적인 오류가 포함되어 치명적인 오류가 침묵되기 때문입니다. 요즘 최신 PHP에서는 더 이상 큰 문제가 아니지만 file_exists() + include()를 사용하는 것은 - 확인 시간과 사용 시간으로 인해 경쟁 조건이 있지만 - 존재하지 않는 파일에 대해서는 안전합니다(경고만). 치명적인 오류는 숨겨지지 않습니다.

    아시다시피, 더 많은 세부 사항을 알수록 미래에도 대비할 수 있는 코드를 작성하기가 더 어려워집니다. 오류 처리 자체에 빠져서는 안 되며, 결과에 집중하고 이러한 오류가 존재하지 않는다고 정의해야 합니다.

    include()는 여전히 데이터가 메모리에 로드되도록 하고, file_exists()는 경고를 "억제"하는 데만 사용됩니다. 그럼에도 불구하고 include()는 경고를 내보내고 하나의 배열 대신 정수를 반환할 수 있다는 것을 알고 있습니다. .


    이제 프로그래밍이 어렵기 때문에 루프로 래핑하고 세 번 재시도하라고 말할 수 있습니다. 숫자 재시도를 계산하고 보호하기 위해 for 루프를 사용하는 것은 어떨까요?

    회신하다
    0
  • P粉550323338

    P粉5503233382023-09-03 00:09:17

    스크립트에 항상 실행자가 하나만 있으면 이 문제가 재현될 수 없습니다.

    이 스크립트를 병렬로 실행하는 것에 대해 이야기하는 경우 문제는 단독 모드에서 파일을 작성해도 나중에 작성 프로세스 중에 파일을 읽는 것을 방지할 수 없다는 것입니다.

    프로세스가 파일에 쓰고 있고 잠금을 소유하고 있을 수 있지만 require 잠금을 적용하지 않습니다(파일 시스템 잠금은 권장 사항이며 강제되지 않음).

    올바른 해결책은 다음과 같습니다.

    으아악

    다른 프로세스가 파일 덮어쓰기를 기다리고 있을 수 있으므로 쓰기 후에는 잠금이 해제되거나 다시 획득되지 않습니다.

    작성된 동일한 코드가 required인지 확인하기 위해 게시하지 않습니다.

    그러나 이 모든 것은 처음부터 의심스러웠습니다.

    나중에 반환할 수 있도록 파일에 기록해야 하는 이유는 무엇입니까 require?

    회신하다
    0
  • 취소회신하다