【问题标题】:What are namespaces?什么是命名空间?
【发布时间】:2011-03-23 23:44:08
【问题描述】:

什么是 PHP 命名空间?

一般来说什么是命名空间?

带有示例的外行回答会很棒。

【问题讨论】:

  • 谢谢..... ???? ??? ☺️ ????

标签: php namespaces


【解决方案1】:

命名空间对函数和类的作用就像作用域对变量的作用一样。它允许您在同一程序的不同部分使用相同的函数或类名,而不会导致名称冲突。

简单来说,将命名空间视为一个人的姓氏。如果有两个名为“John”的人,您可以使用他们的姓氏来区分他们。

情景

假设您编写的应用程序使用名为output() 的函数。您的 output() 函数获取页面上的所有 HTML 代码并将其发送给用户。

稍后您的应用程序变得更大并且您想要添加新功能。您添加一个允许您生成 RSS 提要的库。这个库还使用了一个名为output() 的函数来输出最终的提要。

当您调用output() 时,PHP 如何知道是使用您的output() 函数还是RSS 库的output() 函数?它没有。 除非你正在使用命名空间。

示例

我们如何解决拥有两个output() 函数的问题?简单的。我们将每个 output() 函数粘贴在自己的 namespace 中。

看起来像这样:

namespace MyProject;

function output() {
    # Output HTML page
    echo 'HTML!';
}

namespace RSSLibrary;

function output(){
    # Output RSS feed
    echo 'RSS!';
}

稍后当我们想要使用不同的功能时,我们会使用:

\MyProject\output();
\RSSLibrary\output();

或者我们可以声明我们在其中一个命名空间中,然后我们可以调用该命名空间的output()

namespace MyProject;

output(); # Output HTML page
\RSSLibrary\output();

没有命名空间?

如果我们没有命名空间,我们必须(可能)在添加库时更改大量代码,或者想出繁琐的前缀来使我们的函数名称独一无二。使用命名空间,我们可以避免在将第三方代码与我们自己的项目混合时出现命名冲突的问题。

【讨论】:

  • 出于某种原因,我认为如果您在 file1 中使用命名空间,您就不必在 file2 中要求或包含该文件。单元测试表明情况并非如此。
  • @AaronBell 你可能想看看autoloading
【解决方案2】:

命名空间允许您将一堆代码放在一个名称下,并且不会与类、函数和常量发生任何命名冲突。

它允许您的代码在该命名空间中存在

PHP 使用somewhat controversial character \ 来显示命名空间级别。人们举起武器,因为它也被用作转义字符。

要在 PHP 中使用命名空间,请在文件顶部使用类似这样的内容。

namespace my\namespace;

您可以在official PHP documentation for namespaces 上找到更多信息。

【讨论】:

    【解决方案3】:

    由于通过了解“命名空间”可以更轻松地了解关键字“使用”,所以让我先通过一个基本的 Laravel 项目来解释命名空间。

    有一个控制器类,名称为:Controller.php,它在路径中: app/Http/Controllers 来自项目的根目录 还有另一个控制器类名为:Controller.php,但这个在路径中: vendor/laravel/framework/src/Illuminate/Routing 来自项目的根目录

    如果你是 php 新手,你不需要看源代码,因为它会让你感到困惑,让我给你解释一下 它是我们关心的并将帮助我们理解“命名空间”和“使用”。

    所以事实上,我们的第一个控制器类: app/Http/Controllers/Controller.php 需要使用 第二个控制器类 vendor/laravel/framework/src/Illuminate/Routing/Controller.php。 它实际上需要扩展这个 Class 才能访问其内容以处理一些关键的路由功能。

    那么一个类如何扩展另一个同名的类呢? class Controller extends Controller? 这行不通, 除非有办法区分这两个类,这就是 namespaceuse 关键字派上用场的地方 有助于完成任务,允许使用; (类;方法;接口和常量),具有相同的名称,在相同的范围内。

    现在它是如何在代码中完成的?非常简单!如果我们查看app/Http/Controllers/Controller.php源代码,我们可以在类的顶部看到 命名空间被声明为:namespace App\Http\Controllers,所以这就是你如何给你的类一个命名空间,这样它就可以被其他类引用 现在这看起来与项目根目录中此类的路径相同,几乎没有区别,那就是使用“\”而不是“/(与 windows 中的命令提示符相同), 但还有另一个区别,那就是命名空间中带有大写“A”的 App 与带有“app”的 路径中的小写“a”。 还要注意命名空间区分大小写。

    所以命名空间是一个独立于路径的概念,如果有帮助,它可以遵循路径结构,但它不必是指向 类、方法、接口或常量 例如看看: vendor/laravel/framework/src/Illuminate/Routing/Controller.php源代码,

    我们在类的顶部看到命名空间被声明为:Illuminate\Routing

    现在让我们看看“use”关键字, 我们使用“use”关键字让我们的类知道我们想在我们的类中使用的特定类或函数

    所以我们没有导入或包含任何内容我们只是让我们的班级知道我们将使用特定的班级或 通过它们的命名空间引用它们的方法 我们来看看app/Http/Controllers/Controller.php源码, 从以下行可以看出:“use Illuminate\Routing\Controller as BaseController”,“use”关键字后跟 namespace 对于目标类 (注意 Illuminate\Routing\Controller.php 和 Illuminate\Routing\Controller ‘没有 .php 扩展名’是可以互换的)

    我们可以使用“as”关键字和“use”关键字来给特定的类、方法、接口或常量一个别名,它允许 app/Http/Controllers/Controller.phpIlluminate\Routing\Controller.php 扩展为 BaseController线: “class Controller extends BaseController”。

    【讨论】:

      【解决方案4】:

      在其他编程语言(如 Java 中的包)中存在诸如命名空间之类的技术。它们习惯于在一个项目中拥有多个同名的类。

      来自 php 文档 (http://www.php.net/manual/en/language.namespaces.rationale.php):

      什么是命名空间?在最广泛的定义中,命名空间是一种封装项目的方式。这在很多地方都可以看作是一个抽象的概念。例如,在任何操作系统中,目录用于对相关文件进行分组,并充当其中文件的命名空间。作为一个具体的例子,文件 foo.txt 可以同时存在于目录 /home/greg 和 /home/other 中,但是 foo.txt 的两个副本不能共存于同一目录中。此外,要访问 /home/greg 目录之外的 foo.txt 文件,我们必须使用目录分隔符将目录名添加到文件名前,以获取 /home/greg/foo.txt。同样的原则也适用于编程世界中的命名空间。

      【讨论】:

      • 与 Java 相比是个坏主意。 Java 有包,也有包可见性类。受保护成员的可见性还取决于访问它的包。
      • 它们不等于包,但它们的思想相同。
      • 这个问题还问到命名空间通常是什么,答案是有道理的。
      • @kiam 他们共享一个想法——不冲突的类名。他们不同意可见性的想法。
      • @Artefacto:Kau-Boy 并没有说两种语言的命名空间是相同的。
      【解决方案5】:

      命名空间就像一个目录。您知道如何将文件放在与父(或任何其他)目录中的文件同名的目录中吗?好吧,命名空间允许您在应用程序中为变量、函数和类执行此操作。

      不久前,PHP 出现了一种趋势,即大型静态函数类。调用任何这些函数的唯一方法是在调用前加上类名。这是对命名空间的原始尝试,但没有太多好处。

      【讨论】:

        【解决方案6】:

        很像目录文件,PHP中的命名空间用于分组函数接口常量

        例子:

        Filesystem      |   PHP Namespace
        ----------------|------------------
        /Dir/File.txt   |  \Namespace\Class
        

        它提供了一种从全局空间包装项目的方法,并允许使用普通项目名称而不会在程序中引起名称冲突。 它在 PHP 5.3.0、PHP 7 中受支持。

        但是 PHP 命名空间和基于 Unix 的文件系统之间的类比存在一些限制:

                                  | Filesystem            |        PHP Namespace
        --------------------------|-----------------------|-------------------------
        Cas sensitive             |       No              |        Yes                
        --------------------------|-----------------------|-------------------------
        Name with plain number    |       Yes             |        No
        --------------------------|-----------------------|-------------------------
        Path level                |       Yes             |        Yes   
        --------------------------|-----------------------|-------------------------
        Plain metacharacters name |       Yes             |        No        
        

        在编程word中原理扩展到命名空间。

        【讨论】:

          【解决方案7】:

          命名空间就像将许多东西打包成一个包。将命名空间想象成一个抽屉,您可以在其中放置各种东西:铅笔、尺子、一张纸等等。为避免使用彼此的物品,您决定在抽屉上贴上标签,以便清楚物品属于谁。

          【讨论】:

            【解决方案8】:

            命名空间基本上可以让您将代码放入容器中。这将防止两个同名的函数(以及类和变量)出现问题。

            这些在处理大型应用程序时很有用,可以防止代码段共享同名的问题。

            例如,假设我们想要两个名为 "TheMessage" 的函数。这两者都会打印(回显)不同的消息。 通常,这会导致语法错误,因为您不能拥有两个同名的函数。

            要解决此问题,您可以将这些函数放入单独的命名空间中。这将允许您使用这两个函数而不会出现任何错误。

            【讨论】:

              【解决方案9】:

              命名空间用于封闭一组代码,以便它们可以在不同的地方使用而不会发生名称冲突。 将此视为 jQuery 无冲突方法,您会更好地理解它。

              【讨论】:

              • “jQuery 无冲突方法”是什么意思?这和 PHP 有什么关系?
              【解决方案10】:

              命名空间是控制程序中名称的简单系统。
              它确保名称是唯一的,不会导致任何冲突。

              【讨论】:

              • 你说的是哪几种“名字”?
              【解决方案11】:

              您可以使用命名空间来避免您创建的代码与内部 PHP 类/函数/常量或第三方类/函数/常量之间的名称冲突。 命名空间还具有别名(或缩短)Extra_Long_Names 的能力,旨在减少第一个问题,提高源代码的可读性。

              众所周知,命名空间和特征在 PHP 中并不新鲜,但仍然有许多 php 开发人员不使用这些伟大的概念,因为它们很复杂。 所以,在这篇文章中。我将尝试通过示例来清除它们。 什么是命名空间和特征?

              如何在代码中实现它们以使代码可重用和可扩展?

              命名空间的好处

              您可以使用命名空间来避免您创建的代码与内部 PHP 类/函数/常量或第三方类/函数/常量之间的名称冲突。

              命名空间还具有别名(或缩短)Extra_Long_Names 的能力,旨在减少第一个问题,提高源代码的可读性。 让我们通过一个例子来理解命名空间。 在 htdocs(xampp) 或 www (xwamp) 中创建文件夹名称“php_oops” 在根目录下创建一个名为“namespaces”的新文件夹,然后在命名空间文件夹下创建一个文件 index.php。

              <?php
              // FilePath:- namespaces/index.php
              
              // let's say, we have two classes in index,
              // here, these two classes have global space
              class A 
              { 
                 function __construct()
                 { 
                    echo "I am at Global space, Class A";
                 }
              }
              class B
              {
                 function __construct()
                 {
                    echo "I am at Global space, Class B";
                 }
              }
              // now create an object of class and 
              $object = new A; // unqualified class name
              echo "<br/>";
              $object = new \B; // fully qualified class name
              // output: 
              I am at Global space, Class A
              I am at Global space, Class B
              

              参考- https://medium.com/@akgarg007/php-laravel-namespaces-and-traits-01-9540fe2969cb

              【讨论】:

              • 请谨慎链接到您自己在不同网站上的内容,您不想成为spammer。您应该在此处包含大部分内容,并且仅将链接用作参考。
              【解决方案12】:

              我们经常需要给资源一个名字,一个可以帮助我们理解和谈论它是什么的标签。但是命名不仅仅是分配一个字符序列的简单任务。名称用于区分一物与另一物。

              即使一个标识符指的是单个资源,但这并不意味着没有两个标识符是相同的。

              我们可以通过 GUID 或添加有关 命名空间 的信息来防止或减少标识符冲突。 namespace 是从中选择名称或标识符的域。当我们将命名空间添加到标识符时,我们会创建一个qualified names

              示例时间!

              假设邮政编码 99501 中只有一个JOHN_SMITH。邮政编码 86302 中也只有一个JOHN_SMITH。那么,当我们提到JOHN_SMITH 时,我们怎么知道我们在说哪个JOHN_SMITH ?

              当我们在邮政编码 99501 的上下文中谈论 JOHN_SMITH 时,我们谈论的是离开邮政编码 99501 的 JOHN_SMITH

              <?php
              
              namespace zc99501;
              
              const JOHN_SMITH = "John Smith from 99501";
              
              ?>
              

              当我们在邮政编码 86302 的上下文中谈论 JOHN_SMITH 时,我们谈论的是离开邮政编码 86302 的 JOHN_SMITH

              <?php
              
              namespace zc86302;
              
              const JOHN_SMITH = "John Smith from 86302";
              
              ?>
              

              现在,如果邮政编码 99501 的一个人和邮政编码 86302 的另一个人想谈论 JOHN_SMITH 他们必须说 99501 的 JOHN_SMITH 这样做了,而 86302 的 JOHN_SMITH 这样做了,会发生什么。

              <?php
              
              namespace zc99501;
              
              const JOHN_SMITH = "John Smith from 99501";
              
              namespace zc86302;
              
              const JOHN_SMITH = "John Smith from 86302";
              
              namespace Test;
              
              echo \zc99501\JOHN_SMITH . PHP_EOL;
              echo \zc86302\JOHN_SMITH . PHP_EOL;
              
              ?>
              

              这里,\zc99501\JOHN_SMITH\zc86302\JOHN_SMITH 是限定名称。

              另一个例子。

              假设在一种情况下,当我们使用常量title 时,我们的意思是Book Title。还有Author Namename

              <?php
              
              namespace Book;
              
              const title = "Don Quixote";
              const name = "Miguel de Cervantes Saavedra";
              
              ?>
              

              在另一种情况下,我们指的是Title of a Charactertitle。还有Character's Namename

              <?php
              
              namespace Character;
              
              const title = "Sir";
              const name = "Sancho Panza";
              
              ?>
              

              当我们在两种情况下都需要titlename 时,我们必须特别区分Book TitleTitle of a Character。我们还要特别区分Author NameCharacter's Name

              <?php
              
              namespace Book;
              
              const title = "Don Quixote";
              const name = "Miguel de Cervantes Saavedra";
              
              namespace Character;
              
              const title = "Sir";
              const name = "Sancho Panza";
              
              namespace Test;
              
              echo \Book\title . PHP_EOL;
              echo \Book\name . PHP_EOL;
              echo \Character\title . PHP_EOL;
              echo \Character\name . PHP_EOL;
              
              ?>
              

              这里,\Book\title\Book\name\Character\title\Character\name 是限定名称。

              注意:在 PHP 中只有四种类型的代码受命名空间影响:类、接口、函数和常量。

              就是这样。

              【讨论】:

                猜你喜欢
                • 2011-04-24
                • 2013-06-04
                • 2013-02-08
                • 2012-06-16
                • 1970-01-01
                相关资源
                最近更新 更多