cons () ile tanımla


659

PHP'de ne zaman kullanılır?

define('FOO', 1);

ve ne zaman kullanıyorsun

const FOO = 1;

?

Bu ikisi arasındaki temel farklar nelerdir?


4
Performans hakkında (benim gibi mikro optimizasyon ile zaman kaybı), şu cevaba bakın : constiki kat daha hızlıdır define. Sayfa yükleme süresi ve bellek kullanımı hakkında: bu soruya ve bu makaleye bakın ... Ayrıca burada opcode önbellek ile ilgili bir şeye bakın .
Peter Krauss

2
Sadece geçerli kabul edilen cevaba bakmayın, lütfen kabul edilen cevap olması gerektiği için stackoverflow.com/a/3193704/1412157 adresine bakın
LucaM

1
Yorumunuz için bildirimi gördüm. Kabul edilen cevabı güncelledim.
danjarvis

Yanıtlar:


1039

PHP 5.3'ten itibaren sabitleri tanımlamanın iki yolu vardır : Ya constanahtar sözcüğü kullanarak ya da define()işlevi kullanarak :

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

Bu iki yol arasındaki temel fark const, sabitleri derleme zamanında definetanımlarken, onları çalışma zamanında tanımlamasıdır. Bu, constdezavantajlarının çoğuna neden olur . Bazı dezavantajları const:

  • constkoşullu olarak sabitleri tanımlamak için kullanılamaz. Küresel bir sabit tanımlamak için en dış kapsamda kullanılması gerekir:

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

    Bunu neden yapmak istiyorsun ki? Yaygın bir uygulama, sabitin önceden tanımlanmış olup olmadığını kontrol etmektir:

    if (!defined('FOO')) {
        define('FOO', 'BAR');
    }
  • constStatik bir sayıl (sayı, dize ya da benzeri diğer sabit kabul true, false, null, __FILE__), oysa define()herhangi bir ifade alır. PHP 5.6 sabit ifadelerine de izin verildiğinden const:

    const BIT_5 = 1 << 5;    // Valid since PHP 5.6 and invalid previously
    define('BIT_5', 1 << 5); // Always valid
  • constdüz sabit bir ad alırken define(), herhangi bir ifadeyi ad olarak kabul eder. Bu, bunun gibi şeyler yapmanıza izin verir:

    for ($i = 0; $i < 32; ++$i) {
        define('BIT_' . $i, 1 << $i);
    }
  • consts her zaman büyük / küçük harfe duyarlıdır, oysa büyük / define()küçük harf duyarlı olmayan sabitleri trueüçüncü argüman olarak ileterek tanımlamanıza izin verir (Not: büyük / küçük harfe duyarlı olmayan sabitleri tanımlamak PHP 7.3.0'dan itibaren kullanımdan kaldırılmıştır):

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

Yani, işlerin kötü tarafı buydu. Şimdi const, yukarıdaki durumlardan biri meydana gelmedikçe kişisel olarak her zaman neden kullanmamın nedenine bakalım :

  • constsadece daha güzel okur. Bir işlev yerine bir dil yapısıdır ve ayrıca sınıflardaki sabitleri nasıl tanımladığınızla tutarlıdır.
  • const, bir dil yapısı olan, otomatik takımlama ile statik olarak analiz edilebilir.
  • constdefine()tam ad alanı adının geçirilmesi gerekirken , geçerli ad alanında bir sabit tanımlar :

    namespace A\B\C;
    // To define the constant A\B\C\FOO:
    const FOO = 'BAR';
    define('A\B\C\FOO', 'BAR');
  • PHP 5.6 constsabitleri de diziler olabileceğinden, define()henüz dizileri desteklemez. Ancak, PHP 7'de her iki durum için de diziler desteklenecektir.

    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

Son olarak, constbir sınıf sabitini veya arabirim sabitini tanımlamak için sınıf veya arabirim içinde de kullanılabileceğini unutmayın . definebu amaçla kullanılamaz:

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

özet

Herhangi bir koşullu veya ifade tanımına ihtiyacınız olmadığı sürece, consts yerine s kullanın define()- sadece okunabilirlik uğruna!


1
Ben PHP 5.6 ile bildiği gibi bile basit sayıl ifadeler kullanmayı olasılığını alırsınız constdil yapısının - bkz wiki.php.net/rfc/const_scalar_exprs
mabe.berlin

6
Kullanmanın bir başka yararı da consttırnak eksikliğidir, yani IDE'nizde kullanıldığı yerde biçimlendirilir.
rybo111

3
PHP belgelerinde olan bu olmalıdır. Gördüğüm en iyi açıklama, özellikle de çoğu insanın unuttuğu kısım (derleme ve çalışma zamanı).
James

4
define('a', $_GET['param']);, const b = a;mükemmel çalışır ve const c = $_GET['param'];geçersizken değeri alır . Mı constgerçekten derleme zamanı? Ben pek öyle düşünmüyorum ... (PHP 7.0.7 üzerinde test edilmiştir)
mcserep

1
wiki.php.net/rfc/case_insensitive_constant_deprecation " PHP 8.0'da: Büyük / küçük harfe duyarlı olmayan sabitleri bildirme olasılığını kaldırın. " Burada, büyük / küçük harfe duyarlılık konusunda geleceğe girişimde bulunan herkes için
Scuzzy

196

PHP 5.3'e kadar const, global kapsamda kullanılamadı. Bunu sadece bir sınıf içinden kullanabilirsiniz. Bu, o sınıfa ait bir tür sabit seçenek veya ayar ayarlamak istediğinizde kullanılmalıdır. Ya da belki bir tür enum yaratmak istersiniz.

defineaynı amaç için kullanılabilir, ancak yalnızca global kapsamda kullanılabilir. Yalnızca tüm uygulamayı etkileyen genel ayarlar için kullanılmalıdır.

İyi bir constkullanım örneği, sihirli sayılardan kurtulmaktır. PDO'nun sabitlerine bir göz atın . Bir getirme türü belirtmeniz gerektiğinde PDO::FETCH_ASSOC, örneğin yazarsınız. Consts kullanılmasaydı, sonunda 35(ya da FETCH_ASSOColarak tanımlanan herhangi bir şey) yazmak zorunda kalırsınız . Bu okuyucu için bir anlam ifade etmiyor.

İyi bir definekullanım örneği, uygulamanızın kök yolunu veya kitaplığın sürüm numarasını belirtmektir.


12
Ad constalanlarıyla kullanımından bahsetmeye değer olabilir .
Mart'ta salathe

31
PHP5.3'ün küresel kapsamda const'u çok fazla kullanabileceği de not edilmelidir.
Gordon

5.2 de olabilir. Sabitlerin ve tanımların güzelliği, onları sınıf adının önüne eklemeniz gerektiğidir. Bunları kullanmak kodu daha okunaklı ve güzel hale getirir. Ve bu benim için bir bonus.
Aralık'ta lucifurious

1
@ryeguy ama PHP 5.3'ten sonra const global olarak nasıl tanımlanabilir?
andho

1
@andho, bir adım ileri, bir adım geri, "iyileştirmeler" dansı PHP dans başka bir tebeşir. O. :)
Prof. Falken sözleşmesi

37

Bunun zaten cevaplandığını biliyorum, ancak mevcut cevapların hiçbiri ad boşluklarından ve sabitleri ve tanımları nasıl etkilediğinden bahsetmiyor.

PHP 5.3 itibariyle, sabitler ve tanımlar çoğu bakımdan benzerdir. Ancak yine de bazı önemli farklılıklar vardır:

  • Sabitler bir ifadeden tanımlanamaz. const FOO = 4 * 3;çalışmıyor ama çalışıyor define('CONST', 4 * 3);.
  • Geçirilen adı definead içermesi gerektiğini ad içinde tanımlanacak.

Aşağıdaki kod farklılıkları göstermelidir.

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

namespace {
    var_dump(get_defined_constants(true));
}

Kullanıcı alt dizisinin içeriği olacaktır ['foo\\BAR' => 1, 'BAZ' => 2, 'foo\\BAZ' => 3].

=== GÜNCELLEME ===

Yaklaşan PHP 5.6, biraz daha esneklik sağlayacaktır const. Artık, bu ifadelerin diğer sabitlerden veya değişmez ifadelerden oluşması koşuluyla, ifadeleri ifade ederek tanımları tanımlayabileceksiniz. Bu, aşağıdakilerin 5.6'dan itibaren geçerli olması gerektiği anlamına gelir:

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;

Gereksinimleri yine de değişkenler veya işlev getirileri açısından tanımlayamazsınız, bu nedenle

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

hala dışarıda olacak.


8
Sormaya direnemedim: Bilinçli FORTY_TWOolarak 54 olarak tanımladınız mı?
Punchlinern

9
"Altıdan dokuza? Kırk iki? Her zaman evrende temelde bir sorun olduğunu söylemiştim" Tam bir açıklamaya ihtiyacınız varsa Douglas Adams'ın çalışmalarına bakın.
GordonM

2
Ah. 42'nin cevap hayatı, evren ve her şey olduğunun farkındaydım, ama Altı'yı dokuz parça kaçırmıştım. Açıklama için teşekkürler!
Punchlinern


20

define Global sabitler için kullanıyorum.

const Sınıf sabitleri için kullanıyorum.

Yapamazsınız defineile sınıf kapsam içine ve constbunu yapabilirsiniz. Söylemeye gerek yok, constdış sınıf kapsamını kullanamazsınız .

Ayrıca, constaslında sınıfın bir üyesi haline gelir ve bununla birlikte defineküresel kapsama itilir.


8
Diğer cevaplarda belirtildiği gibi, const PHP 5.3 ve sonraki sürümlerinde sınıf dışında kullanılabilir
MrWhite

Yalnızca sınıflar değil, ad boşluklu bir sabit oluşturmak için yalnızca const anahtar sözcüğü kullanılabilir
Alireza Rahmani Khalili

16

NikiC'nin cevabı en iyisidir, ancak isim alanlarını kullanırken açık olmayan bir uyarı eklememe izin verin, böylece beklenmedik davranışlarla yakalanmıyorsunuz. Hatırlamanız gereken şey , ad alanını tanımlayıcı tanımlayıcının bir parçası olarak açıkça eklemediğiniz sürece , tanımların her zaman genel ad alanında olmasıdır. Bu konuda açık olmayan şey, ad boşluklu tanımlayıcının genel tanımlayıcıyı aşmasıdır. Yani :

<?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);  
}
?>

üretir:

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

Benim için tüm const kavramını gereksiz yere kafa karıştırıcı yapar çünkü onlarca başka dilde bir const fikri, kodunuzda nerede olursanız olun her zaman aynıdır ve PHP bunu gerçekten garanti etmez.


1
Evet ama BARve \foo\BARsadece vardır değil aynı sabitleri. Gerçekten kafa karıştırıcı olduğunu kabul ediyorum, ancak aynı zamanda ad boşlukları mantığı gibi şeylerin bu şekilde tutarlı olduğunu düşünürseniz ve bu ne bir C makrosu ( ) ne constde ne olursa olsun , PHP'nin bir mazereti olabilir. define()#define
Sz.

1
Const nosyonu tam olarak davranması gerektiği şekildedir - bir isim alanındasınız! Ad alanı tanımlayıcısı olmadan istediğiniz, sonra ad alanının dışında oluşturun .. Bu da farklı sözdizimi kullansa bile, bir sınıfta tanımlanan const ile tutarlı hale getirir. Evet, tanım da farklı bir şekilde tutarlıdır.
Gerard ONeill

12

Bu cevapların çoğu yanlış veya hikayenin sadece yarısını anlatıyor.

  1. Ad alanlarını kullanarak sabitlerinizi kapsamlandırabilirsiniz.
  2. Sınıf tanımlarının dışında "const" anahtar sözcüğünü kullanabilirsiniz. Ancak, tıpkı sınıflarda olduğu gibi, "const" anahtar sözcüğü kullanılarak atanan değerlerin sabit ifadeler olması gerekir.

Örneğin:

const AWESOME = 'Bob'; // Valid

Kötü örnek:

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

Değişken sabitleri oluşturmak için define () öğesini şu şekilde kullanın:

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

1
PHP> = 5.6 Zend Engine Compiler'da bazı değişiklikler yapıldı ve const şimdi başka bir şekilde işlem görüyor.
Ankit Vishwakarma

6

Evet, const derleme zamanında tanımlanır ve nikic durumlara tanım () 'ın yapabileceği gibi bir ifade atanamaz. Fakat aynı zamanda const'ler şartlı olarak beyan edilemez (aynı nedenden dolayı). yani. Bunu yapamazsın:

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

Halbuki bir define () ile yapabilirsiniz. Yani, kişisel tercihe inmiyor, her ikisini de kullanmanın doğru ve yanlış bir yolu var.

Bir kenara ... Ben bir ifade atanabilir bir tür sınıf const, sınıflara izole edilebilir bir tür define () görmek ister misiniz?


5

NikiC'nin cevabına eklemek için. constsınıflar içerisinde aşağıdaki şekilde kullanılabilir:

class Foo {
    const BAR = 1;

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

Bunu ile yapamazsın define().


4

Kimse php-doc hakkında bir şey söylemez, ama benim için bu da aşağıdakilerin tercihi için çok önemli bir argüman const:

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

0

Tanımlama anahtar kelime sabiti ile, büyük / küçük harfe duyarlı olmayan tesisler elde edersiniz, ancak const anahtar kelimesi ile almazsınız.

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.