Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

PHP Building Websites with PHP Dependency Management Namespacing

A question about namespaces and use keyword

Trying to get my head around this but to clear things up like in the php file Logger with have

namespace Monolog;

use Monolog\Handler\HandlerInterface;
use Monolog\Handler\StreamHandler;
use Psr\Log\LoggerInterface;
use Psr\Log\InvalidArgumentException;

Does the namespace Monolog define the class of this file the same way you would by writing something like this ?

class Monolog {

 public function __construct(){}
}

Also when using the use is this just the same way as using include or require so rather than loading in all of these classes we're just adding a reference to them by defining and using the shorthand at the end so we can just easily access methods, properties within them etc

And finally just to clear this up in our index.php where we have said

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$log = new Logger('name');
$log->pushHandler(new StreamHandler('app.txt ', Logger::WARNING));

$log->addWarning('No my god');

echo "Hello World!";

With the first 2 use statements are we just saying we want to access the Logger file in the folder monolog & StreamHandler which is nested in the Handler folder with then allows us later to use these methods within these files since we have reference them above.

That was a mouthful hopefully i'm on the right track :D

Hampton Paulk

3 Answers

It sounds like you're almost there.

When you add a namespace to a file that contains a class, it's similar to writing out the file path that your class is sitting in. Let's say that Treehouse project has a directory of models, and inside the directory you have a php User class:

your filepath would be Treehouse/Models/User.php

and the psr-4 convention says your namespace should be Treehouse\Models;

e.g.

<?php

namespace Treehouse\Models;

class User {

    //

}

If you were import (or 'use') this class in another file, you'd say:

<?php

use Treehouse\Models\User;

psr-4 convention is handy - you can guess where everything is sitting because it closely resembles the folder structure.

To answer your questions:

does the namespace Monolog define the class of this file the same way you would by writing something like this ?

No, think of the namespace as a declaration of the location of your class, not the name. It's like saying this Muse track sits within this Muse album. The album might have the same name as one of the songs (and that's fine) but the song name isn't dictated by the album.

Also when using the use is this just the same way as using include or require so rather than loading in all of these classes we're just adding a reference to them by defining and using the shorthand at the end so we can just easily access methods, properties within them etc

Yes, pretty much. It's an additional way to pull in classes from your application. I might be misinformed here (and please correct me if I'm wrong!) - you can include a file of functions and use those functions in the current file. You can also include a file of a class and have the same result. However, you won't be able to 'use' a file of functions because the autoloader is looking for a CLASS.

With the first 2 use statements are we just saying we want to access the Logger file in the folder monolog & StreamHandler which is nested in the Handler folder with then allows us later to use these methods within these files since we have reference them above.

Hmmm, so psr-4 is a convention that means namespacing closely resembles file structure. You can, however, set any namespace you want to. It doesn't automatically mean that you're looking in a specific directory, but if you're being awesome and following conventions, then that's great!

In this directory: Something/Totally/Random.php you could set a namespace:

e.g.

<?php

namespace Bad\Practice

class Namespace {

    //

}

and import that class using

<?php

use Bad\Practice\Namespace;

even thought it's sitting in a different directory.

If you want to check this out, click through the composer files in the vendor directory. You'll be able to see how it assocaites your classes with file paths (/vendor/composer).

Hope this helps

Andrew Shook
Andrew Shook
31,709 Points

Tunde, You are kinda on the right track. The use statement doesn't include or require other files, it simply tells php that you want to use a specific class. So in the case of the Logger class from Monolog you mentioned, the use statement is telling php that when you create a new Logger object that Logger object should be from the Monolog Logger class not another class called Logger.

Now, as you noticed that fully qualified class name, Monolog\Logger, does match the folder structure of the Monolog package. This isn't because php doesn't automatically loads the files for you, but because composer autoloads the file for you. Composer can do this form you because it knows to takes the fully qualified class name, replace the "\" with "/", and knows roughly where to find the file. So Monolog\Logger is probably found inside the package at PACKAGEROOT/scr/Monolog/Logger.php (PSR-0), or at PACKAGEROOT/scr/Logger.php (PSR-4).

The namespace keyword was added to php so that people, and php itself, could distinguish one class from another. Back before php 5, you couldn't have two packages with a class called Logger because there would be a name collision. In other words php wouldn't know which Logger class you meant. So the namespace key word lets php distinguish two classes with the same name. So it will know that AndrewShook\Logger is different then Monolog\Logger. So by using the namespace keyword you are telling PHP that all the classes under that namespace are different then other classes with the same name.

<?php
use Monolog\Logger;
use AndrewShook\Logger;

$log = new Logger('name');
//this will fail because php doesn't know which logger to use.
?>
<?php
namespace SOMENAMESPACE;

$log = new Monolog\Logger('name');
//this will fail because php will look for SOMENAMESPACE\Monolog\Logger.

$log = new \Monolog\Logger('name');
//will work because the "\" at the beginning tell php that the class from another namespace
?>
<?php
use Monolog\Logger;
use AndrewShook\Logger;
$log = new Monolog\Logger('name');
//this will work since php knows that logger means the Logger class form the AndrewShook namespace
$log = new AndrewShook\Logger('name');
//this will work since php knows that logger means the Logger class form the Monolog namespace
?>
<?php
use Monolog\Logger as Monologger;
use AndrewShook\Logger;
$log = new Logger('name');
//this will work since php knows that logger means the Logger class form the AndrewShook namespace
$log = new Monologger('name');
//this will work since php knows that logger means the Logger class form the Monolog namespace
?>

Really wish i could vote both of them as best answers very clear and helpful thanks guy i understand now :D

Andrew Shook
Andrew Shook
31,709 Points

No worries, just here to help.