Instantiating a PHP class using a variable is not working - php

This is working:
$x = new classname();
This is not working:
$class = "classname";
$x = new $class();
The error I get is "Class classname not found". PHP version is 5.4.22. Any ideas? As far as I have researched into this topic this is exactly what you need to do in order to instantiate a class using a variable.
My actual testcode (copy+paste), $build = 1:
//include the update file
$class="db_update_" . str_pad($build, 4, '0', STR_PAD_LEFT);
require_once(__ROOT__ . "/dbupdates/" . $class . ".php");
$x = new db_update_0001();
$xyz="db_update_0001";
$x = new $xyz();
The class definition:
namespace dbupdates;
require_once("db_update.php");
class db_update_0001 extends db_update
{
...
}
I just found out that my editor added
use dbupdates\db_update_0001;
to the file. So that explains why "new db_update_0001();" is working. What i want to achieve is that I dynamically include database updates which are stored in files like dbupdates/db_update_0001.php
Regards,
Alex

You have to use the full qualified class name. Which is namespace\classname. So in your case the code should be:
$x = new db_update_0001();
$xyz="dbupdates\db_update_0001";
$x = new $xyz();
The use statement is useless if you like to instantiate a class by using a variable as classname.

Try this
<?php
$className = yourClassName();
$x = new $className;
?>

Related

new class from variable

I've got a problem. I'm using Laravel 5.4 and on initialization
$class = (string)$module->controller.'Controller';
$class = new $class();
$class->startModule($module->title,$request);
I get a response from server FatalErrorException in ModulesController.php line 29:
Class 'FileManagerController' not found
image
but on manual call it works fine
$class = new FileManagerController();
$class->startModule($module->title,$request)
Plese tell me what's the problem?
First require class and then create instance:
$class = (string)$module->controller.'Controller';
require_once $class . '.php';
$class = new $class();
$class->startModule($module->title,$request);
I've got solution
$class = (string)$module->controller.'Controller';
app('App\Http\Controllers\\'.$class)->startModule($module->title,$request);

Can I use a string variable to initialize a class in PHP?

I'd like to use a string variable to initialize an object. Is something like this possible?
$class = "MyClass";
$x = new $class();
return $x;
Edit: Ha, so when I tried to test this and it didn't work I had a syntax error somewhere else in my script. Apparently this works just fine. Neat.
Yes. Its possible in PHP.
$className = 'MyClass';
$object = new $className;
Attaching PHP documentation snippet on new operator

Use variable as namespace

In some other file (someusername\classes\MyClass for instance), I have
<?php
namespace someusername;
class MyClass
{
static function Test()
{
echo "working";
}
}
?>
I have stumbled across an annoying little barrier:
<?php
$user = "someusername";
$class = "MyClass";
require_once "$user\\classes\\$class";
//This line should be the equivalent of 'use someusername as User;'
use $user as User; //Parse Error: syntax error, unexpected '$user'
$c = "User\\$class";
$UserSpecificClass = new $c();
?>
I can get around it via the following, but the use statement would make things a lot nicer
<?php
$user = "someusername";
$class = "MyClass";
require_once "$user\\classes\\$class";
$c = "$user\\$class";
$UserSpecificClass = new $c();
?>
Is it possible to use variables in use statement in PHP? Or is it better to avoid the use statement with this approach?
Importing is performed at compile-time.
Assigning the variable is done at run-time after compilation, at which point any import should already be imported.
So this is not possible. Best solution would indeed be to use the FQN in a string and initialize that.
$c = "$user\\$class";
$UserSpecificClass = new $c();

PHP : dynamic instance with not fully-qualified namespaces

I'd like to instanciate my class doing :
use somedir\http as Http;
$S_bodyWriterType = 'Http\\' . strtolower($S_requestBodyPayloadType) . '\\RequestBodyWriter';
$this->_O_requestBodyWriter = new $S_bodyWriterType;
It says the class does not exist. However THAT would work (no string involved here) :
$this->_O_requestBodyWriter = new Http\xml\RequestBodyWriter;
And that would also work of course (the namespace is fully qualified) :
$S_bodyWriterType = 'somedir\http\\' . strtolower($S_requestBodyPayloadType) . '\\' . 'RequestBodyWriter';
$this->_O_requestBodyWriter = new $S_bodyWriterType;
i'd definitely prefer to use shortened namespaces instead of having to write long, fully-qualified namespaces in different places of the codebase and having to change them all in case the directory location moves. I've been pulling my hair off for a while now over this.
Thanks for help !
OK, you provided the Bug report yourself ;) But thats the fact: If you define a classname in a string, its not said, that the object is created in the same context.
namespace y {
use a\b as B;
$GLOBALS['class'] = 'B\\MyClass';
}
namespace z {
use k\l as B;
$classname = $GLOBALS['class'];
$a = new $classname;
}
Thus you need to define classnames in string full qualifed. I suggest to use (namespace-/class-)constants
use a\b as B;
const NAMESPACE_B = '\\a\\b';
$classname = NAMESPACE_B . '\\MyClass';
If the class you want to instanciate is in a subnamespace, remember, that the pseudo-constant __NAMESPACE__ always exists;
namespace a;
use a\b as B;
$classname = __NAMESPACE__ . '\\b\\MyClass';
Additional in your case I suggest to create a factory
use somedir\http as Http;
class RequestBodyWriterFactory {
public function create($type) {
$classname = __NAMESPACE__ . "\\$type\\RequestBodyWriter";
return new $classname;
}
}
// somewere else
$this->_O_requestBodyWriter = $this->factory->create(strtolower($S_requestBodyPayloadType));
This way you have more control on what is created and how its created.

PHP custom class loader

i made a custom class loader function in php
something like..
load_class($className,$parameters,$instantiate);
its supposed to include the class and optionally instantiate the class specified
the problem is about the parameters. ive been trying to pass the parameters all day
i tried
load_class('className',"'param1','param2'",TRUE);
and
load_class('className',array('param1','param2'),TRUE);
luckily nothing works xD
is it possible to pass the params?
i even tried..
$clas = new MyClass(array('param1','param2'));
here it is..
function load_class($class, $param=null, $instantiate=FALSE){
$object = array();
$object['is_required'] = require_once(CLASSES.$class.'.php');
if($instantiate AND $object['is_required']){
$object[$class] = new $class($param);
}
return $object;
}
if you are in PHP 5.x I really really recommend you to use autoload. Prior to PHP 5.3 you should create sort of "namespace" (I usually do this with _ (underscore))
autoload allows you to include classes on the fly and if your classes are well designed the overhead is minimun.
usually my autoload function looks like:
<?php
function __autoload($className) {
$base = dirname(__FILE__);
$path = explode('_', $className);
$class = strtolower(implode('/',$path));
$file = $base . "/" . $class;
if (file_exists($file)) {
require $file;
}
else {
error_log('Class "' . $className . '" could not be autoloaded');
throw new Exception('Class "' . $className . '" could not be autoloaded from: '.$file);
}
}
this way calling
$car = new App_Model_Car(array('color' => 'red', 'brand' => 'ford'));
the function will include the class
app/model/car.php
Seems to me that you should be using __autoload() to just load classes as they are referenced and circumvent having to call this method manually. This is exactly what __autoload() is for.

Categories