Is it possible to use namespace without a class?
For example:
namespace Foo;
// rest of the procedural code and functions
Asking because I have notion that namespace are only used where there are classes.
Thanks for your help.
Yes, you can use namespace without a class, like:
//demo.php file
namespace FooDemo;
function first() { return "First"; }
function second() { return "Second"; }
function third() { return "Third"; }
//test.php file
require_once 'demo.php';
foreach (array("first","second","third") as $funcs) {
echo call_user_func('FooDemo\\'.$funcs);
}
Did you mean something like this
Yes, it is. See the documentation.
Extract:
<?php
namespace Foo\Bar;
include 'file1.php';
const FOO = 2;
function foo() {}
class foo
{
static function staticmethod() {}
}
/* Unqualified name */
foo(); // resolves to function Foo\Bar\foo
foo::staticmethod(); // resolves to class Foo\Bar\foo, method staticmethod
echo FOO; // resolves to constant Foo\Bar\FOO
/* Qualified name */
subnamespace\foo(); // resolves to function Foo\Bar\subnamespace\foo
subnamespace\foo::staticmethod(); // resolves to class Foo\Bar\subnamespace\foo,
// method staticmethod
echo subnamespace\FOO; // resolves to constant Foo\Bar\subnamespace\FOO
/* Fully qualified name */
\Foo\Bar\foo(); // resolves to function Foo\Bar\foo
\Foo\Bar\foo::staticmethod(); // resolves to class Foo\Bar\foo, method staticmethod
echo \Foo\Bar\FOO; // resolves to constant Foo\Bar\FOO
?>
Related
I know, that are some stupid questions, but I am a little bit confused.
Above, it is a screenshoot from https://docs.typo3.org/m/typo3/book-extbasefluid/main/en-us/7-Controllers/1-Creating-Controllers-and-Actions.html.
As you can see, in one case there is no '\' before MyVendor, in another one it is. Are both way possible?
In my extensions I have under Classes the following structure.
If I use the use function, It is not necessary to `Classes in the statement.
use MyVendor\ExtName\Controller\MainController is enough?
You are use'ing namespace, not file structure, so you must use exact namespace
If you want to use methods from class, you must use that class. If function (not method) is under namespace, then that function must be used (as there is no class to use)
Leading \ is optional, but preferred style is without leading \
// a.php
namespace MyVendor\ExtName\Controller;
function test() {
echo 'Test2';
}
class MainController {
public static function test() {
echo 'Test';
}
}
// b.php
namespace AnotherVendor\ExtName\Controller;
class MainController {
public static function test() {
echo 'Test 3';
}
}
// c.php
namespace MyVendor\ExtName\Utilities;
use MyVendor\ExtName\Controller\MainController;
use AnotherVendor\ExtName\Controller\MainController as AnotherController;
use function MyVendor\ExtName\Controller\test;
class MainUtility {
public function foo() {
MainController::test();
AnotherController::test();
test();
}
}
Why do I receive an error without using a fully qualified name for Bar?
Foo.php
<?php
namespace Bla\Bla;
require '../../vendor/autoload.php';
class Foo
{
public function getBar()
{
$className="Bar";
$fullClassName='\Bla\Bla\\'.$className;
$obj1=new Bar(); //Works
$obj2=new $fullClassName(); //Works
$obj3=new $className(); //ERROR. Class Bar not found
}
}
$foo=new Foo();
$foo->getBar();
Bar.php
<?php
namespace Bla\Bla;
class Bar {}
$obj1=new Bar();
The statement will work because Bar is defined in namespace Bla\Bla that you are already in.
$obj2=new $fullClassName();
This will work because you are referring to the class from the global namespace.
$obj3=new $className();
This will not work because you try to initiate class Bar from a string, in which the current namespace Bla\Bla is not prepended to the class name.
It would work if you define a class Bar inside the global namespace.
#Bar.php
<?php
namespace Bla\Bla{
class Bar {}
}
namespace {
class Bar {
public function __construct(){ echo 'Hi from global ns!';}
}
}
You have to use the full namespace of the class. Try this: (not tested)
$className="Bla\\Bla\\Bar";
In case the namespace is Bla\Bla.
I'm having some trouble to call a function from a namespaced class in a different namespaced class. In the dummy example below I would like to know how to use Class2 within Class1. I'm getting the error:
Trait 'name1\name2\Class2' not found in class1.php
The code:
#file index.php
require "class1.php";
require "class2.php";
$class1 = new name1\Class1();
$class1->sayHello();
#file class1.php
namespace name1{
class Class1{
use name2\Class2;
public function sayHello(){
echo Class2::staticFunction();
}
}
}
#file class2.php
namespace name2{
class Class2{
public static function staticFunction(){
return "hello!";
}
}
}
Thank you for any advice.
Ok, so you've got several errors which I have fixed.
Here's the working code you need:
# index.php
include "class1.php";
include "class2.php";
$class1 = new name1\Class1();
$class1->sayHello();
# class1.php
namespace name1;
use name2\Class2;
class Class1{
public function sayHello(){
echo Class2::staticFunction();
}
}
# class2.php
namespace name2;
class Class2{
public static function staticFunction(){
return "hello!";
}
}
Some explanations:
When in class definition the use is used for using traits and not namespace
In PHP namespace need not be enclosed in curly brackets
In PHP you include files with include, include_once, require, or require_once, and not import
Inside your first class, your trait is calling class2 as use name2\Class2 but, you are still within the name1{} namespace, so in reality you are calling it as: use name1\name2\Class2
So, you need to change
use name2\Class2; to use \name2\Class2
Try this.
namespace name1{
use \name2\Class2;
class Class1{
public function sayHello(){
echo Class2::staticFunction();
}
}
}
#file class2.php
namespace name2{
class Class2{
public static staticFunction(){
return "hello!";
}
}
}
Also, another tip: If you are separating your classes in separate files, you do not need to separate them as in they way you have done. Just call the namespace simple as:
// file1.php
namespace person;
class name{}
//file2.php
namespace address;
class name{}
Why not drop the static method and just inject the class? Seems like going through extra work for something so simple. That's what function arguments are made for.
namespace name1{
use \name2\Class2;
class Class1{
public function sayHello($Class2){
echo $Class2->someFunction();
}
}
}
namespace name2{
class Class2{
public function someFunction(){
return "hello!";
}
}
}
#index.php
include "class1.php";
include "class2.php";
$Class1 = new name1\Class1();
$Class2 = new name2\Class2();
$Class1->sayHello($Class2);
//hello!
The documentation says
The namespace keyword can be used to explicitly request an element from the current namespace or a sub-namespace. It is the namespace equivalent of the self operator for classes.
I need the equivalent of static instead, ie. if a class extends my class, the namespace of that.
This
return preg_replace('/.[^\\\\]+$/', '', get_class($object));
does it but it makes me sad.
Reflection provides an effective way of doing this via ReflectionObject->getNamespace(), check the following code:
namespace Foo {
class Bar {
public function getNamespace() {
return (new \ReflectionObject($this))->getNamespaceName();
}
}
}
namespace Baz {
use Foo\Bar as BaseClass;
class Bar extends BaseClass {}
}
namespace {
$bar1 = new Foo\Bar();
echo "ns1 is: ", $bar1->getNamespace(), '<br>';
$bar2 = new Baz\Bar();
echo "ns2 is: ", $bar2->getNamespace();
}
I don't think there's a "late static namespace" helper and you will indeed need to hack around.
e.g.
<?php
namespace ProjectFoo;
class Foo {
public static function ns() { echo __NAMESPACE__; }
public static function getNamespace() {
return static::ns();
}
}
namespace ProjectBar;
use ProjectFoo\Foo;
class Bar extends Foo {
public static function ns() { echo __NAMESPACE__; }
}
$foo = new Foo();
$foo::getNamespace();
print "\n";
$bar = new Bar();
$bar::getNamespace();
print "\n";
If I had two classes in separate namespaces (and therefor files), and they both called a function in the global namespace - is there any way to indentify which namespace called that function short of passing the value?
namespace A;
class Test { function run() { \func(); }
...
namespace B;
class Test { function run() { \func(); }
...
function func()
{
// Did a class from "\A" call me or "\B"...?
}
My first thought was to use the __NAMESPACE__ constant. But that is computed in place so it would not solve this problem.
You could define versions of the function in each namespace that then calls func();
namespace A;
class Test { function run() { func(); }
...
namespace B;
class Test { function run() { func(); }
...
namespace A
{
function func()
{
\func(__NAMESPACE__);
}
}
namespace B
{
function func()
{
\func(__NAMESPACE__);
}
}
namespace
{
function func($namespace)
{
//work with $namespace
}
}
debug_backtrace() will show you the call stack. It also gives you the class name of the object that the calls were made from. You could parse this date out and find the namespace.
http://www.php.net/manual/en/function.debug-backtrace.php
function func()
{
$trace = debug_backtrace();
$class = $trace[1]['class']; //Should be the class from the previous function
$arr = explode($class, "\");
array_pop($arr);
$namespace = implode($arr, "\");
}
Let me know if that works. It will probably only work if func() is called from inside an object or class.