I just wonder if there's a way to make a class behave as if it is in global namespace using a "use" keyword, so this class would behave as namespaced class only from outside of the class.
Something like:
namespace wherever\somewhere\deep\deep\inside;
use \; // root namespace.. note: this doesn't work
class stuff{
//....
}
anyone?
Using the global namespace won't work the way you expect.
By default, you can reference a globally namespaced class by adding a backslash -- eg $x = new \PDO(...);. Trying to use \ won't change that.
If you want to drop the backslash from globally namespaced classes, you need to use each of them specifically. In namespaced PHP, any class reference that doesn't have a namespace is assumed to be in the current namespace, unless it is explicitly referenced by a use statement.
eg:
use \PDO, \SplFileObject;
now we can call new PDO(...) or new SplFileObject() without the backslash. But other global classes that aren't in the use would still need the backslash.
You can access the global namespace if you use brackets like this:
namespace My\Space {
function myScopedFunction() { .. }
}
namespace {
function myGlobalFunction() { .. }
}
I don't think you can. If anyone finds a good way please do share.
I tried the below which didn't work obviously (the writeup is here http://www.siteconsortium.com/h/D0000H.php). I would find it really useful to be able to go to the root namespace this way as a lot of legacy code doesn't use namespaces.
$root = \_\_NAMESPACE\_\_; // error
namespace AA;
function foo() { print " What AA "; }
use ($root); // error
namespace $root; // error can't use var
namespace ""; // error
use "/"; // error
namespace "/"; // error
There are a couple different issues here. One thing I thought was strange is that I can use the keyword require_once $script_name but I can't use the keyword namespace $namespace_name.
Related
Getting this error when I put use Blog; at the top.
Warning: The use statement with non-compound name 'Blog' has no effect
in...
Blog is my namespace in which I have 3 classes: Article, List and Category and a few functions.
If I change my statememnt to use Blog\Article; then it works...
Can't I just specify the namespaces I want to use? Do I need to provide classes?
What if I have functions within that namespaces? When I call them outside of the namespace, I'm forced to prepend \Blog\ to each one's name...
PHP's use isn't the same as C++'s using namespace; it allows you to define an alias, not to "import" a namespace and thus henceforth omit the namespace qualifier altogether.
So, you could do:
use Blog\Article as BA;
... to shorten it, but you cannot get rid of it entirely.
Consequently, use Blog is useless, but I believe you could write:
use \ReallyLongNSName as RLNN;
Note that you must use a leading \ here to force the parser into knowing that ReallyLongNSName is fully-qualified. This isn't true for Blog\Article, which is obviously already a chain of namespaces:
Note that for namespaced names (fully qualified namespace names containing namespace separator, such as Foo\Bar as opposed to global names that do not, such as FooBar), the leading backslash is unnecessary and not recommended, as import names must be fully qualified, and are not processed relative to the current namespace.
http://php.net/manual/en/language.namespaces.importing.php
Since this question appears as the first result on Google for this error I will state how I fixed it.
Basically if you have a framework, say like Yii2 you will be used to having to do declare classes like:
use Yii;
use yii\db\WhatEver;
class AwesomeNewClass extends WhatEver
{
}
You will get this error on Use Yii since this class has no namespace.
Since this class has no namespace it automatically inherits the global symbol table and so does not need things like this defining, just remove it.
The use statement in PHP is really just a convenience to alias a long namespace into something that may be a little easier to read. It doesn't actually include any files or do anything else, that effects your development, besides providing convenience. Since, Blog isn't aliased as anything you aren't gaining any of the convenience. I could imagine you could do something like
use \Blog as B;
And that may even work. (It could be argued you actually lose convenience here by obscuring but that's not what the question is about) Because you're actually aliasing the Blog namespace to something else. Using Blog\Article works because, according to the docs:
// this is the same as use My\Full\NSname as NSname
use My\Full\NSname;
So your snippet would be equivalent to:
use Blog\Article as Article;
if you don't want to use 'as' syntax like
use \Blog as B;
define a namespace for the file
namespace anyname;
use Blog
The error "The use statement ... has no effect..." also pops up if you try to use a trait before a class definition.
use My_trait; // should not be here
class My_class{
// use My_trait; should be here instead
}
Perhaps it's something like
namespace Path\To\Your\Namespace\Blog;
use Blog; // Redundant
class Post {
public $linkedArticle;
public function __construct($article = null)
{
$this->linkedArticle = $article ?? new Blog\Article();
}
}
Blog is already available, because that's the namespace you're in, so you can use new Blog\Article(); without use Blog; at the top. That's exactly what the error tells you - the added line has no effect.
Pointless:
use SingleNonNestedClassThatIsAlreadyPresentInTheCurrentNamespace;
Useful:
use SingleNonNestedClassThatIsAlreadyPresentInTheCurrentNamespace as Phew;
If you on the other hand wish to use new Article() then you can do it like this.
namespace Path\To\Your\Namespace\Blog;
use Blog\Article; // Equivalent to "use Blog\Article as Article;"
class Post {
public $linkedArticle;
public function __construct($article = null)
{
$this->linkedArticle = $article ?? new Article();
}
}
In practice you'd do something like
// Fairly separated domains
use Some\TooLong\Namespace\App\User;
use Some\TooLong\Namespace\App\Ecommerce;
use Some\TooLong\Namespace\App\Auth;
but not necessarilly
// Two tools in same domain
use Some\TooLong\Namespace\App\Ecommerce\Cart;
use Some\TooLong\Namespace\App\Ecommerce\Checkout;
as well. I'm positive there are better examples than this ;)
Getting this error when I put use Blog; at the top.
Warning: The use statement with non-compound name 'Blog' has no effect
in...
Blog is my namespace in which I have 3 classes: Article, List and Category and a few functions.
If I change my statememnt to use Blog\Article; then it works...
Can't I just specify the namespaces I want to use? Do I need to provide classes?
What if I have functions within that namespaces? When I call them outside of the namespace, I'm forced to prepend \Blog\ to each one's name...
PHP's use isn't the same as C++'s using namespace; it allows you to define an alias, not to "import" a namespace and thus henceforth omit the namespace qualifier altogether.
So, you could do:
use Blog\Article as BA;
... to shorten it, but you cannot get rid of it entirely.
Consequently, use Blog is useless, but I believe you could write:
use \ReallyLongNSName as RLNN;
Note that you must use a leading \ here to force the parser into knowing that ReallyLongNSName is fully-qualified. This isn't true for Blog\Article, which is obviously already a chain of namespaces:
Note that for namespaced names (fully qualified namespace names containing namespace separator, such as Foo\Bar as opposed to global names that do not, such as FooBar), the leading backslash is unnecessary and not recommended, as import names must be fully qualified, and are not processed relative to the current namespace.
http://php.net/manual/en/language.namespaces.importing.php
Since this question appears as the first result on Google for this error I will state how I fixed it.
Basically if you have a framework, say like Yii2 you will be used to having to do declare classes like:
use Yii;
use yii\db\WhatEver;
class AwesomeNewClass extends WhatEver
{
}
You will get this error on Use Yii since this class has no namespace.
Since this class has no namespace it automatically inherits the global symbol table and so does not need things like this defining, just remove it.
The use statement in PHP is really just a convenience to alias a long namespace into something that may be a little easier to read. It doesn't actually include any files or do anything else, that effects your development, besides providing convenience. Since, Blog isn't aliased as anything you aren't gaining any of the convenience. I could imagine you could do something like
use \Blog as B;
And that may even work. (It could be argued you actually lose convenience here by obscuring but that's not what the question is about) Because you're actually aliasing the Blog namespace to something else. Using Blog\Article works because, according to the docs:
// this is the same as use My\Full\NSname as NSname
use My\Full\NSname;
So your snippet would be equivalent to:
use Blog\Article as Article;
if you don't want to use 'as' syntax like
use \Blog as B;
define a namespace for the file
namespace anyname;
use Blog
The error "The use statement ... has no effect..." also pops up if you try to use a trait before a class definition.
use My_trait; // should not be here
class My_class{
// use My_trait; should be here instead
}
Perhaps it's something like
namespace Path\To\Your\Namespace\Blog;
use Blog; // Redundant
class Post {
public $linkedArticle;
public function __construct($article = null)
{
$this->linkedArticle = $article ?? new Blog\Article();
}
}
Blog is already available, because that's the namespace you're in, so you can use new Blog\Article(); without use Blog; at the top. That's exactly what the error tells you - the added line has no effect.
Pointless:
use SingleNonNestedClassThatIsAlreadyPresentInTheCurrentNamespace;
Useful:
use SingleNonNestedClassThatIsAlreadyPresentInTheCurrentNamespace as Phew;
If you on the other hand wish to use new Article() then you can do it like this.
namespace Path\To\Your\Namespace\Blog;
use Blog\Article; // Equivalent to "use Blog\Article as Article;"
class Post {
public $linkedArticle;
public function __construct($article = null)
{
$this->linkedArticle = $article ?? new Article();
}
}
In practice you'd do something like
// Fairly separated domains
use Some\TooLong\Namespace\App\User;
use Some\TooLong\Namespace\App\Ecommerce;
use Some\TooLong\Namespace\App\Auth;
but not necessarilly
// Two tools in same domain
use Some\TooLong\Namespace\App\Ecommerce\Cart;
use Some\TooLong\Namespace\App\Ecommerce\Checkout;
as well. I'm positive there are better examples than this ;)
I have a lot of classes in multiples subfolders that I load using this autoloader :
spl_autoload_register(function ($class) {
$class = str_replace('\\', DIRECTORY_SEPARATOR, strtolower($class));
if(file_exists(FILES_PATH.'classes/'.$class.'.class.php')){
require_once(FILES_PATH.'classes/'.$class.'.class.php');
}
});
So if i do new Folder\subFolder\Myclass, it works.
The classes in folders are all in a namespace.
All these classes must use the database class, and the problem is here :
When the class is in a namespace and search the database class, it can't find it.
(DB class is in global namespace)
So I try to put "use BDD" (Bdd is the db class) and it still doesn't work, because Bdd is using PDO and so i must do "use bdd, pdo;" in EVERY classes of the project...
I find this stupid. Is this normal ?
Is there a better way to autoload, without using namespaces ?
It's pretty darn simple:
If you're in a namespace like so:
namespace Foo;
all names of all classes are resolved relative to that namespace. Any Bar will mean the class Foo\Bar, not the "global" Bar. If you want to refer in any way, shape or form to a class which is not in the same namespace, say Bar\Baz (class Baz from the namespace Bar), you have two choices:
use a fully qualified name for the class, e.g.:
\Bar\Baz
where the leading \ means the class name shall be resolved from the top namespace, not the current local one, or
if this is getting annoying to do every time, alias it using:
use Bar\Baz;
which is shorthand for
use Bar\Baz as Baz;
which means any time you use "Baz" in this namespace you mean the class Bar\Baz, not Foo\Bar\Baz.
Yes, this applies to each file individually. If you want to refer to PDO in some namespace in some file, you either have to write \PDO to make it resolve to the "global" PDO class or you write use PDO at the top of the file to make a convenience alias. That's how namespaces work.
This applies to all use cases of any class name:
new \PDO
\PDO::staticMethod()
\PDO::CONSTANT
You can explicitly say that BDD is in the global namespace by doing this in your code:
$foo = new \BDD();
Then you should not need to use it.
Moving answer from one of my comments ;)
Using use \Pdo; in BDD class fixed the world :)
I have a file with a class Resp. The path is:
C:\xampp\htdocs\One\Classes\Resp.php
And I have an index.php file in this directory:
C:\xampp\htdocs\Two\Http\index.php
In this index.php file I want to instantiate a class Resp.
$a = new Resp();
I know I can use require or include keywords to include the file with a class:
require("One\Classes\Resp.php"); // I've set the include_path correctly already ";C:\xampp\htdocs". It works.
$a = new Resp();
But I want to import classes without using require or include. I'm trying to understand how use keyword works. I tried theses steps but nothing works:
use One\Classes\Resp;
use xampp\htdocs\One\Classes\Resp;
use htdocs\One\Classes\Resp;
use One\Classes;
use htdocs\One\Classes; /* nothing works */
$a = new Resp();
It says:
Fatal error: Class 'One\Classes\Resp' not found in C:\xampp\htdocs\Two\Http\index.php
How does the keyword use work? Can I use it to import classes?
No, you can not import a class with the use keyword. You have to use include/require statement. Even if you use a PHP auto loader, still autoloader will have to use either include or require internally.
The Purpose of use keyword:
Consider a case where you have two classes with the same name; you'll find it strange, but when you are working with a big MVC structure, it happens. So if you have two classes with the same name, put them in different namespaces. Now consider when your auto loader is loading both classes (does by require), and you are about to use object of class. In this case, the compiler will get confused which class object to load among two. To help the compiler make a decision, you can use the use statement so that it can make a decision which one is going to be used on.
Nowadays major frameworks do use include or require via composer and psr
1) composer
2) PSR-4 autoloader
Going through them may help you further.
You can also use an alias to address an exact class. Suppose you've got two classes with the same name, say Mailer with two different namespaces:
namespace SMTP;
class Mailer{}
and
namespace Mailgun;
class Mailer{}
And if you want to use both Mailer classes at the same time then you can use an alias.
use SMTP\Mailer as SMTPMailer;
use Mailgun\Mailer as MailgunMailer;
Later in your code if you want to access those class objects then you can do the following:
$smtp_mailer = new SMTPMailer;
$mailgun_mailer = new MailgunMailer;
It will reference the original class.
Some may get confused that then of there are not Similar class names then there is no use of use keyword. Well, you can use __autoload($class) function which will be called automatically when use statement gets executed with the class to be used as an argument and this can help you to load the class at run-time on the fly as and when needed.
Refer this answer to know more about class autoloader.
use doesn't include anything. It just imports the specified namespace (or class) to the current scope
If you want the classes to be autoloaded - read about autoloading
Don’t overthink what a Namespace is.
Namespace is basically just a Class prefix (like directory in Operating System) to ensure the Class path uniqueness.
Also just to make things clear, the use statement is not doing anything only aliasing your Namespaces so you can use shortcuts or include Classes with the same name but different Namespace in the same file.
E.g:
// You can do this at the top of your Class
use Symfony\Component\Debug\Debug;
if ($_SERVER['APP_DEBUG']) {
// So you can utilize the Debug class it in an elegant way
Debug::enable();
// Instead of this ugly one
// \Symfony\Component\Debug\Debug::enable();
}
If you want to know how PHP Namespaces and autoloading (the old way as well as the new way with Composer) works, you can read the blog post I just wrote on this topic: https://enterprise-level-php.com/2017/12/25/the-magic-behind-autoloading-php-files-using-composer.html
You'll have to include/require the class anyway, otherwise PHP won't know about the namespace.
You don't necessary have to do it in the same file though. You can do it in a bootstrap file for example. (or use an autoloader, but that's not the topic actually)
The issue is most likely you will need to use an auto loader that will take the name of the class (break by '\' in this case) and map it to a directory structure.
You can check out this article on the autoloading functionality of PHP. There are many implementations of this type of functionality in frameworks already.
I've actually implemented one before. Here's a link.
I agree with Green, Symfony needs namespace, so why not use them ?
This is how an example controller class starts:
namespace Acme\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class WelcomeController extends Controller { ... }
Can I use it to import classes?
You can't do it like that besides the examples above. You can also use the keyword use inside classes to import traits, like this:
trait Stuff {
private $baz = 'baz';
public function bar() {
return $this->baz;
}
}
class Cls {
use Stuff; // import traits like this
}
$foo = new Cls;
echo $foo->bar(); // spits out 'baz'
The use keyword is for aliasing in PHP and it does not import the classes. This really helps
1) When you have classes with same name in different namespaces
2) Avoid using really long class name over and over again.
Using the keyword "use" is for shortening namespace literals. You can use both with aliasing and without it. Without aliasing you must use last part of full namespace.
<?php
use foo\bar\lastPart;
$obj=new lastPart\AnyClass(); //If there's not the line above, a fatal error will be encountered.
?>
Namespace is use to define the path to a specific file containing a class e.g.
namespace album/className;
class className{
//enter class properties and methods here
}
You can then include this specific class into another php file by using the keyword "use" like this:
use album/className;
class album extends classname {
//enter class properties and methods
}
NOTE: Do not use the path to the file containing the class to be implements, extends of use to instantiate an object but only use the namespace.
Getting this error when I put use Blog; at the top.
Warning: The use statement with non-compound name 'Blog' has no effect
in...
Blog is my namespace in which I have 3 classes: Article, List and Category and a few functions.
If I change my statememnt to use Blog\Article; then it works...
Can't I just specify the namespaces I want to use? Do I need to provide classes?
What if I have functions within that namespaces? When I call them outside of the namespace, I'm forced to prepend \Blog\ to each one's name...
PHP's use isn't the same as C++'s using namespace; it allows you to define an alias, not to "import" a namespace and thus henceforth omit the namespace qualifier altogether.
So, you could do:
use Blog\Article as BA;
... to shorten it, but you cannot get rid of it entirely.
Consequently, use Blog is useless, but I believe you could write:
use \ReallyLongNSName as RLNN;
Note that you must use a leading \ here to force the parser into knowing that ReallyLongNSName is fully-qualified. This isn't true for Blog\Article, which is obviously already a chain of namespaces:
Note that for namespaced names (fully qualified namespace names containing namespace separator, such as Foo\Bar as opposed to global names that do not, such as FooBar), the leading backslash is unnecessary and not recommended, as import names must be fully qualified, and are not processed relative to the current namespace.
http://php.net/manual/en/language.namespaces.importing.php
Since this question appears as the first result on Google for this error I will state how I fixed it.
Basically if you have a framework, say like Yii2 you will be used to having to do declare classes like:
use Yii;
use yii\db\WhatEver;
class AwesomeNewClass extends WhatEver
{
}
You will get this error on Use Yii since this class has no namespace.
Since this class has no namespace it automatically inherits the global symbol table and so does not need things like this defining, just remove it.
The use statement in PHP is really just a convenience to alias a long namespace into something that may be a little easier to read. It doesn't actually include any files or do anything else, that effects your development, besides providing convenience. Since, Blog isn't aliased as anything you aren't gaining any of the convenience. I could imagine you could do something like
use \Blog as B;
And that may even work. (It could be argued you actually lose convenience here by obscuring but that's not what the question is about) Because you're actually aliasing the Blog namespace to something else. Using Blog\Article works because, according to the docs:
// this is the same as use My\Full\NSname as NSname
use My\Full\NSname;
So your snippet would be equivalent to:
use Blog\Article as Article;
if you don't want to use 'as' syntax like
use \Blog as B;
define a namespace for the file
namespace anyname;
use Blog
The error "The use statement ... has no effect..." also pops up if you try to use a trait before a class definition.
use My_trait; // should not be here
class My_class{
// use My_trait; should be here instead
}
Perhaps it's something like
namespace Path\To\Your\Namespace\Blog;
use Blog; // Redundant
class Post {
public $linkedArticle;
public function __construct($article = null)
{
$this->linkedArticle = $article ?? new Blog\Article();
}
}
Blog is already available, because that's the namespace you're in, so you can use new Blog\Article(); without use Blog; at the top. That's exactly what the error tells you - the added line has no effect.
Pointless:
use SingleNonNestedClassThatIsAlreadyPresentInTheCurrentNamespace;
Useful:
use SingleNonNestedClassThatIsAlreadyPresentInTheCurrentNamespace as Phew;
If you on the other hand wish to use new Article() then you can do it like this.
namespace Path\To\Your\Namespace\Blog;
use Blog\Article; // Equivalent to "use Blog\Article as Article;"
class Post {
public $linkedArticle;
public function __construct($article = null)
{
$this->linkedArticle = $article ?? new Article();
}
}
In practice you'd do something like
// Fairly separated domains
use Some\TooLong\Namespace\App\User;
use Some\TooLong\Namespace\App\Ecommerce;
use Some\TooLong\Namespace\App\Auth;
but not necessarilly
// Two tools in same domain
use Some\TooLong\Namespace\App\Ecommerce\Cart;
use Some\TooLong\Namespace\App\Ecommerce\Checkout;
as well. I'm positive there are better examples than this ;)