Constantes Mágicas

O PHP fornece um grande número de consntantes predefinidas para qualquer script que ele execute. A maioria dessas constantes, entretanto, são criadas por várias extensões, e somente estarão presentes quando essas extensões estiverem disponíveis, tanto por carregamento dinâmico quanto por compilação direta.

Há sete constantes "mágicas", que mudam dependendo de onde elas são utilizadas. Por exemplo, o valor de __LINE__ depende do número da linha em que é utilizada em seu script. Essas constantes especiais são insensíveis a maiúsculas e minúsculas (case insensitive):

Algumas constantes "mágicas" do PHP
Nome Descrição
__LINE__ A linha atual do script.
__FILE__ O caminho completo e nome do arquivo. Se utilizado dentro de um include, o nome do arquivo incluído será retornado. Desde o PHP 4.0.2, __FILE__ sempre contém um caminho absoluto com links simbólicos resolvidos enquanto em versões antigas ela continha um caminho relativo sob certas circunstâncias.
__DIR__ O diretório do arquivo. Se usado dentro de um include, o diretório do arquivo incluído é retornado. Isto é equivalente a dirname(__FILE__). Este nome do diretório não possui barra no final, a não ser que seja o diretório raiz. (Adicionado no PHP 5.3.0.)
__FUNCTION__ O nome da função (Acrescentado no PHP 4.3.0). A partir do PHP 5 esta constante retorna o nome da função como ela foi declarada (sensível a maiúsculas e minúsculas). No PHP 4 sempre retorna o nome em minúsculas.
__CLASS__ O nome da classe (Adicionado no PHP 4.3.0). A partir do PHP 5 esta constante retorna o nome da função como ela foi declarada (sensível a maiúsculas e minúsculas). No PHP 4 sempre retorna o nome em minúsculas. O nome da classe inclui o namespace em que foi declarado (ex: Foo\Bar). Note que a partir do PHP 5.4, __CLASS__ funciona também em traits. Quando utilizada em um método trait, __CLASS__ é o nome da classe do trait em que foi utilizada.
__TRAIT__ O nome do trait. (Adicionado no PHP 5.4.0) A partir do PHP 5.4 essa constante retorna o trait em que fo delcarado (sensível a maiúsculas e minúsculas). O nome do trait incluir o namespace em que foi declarado (ex: Foo\Bar).
__METHOD__ O nome do método de classe. (Adicionado no PHP 5.0.0). O nome do método é retornado como foi declarado (sensível a maiúsculas e minúsculas).
__NAMESPACE__ O nome do namespace atual (sensível a maiúsculas e minúsculas). Esta constante é definida em tempo de compilação (Adicionada no PHP 5.3.0).

Veja também get_class(), get_object_vars(), file_exists() and function_exists().

add a note add a note

User Contributed Notes 17 notes

up
61
vijaykoul_007 at rediffmail dot com
9 years ago
the difference between
__FUNCTION__ and __METHOD__ as in PHP 5.0.4 is that

__FUNCTION__ returns only the name of the function

while as __METHOD__ returns the name of the class alongwith the name of the function

class trick
{
      function doit()
      {
                echo __FUNCTION__;
      }
      function doitagain()
      {
                echo __METHOD__;
      }
}
$obj=new trick();
$obj->doit();
output will be ----  doit
$obj->doitagain();
output will be ----- trick::doitagain
up
8
raat1979 at gmail dot com
1 year ago
Magic constants can not be tested with defined($name)

<?php
   
if(!defined(__DIR__)){
       
//will not work
   
}
?>

when __DIR__ is not defined and you use it anyway php assumes you meant '__DIR__' and  throws a notice.
because of this assumption we can do:

<?php
if(@__DIR__ == '__DIR__'){
    echo
'magic __DIR__ constant NOT defined';
  
//insert this code where needed, remember that because they are MAGIC constants defining __DIR__ is completely useless
}echo{
    echo
'magic __DIR__ constant IS defined';
 
}

?>
up
4
meindertjan at gmail dot spamspamspam dot com
9 months ago
A lot of notes here concern defining the __DIR__ magic constant for PHP versions not supporting the feature. Of course you can define this magic constant for PHP versions not yet having this constant, but it will defeat its purpose as soon as you are using the constant in an included file, which may be in a different directory then the file defining the __DIR__ constant. As such, the constant has lost its *magic*, and would be rather useless unless you assure yourself to have all of your includes in the same directory.

Concluding: eye catchup at gmail dot com's note regarding whether you can or cannot define magic constants is valid, but stating that defining __DIR__ is not useless, is not!
up
4
chris dot kistner at gmail dot com
3 years ago
There is no way to implement a backwards compatible __DIR__ in versions prior to 5.3.0.

The only thing that you can do is to perform a recursive search and replace to dirname(__FILE__):
find . -type f -print0 | xargs -0 sed -i 's/__DIR__/dirname(__FILE__)/'
up
4
david at thegallagher dot net
2 years ago
You cannot check if a magic constant is defined. This means there is no point in checking if __DIR__ is defined then defining it. `defined('__DIR__')` always returns false. Defining __DIR__ will silently fail in PHP 5.3+. This could cause compatibility issues if your script includes other scripts.

Here is proof:

<?php
echo (defined('__DIR__') ? '__DIR__ is defined' : '__DIR__ is NOT defined' . PHP_EOL);
echo (
defined('__FILE__') ? '__FILE__ is defined' : '__FILE__ is NOT defined' . PHP_EOL);
echo (
defined('PHP_VERSION') ? 'PHP_VERSION is defined' : 'PHP_VERSION is NOT defined') . PHP_EOL;
echo
'PHP Version: ' . PHP_VERSION . PHP_EOL;
?>

Output:
__DIR__ is NOT defined
__FILE__ is NOT defined
PHP_VERSION is defined
PHP Version: 5.3.6
up
2
skoobiedu at gmail dot com
10 months ago
What eyecatchup and I posted are good one-liners, but they are fundamentally flawed. Magic constants cannot be defined in a backward-compatible manner in PHP code because the value of a magic constant is defined at run-time based on the current context.

__DIR__ is defined relative to the current file. If you define it in one file using the method that I or eyecatchup posted, then the value is dependant upon the location of the file where it is defined.

Example:
* directory structure:
/dir/other/other_dir.php
/dir/define_dir.php
/dir/same_dir.php
/parent_dir.php

* /dir/define_dir.php
<?php
/**
* Ensure the __DIR__ constant is defined for PHP 4.0.6 and newer.
*/
(@__DIR__ == '__DIR__') && define('__DIR__', realpath(dirname(__FILE__)));
?>

* /dir/same_dir.php
<?php
require('define_dir.php');

echo
'function: ' . realpath(dirname(__FILE__)) . "\n";
echo
' __DIR__: ' . __DIR__ . "\n";
?>

* /dir/other/other_dir.php
<?php
require('../define_dir.php');

echo
'function: ' . realpath(dirname(__FILE__)) . "\n";
echo
' __DIR__: ' . __DIR__ . "\n";
?>

* /parent_dir.php
<?php
require('dir/define_dir.php');

echo
'function: ' . realpath(dirname(__FILE__)) . "\n";
echo
' __DIR__: ' . __DIR__ . "\n";
?>

*** OUTPUT: PHP 5.2.17 ***
same_dir.php:
function: /dir
__DIR__: /dir

other_dir.php:
function: /dir/other
__DIR__: /dir

parent_dir.php:
function: /
__DIR__: /dir

As you can see, only when the running script is in the same directory as the file that defines __DIR__, will __DIR__ have the correct value.

You could use the following function:
<?php
function abspath($file)
{
  return
realpath(dirname($file));
}
?>

And call it like so wherever you would use __DIR__:
<?php
abspath
(__FILE__);
?>

Magic constants are fickle creatures.
up
3
skoobiedu at gmail dot com
11 months ago
__DIR__ is actually equivalent to realpath(dirname(__FILE__)).

Here's a modified version of the one-liner eyecatchup at gmail dot com[1] wrote:

<?php
// ensure the __DIR__ constant is defined for PHP 4.0.6 and newer
(@__DIR__ == '__DIR__') && define('__DIR__', realpath(dirname(__FILE__)));
?>

Their version also works on PHP 4.0.6, but doesn't use realpath. __DIR__ is an absolute path to the current file.

[1] http://www.php.net/manual/en/language.constants.predefined.php#113233
up
2
eyecatchup at gmail dot com
1 year ago
As pointed out by david at thegallagher dot net[1], you can NOT use the defined() function to check if a *magic* constant is defined.  Often seen, but will not work:
<?php
   
if (!defined('__MAGIC_CONSTANT__')) {
       
// FAIL! even if __MAGIC_CONSTANT__ is defined,
        // defined('__MAGIC_CONSTANT__') will ALWAYS return (bool)false.
   
}
?>

Now, raat1979 at gmail dot com[2] pointed out a solution to check if a magic constant is defined or not (which actually works reliable). Thanks to dynamic typecasting in PHP, if a constant lookup fails PHP interprets the given constant name as string (note that a notice is thrown nonetheless. thus, use "@" to suppress it).
<?php
    var_dump
(@UNDEFINED_CONSTANT_NAME);  //prints: string(23) "UNDEFINED_CONSTANT_NAME"
?>

Meaning we can check for all constants - including magic constants (eg __DIR__) - as follows:
<?php
   
if (@__DIR__ == '__DIR__'){
       
// __DIR__ was interpreted as string. thus, (magic) constant __DIR__ is not defined.
   
}
?>

However, what is wrong in raat1979 at gmail dot com's note[2] is this comment:
> "remember that because they are MAGIC constants defining __DIR__ is completely useless"

In fact, you *can* define magic constants (as long as they haven't been defined before, of course).

Based on all I've read and tested today, here is my code I use to make the `__DIR__` magic constant work with all PHP versions (4.3.1 - 5.5.3):
<?php
   
// Ensure that PHP's magic constant __DIR__ is defined - no matter of the PHP version.

    // If magic __DIR__ constant is not defined, define it.
   
(@__DIR__ == '__DIR__') && define('__DIR__', dirname(__FILE__));

   
// All PHP versions (>= 4.3.1) can use the magic __DIR__ constant now..
    // Demo (outputs and VLD opcodes) here: http://3v4l.org/bm6e1
?>

[1] http://us2.php.net/manual/en/language.constants.predefined.php#107614
[2] http://us2.php.net/manual/en/language.constants.predefined.php#113130
up
0
eldy at destailleur dot fr
23 days ago
Using __METHOD__ always return class name the function belong to. But in some cases (like to make log output), if class B1, B2, B3 inherit class A and call a method of class A, you may would like to see into log which class among B1, B2, B3 is calling.

For example you would like to see:

B1::commond_method_inside_framework
and not
A::commond_method_inside_framework

because you know that common_method_inside_framework is inside common inherited class A.

To solve this, replace __METHOD__ with get_class($this).'::'.__FUNCTION__

class A
    {
        function commond_method_inside_framework()
        {
            echo "This is class " . get_class($this).'::'.__FUNCTION__.' '. __METHOD__.' '."\n";
        }
    }

class B1 extends A
    {
        function commond_method_inside_caller()
        {
            echo "This is class " . get_class($this).'::'.__FUNCTION__.' '. __METHOD__.' '."\n";
        }
    }

    $a = new A();
    $a->commond_method_inside_framework();  

    $b = new B1();
    $b->commond_method_inside_framework();

    $b->commond_method_inside_caller();
?>

Result will be

This is class A::commond_method_inside_framework A::commond_method_inside_framework
This is class B1::commond_method_inside_framework A::commond_method_inside_framework
This is class B1::commond_method_inside_caller B1::commond_method_inside_caller
up
0
user at NOSPAM dot example dot com
1 month ago
__CLASS__ has caused me some confusion before. If you extend from a class that calls __CLASS__ in a function, __CLASS__ will refer to the parent class  and not the extending class.

<?php
   
class A
   
{       
        function
sayClassFromObjectA()
        {
            echo
"<br/>This is class " . __CLASS__;
        }
    }
   
    class
B extends A
   
{
        function
sayClassFromObjectB()
        {
            echo
"<br/>This is class " . __CLASS__;
        }
    }
   
   
$b = new B();
   
   
//I expect it to output "This is class B".
   
$b->sayClassFromObjectA();    //Outputs "This is class A"       
   
   
    //I expect it to output "This is class B".
   
$b->sayClassFromObjectB();    //Outputs "This is class B"   
?>
up
0
php at kenman dot net
7 months ago
Just learned an interesting tidbit regarding __FILE__ and the newer __DIR__ with respect to code run from a network share: the constants will return the *share* path when executed from the context of the share.

Examples:

// normal context
// called as "php -f c:\test.php"
__DIR__ === 'c:\';
__FILE__ === 'c:\test.php';

// network share context
// called as "php -f \\computerName\c$\test.php"
__DIR__ === '\\computerName\c$';
__FILE__ === '\\computerName\c$\test.php';

NOTE: realpath('.') always seems to return an actual filesystem path regardless of the execution context.
up
0
user9 at voloreport dot com
3 years ago
Note that __FILE__ has a quirk when used inside an eval() call. It will tack on something like "(80) : eval()'d code" (the number may change) on the end of the string at run-time. The workaround is:

$script = php_strip_whitespace('myprogram.php');
$script = str_replace('__FILE__',"preg_replace('@\(.*\(.*$@', '', __FILE__,1)",$script);
eval($script);
up
0
madboyka at yahoo dot com
4 years ago
Since namespace were introduced, it would be nice to have a magic constant or function (like get_class()) which would return the class name without the namespaces.

On windows I used basename(__CLASS__). (LOL)
up
0
php at kennel17 dot co dot uk
7 years ago
Further to my previous note, the 'object' element of the array can be used to get the parent object.  So changing the get_class_static() function to the following will make the code behave as expected:

<?php
   
function get_class_static() {
       
$bt = debug_backtrace();
   
        if (isset(
$bt[1]['object']))
            return
get_class($bt[1]['object']);
        else
            return
$bt[1]['class'];
    }
?>

HOWEVER, it still fails when being called statically.  Changing the last two lines of my previous example to

<?php
  foo
::printClassName();
 
bar::printClassName();
?>

...still gives the same problematic result in PHP5, but in this case the 'object' property is not set, so that technique is unavailable.
up
0
Tomek Perlak [tomekperlak at tlen pl]
8 years ago
The __CLASS__ magic constant nicely complements the get_class() function.

Sometimes you need to know both:
- name of the inherited class
- name of the class actually executed

Here's an example that shows the possible solution:

<?php

class base_class
{
    function
say_a()
    {
        echo
"'a' - said the " . __CLASS__ . "<br/>";
    }

    function
say_b()
    {
        echo
"'b' - said the " . get_class($this) . "<br/>";
    }

}

class
derived_class extends base_class
{
    function
say_a()
    {
       
parent::say_a();
        echo
"'a' - said the " . __CLASS__ . "<br/>";
    }

    function
say_b()
    {
       
parent::say_b();
        echo
"'b' - said the " . get_class($this) . "<br/>";
    }
}

$obj_b = new derived_class();

$obj_b->say_a();
echo
"<br/>";
$obj_b->say_b();

?>

The output should look roughly like this:

'a' - said the base_class
'a' - said the derived_class

'b' - said the derived_class
'b' - said the derived_class
up
-2
Anonymous
2 years ago
Further clarification on the __TRAIT__ magic constant.

<?php
trait PeanutButter {
    function
traitName() {echo __TRAIT__;}
}

trait
PeanutButterAndJelly {
    use
PeanutButter;
}

class
Test {
    use
PeanutButterAndJelly;
}

(new
Test)->traitName(); //PeanutButter
?>
up
-1
claude at NOSPAM dot claude dot nl
10 years ago
Note that __CLASS__ contains the class it is called in; in lowercase. So the code:

class A
{
    function showclass()
    {
        echo __CLASS__;
    }
}

class B extends A
{
}

$a = new A();
$b = new B();

$a->showclass();
$b->showclass();
A::showclass();
B::showclass();

results in "aaaa";
To Top