📜 ⬆️ ⬇️

Namespace in PHP, clarification

Note: I know that at the time of translation the current version of PHP is 5.5, and also that there is a wise manual book. But it seemed to me interesting, then as the author presents the namespace functionality, maybe someone from those who only learn the basics (and not only, there are many bearded developers who stopped on PHP 5.2), the article will help to penetrate. Hodor

In PHP, starting with version 5.3 appeared namespaces . Most modern languages ​​have long had such functionality for themselves, but PHP was a bit late. Nevertheless, each new function has its own purpose, let's find out what benefits we can get using the namespace.

In PHP, you cannot have two classes that are named the same; they must all be unique. The problem with this restriction is that if you use someone else's library that provides a class named User , then you cannot create your own class, also called User . This is really bad, because User is a very convenient name for a class, isn't it?

Namespaces allow us to get around this problem, and we can create as many User classes as we need. In addition, namespaces allow us to organize the code into convenient packages, as well as to denote our ownership of this code.

Let's take a look at the most ordinary class. Yes ... I know that you already used them, what is the namespace here? Just trust me on this, ok?
')

Global namespace


Here is such a very simple class:
 <?php // app/models/Eddard.php class Eddard { } 

Nothing particularly, as you can see, and if you want to use it, just do this:
 <?php // app/routes.php $eddard = new Eddard(); 

Dale, I kind of know PHP ...

Good, good, sorry. The bottom line is that we can think of this class as being in a global namespace. I’m not quite sure that this is the correct term, but in my opinion it sounds quite appropriate. Actually, this means that the class does not belong to any package, just an ordinary class.

Simple use of namespaces


Let's create another Eddard, next to that global one.
 <?php namespace Stark; // app/models/another.php class Eddard { } 

Here we have a very similar class with one small change, a namespace directive has been added. String namespace Stark; tells PHP that we are working in the Stark namespace and any code (declaration of classes, functions, variables, etc.) will apply to it.

So, we need to create a new Edd, if you decide that it needs to be done like this:
 <?php // app/routes.php $eddard = new Eddard(); 

That no, it is not. Here we get an instance of the class from the first example we created earlier. Not the one in the Stark namespace. Let's try creating an instance of Eddard Stark.
 <?php // app/routes.php $eddard = new Stark\Eddard(); 

To create an instance of a class, we need to prefix the class name with a prefix from the namespace name to which the class belongs, and use a backslash as a separator. As a result, we have an instance of exactly the class that we need. Isn't it magical?

By the way, namespaces can form an arbitrarily complex hierarchy, using as many levels as necessary. For example:
 This\Namespace\And\Class\Combination\Is\Silly\But\Works 

Theory of relativity


Remember, as I told you, PHP always works relative to the current namespace. Let's take a look at this in action:
 <?php namespace Stark; // app/routes.php $eddard = new Eddard(); 

By adding a namespace directive, we made it clear to PHP that we are in the Stark namespace. Since we defined the class Eddard in it, we will receive it. See, everything is relative.

Now that we have changed the namespace, we have one small problem. Any idea what I mean? And how do we get our original Eddard class now? Well, the one in the global space?

Fortunately, PHP has a trick that will allow us to solve this problem by simply adding \ to the class name.
 <?php // app/routes.php $eddard = new \Eddard(); 

Seeing the leading slash PHP understands that you need to look beyond the current namespace and creates an instance of the class we need.

Now turn on your imagination. Imagine that we have a class from another namespace called Tully \ Edmure. Now we need to use it inside the Stark space. And how do we do this?
 <?php namespace Stark; // app/routes.php $edmure = new \Tully\Edmure(); 


Again, we had to use the backslash to go to global visibility before creating an instance of the class in Tully space.

In general, referring to classes from other namespaces like this, using the full hierarchy in the name, can be quite tedious. But fortunately, there is an opportunity to make a shortcut, let's see:
 <?php namespace Stark; use Tully\Edmure; // app/routes.php $edmure = new Edmure(); 


Using the use directive, we can get a class from another namespace. But please do not ask me, “why didn’t we put a slash here at the beginning?”, Because I just don’t know. As far as I know, this is the only exception. No, you can use a slash here. but there is no point in this.

Oh, one more little trick! We can give our imported classes nicknames:
 <?php namespace Stark; use Tully\Brynden as Blackfish; // app/routes.php $brynden = new Blackfish(); 

Using the as keyword, we assigned the nickname Blackfish to the Tully / Brynden class, which allows us to use the new nickname to identify it in the current namespace. Clever, isn't it? This is also very convenient if you need to use two classes, named the same, within the same namespace:
 <?php namespace Targaryen; use Dothraki\Daenerys as Khaleesi; // app/routes.php class Daenerys { } // Targaryen\Daenerys $daenerys = new Daenerys(); // Dothraki\Daenerys $khaleesi = new Khaleesi(); 


By giving Daenerys from the Dothraki space the nickname Khaleesi, we can use both Daenerys classes. Quite convenient, there we can use all the necessary classes in our application.
 <?php namespace Targaryen; use Dothraki\Daenerys; use Stark\Eddard; use Lannister\Tyrion; use Snow\Jon as Bastard; 


Structure


Namespaces can also help us in organizing our code. Let me show you.

Let's say I want to create an open source library. I would really like others to use my code, that would be great! The trouble is that the class names in my code conflict with the user's own application of my library. That would be terribly uncomfortable. Here is how I solve this problem:
 Dayle\Blog\Content\Post Dayle\Blog\Content\Page Dayle\Blog\Tag 

Here I used my name to show that the code belongs to me, and to separate my code from the user code of my library. Inside the base namespace, I created the structure of classes according to their hierarchy.

When you start using composer, you will learn how to use namespaces to simplify code autoloading. I highly recommend that you take a look at this useful mechanism.

disadvantages


In truth, I feel a little guilty for calling this subtitle "Flaws". What I am going to talk about is not really a mistake.

The fact is that in other languages ​​the namespace functionality is implemented in a similar way, and at the same time, languages ​​provide additional functionality for interacting with namespaces.

In Java, for example, you can import several classes into the current namespace using an import statement. In Java, import is analogous to use and it uses dots to separate nested namespaces (or packages). Here is an example:
 import dayle.blog.*; 

This will import all classes found in the package 'dayle.blog .

In PHP, you will not get it. You must import each class separately. Excuse me. Actually, why am I sorry? Go and complain to the PHP development team, but I ask you - be polite. They have done a lot of interesting things lately.

Here is a neat trick to smooth out a bit of a voiced problem. Imagine that we have a class structure from the previous example. We can take a part of the subspace and give it a pseudonym.
 <?php namespace Baratheon; use Dayle\Blog as Cms; // app/routes.php $post = new Cms\Content\Post; $page = new Cms\Content\Page; $tag = new Cms\Tag; 

This can be useful when using a large number of classes. Good for all!



All wishes and suggestions with pleasure I will accept in a personal, thank you.

Source: https://habr.com/ru/post/212773/


All Articles