Is there any way to temporary use a namespace ?
I'm using a library to create forms and it uses namespaces, the problem is that I usually want to create a form in the middle of a page, which is thus in the global namespace. Then if I want to call any function of this library I have to prefix everything with Namespace\
Isn't there any way in PHP to do something like this :
Blabla global namespace
strlen('test'); // 4
namespace Namespace
{
test();
}
More global PHP
And have it refer to Namespace\test ?
http://www.php.net/manual/en/language.namespaces.importing.php
<?php
namespace foo;
use My\Full\Classname as Another;
// this is the same as use My\Full\NSname as NSname
use My\Full\NSname;
// importing a global class
use ArrayObject;
$obj = new namespace\Another; // instantiates object of class foo\Another
$obj = new Another; // instantiates object of class My\Full\Classname
NSname\subns\func(); // calls function My\Full\NSname\subns\func
$a = new ArrayObject(array(1)); // instantiates object of class ArrayObject
// without the "use ArrayObject" we would instantiate an object of class foo\ArrayObject
?>
This is about the closest you can get - there's no way to change the default namespace temporarily.
I know this is an old question, and while the accepted answer answers the question as it was asked, I feel like what the OP is really asking is "Can I use items in the global namespace from another namespace. The answer here is a clear and simple yes.
Imagine two classes (one in the global namespace, another in its own:
ClassInGlobal.php
<?php
class ClassInGlobal
{
public static function doStuff()
{
echo 'I do some stuff';
}
}
ClassInNamespace.php
<?php
namespace App\Classes;
class ClassInNamespace
{
public function callDoStuff()
{
\ClassInGlobal::doStuff();
}
}
The above executes fine. All that is required is a leading slash to specify the fully qualified global namespace. Additionally, you could add a use ClassInGlobal declaration right after the namespace declaration and omit the leading slash.
This might translate into the original question by abstracting the namespaced functions into a class Then you could modify the OP's code slightly to acheive this:
require './Namespace/Utilities.php';
Blabla global namespace
strlen('test'); // 4
\Namespace\Utilities::test();
More global PHP
Hope that helps someone coming here looking for that.
Related
I'm new to PHP. When working with namespaces, I ran into a problem with RedBeanPHP.
I have php script "db.php":
namespace Fromtify\Database {
require_once('../libs/rb-mysql.php');
class Contoller
{
public function Connect()
{
R::setup(
#My database settings here...
);
if (!R::testConnection()) {
echo 'Cant connect to database';
exit;
}
}
}
}
My IDE(VSCode) tells me: "Undefined type 'Fromtify\Database\R"
How can I solve the problem?
Thank you in advance
When you use namespaces, PHP will assume that any class you load is under that namespace as well, unless you've imported it.
Example:
namespace Foo;
$bar = new Bar;
This will assume that Bar also is under the namespace Foo.
If the class you're using is under another namespace, or not in a namespace at all (the global namespace), you need to tell PHP which class to use by importing it. You do this with the use
namespace Foo;
use Bar;
$bar = new Bar;
So in your case, it should be:
namespace Fromtify\Database {
use R;
R:setup(...);
// The rest of your code
}
Side note!_
Unless you have multiple namespaces in the same file, which you usually don't have, there's not need for the syntax:
namespace Foo {
// your code
}
You can simpy do:
namespace Foo;
// Your code.
...which makes the code a bit cleaner.
You can read more about defining namespaces and using namespaces in the manual
I am kind of confused about using name spaces in php,would try to explain using the problem I have with one of my project
I have a class under a namespace as
namespace BigBlueButton;
class BigBlueButton
{
public function createMeeting($createMeetingParams, $xml = '')
{
//some code
return new CreateMeetingResponse($xml);
}
}
I use it as
use \BigBlueButton;
$bbb = new BigBlueButton\BigBlueButton();
//then I try to reference the variable $bbb in a function but I can't
function easymeet_create_meeting($id) {
// $bbb = new BigBlueButton\BigBlueButton(); I don't want to create a new object here but reference the object I created above,something like this
$bbb=BigBlueButton\bbb;
}
But I can't seem to access the above variable i.e. $bbb , I tried global $bbb ,but $bbb doesn't seem to be in the global namespace, I understand I am trying to access a constant $bbb in the above code, but I showed it anyway to tell what I am trying to do
Namespacing does not extend to variables like that:
In the PHP world, namespaces are designed to solve two problems that
authors of libraries and applications encounter when creating
re-usable code elements such as classes or functions:
Name collisions between code you create, and internal PHP classes/functions/constants or third-party
classes/functions/constants.
Ability to alias (or shorten) Extra_Long_Names designed to alleviate the first problem, improving readability of source code.
http://php.net/manual/en/language.namespaces.rationale.php
Your class declaration is fine, but you've mis-used the use keyword as it should refer to specific classes, not a namespace.
use \BigBlueButton\BigBlueButton;
function easymeet_create_meeting($id, BigBlueButton $bbb) {
/* ... */
}
$bbb = new BigBlueButton();
$result = easymeet_create_meeting(1234, $bbb);
You'll notice that I've also moved $bbb into the function parameters because global state is the devil. It's also type-hinted because why not?
Better yet:
class BigBlueButton implements ButtonInterface {}
class BigRedButton implements ButtonInterface {}
And:
function easymeet_create_meeting($id, ButtonInterface $bbb) {}
$result[] = easymeet_create_meeting(1234, new BigBlueButton());
$result[] = easymeet_create_meeting(5678, new BigRedButton());
And now we're looking at the rudiments of Dependency Injection, which is a good habit to get into.
If I understand it right the problem is not with namespace.
As you said you could try using a global variable for example:
use \BigBlueButton;
global $bbb;
$bbb = new BigBlueButton\BigBlueButton();
function easymeet_create_meeting($id) {
global $bbb;
// you can use it
}
or you can send the variable to the function
function easymeet_create_meeting($id, $bbb) {
}
I do not know the entire problem, but you could also use a singleton design pattern in the class so you always get the same instance every time you use it.
If you try using class_exists() inside a method of a class in PHP you have to specify the full name of the class--the current namespace is not respected. For example if my class is:
<?
namespace Foo;
class Bar{
public function doesBooClassExist(){
return class_exists('Boo');
}
}
And Boo is a class (which properly autoloads) and looks like this
namespace Foo;
class Boo{
// stuff in here
}
if I try:
$bar = new Bar();
$success = $bar->doesBooClassExist();
var_dump($success);
you'll get a false... is there an alternative way to do this without having to explicitly specify the full class name ( i.e. class_exits('Foo\Boo') )?
Prior to 5.5, the best way to do this is to always use the fully qualified class name:
public function doesBooClassExist() {
return class_exists('Foo\Boo');
}
It's not difficult, and it makes it absolutely clear what you're referring to. Remember, you should be going for readability. Namespace imports are handy for writing, but make reading confusing (because you need to keep in mind the current namespace and any imports when reading code).
However, in 5.5, there's a new construct coming:
public function doesBooClassExist() {
return class_exists(Boo::class);
}
The class pseudo magic constant can be put onto any identifier and it will return the fully qualified class name that it will resolve to.......
Example in file 1:
namespace A;
class Foo{
}
file 2:
use A\Foo;
do_stuff('A\Foo'); // <- need namespace here :(
Foo::someStaticMethod(); // <- namespace not required :D
Is there any way I can pass class names in function arguments like constants or something, so I don't need to prepend the namespace?
Update :)
When I know, that I need to pass the classnames of some classes around as string I'm used to create special class constant
namespace Foo\Bar;
class A {
const __NAMESPACE = __NAMESPACE__;
const __CLASS = __CLASS__;
}
Now you can reference the classname like
use Foo\Bar\A as Baz;
echo Baz::__CLASS;
With PHP5.5 this will be builtin
echo Baz::class;
Full-Qualified-Names (FQN) for namespaces always starts with a namespace separator
do_stuff('\A\Foo');
except (and thats the only exception) in use-statements, because there can only appear complete namespace identifiers, so for convenience you can omit it there.
However, a string is a string and where you use it as a class name is out of scope of the interpreter, so it lost the reference to the former use A\Foo-aliasing. With PHP5.5 you can write Foo::class, but I think thats not an option right now ;)
You could instantiate a new object, then call get_class() to get the fully qualified name for the class.
use A\Foo;
$foo = new Foo();
do_stuff(get_class($foo)); // get_class($foo) = '\A\Foo'
This means that the namespace of Foo is only defined by the use statement (ie. less code maintenance).
Or you can pass class reflection.
ReflectionClass
No, not without tracing the caller, as far as I know. The function you are calling must exists within the same namespace as the object you are trying to pass.
You might want to have a look at the debug_backtrace function if you require the namespace resolution. But this requires the file-paths to be translated into namespace resolutions or similar.
This is however possible: (I see Andrew has answered with the same type of solution.)
function doStuff ($obj)
{
$name = (is_object($obj))
? (new ReflectionClass(get_class($obj)))->getName()
: $obj;
// $name will now contain the fully qualified name
}
namespace Common;
class Test
{}
$testObj = new Test();
// This will work, but requires argument to be
// fully quialified or an instance of the object.
\doStuff($testObj);
\doStuff("\Common\Test");
I'll try to describe the situation I'm having problems with:
I have one main folder. I keep all files in there (empty classes for a reason), and one sub-folder, containing the same files, with all implementations here (empty classes extend them).
the main folder's namespace is declared as Project/Folder, and the sub-folder as Project/Folder/Subfolder. These are class's declarations:
namespace Project\Folder;
class Foo extends Subfolder\Foo { }
namespace Project\Folder\Subfolder;
class Foo { }
What I want to achieve is to be able to call other classes from inside of the Project\Folder\Subfolder\Foo through these empty classes on the lower level, with only its name, e.g.:
namespace Project\Folder\Subfolder;
class Foo {
function bar() {
Another_Class::do_something();
}
}
By default, there will be called Another_Class from the Project\Folder\Subfolder namespace. I want this to refer to Another_Class from the Project\Folder namespace with the same syntax - is that possible?
I hope I explained this clear enough, if not, write a commend, and I'll try to make it clearer.
You can achieve that using the use statement.
use Project\Folder\Subfolder\Another_Class as SomeAlias;
// ...
SomeAlias::doSomething();
// or
$object = new SomeAlias();
$object->doSomething();
Alternatively, you would have to reference the entire namespace:
\Project\Folder\Subfolder\Another_Class::doSomething();
// or
$object = new \Project\Folder\Subfolder\Another_Class();
$object->doSomething();
More information here.