Using namespace prefix versus use statement

I am reading PHP and MySQL: Novice to Ninja (edition 6)

On page 408, the authors have just explained the use of namespaces and, once a class has been added to a namespace by adding "namespace whatever to the top of the class file, the need to reference it with \namespace\class instead of just class. I get this.

But, they proceed to say:

“We could fix this the same way as above—by providing the class name with the
namespace (which PHP refers to as a Fully qualified class name): \Ninja
DatabaseTable . But a neater solution is importing the class DatabaseTable into
the current namespace.
We can do this with the use keyword after the namespace declaration:”

<?php
namespace Ijdb\Controllers;
use \Ninja\DatabaseTable;
class Joke {
private $authorsTable;
// ...

I’d appreciate some further explanation here. When to use the “fully qualified” prefix and when to use “use” and import. I am assuming they are two ways of doing exactly the same thing (or am I wrong?).

Advantages, disadvantages of each?

Thank you,
Mike

I don’t consider myself an expert but I’ve used namespaces for awhile and this has been my experience:

Yes, if I understand you correctly using a fully qualified prefix is the same as placing a use statement at the beginning of your php code and calling the abbreviated class or function (meaning without the prefixing you defined in the use statement).

Using your example, assuming DatabaseTable refers to a class, I could reference it 2 different ways:

$db_table = new DatabaseTable($parameters);

or

$db_table = new \Ninja\DatabaseTable($parameters);

The autoclass loader (I’m also assuming you are using an autoloader) always receives a fully qualified name which is generated by the parser if you are using a “use” statement, so basically the “use” statement is useful in not having to type the fully qualified name every time you want to access the defined class or function. I don’t think there is a performance advantage or penalty in the “use” statement. It’s for convenience so that you wouldn’t have to type \A\Really\Really\Long\Namespace\Definition every time you want to create a new Widget object, for example.

I hope this makes sense.

Daniel

1 Like

Hi, Daniel.

Thank you for your response and apologies for the delay in getting back to you.

Yes, you seem to understand me in the sense that, yes, I am saying that, as far as I understand it, adding a Namespace and adding a Use statement at the top of your file do the SAME thing: they mean you don’t have to type the fully qualified prefix.

What I’m not sure about is: what’s the difference? Why use one and not the other?

Mike

Just to be clear:

A namespace defines a hierarchical scheme to isolate code. For example, if I wanted to create my own DateTime object, as opposed to using the provided DateTime object in php, I can do so by declaring a different namespace, like “\BornD\Objects”, than the global namespace, which is “\”. To create this new DateTime class, I would place the following code at the top of my php class file:
namespace \BornD\Objects;

class DateTime()
{....}

Whenever I use the “namespace” command then every time I create a new class or call a custom function that namespace is automatically attached to it, unless I specificy a “” at the beginning of the object or function name, which means “I’m going to provide the entire path; don’t attach any pre-defined name spaces” to the interpreter. If I don’t declare a namespace then I’m automatically in the global “\” namespace.

So, later when I want to use the new DateTime object (assuming I am NOT in the \BornD\Object namespace already), I would put:

$today = new \BornD\Object\DateTime();

in my code to make sure I reference the custom DateTime class I created. Now, let’s say I’m going to create a lot of dates for some process. Without using the “use” statement, I would have to put “new \BornD\Object\DateTime();” every time I wanted a new date. The “use” statement allows me to define at the top of my file that I’m going to use DateTime from \BornD\Object\DateTime so that I don’t have to type the full name every time, but rather I can just say:

$date = new DateTime();

Because I defined a prefix of \BornD\Object\DateTime with the use statement, the php interpreter will be able to find the custom class.

If, however, I wanted to access the php defined DateTime at the same time, I can – I just have to qualify the name using the “\” global namespace qualifier:

$php_date = new \DateTime();

Some people may want to use the fully qualified name in their code and that’s fine: there’s nothing that says you can’t. However, some people might want to use the “use” statement because it’s more readable to them to take all of the prefixes out.

So, to me, it’s really about readability in your code (some prefer a full prefix, some do not) and/or typing a fully qualified name every time as opposed to giving php a “search” path for your objects.

Hope this helps,
Daniel

Thanks, Daniel.

So, if ClassA is in namespace A and I was instantiating it from code that was in namespace A, I could use the unqualified classname, ClassA, BUT if I was instantiating it from code that was in namespace B, I would have to EITHER import ClassA into namespace B with a USE statement first OR use namespaceA\ClassA to refer to it.

Yes?

Mike

I use namespace and it is still not 100% clear in my mind the correct usage :frowning:

Is it possible to show with and without detailed namespace examples including classes from other directories preferably illustrated with diagrams

Yes, Mike, that’s right.

Thanks, Daniel. I really appreciate you patience and persistence.

Hi, John.

I’m honestly probably not the best person to ask as I am learning this more advanced stuff myself. I hope someone else comes in to the thread and helps you out otherwise I’ll try my best later.

Mike

1 Like

I really don’t know how to give an example without being detailed, but I’ll attempt this anyway:

Remember, a namespace is a hierarchical structure to help isolate code. It uses a folder paradigm to help with organization. It may or may not reflect the actual file structure for the php code (FIG standards suggest doing so, however. See the FIG PSR-4 standard for reference: https://www.php-fig.org/psr/psr-4/).

In this example I’m assuming the classes are loading automatically. That’s a completely different topic that I won’t cover here. (web search “php autoloading classes” for details.)

Consider the following namespace structure:

Vendor (the “root” namespace)

  • Log
  • User
  • Elements
    • Button
    • Checkbox
    • Textbox
  • Processes
    • Login
    • Menu
    • ProcessData
    • GetReport

Elements and Processes are sub-namespaces, like a sub-directory in a filing system. Log and User are classes in the \Vendor root namespace. Button, Checkbox, and Textbox are classes in the Elements sub-namespace, and Login, Menu, ProcessData and GetReport are classes in the Processes sub-namespace.

Let’s say I’m creating the Menu class in the Processes sub-namespace. I will put

namespace Vendor\Processes;

at the beginning of my Menu class php file showing that Menu is a part of the Vendor\Processes namespace, as the namespace command declares what code name space I’m defaulting to. If I failed to put the namespace command above in my Menu class php file, then Menu would automatically be in the Global namespace, denoted by a single backslash “\”.

As a member of the \Vendor\Processes namespace, the Menu class would have default access to Login, ProcessData, and GetReport. Meaning, if I needed to instantiate them I could simple use:

$process = new Login();

without qualifying the namespace structure because Login and Menu share the same namespace. If, however, I wanted to instantiate the Button class from Elements, I would need to qualify the Elements class so that php can reference the appropriate class. This is achieved by using

$button = new \Vendor\Elements\Button();

OR

use \Vendor\Elements\Button;   // This is placed at the beginning of the file, typically under the namespace statement

$button = new Button();     // when I need to instantiate the new class

The “use” is like an include-in-search-path statement for name spaces. You can have several “use” statements each referring to a different name path. Also, the path does not have to include the class, it can just be a portion of the path (I’ll give an example in a moment). However, if you do this, the last part of the namespace path MUST be referenced when instantiating. This is a little confusing, so here is an example.

If I want to use the Button AND Textbox classes, there are 3 different ways I can accomplish it.

Method 1 - fully qualify the class name at instantiation:

$my_button = new \Vendor\Elements\Button();
// this is explained above

Method 2 - reference the parent path only:

use \Vendor\Elements;

then to instantiate my classes:

$button = new Elements\Button();
$textbox = new Elements\Textbox();

Notice I MUST included Elements again in the instantiation, or php will not find the class.

Method 2 - fully reference the classes in the “use” statement.

use \Vendor\Elements\Button;
use \Vendor\Elements\Textbox;

then later in my code instantiating the classes:

$my_button = new Button();
$my_textbox = new Textbox();

*coding tip: you can compress the 2 “use” statements above by including the final classes in curly brackets {} like this:

use \Vendor\Elements\{Button, Textbox};

All methods (fully qualify the class at instantiation, place a “use” statement referring to the parent namespace, or placing a “use” statement referring to the class itself) produce the same result. The Button and Textbox class are referenced appropriately. As to which method you use is really up to the programmer or programming team. There is no right or wrong way.

2 Likes

There really isn’t much of a technical answer. It’s more of a coding style thing like brace positions and tabs vs spaces

The use statement has a couple of practical benefits:

  1. Other people can look at your class and immediately see what other classes it relies on
  2. The code is a bit cleaner new Bar() instead of new \Foo\Bar() if the namespaces are long you can end up with some very long lines that aren’t really doing a lot new \MyProject\Controllers\User(new \MyProject\Library\Session(), new \MyProject\Model\Authentication) in place of new User(new Session, new Authentication)

But, it really is down to personal preference.

1 Like

Thank you Tom (and apologies for the late reply). Yes, I get it. I think that the fact that it is exactly what you’ve said is why I was having trouble with it: both are valid.

Cheers for the response.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.