I noticed following notation in PHP. What does it mean?
$locales = GeneralUtility::makeInstance(Locales::class);
i have problems understanding parameter of makeInstance. Locales seems to be another static class. What means notation of
Locales::class
explicitly? What kind of parameter will it expect?
According to the documentation, http://php.net/manual/en/migration55.new-features.php#migration55.new-features.class-name, you can use it to get the fully qualified name of a class.
In your case, let's assume the Locale class is defined like this:
file1.php
<?php
namespace App\Core;
class Locale {}
echo Locale::class; // output - App\Core\Locale
In a separate file, you could require/autoload the file,
file2.php
<?php
require_once #pathToFile1/file1.php;
use App\Core\Locale;
echo Locale::class; // output - App\Core\Locale
We can also see from this that we no longer have to save our class name in a variable as we can always call Locale::class and get going.
To address one of the comments on the question, yes, class is a keyword and using it for function name usually result in a parse error.. That changed in PHP 7 though...thus you can define a function and name it class, function etc. It's best not to do this though unless you think it's absolutely necessary.
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 ;)
I want to write a small add on for an existing CMS. To do so, I need to extend a class from that CMS' code.
My code will be written inside its own namespace, while the CMS' code does not use namespacing, which basically means it exists inside the global namespace.
Inside my code, I create a new stdClass:
$var = new stdClass();
With that code is place, it always produces a fatal error:
Fatal error: Class 'MyNamespace\something\StdClass' not found in /some/rather/long/path/to/class.php on line 123
Creating the stdClass like this solves that problem:
$var = new \stdClass();
Since I am still pretty new to namespaces, I am not exactly sure what the problem here is?
My guess is that in the first example, the stdClass would be created in the namespace of my class. This actually means the constructor of a class called stdClass existing in my namespace would be called, but since that class does not exist, an error is thrown.
In the second example, I signalize that I want to instantiate the class called stdClass from the global namespace, which somehow suddenly makes sense.
If anyone could elaborate what is happening here I would be very happy.
You appear to understand the concept behind namespaces, and you are headed in the right direction on your analysis of what is happening.
When you are working inside of a namespace you are able to refer to names as unqualified, qualified, and fully qualified.
When you make a namespace you are telling PHP to organize (and resolve) the names of your classes, function, methods, etc. away from the same scope where the built-in PHP code lives along with any other code behind its own namespace. It is away to organize your code and avoid naming collisions among libraries and built-in PHP functions.
Here is a brief on how names get resolved:
If you are trying to resolve a name within the same namespace you can use the unqualified name. So for class \Foo\Bar\Baz you can use new Baz(); as long as you are in namespace \Foo\Bar.
If you are trying to resolve a name that is lower in the same parent namespace you can use the qualified name. So for class \Foo\Bar\Baz you would need to use new Bar\Baz(); if you were in namespace \Foo.
If you are trying to resolve a name that is not in your namespace or is in the global namespace (built-in PHP stuff) then you must use the fully qualified name. If you are in namespace \Foo\Bar and you want to make use of something like the mysqli class you would need to call it by its fully qualified name. e.g. new \mysqli() Your question above is a perfect example that illustrates this. Likewise, if you need to access a class in a totally different namespace you would also need the fully qualified name: new \Third\Party\AppClass();
So to summarize, you are right, the built-in stdClass does not exist in your namespace, therefore you need to access it by the fully qualified name. The reason you must do thing this way had to do with conforming to the rules PHP uses when resolving names.
If you ever need to find out what namespace you are in it will be in the __NAMESPACE__ constant.
In case you haven't already read it, here is the documentation on name resolution in PHP: http://php.net/manual/en/language.namespaces.rules.php
The code is evaluated in your namespace and stdClass doesn't exist there. You are effectively answering your own question with your guess.
Your guess is correct. Look at the comments in "class references" section of Example #1 on this page.
http://php.net/manual/en/language.namespaces.rules.php
PHP 5.5 has implemented as a new feature a new way to retrieve the classname through the syntax ::class:
<?php
namespace Testing;
class Test{}
echo Test::class; // Testing\Test;
This works perfectly, alright? BUt what me and some other friends wanted to know is why this syntax also returns a classname when used alongside an undeclared class. E.g.:
<?php
echo UndeclaredClass::class; // UndeclaredClass
In several other cases an error is raised, but not here. Anyone know, with concrete basis if possible, why does this happen?
Does it have anything to Late Static Bindings or it's just a (temporary) limitation/bug of this brand new feature?
Finally an official answer... relatively speaking. It was presented to me by someone identified by requinix#php.net in a bu report i created today. The only exception is about how involved with PHP development this person is.
TL;DR
PHP doesn't need ot know the definition of a class to get its fully-qualified name. All the required informations are available in compile-time so it doesn't need to load it.
Director's Cut
Namespaces like the uses are resolved in compile-time, i.e., when the file is compiled before its execution. That's why there are strict requirements in order to use them.
Because of all of those requirements, when PHP encounters a class name it can immediately know its fully-qualified name. Thinking of it as a filesystem the namespace would be a directory for relative locations and the use would be symlinks.
The class name is either absolute ("\Testing\Test") or relative ("Test"), and if relative it could be a normal name. [more context required]
namespace Testing {
echo Test::class; // \Testing + Test = \Testing\Test
}
Or an alias:
use Testing\Test as AliasedTest;
echo AliasedTest::class; // AliasedTest + use = \Testing\Test
Without all of this autoloading wouldn't work!
::class is just a new tool to expose information PHP has always known.
This "extended answer" is pretty much the same of what I received as bug report. The reason of so much apparent copy & paste is because, originally, I built up this answer for another Stack Overflow Community
You can use get_class function get the class name with the namespace. It will be the good to use it.
Here is the code which you can try this code:
<?php
namespace Testing;
class Test{
public function abc()
{
echo "This is the ABC.";
}
}
namespace Testing1;
class Test{
public function abc()
{
echo "This is the ABC.";
}
}
// echo Test::class; // Testing\Test;
$test = new Test();
print_r(get_class($test));
// echo "<br>";
// echo UndeclaredClass::class;
?>
Seeing this line in PHP from password_compat, I am not sure what it does:
namespace {
//...
}
Is it similar to wrapping some code in an anonymous function in javascript? What's it purpose?
Note: I know how to normally use namespaces, I just don't understand this, since it looks like a namespace but without any name in it and, for me so far, without any purpose.
It declares the code to be in the global namespace. The purpose of this is that later on in the file there are two functions implemented in a private namespace, and PHP requires that if any namespace is used in the file the first keyword in the file must be namespace. So to mix global and namespaced code in the same file, this is how it needs to look.
See https://github.com/ircmaxell/password_compat/commit/88911e6abebb324cca88f546f04d6e71ce778bd3 for the particular commit.
That definition is to ensure that the file containing it loads in the global namespace. Have a look at this answer
namespace // empty namespace means global
{
// Ensure everything you put here belongs the global namespace
}
But, technically speaking, it is exactly the same as not declaring any namespace at all. In both cases everything in it will belong to the global namespace.
How can I "reset" a namespace to the global one? Given the following code:
namespace foo;
include 'myfile.php';
myfile.php will now try to load all of its classes in the foo namespace, even though its classes are in the global namespace. Now it wouldn't be a big deal to swap the order of those lines, but how would I deal with myfile.php having an autoloader? It will try to load the classes in namespace foo.
Namespaces work on a per-file basis. If myfile.php doesn't declare any namespace then everything in it will belong to the global namespace, regardless of the namespace in which include was used.
Long story short, namespace declarations only apply to their own file, not includes.
myfile.php should declare the namespace that it wants to be in. If you want to ensure that myfile.php loads in the global namespace, I believe you can put
namespace // empty namespace means global
{
}
around the body of myfile.php. Make sure that you use the braces, or else you'll redefine the rest of the file in which myfile.php is included to also be in the global namespace.
Maybe I didn't understand your question well ; in that case, could you provide an example of what you get, and what you'd expect ?
Are you sure it will try to load the functions from myfile.php in the foo namespace ?
Considering I have one file (temp-2.php) that looks like this :
<?php
namespace foo;
function my_function_this_file() {
var_dump(__FUNCTION__);
}
my_function_this_file();
include 'my_other_file.php';
my_function_the_other_file();
And another one (my_other_file.php) that looks like this :
<?php
function my_function_the_other_file() {
var_dump(__FUNCTION__);
}
When I call the first one from my browser, I get this output :
string 'foo\my_function_this_file' (length=25)
string 'my_function_the_other_file' (length=26)
This seems to indicate the second function is not inside any namespace, except the global one -- which corresponds to the fact that it's not declared in any namespace.
If I remember correctly, the "namespace" instruction is only valid for the file it is used in, and not for included files.
The Import names cannot conflict with classes defined in the same file page from the namespaces FAQ seems to indicate that too.
Hope this helps, and I understood the question correctly...
EDIT : btw, swapping the order of the to lines, like this :
<?php
include 'my_other_file.php';
namespace foo;
Wouldn't work : the "namespace" instruction must be the first one of the file : you'll get a Fatal Error, if you do that :
Fatal error: Namespace declaration statement has to be the very first statement in the script
I'd just like to chime in on this with my findings. Since PHP cannot handle exceptions in __toString methods, the solution is to do it yourself: something along the lines of
public function __toString()
{
try {
return $this->draw();
} catch ( \Exception $e ) {
die( \error::_getExceptionPage( $e ) );
}
}
However what becomes really weird, the namespace of the call to error::_getExceptionPage($e) becomes the same as the class in which __toString was defined - and I wasn't able to find a way around that except prefixing everything in my exception handling code with \, i.e. every call to any class in getExceptionPage must become \someClass::staticMethod().
Same goes for included files, everything - all code since the thrown exception becomes embedded in the namespace of the faulty class. Tested with PHP 5.3.17