Creating a PHP object where the classname is a variable - php

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.

Related

PHP: Namespace and calling one class into other

I have two classes, Class1 and Class2 which are under namespace myNameSpace.
I want to create an instance of Class2 in classand I am getting an error in implementing fileClass 'myNameSpace\Class2' not found in.. `. Code given below:
Class1.php
namespace myNameSpace {
use myNameSpace\Class2;
class Class1
{
public function myMethod()
{
$obj = new Class2();
}
}
call.php
namespace myNameSpace {
include 'Class1.php';
error_reporting(E_ALL);
ini_set('display_errors',1);
use myNameSpace\Class1;
$o = new Class1();
$o->myMethod();
}
If they're both in the same namespace you should not have to use a "use" statement. Seems more likely that you're not simply includeing both files.
Maybe what you're looking for is autoloading? http://php.net/manual/en/language.oop5.autoload.php

Call function from different class and namespace

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!

Namespacing forces my class to be unfound

namespace foo;
class foo{
}
$foo = new foo();
If I removed the namespace, the class works just fine, if the namespace is there, I get class foo unfound error. What is the reason for this?
If your class is namespaced, then you need to reference that namespace when instantiating (assuming you're in the global namespace when you instantiate).
$foo = new foo\foo();
That's the whole point. You can have multiple foo classes in different namespaces.
namespace foo;
class foo {}
And then...
namespace bar;
class foo {}
And now...
$foo1 = new foo\foo();
$foo2 = new bar\foo();
Read up on how namespaces work: http://it2.php.net/namespaces

Tthe namespace equivalent of the static operator for classes in PHP?

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";

Is it possible to use namespace without a class

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
?>

Categories