PHP.mk документација

Правила за резолуција на имиња

Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.

language.namespaces.rules.php PHP.net прокси Преводот се освежува
Оригинал на PHP.net
Патека language.namespaces.rules.php Локална патека за оваа страница.
Извор php.net/manual/en Оригиналниот HTML се реупотребува и локално се стилизира.
Режим Прокси + превод во позадина Кодовите, табелите и белешките остануваат читливи во истиот тек.
Правила за резолуција на имиња

Референца за `language.namespaces.rules.php` со подобрена типографија и навигација.

language.namespaces.rules.php

Правила за резолуција на имиња

(PHP 5 >= 5.3.0, PHP 7, PHP 8)

За целите на овие правила за резолуција, еве неколку важни дефиниции:

Дефиниции на имиња на простори
Неквалификувано име

Ова е идентификатор без разделувач на простор, како на пр. Foo

Квалификувано име

Ова е идентификатор со разделувач на простор, како на пр. Foo\Bar

Целосно квалификувано име

Ова е идентификатор со разделувач на простор што започнува со разделувач на простор, како на пр. \Foo\Bar. Просторниот простор \Foo исто така е целосно квалификувано име.

Релативно име

Ова е идентификатор што започнува со namespace, како на пр. namespace\Foo\Bar.

Имињата се решаваат следејќи ги овие правила за резолуција:

  1. Целосно квалификуваните имиња секогаш се решаваат до името без водечкиот разделувач на простор. На пример \A\B се решава до A\B.
  2. Релативните имиња секогаш се решаваат до името со namespace се заменува со тековниот простор. Ако името се појави во глобалниот простор, namespace\ префиксот се отстранува. На пример namespace\A внатре во именскиот простор X\Y се решава до X\Y\A. Истото име во глобалниот именски простор се решава на A.
  3. За квалификувани имиња, првиот сегмент од името се преведува според тековната табела за увоз на класи/именски простори. На пример, ако именскиот простор A\B\C се увезе како C, името C\D\E се преведува на A\B\C\D\E.
  4. За квалификувани имиња, ако не важи правило за увоз, тековниот именски простор се додава на почетокот на името. На пример, името C\D\E внатре во именскиот простор A\B, се решава на A\B\C\D\E.
  5. За неквалификувани имиња, името се преведува според тековната табела за увоз за соодветниот тип симбол. Ова значи дека имињата слични на класи се преведуваат според табелата за увоз на класи/именски простори, имињата на функциите според табелата за увоз на функции и константите според табелата за увоз на константи. На пример, по use A\B\C; употреба како new C() се решава на името A\B\C(). Слично, по use function A\B\foo; употреба како foo() се решава на името A\B\foo.
  6. За неквалификувани имиња, ако не важи правило за увоз и името се однесува на симбол сличен на класа, тековниот именски простор се додава на почетокот. На пример new C() внатре во именскиот простор A\B се решава на името A\B\C.
  7. За неквалификувани имиња, ако не важи правило за увоз и името се однесува на функција или константа и кодот е надвор од глобалниот именски простор, името се решава при извршување. Претпоставувајќи дека кодот е во именскиот простор A\B, еве како се решава повик до функција foo() :
    1. Бара функција од тековниот именски простор: A\B\foo().
    2. Се обидува да ја најде и повика global function foo().

Пример #1 Илустрирани решенија на имиња

<?php
namespace A;
use
B\D, C\E as F;

// function calls

foo(); // first tries to call "foo" defined in namespace "A"
// then calls global function "foo"

\foo(); // calls function "foo" defined in global scope

my\foo(); // calls function "foo" defined in namespace "A\my"

F(); // first tries to call "F" defined in namespace "A"
// then calls global function "F"

// class references

new B(); // creates object of class "B" defined in namespace "A"
// if not found, it tries to autoload class "A\B"

new D(); // using import rules, creates object of class "D" defined in namespace "B"
// if not found, it tries to autoload class "B\D"

new F(); // using import rules, creates object of class "E" defined in namespace "C"
// if not found, it tries to autoload class "C\E"

new \B(); // creates object of class "B" defined in global scope
// if not found, it tries to autoload class "B"

new \D(); // creates object of class "D" defined in global scope
// if not found, it tries to autoload class "D"

new \F(); // creates object of class "F" defined in global scope
// if not found, it tries to autoload class "F"

// static methods/namespace functions from another namespace

B\foo(); // calls function "foo" from namespace "A\B"

B::foo(); // calls method "foo" of class "B" defined in namespace "A"
// if class "A\B" not found, it tries to autoload class "A\B"

D::foo(); // using import rules, calls method "foo" of class "D" defined in namespace "B"
// if class "B\D" not found, it tries to autoload class "B\D"

\B\foo(); // calls function "foo" from namespace "B"

\B::foo(); // calls method "foo" of class "B" from global scope
// if class "B" not found, it tries to autoload class "B"

// static methods/namespace functions of current namespace

A\B::foo(); // calls method "foo" of class "B" from namespace "A\A"
// if class "A\A\B" not found, it tries to autoload class "A\A\B"

\A\B::foo(); // calls method "foo" of class "B" from namespace "A"
// if class "A\B" not found, it tries to autoload class "A\B"
?>

Белешки од корисници 6 белешки

kdimi
пред 15 години
If you like to declare an __autoload function within a namespace or class, use the spl_autoload_register() function to register it and it will work fine.
rangel
пред 16 години
The term "autoload" mentioned here shall not be confused with __autoload function to autoload objects. Regarding the __autoload and namespaces' resolution I'd like to share the following experience:

->Say you have the following directory structure:

- root
      | - loader.php 
      | - ns
             | - foo.php

->foo.php

<?php
namespace ns;
class foo
{
    public $say;
    
    public function __construct()
    {
        $this->say = "bar";
    }
    
}
?>

-> loader.php

<?php
//GLOBAL SPACE <--
function __autoload($c)
{
    require_once $c . ".php";
}

class foo extends ns\foo // ns\foo is loaded here
{
    public function __construct()
    {
        parent::__construct();
        echo "<br />foo" . $this->say;
    }
}
$a = new ns\foo(); // ns\foo also loads ns/foo.php just fine here.
echo $a->say;   // prints bar as expected.
$b = new foo;  // prints foobar just fine.
?>

If you keep your directory/file matching namespace/class consistence the object __autoload works fine.
But... if you try to give loader.php a namespace you'll obviously get fatal errors. 
My sample is just 1 level dir, but I've tested with a very complex and deeper structure. Hope anybody finds this useful.

Cheers!
safakozpinar на NOSPAM точка gmail точка com
пред 15 години
As working with namespaces and using (custom or basic) autoload structure; magic function __autoload must be defined in global scope, not in a namespace, also not in another function or method.

<?php
namespace Glue {
    /**
     * Define your custom structure and algorithms
     * for autoloading in this class.
     */
    class Import
    {
        public static function load ($classname)
        {
            echo 'Autoloading class '.$classname."\n";
            require_once $classname.'.php';
        }
    }
}

/**
 * Define function __autoload in global namespace.
 */
namespace {
    
    function __autoload ($classname)
    {
        \Glue\Import::load($classname);
    }

}
?>
llmll
пред 11 години
The mentioned filesystem analogy fails at an important point:

Namespace resolution *only* works at declaration time. The compiler fixates all namespace/class references as absolute paths, like creating absolute symlinks.

You can't expect relative symlinks, which should be evaluated during access -> during PHP runtime.

In other words, namespaces are evaluated like __CLASS__ or self:: at parse-time. What's *not* happening, is the pendant for late static binding like static:: which resolves to the current class at runtime.

So you can't do the following:

namespace Alpha;
class Helper {
    public static $Value = "ALPHA";
}
class Base {
    public static function Write() { 
        echo Helper::$Value;
    }
}

namespace Beta;
class Helper extends \Alpha\Helper {
    public static $Value = 'BETA';
}    
class Base extends \Alpha\Base {}    

\Beta\Base::Write(); // should write "BETA" as this is the executing namespace context at runtime.

If you copy the write() function into \Beta\Base it works as expected.
Kavoir.com
12 години пред
For point 4, "In example, if the namespace A\B\C is imported as C" should be "In example, if the class A\B\C is imported as C".
anrdaemon на freemail точка ru
пред 10 години
Namespaces may be case-insensitive, but autoloaders most often do.
Do yourself a service, keep your cases consistent with file names, and don't overcomplicate autoloaders beyond necessity.
Something like this should suffice for most times:

<?php

namespace org\example;

function spl_autoload($className)
{
  $file = new \SplFileInfo(__DIR__ . substr(strtr("$className.php", '\\', '/'), 11));
  $path = $file->getRealPath();
  if(empty($path))
  {
    return false;
  }
  else
  {
    return include_once $path;
  }
}

\spl_autoload_register('\org\example\spl_autoload');
?>
На оваа страница

Автоматски outline од активната документација.

Насловите ќе се појават тука по вчитување.

Попрегледно читање

Примерите, changelog табелите и user notes се визуелно издвоени за да не се губат во долгата содржина.

Брз совет Користи го outline-от Скокни директно на главните секции од активната страница.
Извор Оригиналниот линк останува достапен Кога ти треба целосен upstream context, отвори го PHP.net во нов tab.