ホームページ > バックエンド開発 > PHPチュートリアル > PHP名前空間の詳しい使い方

PHP名前空間の詳しい使い方

小云云
リリース: 2023-03-20 15:08:01
オリジナル
2452 人が閲覧しました

名前空間の最も明確な目的の 1 つは、重複した名前の問題を解決することです。PHP では、2 つの関数またはクラスが同じ名前を持つことを許可しません。そうしないと、致命的なエラーが発生します。この場合、名前の重複を避ける限り解決できます。最も一般的な方法は、プレフィックスを合意することです。

例: プロジェクトには記事とメッセージボードの 2 つのモジュールがあり、それぞれにユーザーのコメントを処理するクラス Comment があります。後で、すべてのユーザー メッセージの情報統計関数を追加する場合があります。たとえば、すべてのメッセージの数を取得したいとします。この時点で、Comment によって提供されるメソッドを呼び出すことは良い考えですが、それぞれの Comment クラスを同時に導入することは明らかに不可能であり、コードでエラーが発生し、Comment を別の場所に書き換えるとエラーが発生します。メンテナンス性が低下します。次に、クラス名をリファクタリングするだけで、次のようにクラス名の前にモジュール名を追加するという名前付けルールに同意しました。将来的には、より多くのコード (少なくともより多くの文字) が記述される予定です。さらに、将来的に各モジュールに統合関数を追加したり、相互に呼び出したりする場合は、名前が重複した場合に名前を再構築する必要があります。もちろん、プロジェクトの開始時にこの問題に気づき、名前付けルールを指定することで、この問題は回避できます。別の解決策は、名前空間を使用することです。

注:

この記事で説明されている定数: PHP5.3 以降、const キーワードはクラスの外で使用できるようになりました。 const と define はどちらも定数の宣言に使用されます (その違いについては詳しく説明しません) が、名前空間では、define はグローバルに機能するのに対し、const は現在の空間に対して機能します。記事内で言及した定数は、const を使用して宣言された定数を指します。

基本

名前空間は、コードを異なる空間(領域)に分割します。各空間の定数、関数、クラスの名前(面倒なので、以下では要素と呼びます)は相互に影響を与えません。私たちがよく行うこと 「カプセル化」の概念について言及しました。


名前空間を作成するには、次のように namespace キーワードを使用する必要があります:

次のようにコードをコピーします:

<?php//创建一个名为&#39;Article&#39;的命名空间namespace Article;?>
ログイン後にコピー

現在のスクリプト ファイルの最初の名前空間の前にコードを置くことはできないことに注意してください。次の記述は間違っています: 次のようにコードをコピーします:


//例 1

//スクリプトの前にロジック コードを書きます

<?php$path = "/";class Comment { }namespace Article;?>
ログイン後にコピー

//例 2//スクリプトの前にいくつかの文字を出力します

<html></html><?php
    namespace Article;?>
ログイン後にコピー

なぜ最初のことを言うのですか? 名前空間についてはどうですか?同じスクリプト ファイル内に複数の名前空間を作成できるためです。

以下の 2 つの名前空間を作成し、これら 2 つの空間のそれぞれに Comment クラス要素を追加しました:

次のようにコードをコピーします:

<?php//创建一个名为&#39;Article&#39;的命名空间namespace Article;//此Comment属于Article空间的元素class Comment { }//创建一个名为&#39;MessageBoard&#39;的命名空间namespace MessageBoard;//此Comment属于MessageBoard空间的元素class Comment { }?>
ログイン後にコピー

異なる空間間で他の要素を直接呼び出すことはできません。名前空間を使用する必要があります。 構文: Copyコードは次のとおりです:

<?phpnamespace Article;class Comment { }namespace MessageBoard;class Comment { }//调用当前空间(MessageBoard)的Comment类$comment = new Comment();//调用Article空间的Comment类$article_comment = new \Article\Comment();?>
ログイン後にコピー

メッセージボードスペースの記事スペースでCommentクラスを呼び出す際に、ファイルパスのような構文が使用されていることがわかります: スペース名 要素名

クラスに加えて、関数と定数は同じです。以下では、2 つのスペースに新しい要素を作成し、その値をメッセージボード スペースに出力します。

次のようにコードをコピーします:

<?phpnamespace Article;const PATH = &#39;/article&#39;;function getCommentTotal() {
    return 100;
}class Comment { }namespace MessageBoard;const PATH = &#39;/message_board&#39;;function getCommentTotal() {
    return 300;
}class Comment { }//调用当前空间的常量、函数和类echo PATH; ///message_boardecho getCommentTotal(); //300$comment = new Comment();//调用Article空间的常量、函数和类echo \Article\PATH; ///articleecho \Article\getCommentTotal(); //100$article_comment = new \Article\Comment();?>
ログイン後にコピー

それから、Article スペースの要素データを取得しました。

サブスペース

ネームスペースの呼び出し構文はファイル パスに似ており、これによりサブスペースをカスタマイズして各空間間の関係を記述することができます。


申し訳ありませんが、2 つのモジュールの記事と掲示板が実際には同じブログ プロジェクト内にあることを言い忘れていました。名前空間を使用してそれらの関係を表現すると、次のようになります:

次のようにコードをコピーします:

<?php//我用这样的命名空间表示处于blog下的article模块namespace Blog\Article;class Comment { }//我用这样的命名空间表示处于blog下的message board模块namespace Blog\MessageBoard;class Comment { }//调用当前空间的类$comment = new Comment();//调用Blog\Article空间的类$article_comment = new \Blog\Article\Comment();?>
ログイン後にコピー

さらに、サブスペースは、BlogArticleArchivesDate

パブリックスペースなど、多くのレベルを定義することもできます

common_inc.php スクリプトファイルがあります。 inside いくつかの便利な関数とクラスがあります:

次のようにコードをコピーします:

<?phpfunction getIP() { }class FilterXSS { }?>
ログイン後にコピー

このスクリプトを名前空間に導入すると、スクリプト内の要素はこの名前空間に属しません。このスクリプトで他の名前空間が定義されていない場合、その要素は常にパブリック スペースにあります: 次のようにコードをコピーします:

<?phpnamespace Blog\Article;//引入脚本文件include &#39;./common_inc.php&#39;;$filter_XSS = new FilterXSS(); //出现致命错误:找不到Blog\Article\FilterXSS类$filter_XSS = new \FilterXSS(); //正确?>
ログイン後にコピー

パブリック スペースを呼び出す方法は、要素名の前に直接追加することです。それ以外の場合は、 PHP パーサーは、現在のスペースの下にある要素を呼び出したいと考えます。カスタム要素に加えて、PHP 独自の要素も含まれており、それらはすべてパブリック スペースに属します。

実際、パブリックスペースの関数と定数は追加しなくても通常通り呼び出すことができますが(なぜPHPがこれを行うのか理解できません)、要素を正しく区別するために

を追加することをお勧めします。関数を呼び出すときの名前用語

。エイリアスを設定してインポートする前に、スペースの 3 つの名前の用語と、PHP がそれらを解析する方法を理解しておく必要があります。公式ドキュメントは非常に優れているので、そのまま使用しました。


1. 非修飾名、またはプレフィックスのないクラス名 ($comment = new Comment(); など)。現在の名前空間が BlogArticle の場合、Comment は BlogArticleComment として解析されます。コメントを使用するコードに名前空間 (グローバル空間) のコードが含まれていない場合、コメントはコメントとして解析されます。

2.限定名称,或包含前缀的名称,例如 $comment = new Article\Comment();。如果当前的命名空间是Blog,则Comment会被解析为Blog\Article\Comment。如果使用Comment的代码不包含在任何命名空间中的代码(全局空间中),则Comment会被解析为Comment。

3.完全限定名称,或包含了全局前缀操作符的名称,例如 $comment = new \Article\Comment();。在这种情况下,Comment总是被解析为代码中的文字名(literal name)Article\Comment。

其实可以把这三种名称类比为文件名(例如 comment.php)、相对路径名(例如 ./article/comment.php)、绝对路径名(例如 /blog/article/comment.php),这样可能会更容易理解。

我用了几个示例来表示它们:
复制代码代码如下:

<?php//创建空间Blognamespace Blog;class Comment { }//非限定名称,表示当前Blog空间//这个调用将被解析成 Blog\Comment();$blog_comment = new Comment();//限定名称,表示相对于Blog空间//这个调用将被解析成 Blog\Article\Comment();$article_comment = new Article\Comment(); //类前面没有反斜杆\//完全限定名称,表示绝对于Blog空间//这个调用将被解析成 Blog\Comment();$article_comment = new \Blog\Comment(); //类前面有反斜杆\//完全限定名称,表示绝对于Blog空间//这个调用将被解析成 Blog\Article\Comment();$article_comment = new \Blog\Article\Comment(); //类前面有反斜杆\//创建Blog的子空间Articlenamespace Blog\Article;class Comment { }?>
ログイン後にコピー

其实之前我就一直在使用非限定名称和完全限定名称,现在它们终于可以叫出它们的名称了。

别名和导入
别名和导入可以看作是调用命名空间元素的一种快捷方式。PHP并不支持导入函数或常量。

它们都是通过使用use操作符来实现:
复制代码代码如下:

<?phpnamespace Blog\Article;class Comment { }//创建一个BBS空间(我有打算开个论坛)namespace BBS;//导入一个命名空间use Blog\Article;//导入命名空间后可使用限定名称调用元素$article_comment = new Article\Comment();//为命名空间使用别名use Blog\Article as Arte;//使用别名代替空间名$article_comment = new Arte\Comment();//导入一个类use Blog\Article\Comment;//导入类后可使用非限定名称调用元素$article_comment = new Comment();//为类使用别名use Blog\Article\Comment as Comt;//使用别名代替空间名$article_comment = new Comt();?>
ログイン後にコピー

我注意到,如果导入元素的时候,当前空间有相同的名字元素将会怎样?显然结果会发生致命错误。

例:
复制代码代码如下:

<?phpnamespace Blog\Article;class Comment { }namespace BBS;class Comment { }Class Comt { }//导入一个类use Blog\Article\Comment;$article_comment = new Comment(); //与当前空间的Comment发生冲突,程序产生致命错误//为类使用别名use Blog\Article\Comment as Comt;$article_comment = new Comt(); //与当前空间的Comt发生冲突,程序产生致命错误?>
ログイン後にコピー

动态调用
PHP提供了namespace关键字和NAMESPACE魔法常量动态的访问元素,NAMESPACE可以通过组合字符串的形式来动态访问:
复制代码代码如下:

<?phpnamespace Blog\Article;const PATH = &#39;/Blog/article&#39;;class Comment { }//namespace关键字表示当前空间echo namespace\PATH; ///Blog/article$comment = new namespace\Comment();//魔法常量__NAMESPACE__的值是当前空间名称echo __NAMESPACE__; //Blog\Article//可以组合成字符串并调用$comment_class_name = __NAMESPACE__ . &#39;\Comment&#39;;$comment = new $comment_class_name();?>
ログイン後にコピー

字符串形式调用问题

上面的动态调用的例子中,我们看到了字符串形式的动态调用方式,如果要使用这种方式要注意两个问题。

  1. 使用双引号的时候特殊字符可能被转义
    复制代码代码如下:

<?phpnamespace Blog\Article;class name { }//我是想调用Blog\Article\name$class_name = __NAMESPACE__ . "\name"; //但是\n将被转义为换行符$name = new $class_name(); //发生致命错误?>
ログイン後にコピー
  1. 不会认为是限定名称

PHP在编译脚本的时候就确定了元素所在的空间,以及导入的情况。而在解析脚本时字符串形式调用只能认为是非限定名称和完全限定名称,而永远不可能是限定名称。
复制代码代码如下:

<?phpnamespace Blog;//导入Common类use Blog\Article\Common;//我想使用非限定名称调用Blog\Article\Common$common_class_name = &#39;Common&#39;;//实际会被当作非限定名称,也就表示当前空间的Common类,但我当前类没有创建Common类$common = new $common_class_name(); //发生致命错误:Common类不存在//我想使用限定名称调用Blog\Article\Common$common_class_name = &#39;Article\Common&#39;;//实际会被当作完全限定名称,也就表示Article空间下的Common类,但我下面只定义了Blog\Article空间而不是Article空间$common = new $common_class_name(); //发生致命错误:Article\Common类不存在namespace Blog\Article;class Common { }?>
ログイン後にコピー

总结
我对PHP的命名空间刚刚接触,也不能随便给一些没有实践的建议。我个人认为命名空间的作用和功能都很强大,如果要写插件或者通用库的时候再也不用担心重名问题。不过如果项目进行到一定程度,要通过增加命名空间去解决重名问题,我觉得工作量不会比重构名字少。也不得不承认它的语法会对项目增加一定的复杂度,因此从项目一开始的时候就应该很好的规划它,并制定一个命名规范。

相关推荐:

PHP命名空间、性状与生成器详解

php命名空间用法详解

实例详解PHP命名空间用法

以上がPHP名前空間の詳しい使い方の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート