const () 대 const


659

PHP에서 언제 사용합니까

define('FOO', 1);

언제 사용합니까

const FOO = 1;

?

이 둘의 주요 차이점은 무엇입니까?


4
성능 (나 같은 마이크로 최적화와 시간의 낭비) 정보를 참조하십시오 이 답변 : const두 배 빠른 속도로보다 define. 페이지로드 시간 및 메모리 사용량 정보 : 이 질문 및 이 기사를 참조 하십시오 . opcode 캐시에 대한 내용도 여기를 참조 하십시오 .
— 피터 크라우스

2
현재 허용 된 답변 만 보지 말고 stackoverflow.com/a/3193704/1412157 을 참조하십시오. 답변 은 반드시 답변해야합니다
— LucaM

1
귀하의 의견에 대한 알림을 보았습니다. 허용되는 답변을 업데이트했습니다.
— danjarvis

답변:


1039

PHP 5.3부터는 상수 를 정의하는 두 가지 방법이 있습니다 : const키워드를 사용하거나 define()함수를 사용합니다 :

const FOO = 'BAR';
define('FOO', 'BAR');

이 두 가지 방법의 근본적인 차이점은 const컴파일 타임에 상수를 define정의하는 반면 런타임에는 상수 를 정의 한다는 것입니다. 이로 인해 대부분 const의 단점 이 발생 합니다. 몇 가지 단점 const은 다음 과 같습니다.

  • const조건부 상수를 정의하는 데 사용할 수 없습니다. 전역 상수를 정의하려면 가장 바깥 쪽 범위에서 사용해야합니다.

    if (...) {
        const FOO = 'BAR';    // Invalid
    }
    // but
    if (...) {
        define('FOO', 'BAR'); // Valid
    }

    어쨌든 왜 그렇게 하시겠습니까? 일반적인 응용 프로그램 중 하나는 상수가 이미 정의되어 있는지 확인하는 것입니다.

    if (!defined('FOO')) {
        define('FOO', 'BAR');
    }
  • const정적 스칼라 (숫자 나 문자열과 같은 다른 일정 받아 true, false, null, __FILE__), 반면에 define()임의의 표현을 취한다. PHP 5.6부터 상수 표현식도 허용됩니다 const.

    const BIT_5 = 1 << 5;    // Valid since PHP 5.6 and invalid previously
    define('BIT_5', 1 << 5); // Always valid
  • const일반 상수 이름을 사용하지만 define()모든 식을 이름으로 허용합니다. 이를 통해 다음과 같은 작업을 수행 할 수 있습니다.

    for ($i = 0; $i < 32; ++$i) {
        define('BIT_' . $i, 1 << $i);
    }
  • consts는 항상 대소 문자를 구분하지만 세 번째 인수로 define()전달 true하여 대소 문자를 구분하지 않는 상수를 정의 할 수 있습니다 (참고 : 대소 문자를 구분하지 않는 상수 정의는 PHP 7.3.0부터 더 이상 사용되지 않습니다).

    define('FOO', 'BAR', true);
    echo FOO; // BAR
    echo foo; // BAR

그래서 그것은 나쁜 것입니다. 이제 const위의 상황 중 하나가 발생하지 않는 한 개인적으로 항상 사용하는 이유를 살펴 보겠습니다 .

  • const단순히 더 잘 읽습니다. 함수 대신 언어 구성이며 클래스에서 상수를 정의하는 방법과 일치합니다.
  • const언어 구조 인,는 자동화 된 툴링으로 정적으로 분석 될 수 있습니다.
  • const현재 네임 스페이스에서 상수를 정의 define()하고 전체 네임 스페이스 이름을 전달해야합니다.

    namespace A\B\C;
    // To define the constant A\B\C\FOO:
    const FOO = 'BAR';
    define('A\B\C\FOO', 'BAR');
  • PHP 5.6 const상수도 배열이 될 define()수 있지만 아직 배열을 지원하지는 않습니다. 그러나 PHP 7에서는 두 경우 모두 배열이 지원됩니다.

    const FOO = [1, 2, 3];    // Valid in PHP 5.6
    define('FOO', [1, 2, 3]); // Invalid in PHP 5.6 and valid in PHP 7.0

마지막으로, 클래스 상수 또는 인터페이스 상수 const를 정의하기 위해 클래스 또는 인터페이스 내에서 사용될 수도 있습니다 . 이 목적으로 사용할 수 없습니다 :define

class Foo {
    const BAR = 2; // Valid
}
// But
class Baz {
    define('QUX', 2); // Invalid
}

요약

조건부 또는 표현 정의 유형이 필요하지 않은 경우 가독성을 위해 consts 대신 s를 사용 define()하십시오!


1
PHP 5.6에서 알 수 있듯이 const언어 구성 에서도 간단한 스칼라 식을 사용할 수 있습니다. wiki.php.net/rfc/const_scalar_exprs
— mabe.berlin at 14:14

6
사용의 또 다른 이점 const은 인용 부호가 없다는 것입니다. 즉, IDE에서 사용되는 위치와 동일하게 형식이 지정됩니다.
— rybo111

3
이것은 PHP 문서에있는 것이어야합니다. 내가 본 최고의 설명, 특히 대부분의 사람들이 잊어 버린 부분 (컴파일 대 런타임).
— 제임스

4
define('a', $_GET['param']);, const b = a;완벽하게 작동하고 const c = $_GET['param'];유효하지 않은 동안 값을 얻습니다 . 가 const정말 컴파일 시간은? 나는 그렇게 생각하지 않습니다 ... (PHP 7.0.7에서 테스트)
— mcserep

1
wiki.php.net/rfc/case_insensitive_constant_deprecation " PHP 8.0 : 대소 문자를 구분하지 않는 상수를 선언 할 가능성을 제거하십시오. " 대소 문자 구분 과 관련하여 미래에
— 벤트

196

PHP 5.3까지는 const글로벌 스코프에서 사용할 수 없었습니다. 클래스 내에서만 사용할 수 있습니다. 일정 종류의 상수 옵션을 설정하거나 해당 클래스와 관련된 설정을하려는 경우에 사용해야합니다. 또는 일종의 열거 형을 만들고 싶을 수도 있습니다.

define동일한 목적으로 사용될 수 있지만 전역 범위에서만 사용할 수 있습니다. 전체 응용 프로그램에 영향을 미치는 전역 설정에만 사용해야합니다.

좋은 const사용법 의 예는 매직 넘버를 제거하는 것입니다. PDO의 상수를 살펴보십시오 . 페치 유형을 지정해야하는 경우 예를 들어을 입력합니다 PDO::FETCH_ASSOC. const가 사용되지 않으면 다음과 같이 입력 35하거나 FETCH_ASSOC정의 된 내용을 입력하게됩니다 . 독자에게는 이치에 맞지 않습니다.

좋은 define사용법 의 예는 응용 프로그램의 루트 경로 또는 라이브러리의 버전 번호를 지정하는 것입니다.


12
const네임 스페이스와 함께 사용하는 것이 좋습니다 .
— salathe

31
PHP5.3은 전역 범위에서 const를 매우 많이 사용할 수 있습니다.
— Gordon

5.2도 가능합니다. const 대 vs 정의의 장점은 클래스 이름을 접두사로 사용해야한다는 것입니다. 그것들을 사용하면 코드를 더 읽기 쉽고 더 예쁘게 만듭니다. 그리고 그것은 나에게 보너스입니다.
— lucifurious

1
@ryeguy 그러나 PHP 5.3 이후 const는 정의처럼 전역 적으로 사용할 수 있습니까?
— andho

1
@andho, 한 단계 앞으로, 한 단계 뒤로, "개선"의 춤으로 PHP 댄스에 또 다른 것을 올리십시오. 그. :)
— Falken 교수 교수는

37

나는 이것이 이미 답변되었지만 현재 답변 중 어느 것도 네임 스페이스에 대해 언급하지 않으며 상수와 정의에 미치는 영향에 대해 언급하지 않습니다.

PHP 5.3부터 const와 정의는 대부분 비슷합니다. 그러나 여전히 몇 가지 중요한 차이점이 있습니다.

  • 표현식에서 상수를 정의 할 수 없습니다. const FOO = 4 * 3;작동하지 않지만 작동 define('CONST', 4 * 3);합니다.
  • 전달 된 이름 define은 해당 네임 스페이스 내에 정의 할 네임 스페이스를 포함해야합니다.

아래 코드는 차이점을 설명해야합니다.

namespace foo 
{
    const BAR = 1;
    define('BAZ', 2);
    define(__NAMESPACE__ . '\\BAZ', 3);
}

namespace {
    var_dump(get_defined_constants(true));
}

사용자 하위 배열의 내용은입니다 ['foo\\BAR' => 1, 'BAZ' => 2, 'foo\\BAZ' => 3].

=== 업데이트 ===

다가오는 PHP 5.6은와 약간의 유연성을 허용합니다 const. 이제 표현식이 다른 const 또는 리터럴로 구성된 경우 표현식 측면에서 const를 정의 할 수 있습니다. 이는 다음이 5.6부터 유효해야 함을 의미합니다.

const FOOBAR = 'foo ' . 'bar';
const FORTY_TWO = 6 * 9; // For future editors: THIS IS DELIBERATE! Read the answer comments below for more details
const ULTIMATE_ANSWER = 'The ultimate answer to life, the universe and everything is ' . FORTY_TWO;

그래도 변수 또는 함수 반환 측면에서 const를 정의 할 수는 없으므로

const RND = mt_rand();
const CONSTVAR = $var;

여전히 나갈 것입니다.


8
나는 묻는 것에 저항 할 수 없었다 : 당신은 의식적 FORTY_TWO으로 54로 정의 했습니까 ?
— Punchlinern

9
"6시 9 분? 42시? 나는 항상 우주에 근본적으로 문제가 있다고 말 했어요."더 자세한 설명이 필요하다면 Douglas Adams의 작품을 확인하십시오.
— GordonM

2
오. 나는 42가 대답의 삶, 우주, 그리고 모든 것을 제외하고는 여섯 부분을 아홉 부분으로 놓쳤다는 것을 알고있었습니다. 설명 주셔서 감사합니다!
— Punchlinern


20

define 전역 상수에 사용합니다.

const 클래스 상수에 사용합니다.

define수업 범위에 들어갈 수 없으며 함께 const할 수 있습니다. 말할 것도없이, 당신은 사용할 수 없습니다const 교실 밖에서 .

또한을 사용 const하면 실제로 클래스의 멤버 define가되고을 사용하면 전역 범위로 푸시됩니다.


8
다른 답변에서 언급했듯이 const는 PHP 5.3 이상에서 클래스 외부에서 사용할 수 있습니다.
— MrWhite

const 키워드 만이 클래스뿐만 아니라 네임 스페이스 상수를 생성하는데 사용될 수 있습니다
— Alireza Rahmani Khalili

16

NikiC의 답변이 가장 좋지만 네임 스페이스를 사용할 때 분명하지 않은 경고를 추가하여 예기치 않은 동작에 걸리지 않도록합니다. 기억해야 할 것은 정의 식별자의 일부로 네임 스페이스를 명시 적으로 추가하지 않는 한, 정의는 항상 글로벌 네임 스페이스에 있다는 것 입니다. 분명하지 않은 것은 네임 스페이스 식별자가 글로벌 식별자보다 우선한다는 것입니다. 그래서 :

<?php
namespace foo
{
  // Note: when referenced in this file or namespace, the const masks the defined version
  // this may not be what you want/expect
  const BAR = 'cheers';
  define('BAR', 'wonka');

  printf("What kind of bar is a %s bar?\n", BAR);

  // To get to the define in the global namespace you need to explicitely reference it
  printf("What kind of bar is a %s bar?\n", \BAR);
}

namespace foo2
{
  // But now in another namespace (like in the default) the same syntax calls up the 
  // the defined version!
  printf("Willy %s\n", BAR);
  printf("three %s\n", \foo\BAR);  
}
?>

생산 :

What kind of bar is a cheers bar? 
What kind of bar is a wonka bar?
willy wonka 
three cheers

수십 개의 다른 언어로 된 const의 개념은 코드의 어느 위치에서나 항상 동일하고 PHP가 실제로 그것을 보장하지 않기 때문에 전체 const 개념을 불필요하게 혼란스럽게 만듭니다.


1
그래,하지만 BAR및 \foo\BAR단지입니다 하지 같은 상수. 나는 정말 혼란 동의하지만, 당신은 또한 네임 스페이스 지정 논리가 이런 식으로 일관되고 같은 것들을 고려하고, 어느 쪽도 있다는 경우 const도 define()는 C처럼 매크로 ( #define), 다음 PHP는 어떤 변명을 가질 수 없습니다.
— Sz.

1
const 개념은 정확히 동작하는 방식입니다. 네임 스페이스에 있습니다! 네임 스페이스 식별자없이 원하는 경우 네임 스페이스 외부에서 생성합니다. 이렇게하면 다른 구문을 사용하더라도 클래스에 정의 된 const와 일치하게됩니다. 예, 정의도 다른 방식으로 일관성이 있습니다.
— Gerard ONeill

12

이 답변의 대부분은 틀리거나 절반 만 이야기하고 있습니다.

  1. 네임 스페이스를 사용하여 상수 범위를 지정할 수 있습니다.
  2. 클래스 정의 외부에서 "const"키워드를 사용할 수 있습니다. 그러나 클래스에서와 마찬가지로 "const"키워드를 사용하여 지정된 값은 상수 표현식이어야합니다.

예를 들면 다음과 같습니다.

const AWESOME = 'Bob'; // Valid

나쁜 예 :

const AWESOME = whatIsMyName(); // Invalid (Function call)
const WEAKNESS = 4+5+6; // Invalid (Arithmetic) 
const FOO = BAR . OF . SOAP; // Invalid (Concatenation)

변수 상수를 만들려면 다음과 같이 define ()을 사용하십시오.

define('AWESOME', whatIsMyName()); // Valid
define('WEAKNESS', 4 + 5 + 6); // Valid
define('FOO', BAR . OF . SOAP); // Valid

1
PHP> = 5.6 Zend Engine Compiler에서 일부 변경이 이루어졌으며 const는 현재 다른 방식으로 처리되고 있습니다.
— Ankit Vishwakarma

6

예, const는 컴파일 타임에 정의되며, nikic 상태에 define ()의 can처럼 표현식을 할당 할 수 없기 때문에. 그러나 const도 조건부로 선언 할 수 없습니다 (같은 이유로). 즉. 너는 이것을 못해:

if (/* some condition */) {
  const WHIZZ = true;  // CANNOT DO THIS!
}

define ()으로 할 수있는 반면. 따라서 실제로 개인 취향에 미치지는 않으며, 둘 다 사용하는 정확하고 잘못된 방법이 있습니다.

옆으로 ... 식에 할당 할 수있는 일종의 클래스 const, 클래스에 격리 될 수있는 일종의 define ()을보고 싶습니다.


5

NikiC의 답변을 추가하십시오. const클래스 내에서 다음과 같은 방식으로 사용할 수 있습니다.

class Foo {
    const BAR = 1;

    public function myMethod() {
        return self::BAR;
    }
}

으로이 작업을 수행 할 수 없습니다 define().


4

아무도 php-doc에 대해 아무 말도하지 않지만 나에게 그것은 또한 선호도에 대한 매우 중요한 주장입니다 const.

/**
 * My foo-bar const
 * @var string
 */
const FOO = 'BAR';

0

키워드 상수를 정의하면 대소 문자를 구분하지 않지만 const 키워드를 사용하지 않은 기능을 얻을 수 있습니다.

define("FOO", 1, true);
echo foo; //1
echo "<br/>";
echo FOO; //1
echo "<br/>";

class A {
  const FOO = 1;
}

echo A::FOO; //valid
echo "<br/>";

//but

class B {
  define FOO = 1; //syntax error, unexpected 'define'
}

echo B::FOO; //invalid
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.