찾다
백엔드 개발PHP 튜토리얼PHP 날짜 문자열 비교 예

프로젝트에 회원 만료 여부를 비교하는 기능이 있습니다. 동료의 코드를 검토한 결과 작성 방법이 다소 이상한 것을 발견했지만 온라인에서는 버그가 없었습니다.

구현:

  1. $expireTime = "2014-05-01 00:00:00";
  2. $currentTime = 날짜('Y-m-d H:i:s' , time());
  3. if($currentTime return false;
  4. } else {
  5. return true;
  6. }
코드 복사

두 개의 시간을 비교해야 하는 경우 일반적으로 유닉스 타임스탬프로 변환하여 두 개의 int 유형 숫자와 비교합니다. 이 구현은 구체적으로 시간을 문자열로 표현한 다음 두 문자열에 대해 비교 작업을 수행합니다.

작성방법은 차치하고, PHP 내부에서는 어떻게 비교가 이루어지는지 매우 궁금합니다.

더 이상 고민하지 말고 소스 코드부터 추적을 시작해 보겠습니다.

편집 기간 다음과 유사한 구문은 zend_언어_parse.y에서 찾을 수 있습니다.

  1. expr === expr { zend_do_binary_op(ZEND_IS_IDENTICAL, &$$, &$1, &$3 TSRMLS_CC) }
  2. expr !== expr { zend_do_binary_op(ZEND_IS_NOT_IDENTICAL, &$$, &$1, &$3 TSRMLS_CC) }
  3. expr == expr { zend_do_binary_op(ZEND_IS_EQUAL, &$$, &$1, &$3 TSRMLS_CC) }
  4. expr != expr { zend_do_binary_op(ZEND_IS_NOT_EQUAL, &$$, &$1, &$3 TSRMLS_CC) }
  5. expr expr expr > expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$3, &$1 TSRMLS_CC) }
  6. expr >= expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC) }
코드 복사

분명히 여기에서 opcode로 컴파일하는 것이 편리합니다. zend_do_binary_op.

  1. void zend_do_binary_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
  2. {
  3. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  4. opline->opcode = op;
  5. opline->result.op_type = IS_TMP_VAR;
  6. opline-> result.u.var = get_temporary_variable(CG(active_op_array));
  7. opline->op1 = *op1;
  8. opline->op2 = *op2;
  9. *result = opline->result;
  10. }
코드 복사

이 함수는 특별한 처리를 수행하지 않고 단순히 opcode, 피연산자 1, 피연산자 2만 저장합니다.

집행기간 Opcode에 따라 해당 처리 함수인 ZEND_IS_SMALLER_SPEC_CONST_CONST_HANDLER로 점프합니다.

  1. 정적 정수 ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
  2. {
  3. zend_op *opline = EX(opline);
  4. z 발 *결과 = &EX_T(opline->result.u.var).tmp_var;
  5. Compare_function(result,
  6. &opline->op1.u.constant,
  7. &opline->op2.u. 상수 TSRMLS_CC);
  8. ZVAL_BOOL(결과, (Z_LVAL_P(결과)
  9. ZEND_VM_NEXT_OPCODE();
  10. }
코드 복사

두 zval의 비교는 Compare_function을 사용하여 처리됩니다.

  1. ZEND_API int Compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
  2. {
  3. int ret;
  4. int 변환 = 0;
  5. zval op1_copy, op2_copy;
  6. zval *op_free;
  7. while (1) {
  8. 스위치 (TYPE_PAIR(Z_TYPE_P(op1)), Z_TYPE_P( op2))) {
  9. 케이스 TYPE_PAIR(IS_LONG, IS_LONG):
  10. ...
  11. 케이스 TYPE_PAIR(IS_DOUBLE, IS_LONG):
  12. ...
  13. 케이스 TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
  14. ...
  15. ...
  16. // 두 문자열 비교
  17. case TYPE_PAIR(IS_STRING, IS_STRING):
  18. zendi_smart_strcmp(result, op1, op2);
  19. return SUCCESS;
  20. ...
  21. }
  22. }
  23. }
코드 복사

이 함수는 이 기사의 사례에 따라 몇 가지 상황을 예시합니다. 자세히 살펴보려면 zendi_smart_strcmp를 입력하세요.

  1. ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2) /* {{{ */
  2. {
  3. int ret1 , ret2;
  4. long lval1, lval2;
  5. double dval1, dval2;
  6. // 문자열을 숫자 유형으로 변환해 봅니다.
  7. if ((ret1=is_numeric_string(Z_STRVAL_P(s1), Z_STRLEN_P(s1), &lval1, &dval1, 0)) &&
  8. (ret2=is_numeric_string(Z_STRVAL_P(s2), Z_STRLEN_P(s2), &lval2, &dval2, 0))) {
  9. // 숫자 간 변환 비교
  10. ...
  11. } else {
  12. // 모두 숫자로 변환할 수 없습니다
  13. // 그런 다음 zend_binary_zval_strcmp를 호출합니다
  14. // 기본적으로 memcmp의 1계층 캡슐화
  15. Z_LVAL_P(결과) = zend_binary_zval_strcmp(s1, s2);
  16. ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(result)));
  17. }
  18. }
코드 복사

'2014-05-01 00:00:00'을 숫자로 변환할 수 있나요?

is_numeric_string의 구현 규칙을 살펴봐야 합니다.

  1. 정적 인라인 zend_uchar is_numeric_string(const char *str, int length, long *lval, double *dval, intallow_errors)
  2. {
  3. const char *ptr;
  4. int base = 10, 숫자 = 0, dp_or_e = 0;
  5. double local_dval;
  6. zend_uchar type;
  7. if (!length) {
  8. return 0;
  9. }
  10. /* 문자열 시작 부분의 공백 부분을 잘라냅니다*/
  11. while (*str == ' ' || *str == 't' || *str = = 'n' || *str == 'r' || *str == 'v' || *str == 'f') {
  12. str ;
  13. 길이--;
  14. }
  15. ptr = str;
  16. if (*ptr == '-' || *ptr == ' ') {
  17. ptr ;
  18. }
  19. if (ZEND_IS_DIGIT( *ptr) ) {
  20. /* 16진수인지 확인*/
  21. if (length > 2 && *str == '0' && (str[1] == 'x' || str[1 ] = = 'X')) {
  22. base = 16;
  23. ptr = 2;
  24. }
  25. /* 다음 0은 무시 */
  26. while (*ptr == ' 0') {
  27. ptr ;
  28. }
  29. /* 자릿수를 계산하여 정수인지 부동 소수점인지 결정합니다*/
  30. for (type = IS_LONG; !(digits > ;= MAX_LENGTH_OF_LONG && (dval || 허용_오류 == 1)); 숫자 , ptr ) {
  31. check_digits:
  32. if (ZEND_IS_DIGIT(*ptr) || (base == 16 && ZEND_IS_XDIGIT(*ptr)) ) {
  33. 계속;
  34. } else if (base == 10) {
  35. if (*ptr == '.' && dp_or_e goto process_double;
  36. } else if ((*ptr == 'e' || *ptr == 'E') && dp_or_e const char *e = ptr 1;
  37. if (*e == ' -' || *e == ' ') {
  38. ptr = e ;
  39. }
  40. if (ZEND_IS_DIGIT(*e)) {
  41. goto process_double;
  42. }
  43. }
  44. }
  45. break;
  46. }
  47. if (base == 10) {
  48. if (digits >= MAX_LENGTH_OF_LONG) {
  49. dp_or_e = -1;
  50. goto process_double;
  51. }
  52. } else if (!(digits if (dval) {
  53. local_dval = zend_hex_strtod(str, (char **)&ptr);
  54. }
  55. type = IS_DOUBLE;
  56. }
  57. } else if (*ptr = = '.' && ZEND_IS_DIGIT(ptr[1])) {
  58. // 부동 소수점 숫자 처리
  59. } else {
  60. return 0;
  61. }
  62. // 내결함성인 경우 허용되지 않는 경우 오류를 보고하고 종료합니다.
  63. if (ptr != str length) {
  64. if (!allow_errors) {
  65. return 0;
  66. }
  67. if (allow_errors == - 1) {
  68. zend_error (E_NOTICE, "잘못된 형식의 숫자 값이 발생했습니다.");
  69. }
  70. }
  71. // 내결함성을 허용하려면 str을 숫자로 변환해 보세요
  72. if (type == IS_LONG) {
  73. if (digits == MAX_LENGTH_OF_LONG - 1) {
  74. int cmp = strcmp(&ptr[-digits], long_min_digits);
  75. if (!( cmp if (dval) {
  76. *dval = zend_strtod(str, NULL);
  77. }
  78. return IS_DOUBLE;
  79. }
  80. }
  81. if (lval) {
  82. *lval = strtol(str, NULL, base);
  83. }
  84. return IS_LONG;
  85. } else {
  86. if (dval) {
  87. *dval = local_dval;
  88. }
  89. return IS_DOUBLE;
  90. }
  91. }
코드 복사

코드는 비교적 길지만 주의 깊게 읽어보면 str을 num으로 변환하는 규칙은 여전히 ​​매우 명확합니다.

이 예에서 "2014-05-01 00:00:00"을 숫자로 변환할 수 없음을 직접 결정하는 Allow_errors 매개변수에 특히 주의하세요.

결국 "2014-04-17 00:00:00"

memcmp이기 때문에 글 시작 부분에서 언급한 작성 방법도 왜 제대로 실행되는지 이해하는 것은 어렵지 않습니다.

내결함성 변환 Allow_errors는 언제 true인가요? 훌륭한 예는 zend_parse_parameters입니다. zend_parse_parameters의 구현은 자세히 설명하지 않습니다. 관심 있는 독자는 스스로 연구할 수 있습니다. is_numeric_string을 호출하면allow_errors가 -1로 설정됩니다.

예:

  1. static void php_date(INTERNAL_FUNCTION_PARAMETERS, int localtime)
  2. {
  3. char *format;
  4. int format_len;
  5. long ts;
  6. char *string;
  7. // 예상되는 두 번째 매개변수는 긴 타임스탬프입니다.
  8. // 상위 계층이 호출될 때 문자열이 실수로 전달되었다고 가정하면 zend_parse_parameters는 여전히 그만큼 시도합니다. 가능한 한 긴 문자열로 구문 분석
  9. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &format, &format_len, &ts) == FAILURE) {
  10. RETURN_FALSE;
  11. }
  12. if (ZEND_NUM_ARGS ( ) == 1) {
  13. ts = time(NULL);
  14. }
  15. string = php_format_date(format, format_len, ts, localtime TSRMLS_CC);
  16. RETVAL_STRING(string , 0);
  17. }
코드 복사

PHP 날짜 함수의 내부 구현입니다.

date를 호출할 때 두 번째 매개변수를 string으로 전달하면 효과는 다음과 같습니다.

  1. echo date('Y-m-d', '0-1-2');
  2. // 출력
  3. PHP 공지사항 : 1행의 명령줄 코드에서 잘못된 형식의 숫자 값이 발견되었습니다.
  4. 1970-01-01
코드 복사

알림은 다음과 같습니다. 레벨 오류가 보고되었지만 여전히 '0-1-2'를 0으로 성공적으로 변환했습니다



성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
PHP 세션에 어떤 데이터를 저장할 수 있습니까?PHP 세션에 어떤 데이터를 저장할 수 있습니까?May 02, 2025 am 12:17 AM

phpsessionscanstorestrings, 숫자, 배열 및 객체 1.Strings : TextDatalikeUsernames.2.numbers : integorfloatsforcounters.3.arrays : listslikeshoppingcarts.4.objects : complexStructuresThatareserialized.

PHP 세션을 어떻게 시작합니까?PHP 세션을 어떻게 시작합니까?May 02, 2025 am 12:16 AM

tostartAphPessession, us

세션 재생이란 무엇이며 보안을 어떻게 개선합니까?세션 재생이란 무엇이며 보안을 어떻게 개선합니까?May 02, 2025 am 12:15 AM

세션 재생은 세션 고정 공격의 경우 사용자가 민감한 작업을 수행 할 때 새 세션 ID를 생성하고 이전 ID를 무효화하는 것을 말합니다. 구현 단계에는 다음이 포함됩니다. 1. 민감한 작업 감지, 2. 새 세션 ID 생성, 3. 오래된 세션 ID 파괴, 4. 사용자 측 세션 정보 업데이트.

PHP 세션을 사용할 때 몇 가지 성능 고려 사항은 무엇입니까?PHP 세션을 사용할 때 몇 가지 성능 고려 사항은 무엇입니까?May 02, 2025 am 12:11 AM

PHP 세션은 응용 프로그램 성능에 큰 영향을 미칩니다. 최적화 방법은 다음과 같습니다. 1. 데이터베이스를 사용하여 세션 데이터를 저장하여 응답 속도를 향상시킵니다. 2. 세션 데이터 사용을 줄이고 필요한 정보 만 저장하십시오. 3. 비 차단 세션 프로세서를 사용하여 동시성 기능을 향상시킵니다. 4. 사용자 경험과 서버 부담의 균형을 맞추기 위해 세션 만료 시간을 조정하십시오. 5. 영구 세션을 사용하여 데이터 읽기 및 쓰기 시간의 수를 줄입니다.

PHP 세션은 쿠키와 어떻게 다릅니 까?PHP 세션은 쿠키와 어떻게 다릅니 까?May 02, 2025 am 12:03 AM

phpsessionsareser-side, whilecookiesareclient-side.1) sessions stessoredataontheserver, andhandlargerdata.2) cookiesstoredataonthecure, andlimitedinsize.usesessionsforsensitivestataondcookiesfornon-sensistive, client-sensation.

PHP는 사용자 세션을 어떻게 식별합니까?PHP는 사용자 세션을 어떻게 식별합니까?May 01, 2025 am 12:23 AM

phpidifiesauser의 sssessionusessessioncookiesandssessionids.1) whensession_start () iscalled, phpgeneratesauniquessessionStoredInacookienamedPhpsSessIdonSeuser 'sbrowser.2) thisidallowsphptoretrievessessionDataTromServer.

PHP 세션을 확보하기위한 모범 사례는 무엇입니까?PHP 세션을 확보하기위한 모범 사례는 무엇입니까?May 01, 2025 am 12:22 AM

PHP 세션의 보안은 다음 측정을 통해 달성 할 수 있습니다. 1. Session_REGENEREAT_ID ()를 사용하여 사용자가 로그인하거나 중요한 작업 일 때 세션 ID를 재생합니다. 2. HTTPS 프로토콜을 통해 전송 세션 ID를 암호화합니다. 3. 세션 _save_path ()를 사용하여 세션 데이터를 저장하고 권한을 올바르게 설정할 보안 디렉토리를 지정하십시오.

PHP 세션 파일은 기본적으로 어디에 저장됩니까?PHP 세션 파일은 기본적으로 어디에 저장됩니까?May 01, 2025 am 12:15 AM

phpsessionfilesarestoredInTheRectorySpecifiedBysession.save_path, 일반적으로/tmponunix-likesystemsorc : \ windows \ temponwindows.tocustomizethis : 1) austession_save_path () toSetacustomDirectory, verlyTeCustory-swritation;

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

SecList

SecList

SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

DVWA

DVWA

DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

MinGW - Windows용 미니멀리스트 GNU

MinGW - Windows용 미니멀리스트 GNU

이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.