I'm learning about the namespaces in PHP. Here is the code I use
lib1.php
<?php
namespace App\Lib1;
const MYCONST = "App\Lib1\MYCONST";
function MyFunction() {
return __FUNCTION__;
}
class MyClass {
static function WhoAmI() {
return __METHOD__;
}
}
app.php
<?php
header('Content-type: text/plain');
require_once 'lib1.php';
echo App\Lib1\MYCONST;
The problem is that for some reason I get
Undefined constant 'App\Lib1\MYCONST' in <b>/Applications/MAMP/htdocs/namespaces/myapp.php
What I'm doing wrong?
namespace App\Lib1;
const MYCONST = "App\Lib1\MYCONST";
function MyFunction() {
return __FUNCTION__;
}
class MyClass {
static function WhoAmI() {
return __METHOD__;
}
}
header('Content-type: text/plain');
require_once 'lib1.php';
use App\Lib1;
echo \App\Lib1\MYCONST;
Try this though tbh I'm not massively familiar with namespacing in php. I'm not sure the use is 100% required or if indeed it needs the leading \ on it it could need to be use \App\Lib1
I would also think that instead it should just be namespace App; in your declaration file then you'd do echo \App\MYCONST; but again not familiar enough it could be fine with sub namespace
Related
Decided to start using namespaces in my PHP projects and am struggling in getting this simple setup to work... What am I doing wrong?
First.php
<?php
namespace MyNamespace;
use PDO;
class First {
function hello() {
return 'hello';
}
}
Second.php
<?php
namespace MyNamespace;
use PDO;
use function \MyNamespace\First;
class Second {
function world() {
$firstpart = \MyNamespace\First::hello();
return $firstpart . ' world';
}
}
index.php
<?php
echo \MyNamespace\Second::world();
?>
This gives me an error:
Strict Standards: Non-static method MyNamespace\Second::world() should not be called statically in /var/www/testsite/index.php on line 2
Basically, I am looking for a way to call different functions in different classes within the same namespace. Have never used namespaces before and for the life of me however I try to call my functions, they end up giving me the same errors. Any pointers please?
Your error indicates an attempt to call a static method, which is not (class Second, method world - not static)
And importing function space names must be as follows:
First.php
<?php
namespace MyNamespace;
function hello() {
return 'hello';
}
Second.php
<?php
namespace MyNamespace;
use function \MyNamespace\First\hello;
class Second {
static function world() {
$firstpart = hello();
return $firstpart . ' world';
}
}
And use, for example:
Second::world()
(I add static word in declaration method world)
Read this
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.
This post is due to some difficulty I am having extending a class defined in a first namespace from a second namespace. Based on this post :
PHP how to import all classes from another namespace
I tried this :
File NameSpace1 :
<?php
namespace FirstNS;
class baseObject
{
public $baseVar = 1;
public function baseFun() {}
}
?>
File NameSpace2 :
<?php
namespace SecondNS;
use FirstNS;
class extendedObject extends FirstNS\baseObject {
public $extendedVar = 1;
public function extendedFun() {
}
}
?>
However $this in extendedFun can only access $extendedVar and extendedFun, not $baseVar and baseFun. I have also tried use FirstNS as ClassFromFirstNS; and class extendedObject extends ClassFromFirstNS however $baseVar and baseFun are still not accessible via $this. The information at http://www.php.net/manual/en/language.namespaces.rationale.php, http://www.php.net/manual/en/language.namespaces.definition.php and http://www.php.net/manual/en/language.namespaces.importing.php also did not seem to directly address this case.
Give this a shot:
// File1.php
namespace FirstNS;
class baseObject
{
public $baseVar = 1;
public function baseFun() {}
}
// File2.php
namespace SecondNS;
include 'File1.php';
use FirstNS;
class extendedObject extends FirstNS\baseObject {
public $extendedVar = 2;
public function extendedFun()
{
var_dump($this->baseVar); // Outputs 1
var_dump($this->extendedVar); // Outputs 2
}
}
// File3.php
include 'File2.php';
$object = new SecondNS\extendedObject();
$object->extendedFun();
I have no problems to get your code to work, it's not clear from your question where you've got a problem:
namespace FirstNS
{
class baseObject
{
public $baseVar = 1;
public function baseFun() {}
}
}
namespace SecondNS
{
use FirstNS;
class extendedObject extends FirstNS\baseObject
{
public $extendedVar = 1;
public function extendedFun()
{
echo $this->extendedVar, "\n"; # works
$this->baseFun(); # works
}
}
echo '<pre>';
$obj = new extendedObject();
echo $obj->baseVar, "\n"; # works
$obj->extendedFun();
}
Demo - Hope this is helpful.