Use of the PHP namespace of Namespace

  • 2020-06-01 09:00:20
  • OfStack

For namespaces, the official documentation has been very detailed [view], and I have done a practice and summary here.

One of the most explicit purposes of namespace 1 is to solve the problem of multiple names. PHP does not allow two functions or classes to have the same name, otherwise a fatal error will be generated. In this case, as long as the name duplication is avoided, the most common one is to agree on a prefix.

Example: there are two modules in the project: article and message board, each with a class Comment for handling user comments. Then I might want to add some statistics for all user comments, like I want to get the number of all comments. It is good practice to call the methods provided by their Comment, but introducing their respective Comment classes at the same time is obviously not the way to go, the code will go wrong, and overwriting any Comment in another place will reduce the maintainability. At this point, you can only refactor the class name. I made a convention to add the module name before the class name, like this: Article_Comment, MessageBoard_Comment

As you can see, the name has become very long, which means more code (or at least more characters) will be written when using Comment in the future. In addition, if you want to add more integration functions to each module or call each other in the future, you will need to refactor the name when the name is changed. Of course, taking note of this problem at the beginning of the project and having a naming convention is a good way to avoid it. Another solution to consider is to use namespaces.


Note:

The constants mentioned in this article: the PHP5.3 start const keyword can be used outside of a class. Both const and define are used to declare constants (the difference will not be detailed), but in namespaces, define ACTS globally, while const ACTS in the current space. The constants I refer to in this article are constants declared using const.


basis
Namespaces divide code into different Spaces (regions) where the names of constants, functions, and classes (which I'll refer to as elements for the sake of laziness) don't matter, a bit like the familiar notion of 'encapsulation.'

To create a namespace, use the namespace keyword:


<?php
// create 1 called 'Article' The namespace of 
namespace Article;
?>

Note that the first namespace of the current script file cannot have any code in front of it, and the following is all wrong:

// case 1
// Written in front of the script 1 Some logic code 
<?php
$path = "/";
class Comment { }
namespace Article;
?>
 
// case 2
// Output in front of the script 1 Some characters 
<html></html>
<?php
namespace Article;
?>

Why do we say the first namespace? Because you can create multiple namespaces in the same script file.

Here I create two namespaces and add an Comment element to each of them:


<?php
// create 1 called 'Article' The namespace of 
namespace Article;
// this Comment Belong to Article Elements of space 
class Comment { }

// create 1 called 'MessageBoard' The namespace of 
namespace MessageBoard;
// this Comment Belong to MessageBoard Elements of space 
class Comment { }
?>

You cannot call other elements directly between different Spaces. You need to use the syntax of the namespace:

<?php
namespace Article;
class Comment { }

namespace MessageBoard;
class Comment { }
// Call current space ( MessageBoard ) Comment class 
$comment = new Comment();
// call Article Of the space Comment class 
$article_comment = new \Article\Comment();
?>

As you can see, when calling the Comment class in article space, you use a syntax that looks like a file path: \ space name \ element name

With the exception of classes, the usage of functions and constants is the same. Here I create new elements for two Spaces and output their values in the MessageBoard space.


<?php
namespace Article;
const PATH = '/article';
function getCommentTotal() {
    return 100;
}
class Comment { }

namespace MessageBoard;
const PATH = '/message_board';
function getCommentTotal() {
    return 300;
}
class Comment { }
// Calls the constants, functions, and classes of the current space 
echo PATH; ///message_board
echo getCommentTotal(); //300
$comment = new Comment();
// call Article Space constants, functions, and classes 
echo \Article\PATH; ///article
echo \Article\getCommentTotal(); //100
$article_comment = new \Article\Comment();
?>

And then I did get the element data for the Article space.


subspace
It makes sense that the namespace invocation syntax is like file path 1, which allows us to customize subspaces to describe the relationships between the Spaces.

Sorry I forgot to mention that both modules article and message board are actually in the same blog project. If you use a namespace to express their relationship, it looks like this:


<?php
// I'm going to use a namespace that looks like this to represent theta blog Under the article The module 
namespace Blog\Article;
class Comment { }

// I'm going to use a namespace that looks like this to represent theta blog Under the message board The module 
namespace Blog\MessageBoard;
class Comment { }
// Calls the class of the current space 
$comment = new Comment();
// call Blog\Article Space of the class 
$article_comment = new \Blog\Article\Comment();
?>

Furthermore, subspaces can be defined at many levels, such as Blog\Article\Archives\Date


The public space
I have an common_inc.php script file with some useful functions and classes:


<?php
function getIP() { }
class FilterXSS { }
?>

If you introduce this script into a namespace, elements in the script will not belong to that namespace. If no other namespace is defined in the script, its elements are always in the public space:

<?php
namespace Blog\Article;
// Import script file 
include './common_inc.php';
$filter_XSS = new FilterXSS(); // Fatal error: not found Blog\Article\FilterXSS class 
$filter_XSS = new \FilterXSS(); // correct 
?>

The way to call the public space is to simply put an \ before the element name, otherwise the PHP parser will think I want to call the element in the current space. In addition to the custom elements, PHP also includes its own elements, which belong to the public space.

To mention 1, public space functions and constants can be called without adding \ (I don't know why PHP is doing this), but it is recommended to add \ when calling functions in order to distinguish elements correctly


The name of the term
Before you talk about aliases and imports, you need to know the terminology for the three names of Spaces and how PHP parses them. The official documentation was so good that I went straight for it.

1. An unqualified name, or a class name that does not contain a prefix, such as $comment = new Comment(); . If the current namespace is Blog\Article, Comment will be resolved to Blog\Article\Comment. If the code that USES Comment is not included in any namespace (in the global space), Comment is resolved to Comment.

2. Qualified name, or name with prefix, e.g. $comment = new Article\Comment(); . If the current namespace is Blog, Comment will be resolved to Blog\Article\Comment. If the code that USES Comment is not included in any namespace (in the global space), Comment is resolved to Comment.

3. Fully qualified name, or name that contains a global prefix operator, such as $comment = new \Article\Comment(); . In this case, Comment is always resolved to the literal name in the code (literal name)Article\Comment.

Can actually put this three name analogy for the file name (for example comment. php), relative path names (for example)/article comment) php), absolute path name (for example/blog article/comment php), it may be easier to understand.

I've used a few examples to represent them:


<?php
// To create a space Blog
namespace Blog;
class Comment { }
// Unqualified name, indicating current Blog space 
// This call will be parsed to  Blog\Comment();
$blog_comment = new Comment();
// Qualified name, indicating relative to Blog space 
// This call will be parsed to  Blog\Article\Comment();
$article_comment = new Article\Comment(); // There is no backdip bar in front of the class \
// Fully qualified name, indicating absolute Blog space 
// This call will be parsed to  Blog\Comment();
$article_comment = new \Blog\Comment(); // Class has an anticline bar in front of it \
// Fully qualified name, indicating absolute Blog space 
// This call will be parsed to  Blog\Article\Comment();
$article_comment = new \Blog\Article\Comment(); // Class has an anticline bar in front of it \

// create Blog The subspace Article
namespace Blog\Article;
class Comment { }
?>

I've been using unqualified names and fully qualified names before, but now they can finally call them.


Aliases and imports
Aliases and imports can be thought of as a shortcut to calling namespace elements. PHP does not support importing functions or constants.

They are implemented using the use operator:


<?php
namespace Blog\Article;
class Comment { }

// create 1 a BBS Space (I was thinking of opening a forum) 
namespace BBS;
// The import 1 Individual namespaces 
use Blog\Article;
// After importing a namespace, you can call an element with a qualified name 
$article_comment = new Article\Comment();
// Use aliases for namespaces 
use Blog\Article as Arte;
// Use aliases instead of space names 
$article_comment = new Arte\Comment();
// The import 1 A class 
use Blog\Article\Comment;
// After importing the class, you can call the element with an unqualified name 
$article_comment = new Comment();
// Use aliases for classes 
use Blog\Article\Comment as Comt;
// Use aliases instead of space names 
$article_comment = new Comt();
?>

I noticed what happens if you import an element and the current space has the same name element? Obviously the result is going to be a fatal error.

Ex. :


<?php
namespace Blog\Article;
class Comment { }

namespace BBS;
class Comment { }
Class Comt { }

// The import 1 A class 
use Blog\Article\Comment;
$article_comment = new Comment(); // With the current space Comment A collision occurred and the program produced a fatal error 
// Use aliases for classes 
use Blog\Article\Comment as Comt;
$article_comment = new Comt(); // With the current space Comt A collision occurred and the program produced a fatal error 
?>

The dynamic invocation
PHP provides a dynamic access element with the namespace keyword and the s 179en__ magic constant. S 180en__ can be accessed dynamically by combining strings:

<?php
namespace Blog\Article;
const PATH = '/Blog/article';
class Comment { }

//namespace The keyword represents the current space 
echo namespace\PATH; ///Blog/article
$comment = new namespace\Comment();
// Magic constant __NAMESPACE__ Is the current space name 
echo __NAMESPACE__; //Blog\Article
// Can be combined into strings and called 
$comment_class_name = __NAMESPACE__ . '\Comment';
$comment = new $comment_class_name();
?>

String invocation problem

In the dynamic invocation example above, we saw a dynamic invocation in the form of a string. There are two problems to be aware of if you want to use this method.

1. Special characters may be escaped when using double quotation marks


<?php
namespace Blog\Article;
class name { }
// I want to call Blog\Article\name
$class_name = __NAMESPACE__ . "\name"; // but \n Will be escaped as a newline character 
$name = new $class_name(); // Fatal error 
?>

2. Not considered qualified

PHP determines where the element is and what happens when it is imported when the script is compiled. When parsing scripts, string-style calls can only be thought of as unqualified and fully qualified names, and can never be qualified names.


<?php
namespace Blog;
// The import Common class 
use Blog\Article\Common;
// I want to call it with an unqualified name Blog\Article\Common
$common_class_name = 'Common';
// It is actually treated as an unqualified name, which represents the current space Common Class, but I'm not currently creating a class Common class 
$common = new $common_class_name(); // Fatal error: Common Class does not exist 
// I want to call it with a qualified name Blog\Article\Common
$common_class_name = 'Article\Common';
// It will actually be treated as a fully qualified name, which means Article Under the space of Common Class, but I'm just going to define it Blog\Article Space instead of Article space 
$common = new $common_class_name(); // Fatal error: Article\Common Class does not exist 

namespace Blog\Article;
class Common { }
?>

conclusion
I'm new to the PHP namespace, and I can't just give you unpractical advice. I personally think that namespaces are powerful and that you don't have to worry about duplicate names when you're writing plug-ins or generic libraries. However, if the project is at a certain point, I don't think it will be any less work than refactoring the name to solve the problem of multiple names by adding more namespaces. It has to be admitted that its syntax will add a certain amount of complexity to the project, so it should be well planned from the beginning of project 1 and a naming convention should be established.


Related articles: