PHP namespaced class within variable - php

Can anyone explain why the below code causes a "Cannot find class" error? Instantiating the class with the fully qualified name works, but eliminates the advantage of the "use" statement.
<?php
namespace
{
use Foo\Bar;
new Bar; // Works
$class = 'Foo\Bar';
new $class; // Works
$class = 'Bar';
new $class; // "Cannot find class" error
}
namespace Foo
{
class Bar {}
}
Thanks

Well, I suppose it's actually a feature. And aliases won't help here, for the same reasons:
Importing is performed at compile-time, and so does not affect dynamic
class, function or constant names. [...]
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // instantiates object of class My\Full\Classname
$a = 'Another';
$obj = new $a; // instantiates object of class Another
?>
And yes, it sorts of defeats the purpose of use with dynamic classes.

Related

Alias inexistent class names in php

Consider the following code:
use ReplacementClass;
class A extends ReplacementClass {
}
The ReplacementClass name in this code should only be a placeholder, an undefined, inexistent class. At runtime, or before runtime, I would like to alias this inexistent class, with a dynamically set existing class, for my code to work. Is there any way in PHP to do this?
Why I would like to achieve this, is that A defined in the above example, is a class in a project plugin, which I would like to make portable, so is ReplacementClass in the original plugin. I would like to keep an option for the team, to extend on these classes, and add new functionalities to them, which are only needed in the specific project that they are working on.
In the above situation, if both of those are real classes, I could extend a B class with A, and add the new functionalities in B, and I could also extend ReplacementClassSpecific with ReplacementClass and add new functionalities to it, but given the single inheritance of PHP, I couldn't extend both.
One way you could do this is with class_exists, and adding a dummy placeholder if it doesn't exist.
But ideally I'd suggest you look into Facades like Laravel uses. This way you can be flexible with implementations, without relying on inheritance.
see it online https://ideone.com/pWf8QU
/* // unhide this to see the two behaviours
class ReplacementClass {
public function foo() {
return "foo";
}
public function bar() {
return "bar";
}
}*/
if(!class_exists('ReplacementClass')) {
class MyReplacementClass {
public function foo() {
echo " foo does not exist, this is a placeholder";
}
public function bar() {
echo " bar does not exist, this is a placeholder";
}
}
}
else {
class MyReplacementClass extends ReplacementClass {
}
}
class FooBar extends MyReplacementClass {
}
$x = new FooBar();
echo $x->foo() . $x->bar() . "\n";
You could use eval() for this. But this is very dirty.
eval("class $className extends $parentClassName {}");
Example
class Foo {}
$className = 'Bar';
$parentClassName = 'Foo';
eval("class $className extends $parentClassName {}");
$bar = new Bar();
var_dump($bar); // gives 'object(Bar)#1 (0) {}'
var_dump($bar instanceof Bar); // gives bool(true)
var_dump($bar instanceof Foo); // gives bool(true)
Caution! Using eval is inefficient and can be very dangerous. Consult the documentation before even thinking about using it.
It would be better to reconsider your use case. There is literally nothing I can think of which would require a fully dynamic class name. If you import your library to a code base at that point you should know what class name is expected and at that point you could extend your parent class with a class of that name.

PHP, execute public static function from $class

how to call public static function of class from different namespace in php. I have this code:
namespace x\y\z;
use x\y\z\h\Foo;
...
$classinstring = 'Foo';
$classinstring::getType();
and i got error that php can't find class Foo Fatal error: Uncaught Error: Class 'Foo' not found how i can do this?
To instantiate a class, you should use new.
$classinstring = new Foo();
Writing $classinstring = 'Foo' assigns $classinstring the string literal "Foo".
Namespacing is a shortcut to your classes. These two statements are equal:
namespace x\y\z;
use x\y\z\h\Foo;
$bar = new Foo();
and
$bar = new \x\y\z\h\Foo();
Also make sure you have your class names spelled exactly the same as the file name.
Static methods do not need to be instantiated to be used; you can call them directly from the class name.
Foo::someCustomMethod();
You are using getType() as an example, although this is a native PHP global function and cannot be called as a static method, unless you have defined your own getType() method within the class.
class Foo
{
public function getType()
{
echo 'This is my own function.';
}
public static function callAnywhere()
{
echo 'You don't have to make a new one to use one.';
}
}
This is good if you need to call class methods.
Foo::callAnywhere() // prints 'You don't have to make a new one to use one.';
$bar = new Foo();
$bar->getType(); // prints 'This is my own function.'
$other = new stdClass();
echo getType($other); // prints 'object';
Try this.
namespace x\y\z;
use x\y\z\h\Foo;
...
$classinstring = 'Foo';
$classinstring = new $classinstring;
$classinstring::getType();
OR
Maybe your file just could not find and access the class x\y\z\h\Foo. Make sure that your class Foo has the namespace of namespace \x\y\z\h.

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

Is it wise to create object of class in the same php class file?

I am a newbie in php oop. My question is is it wise to create object/instance of class in the same class file? like this:
myclass.php
<?php
class myClass{
public $a
function myFunction()
echo $this->a;
}
}
$obj= new myClass;
$obj->$a='This is my class file';
?>
Probably this is wellknown to all expert of php but this is very new and basic concept for me.
There's no rule preventing instantiation of the class in the same file it was defined. It all comes down to what exactly you want to do with it.
For example, you could have a static method that instantiates the class and returns the instance. This is useful for implementing the singleton pattern or the factory pattern. It is however considered bad practice to have global variables like the variable $obj you're defining in your example.
If all you want to do is initialize the instance as it's being created, then you should do so in the constructor.
For example, the MyClass class could reside in a MyClass.php file:
<?php
class MyClass {
private $a;
public function __construct() {
$this->a = 'This is my class file';
}
public function myFunction() {
return $this->a;
}
}
Then, in the file you actually want to use a MyClass instance, you could do something like this:
<?php
require_once 'MyClass.php';
$myInstance = new MyClass();
echo $myInstance->myFunction();

Redeclare class in PHP

Anyone know how to redeclare function?
For example:
class Name{}
//Code here
class Name{}
And the output is:
Cannot redeclare class
So I tried to name the class as a variable:
$foo = 'name';
class $foo{}
//Code
class $foo{}
Edit: I have a DataBase table and I am reading data from the table user 'while()' loop.
I have a class that uses the table and echo some information.
That is the reason.
And it's still not working...
Any suggestions?
If you want to have several classes with the same name, then you should be using namespaces.
Use PHP NameSpace
namespace A {
class Name {
function __toString() {
return __METHOD__;
}
}
}
namespace B {
class Name {
function __toString() {
return __METHOD__;
}
}
}
namespace C {
echo new \A\Name ,PHP_EOL;
echo new \B\Name ,PHP_EOL;
}
Output
A\Name::__toString
B\Name::__toString
Nope. PHP simply doesn't support runtime modification of an existing class
Why would you want to re-declare a class? when you ca reference to it at any point?
I think what you're looking for is to create a new instance of a class:
$foo = 'name';
$obj1 = new $foo();
//Code
$obj2 = new $foo();
You shouldn't have 2 or more classes with the same name. This is not working. How should the interpreter know which class is the correct class?
Change the name of the second class and extend them if you need it.
Edit: Use Namespaces of you need the same classname or if you have an existing class.
If you need two instances of a class you can just initialise it twice as two different varialbes;
class Foo{}
$foo1 = new Foo;
$foo2 = new Foo;
Use PHP namespaces to declare classes with the same name but different purposes.
First of all: Do not do this.
That said, if you really need to "refedine" a class, you can use a wrapper class to do so
<?php
class foo { //Original definition here };
class bar {
var $baseobj;
function bar($some, $args) {
$this->baseobj=new $which($some, $args);
}
function someMethod() {
return $this->baseobj->someMthod();
}
//...
}
class baz {
function someMethod() {
return "This is the result";
}
//...
}
$obj=new bar($this, $that);
//$obj is now a wrapped foo object
echo $obj->someMethod(); //Will call into foo
$obj->baseobj=new baz($this, $that);
//$obj is now a wrapped baz object
echo $obj->someMethod(); //Will call into baz
?>
Again: Do not do this without a very, very good reason!
Disclaimer: This implementation is more than crude, it is only ment to transport the idea.

Categories