Namespace & use

So I’m trying to get a grasp of this whole namespace thing. I don’t get why people use the use keyword if it’s the same thing without it.

Example:

index.php

<?php
namespace index;

require('foo.php');

use Foobar as Foo;

print(Foo\Bar::foo());

foo.php

<?php
namespace Foobar;

class Bar {

    static function foo() {

        return('In the foo function');

    }

}

This will result In the foo function.

Then without the use keyword.

index.php

<?php
namespace index;

require('foo.php');

print(\Foobar\Bar::foo());

foo.php

<?php
namespace Foobar;

class Bar {

    static function foo() {

        return('In the foo function');

    }

}

This will also return In the foo function.

With the second example, you use 1 less line. You just append another backslash to the current namespace and use the actual namespace name to make it available.

I just don’t really get why big frameworks like Symfony use the use keyword if it seems to be wasting space when you can achieve just the same thing without the use keyword.

Please enlighten me on this subject.


EDIT

Sorry everyone. I am referring to the use of use keyword.

Let’s start with your example.
Why do you start with namespace index ?

As for usage of use.
Bassicly it makes sure your code doesn’t conflict if you have 2 separate classes but other namespaces.

It also helps to create nice readable code.
You don’t use includes with long folder names, instead you are working with the use statement alongside a autoloader which loads in the files by looking at the namespace.

The purpose of namespacing is to avoid clashing class names in different packages or libraries. In PHP before version 5.3, clashing class names was always a possible issue you had to account for. With namespacing, clashing class names is a relic PITA of the past. You should also think of namespacing as an internal directory structure within PHP (and not the file system, which is what threw me for a loop learning about namespaces).

The purpose of the use statement is to import classes from outside packages into your own package or application. The other feature of use, as you noted, is to alias the class name.

Things also start to make even more sense, as is in pretty much all cases when using Symfony, when we have an autoloader running the show for “requiring” the files needed to load classes. When we have an autoloader, your first example would look like this.

namespace index;

use Foobar\Bar as Foo;

print(Foo::foo());

The require isn’t necessary with an autoloader. And, you would usually alias the class and not the namespace.

With PHP7, we can even consolidate the use class importing, if all the classes come from the same namespace.

//current usage of use.
use FooLibrary\Bar\Baz\ClassA;
use FooLibrary\Bar\Baz\ClassB;
use FooLibrary\Bar\Baz\ClassC;
use FooLibrary\Bar\Baz\ClassD as Fizbo;
// new usage of use in PHP7.

use FooLibrary\Bar\Baz\{ ClassA, ClassB, ClassC, ClassD as Fizbo };

If you are a fan of Game of Thrones, then you might like this blog post and explanation of namespaces.

Scott

Obviously because it’s the index file? Plus if I had a class on the index page with the same name as Bar, I can still use both classes.

I don’t really understand what you are talking about here. If you’re talking about having the same namespace, but different classes. It still returns the same thing. If you’re talking about having the same classes, but different namespace. That still is the same thing.

Observe


index.php

<?php
namespace index;

require('foo.php');
require('bar.php');

print(\Foobar\Bar::foo());
print(\Foobar\Bars::foo());

foo.php

<?php
namespace Foobar;

class Bar {

    static function foo() {

        return('In the foo function');

    }

}

bar.php

<?php
namespace Foobar;

class Bars {

    static function foo() {

        return('<br />In the foo function, but is in bar.php');

    }

}

These snippets return.

In the foo function
In the foo function, but is in bar.php

I don’t get this either. So

\Foobar\Bar::foo()

isn’t readable? I read it like \{namespace}\{class}::{function}(). I do want to understand the autoloader part with the use of the use keyword though. Please explain a little more.

Sorry Scott. I was referring to the use keyword. I’m not sure if the use keyword and namespace relates a whole lot, but I was really confused about the use keyword.

Wait. Take it a step back. So when you use the use keyword like

use Foobar\Bar as Foo;

Does that mean you don’t have to use require and include? And does it look for the file Foobar.php and look for the namespace Bar? I am really confused.

Using use and namespacing go hand in hand, because it is the namespace you need to use in the use statement.

Yes! You don’t need require or include, IF you are using autoloading, which there is basically two standards for now in today’s PHP dev landscape. PSR-0 and PSR-4.

Edit: Also, autoloading is (almost) automatically added to your app, as a part of composer, when you install and use composer for your application development.

1 Like

Well in my index/bootstrap file I do not use a namespace.

Normally I would load my application in that file without creating a function in there.

And yes i meant if you have the same class but different namespace it works fine but if you had 2 classes with same namespace it would conflict in some way I guess.
( I never use the same class in the index file a second time so not sure what would happen.)

Please forgive me for the confusion but I am used to use composers autoloader.

I’d like to complete your answer (I hope you don’t mind).
This may be confusing for some beginners.

Autoloading is a separate thing, with or without namespaces.
Namespaces will help you create a good structure of your code, based on business logic (or not). You can create a cool structure or you can create a real mess, it’s up to you.

You can consider namespaces as folders on your hard-drive: “music” in a folder, “movies” in another. Both are in the folder “entertainment”. Or, you can have a mess: “music” in the “projects” folder but you are not a musician :slight_smile:

However, the autoloader is needed anyway.
And yes, one file => one class
Two files, two classes, one namespace for both, same folder.

Index is a bootstrap. My opinion is that you should not have a class there.

1 Like

No problem. Because…

I want to complete your reply too. :smiley:

As I briefly mentioned above, namespaces have nothing to do with the file system, so don’t confuse what is on the file system to what you have in your namespaces. Namespaces are completely internal to PHP and independent of the file system.

Scott

1 Like

I think @vectorialpx’s comments were meant as an analogy. Namespaces fulfil the same function for classes as folders do for files; they keep things organised into a structure, and allow you to have items with the same name, which wouldn’t be possible if you threw all your files into one big folder (or all your classes into the global scope/namespace.

2 Likes

I realized that too.

However, it was similar analogies, which also got me confused about namespaces, when I was learning about them. The analogies were made, but there was never a mention that namespaces have nothing to do with the file system (the examples where just analogies). I just wanted to make that point doubly clear. Now it’s been made quadrupedally clear. LOL! :smiley:

Scott

3 Likes

Ok, so here’s the final question. Should I use the use keyword or not? The project isn’t going to be a big one so it won’t be using anything big.

It’s up to you

<?php
namespace App\Merchant\Newsletter\Manager;
class someClass {
    public $db = null;
    public function __construct() {
        $this->db = \App\System\Storage\Database;
    }
}

or

<?php
namespace App\Merchant\Newsletter\Manager;
use \App\System\Storage\Database; // use -->
class someClass {
    public $db = null;
    public function __construct() {
        $this->db = Database; // <--
    }
}
2 Likes

I’d say, yes! And on top of that, you should use autoloading too (by using composer). These things are currently “the norm” for programming modern PHP applications. In addition, you never know. Maybe your project might just end up bigger than you expected. Better to plan for big now, than refactor it in later. The use operator and autoloading will also make your programming life simpler in the end, even if the project is small.

Also, if you don’t follow today’s programming “norms”, then you’ll have a lot less interoperability with your project, which would mean your project can’t be easily added to other projects or extended. It also means less to no support from the OSS scene.

If all of that doesn’t really matter to you, then you can do whatever you’d like. :smile:

Scott

1 Like

Just thought I’d throw in another example of namespaces that go a bit beyond the basic foo/bar stuff:

// app.php
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
use Psr\Http\Message\ServerRequestInterface  as Psr7Request;

use Symfony\Component\HttpFoundation\Response as Response;

require_once 'vendor/autoload.php';

class Controller
{
  public function action(Psr7Request $request)
  {
    $loader = new \Twig_Loader_Filesystem('/path/to/templates');

    return new Response();
  }
}
class App
{
  public function handle(SymfonyRequest $request)
  {
    $controller = new Controller();
    $reponse = $controller->action($request);
  }
}
$request = SymfonyRequest::createFromGlobals();
$app = new App();
$app->handle($request);
  1. The app.php file has no namespace statement. There is really no need for one because app itself is never going to be used outside of this file. Just because namespaces are being used does not mean every file has to have a namespace statement.

  2. The simple require autoload.php file eliminates the need for requiring specific files to get their classes. If you use composer to install the components then it generates the autoload file for you.

  3. In this example, the app is using the Symfony request object but the controllers themselves can use any psr7 compliant object. I don’t think the ‘as’ clause has been discussed yet in this thread but being able to alias the class name can be very useful.

The use statement helps to make who is using what a bit clearer. I should point out that the symfony request object is not currently psr7 compliant so the posted code won’t work. In practice there is a bit of code that generates a psr7 request from the symfony request.

  1. The $loader line shows how to use a non-namespaced library as well as what the code might look like without a use statement for namespaced classes. Works just fine but always having to type out the full class name does tend to make (in my opinion) the code less readable.

  2. In my opinion, the use statement adds a bit of documentation to your files. You see at a glance at the top of the file exactly which objects are being used.

  3. Finally, I’d suggest taking a bit of actual code that uses the use statement and rewriting it without it. Or vice versa. Compare the two files side by side my side and determine for yourself which is more maintainable.

1 Like

Thank you Scott. One last question about namespace and the use keyword. I know that we are using static calls to those functions, but I would really like to use the $this-> operator. The bad part about using static calls is that I cannot call $this-> in a static function. Therefore I have a choice between; namespace + use keyword + static calls or namespace + $this-> operator.

I’ve been trying for hours and I cannot get my construct function to work alongside a static call. I am not knowledgeable like you so I have limit myself to what I can use right now.

Is the as clause any different than the use keyword? If so, how do they differ? So wait, you can call 3rd party platforms to be synced with your application and you can use their elements for your application?

bassicly “as” is used to alias if I explain that correct.
You could for example do :

<?php 
use ConceptCore\Invoiced\Core as InvoiceGenarator;
use ConceptCore\Invoiced\Core;

//Normal
$i = new Core;
// Aliased
$i2 = new InvoiceGenarator;

I probably don’t understand the question.

Of course you can use classes from third party libraries. Why would you think that you couldn’t?

What you have written above, unfortunately, leads me to believe you don’t quite have the right grasp of OOP programming with PHP. The pseudo-variable $this-> is part of the internal structure of classes and has nothing directly to do with use or namespaces. Moreover, $this-> should not be accessible outside of the object it was created in. Thus, it is purposely “not available” within external static function calls.

Put simply another way, calls to static functions should be generally avoided! They are real pain for testing and are bad for a good number of other reasons. So, the golden rule is, don’t use static methods or calls to them, unless you absolutely have to. And, I would say, in 99,9% of the cases where you think you might need a static method call, there are most likely proper OOP ways to call the methods you need. :smile:

Can you maybe post some of your code, where you create and call static methods? Maybe we can show you alternative and better ways to go about it.

Scott

Well, no and yes. I understand how to use the $this-> operator, but I’ve always seen big frameworks like Symfony call for static methods and I am really confused as to understand what is the best approach when it comes to OOP. I know that you cannot call $this-> unless you declare a class and a function, but they have to be a non-static function.

Like

function __construct() {

    $this->new_function();

}

public function new_function() {

    return('You are in the new function method');

}

Now, my main concern is to understand how big frameworks like Symfony use static calls to functions without having to use the $this-> operator.

An example from Symfony can be found on this page. http://symfony.com/doc/current/components/dependency_injection/factories.html

Continuing with this post: I’ve always used regular calls without using static methods, however when I look at frameworks, I want to understand if taking a regular approach is worth it or taking the approach like big frameworks is worth it. If you don’t understand this post, let me explain.

I am in love with the MVC pattern, however, if I take the approach to use namespaces and the use keyword, it’s kind of like the examples I have posted in this topic. So that being said. It looks like

index.php

<?php
namespace index;

use Router;

require('router.php');

\Router\Router::main();

router.php

<?php
namespace Router;

Class Router {

    static function main() {

        print('In router');

    }

}

However, if I take the approach of using the use keyword, I most likely will have to use static calls because the only thing right now that I have use for the use keyword is for aliasing.


NOTE:

This is me thinking now, I could be completely wrong, but it’s just what I think.


What I think is that the use keyword has no relevance if it isn’t being used in the snippet. It’ll just be hanging there with no purpose for it. Here’s a snippet to explain.

index.php

<?php
namespace index;

use Router;

require('router.php');

$router = new \Router\Router(); // \{namespace}\{class}

router.php

<?php
namespace Router;

Class Router {

    function __construct() {

        print('In router');

    }

}

The lines that read use Router; isn’t even being used in this snippet as opposed to the earlier snippet. Since the earlier snippet was using the use Router; alias, it is being used and has a purpose, but since I am using regular calls and not static calls, the use keyword doesn’t really do much in this snippet.

Now, why do I keep bringing Symfony up? Well, because they use the use keyword along with what seems to be static calls in their MVC. This confuses me because I want to know what is the best choice when it comes to the MVC pattern.

^ that is totally off-topic since we are talking about namespace & the use keyword, but I think they go hand in hand because these elements are what I am ultimately going to be using for my MVC layout.

Please correct me if I am completely wrong and not understanding any points given in this topic.

That is a class instantiation function. The Symfony docs are saying, in order to let the the DI container create the newsletterManager, then you can make a static class instantiation function and have the DI container call that function through configuration. It isn’t a static function for directly calling on functionality within the class, which should be avoided.

Scott