PHP 7.2.0 Release Candidate 4 Released

SSS: İsim alanları hakkında bilinmesi gerekenler

Bu SSS iki bölüme ayrılır: genel sorular ve isim alanlarını tamamen anlamaya yardımcı olacak gerçeklenime özgü ayrıntılar.

Önce genel sorularla başlıyoruz.

  1. İsim alanlarını kullanmayacak olsam bile bu konuyla yine de ilgilenmeli miyim?
  2. Yerleşik ve küresel sınıfları bir isim alanı içinde nasıl kullanabilirim?
  3. İsim alanlarının sınıflarını, işlevlerini ve sabitlerini kendi isim alanlarında nasıl kullanabilirim?
  4. \bir\isim veya \isim gibi bir isim nasıl çözümlenir?
  5. bir\isim gibi bir isim nasıl çözümlenir?
  6. isim gibi bir nitelenmemiş sınıf ismi nasıl çözümlenir?
  7. isim gibi bir nitelenmemiş işlev veya sabit ismi nasıl çözümlenir?

İsim alanları gerçeklenimini tamamen anlamaya yardımcı olacak gerçeklenime özgü bir kaç ayrıntı vardır.

  1. İthal edilen isimler aynı dosyada tanımlı sınıf isimleriyle çakışmamalıdır.
  2. İç içe isim alanlarına izin verilmez.
  3. use deyimi üzerinden ne işlevler ne de sabitler ithal edilebilir.
  4. Devingen isim alanları isimlerinin (tırnak içine alınmış betimleyiciler) içindeki tersbölülerin öncelenmesi gerekir.
  5. Tersbölü kullanılarak atıf yapılan tanımsız sabitler ölümcül hataya sebep olur.
  6. Özel NULL, TRUE, FALSE, ZEND_THREAD_SAFE ve ZEND_DEBUG_BUILD sabitleri geçersiz kılınamaz.

İsim alanlarını kullanmayacak olsam bile bu konuyla yine de ilgilenmeli miyim?

Hayır. Ne isim alanları mevcut koddan etkilenir ne de isim alanlarını içermeyen kodlar isim alanlarından etkilenir. İsterseniz kodu böyle yazabilirsiniz:

Örnek 1 - Küresel sınıflara bir isim alanı dışından erişim

<?php
$a 
= new \stdClass;

Bu kod şuna eşdeğerdir:

Örnek 2 - Küresel sınıflara bir isim alanı dışından erişim

<?php
$a 
= new stdClass;

Yerleşik ve küresel sınıfları bir isim alanı içinde nasıl kullanabilirim?

Örnek 3 - İsim alanı içinden yerleşik sınıflara erişim

<?php
namespace fan;
$a = new \stdClass;

function 
test(\ArrayObject $typehintexample null) {}

$a = \DirectoryIterator::CURRENT_AS_FILEINFO;

// Bir yerleşik veya küresel sınıfın genişletilmesi
class MyException extends \Exception {}
?>

İsim alanlarının sınıflarını, işlevlerini ve sabitlerini kendi isim alanlarında nasıl kullanabilirim?

Örnek 4 - İsim alanındaki dahili sınıf, işlev ve sabitlere erişim

<?php
namespace fan;

class 
Sınıfım {}

// bir ipucu yazdırmak için geçerli isim alanındaki bir sınıfın kullanımı
function dnm(Sınıfım $biripucuörneği null) {}
// ipucu yazdırmak için geçerli isim alanındaki bir sınıfın başka
// bir yolla kullanımı
function dnm(\fan\Sınıfım $biripucuörneği null) {}

// geçerli isim alanındaki bir sınıfın genişletilmesi
class AltSınıfım extends Sınıfım {}

// bir küresel işleve erişim
$a = \küreselişlev();

// bir küresel sabite erişim
$b = \INI_ALL;
?>

\bir\isim veya \isim gibi bir isim nasıl çözümlenir?

\ ile başlayan isimler daima yazıldıkları gibi çözümlenirler, bu bakımdan \bir\isim aslında bir\isim'dir; \Exception da aslında Exception'dır.

Örnek 5 - Tamamen nitelenmiş isimler

<?php
namespace fan;
$a = new \bir\isim(); // "bir\isim" sınıfını örnekler
echo \strlen('hi');   // "strlen" işlevini çağırır
$a = \INI_ALL;        // $a değişkenine "INI_ALL" sabitinin değeri atanır
?>

bir\isim gibi bir isim nasıl çözümlenir?

Bir tersbölü içeren, ancak tersbölü ile başlamayan bir\isim gibi isimler iki farklı yolla çözümlenebilir.

bir ismini başka bir isimle ithal eden bir deyim varsa bu takma isim bir\isim içindeki bir'e uygulanır.

Aksi takdirde, bir\isim isminin önüne geçerli isim alanı adı getirilir.

Örnek 6 - Nitelenmiş isimler

<?php
namespace fon;
use 
fan\fin as fon;

$a = new bir\isim(); // "fon\bir\isim" sınıfını örnekler
fon\bar::isim(); // "fan\fin\bar" sınıfının "isim" duruk yöntemi çağrılır
bir\bar();        // "fon\bir\bar" işlevi çağrılır
$a bir\BAR;    // $a değişkenine "fon\bir\BAR" sabitinin değeri atanır
?>

isim gibi bir nitelenmemiş sınıf ismi nasıl çözümlenir?

isim gibi tersbölü içermeyen sınıf isimleri 2 farklı yolla çözümlenebilir.

isim ismini başka bir isimle ithal eden bir deyim varsa bu takma isim isim'e uygulanır.

Aksi takdirde, isim ismininin önüne geçerli isim alanı getirilir.

Örnek 7 - Nitelenmemiş sınıf isimleri

<?php
namespace fon;
use 
fan\fin as fon;

$a = new isim(); // "fon\isim" sınıfı örneklenir
fon::isim();     // "fan\fin" sınıfının "isim" duruk yöntemi çağrılır
?>

isim gibi bir nitelenmemiş işlev veya sabit ismi nasıl çözümlenir?

isim gibi tersbölü içermeyen işlev ve sabit isimleri 2 farklı yolla çözümlenebilir.

Önce isim isminin önüne geçerli isim alanı ismi getirilir.

Son olarak, eğer isim alanında isim diye bir işlev veya sabit yoksa ve isim diye bir küresel işlev veya sabit varsa küresel alandaki kullanılır.

Örnek 8 - Nitelenmemiş işlev veya sabit isimleri

<?php
namespace fon;
use 
fan\fin as fon;

const 
FON 1;

function 
bir() {}
function 
fon() {}
function 
sort(&$a)
{
    
sort($a);
    
$a array_flip($a);
    return 
$a;
}

bir(); // "fon\bir" çarılır
$a strlen('hi');  // "fon\strlen" mevcut olmadığından küresel
                    // "strlen" işlevi çağrılır
$arr = array(1,3,2);
$b sort($arr);    // "fon\sort" işlevi çağrılır
$c fon(); // "fon\fon" işlevi çağrılır - ithal işlemi uygulanmaz

$a FON;     // $a değişkenine "fon\FON" sabitinin değeri
              // atanır - ithal işlemi uygulanmaz
$b INI_ALL// $b değişkenine "INI_ALL" küresel sabitinin değeri atanır
?>

İthal edilen isimler aynı dosyada tanımlı sınıf isimleriyle çakışmamalıdır.

Aşağıdaki iki betik birlikte kurallara uygundur:

dosya1.php

<?php
namespace bir\isim;
class 
Sınıfım {}
?>

dosya2.php

<?php
namespace diğer;
class 
BirŞey {}
?>

dosya.php

<?php
namespace bir\isim;
include 
'dosya1.php';
include 
'dosya2.php';

use 
diğer\BirŞey as Sınıfım;
$a = new Sınıfım// "diğer" isim alanındaki "BirŞey" sınıfını örnekler
?>

Sınıfım sınıfı bir\isim isim alanında mevcut olduğu halde Sınıfım ayrı bir dosyada tanımlandığından herhangi bir isim çakışması olmaz. Ancak, sonraki örnekte, Sınıfım sınıfı use deyimi ile aynı dosyada tanımlandığından isim çakışmasından dolayı ölümcül hata oluşur.

<?php
namespace bir\isim;
use 
diğer\BirŞey as Sınıfım;
class 
Sınıfım {} // ölümcül hata: Sınıfım ithal edilen sınıfla çakışır
$a = new Sınıfım;
?>

İç içe isim alanlarına izin verilmez.

PHP isim alanlarının böyle iç içe tanımlanmasına izin vermez:

<?php
namespace bir\isim {
    namespace 
içiçe {
        class 
fan {}
    }
}
?>
Bununla birlikte, isim alanlarını birbirinin içinde şöyle tanımlamak mümkündür:
<?php
namespace bir\isim\içiçe {
    class 
fan {}
}
?>

use deyimi üzerinden ne işlevler ne de sabitler ithal edilebilir.

use deyimlerinden sadece isim alanları ve sınıf isimleri etkilenir. Uzunca bir işlev veya sabit ismini kısaltmak için kendilerini içeren isim alanını ithal etmeniz yeterlidir.

<?php
namespace benimki;
use 
epeyce\fazla\uzun\isim;

$a isim\SABİT;
isim\işlev();
?>

Devingen isim alanları isimlerinin (tırnak içine alınmış betimleyiciler) içindeki tersbölülerin öncelenmesi gerekir.

Tersbölü imi dizgelerin içinde bir önceleme karakteri olarak kullanıldığından çift tırnaklar arasına alınmış bir dizge içindeki bir tersbölü karakterinin tersbölü ile öncelenmesi gerekir. Aksi takdirde, istenmeyen durumlar ortaya çıkabilir:

Örnek 9 - İsim alanlı isimleri çift tırnaklar arasında kullanmak tehlikelidir

<?php
$a 
= new "tehlikeli\nesne"// \n, çift tırnaklı dizge içinde
                            // satırsonu karakteridir!
$obj = new $a;

$a = new 'bu\tamamen\tehlikesiz\nesne'// burada sorun yok.
$obj = new $a;
?>
Tersbölüleri tek tırnakları arasına alınmış bir dizge içinde kullanmak daha güvenli olsa da her iki dizge türünde de tersbölüleri öncelemek en güvenlisidir.

Tersbölü kullanılarak atıf yapılan tanımsız sabitler ölümcül hataya sebep olur.

FAN gibi nitelenmemiş olarak tanımsız sabitlere rastlandığında PHP, bunun FAN değerli bir sabit varsayıldığını belirten bir uyarı üretecektir. İster nitelenmiş olsun ister tamamen nitelenmiş olsun tanımsız bir sabit daima ölümcül hataya sebep olur.

Örnek 10 - Tanımsız sabitler

<?php
namespace bar;
$a FAN;  // uyarı üretir - "FAN" sabit olarak tanımsız olduğundan
           // bir sabit ismi değil, bir sabit değer olarak ele alınır.
$a = \FAN;     // ölümcül hata, isim alanlı tanımsız sabit: FAN
$a Fin\FAN;  // ölümcül hata, isim alanlı tanımsız sabit: bar\Fin\FAN
$a = \Fin\FAN// ölümcül hata, isim alanlı tanımsız sabit: Fin\FAN
?>

Özel NULL, TRUE, FALSE, ZEND_THREAD_SAFE ve ZEND_DEBUG_BUILD sabitleri geçersiz kılınamaz.

Bir özel, yerleşik sabiti bir isim alanlı sabit olarak tanımlamaya kalkışmak ölümcül hatayla sonuçlanır.

Örnek 11 - Tanımsız sabitler

<?php
namespace bar;
const 
NULL 0;       // ölümcül hata;
const true 'ahmak'// bu da ölümcül hata;
// etc.
?>

add a note add a note

User Contributed Notes 5 notes

up
17
manolachef at gmail dot com
5 years ago
There is a way to define a namespaced constant that is a special, built-in constant, using define function and setting the third parameter case_insensitive to false:

<?php
namespace foo;
define(__NAMESPACE__ . '\NULL', 10); // defines the constant NULL in the current namespace
var_dump(NULL); // will show 10
var_dump(null); // will show NULL
?>

  No need to specify the namespace in your call to define(), like it happens usually
<?php
namespace foo;
define(INI_ALL, 'bar'); // produces notice - Constant INI_ALL already defined. But:

define(__NAMESPACE__ . '\INI_ALL', 'bar'); // defines the constant INI_ALL in the current namespace
var_dump(INI_ALL); // will show string(3)"bar". Nothing unespected so far. But:

define('NULL', 10); // defines the constant NULL in the current namespace...
var_dump(NULL); // will show 10
var_dump(null); // will show NULL
?>

  If the parameter case_insensitive is set to true
<?php
namespace foo;
define (__NAMESPACE__ . '\NULL', 10, true); // produces notice - Constant null already defined
?>
up
2
shaun at slickdesign dot com dot au
1 year ago
When creating classes or calling static methods from within namespaces using variables, you need to keep in mind that they require the full namespace in order for the appropriate class to be used; you CANNOT use an alias or short name, even if it is called within the same namespace. Neglecting to take this into account can cause your code to use the wrong class, throw a fatal missing class exception, or throw errors or warnings.

In these cases, you can use the magic constant __NAMESPACE__, or specify the full namespace and class name directly. The function class_exists also requires the full namespace and class name, and can be used to ensure that a fatal error won't be thrown due to missing classes.

<?php

namespace Foo;
class
Bar {
    public static function
test() {
        return
get_called_class();
    }
}

namespace
Foo\Foo;
class
Bar extends \Foo\Bar {
}

var_dump( Bar::test() ); // string(11) "Foo\Foo\Bar"

$bar = 'Foo\Bar';
var_dump( $bar::test() ); // string(7) "Foo\Bar"

$bar = __NAMESPACE__ . '\Bar';
var_dump( $bar::test() ); // string(11) "Foo\Foo\Bar"

$bar = 'Bar';
var_dump( $bar::test() ); // FATAL ERROR: Class 'Bar' not found or Incorrect class \Bar used
up
1
phpcoder
2 years ago
Regarding "Neither functions nor constants can be imported via the use statement." Actually you can do it in PHP 5.6+:

<?php

// importing a function (PHP 5.6+)
use function My\Full\functionName;

// aliasing a function (PHP 5.6+)
use function My\Full\functionName as func;

// importing a constant (PHP 5.6+)
use const My\Full\CONSTANT;
?>
up
1
teohad at NOSPAM dot gmail dot com
1 year ago
[Editor's note: that behavior is caused by a bug in PHP 7.0, which has been fixed as of PHP 7.0.7.]

Regarding the entry "Import names cannot conflict with classes defined in the same file".
- I found that since PHP 7.0 this is no longer the case.
In PHP 7.0 you can have a class with a name that matches an imported class (or namespace or both at the same time).

<?php
namespace ns1 {
  class
ns1 {
    public static function
write() {
      echo
"ns1\\ns1::write()\n";
    }
  }
}

namespace
ns1\ns1 {
  class
ns1c {
    public static function
write() {
      echo
"ns1\\ns1\\ns1c::write()\n";
    }
  }
}

namespace
ns2 {
  use
ns1\ns1 as ns1; // both a class in ns1, and a namespace ns1\ns1
   
  // the next class causes fatal error in php 5.6, not in 7.0
 
class ns1 {
    public static function
write() {
      echo
"ns2\\ns1::write()\n";
    }
  }
   
 
ns1::write(); // calls imported ns1\ns1::write()
 
ns1\ns1c::write(); // calls imported ns1\ns1\ns1c::write()
 
namespace\ns1::write(); // calls ns2\ns1::write()
}
?>
up
-1
okaresz
4 years ago
To correct manolachef's answer: define() ALWAYS defines constants in the GLOBAL namespace.

As nl-x at bita dot nl states in the note at http://www.php.net/manual/en/function.define.php, the constant "NULL" can be defined with define() case-sensitively, but can only be retrieved with constant(), leaving the meaning of NULL uppercase keyword as the only value of the type null.
To Top