PHP Problems with constructing classes (variables and namespaces) - php

I just got stuck with the following problem. I'm trying to construct a class but it isn't working. When I'm constructing the class it uses namespaces and variables, because the variable has to be put behind a backslash (for the namespace) it gives an error.
Here's an example code of defining the class;
$className = 'Help';
$controller = new \controller\$className;
The class name is defined in a variable, in the example code above I've just set it to 'Help'. When constructing the class it has \controller\ in front of it, that's cause it's in that namespace. If I remove the namespace thing away so it just has;
$controller = new $className;
it does work. The problem is probably caused because there's a backslash in front of the variable which contains the class name to construct. I am not able to add use controller; in the beginning of the code because the file containing the class is loaded inside the constructor, and the class is immediately constructed after the file has been loaded. The use function could only be used in the beginning of your file, not inside a method, I think.
I hope someone could help me out,.
Thanks in advance,
Tim Visée

Your first example is invalid syntax. You would need instead something like:
$className = '\controller\Help';
$controller = new $className();

Set the fully qualified class name to a variable and use that to instantiate a new object:
$className = '\controller\Help';
$controller = new $className;

Related

Laravel, resolve dependecy by passing class name as string

When I try to resolve a dependecy class like this
app(MyClass::class);
it works perfectly, but what I actually need is to pass the name of the class like a string, something similar to this:
$className = 'MyClass';
app($className::class);
I tried using reflection and every possible way but without success.
You have to pass full namespace of your class such as:
$className = "\\App\\MyClass";
app($className);

Define classes based on variables in PHP

So, I'm developing a webapp under my own mvc structure and all Controller classes are defined inside their own files, e.g.: HomeController is defined inside HomeController.php. So my question is: is it possible to automatically define a class based on its file name? Like, I tried to catch the filename using FILE, then to define a class based on that.
$path = __FILE__; // "C:.../app/Controller/HomeController.php"
$array = explode(DIRECTORY_SEPARATOR, $path);
array_pop($array); // In order to remove "HomeController.php"
$class = end($array); // Controller
$className = 'Home'.$class;
class $className {} // This is not working, so is it possible or not?
Short answer: no.
Long answer: you cannot do it the way you want to. What you could do is create code that creates the PHP file and generates a boilerplate class from a template.
It is possible by using the infamous PHP function eval():
$className = 'Home'.$class;
eval("class $className {}");
But it is not practical for your purpose.
This method is used by the testing tools to create mock objects. PHPUnit's Mock Object library, for example, uses it a lot.

PHP Instance object with path

I'm trying to create an instance of an object with a path like(C:\wamp\www...)
In a new project I have this method, and I try with that to instance an object of an another project.
public function getControllerObject($class)
{
$object = null;
$class = realpath($class);
$class = str_replace('.php','',$class);
$object = new $class();
}
the variable $class have for exemple this value :
C:\wamp\www\myproject\projectBundle\Controller\DefaultController
But i get FatalErrorException: Error: Class. Class not found
I already try to put 2 backslash but it doesn't work.
Any idea?
Use basename, not realpath:
$class = basename($class);
For your example it should produce DefaultController.
First of all, what you are trying to do sounds like a horrible idea! If you want to access the class from another project you should add it (the project or the files) to your dependencies.
Your problem is, that what you basically do is:
$object = new C:\wamp\www\myproject\projectBundle\Controller\DefaultController();
which is obviously not what you want. When you do not enter a valid path (which I assume is what happened) realpath will return false and it won't work either.
You have to somehow determine which part of the path is part of the namespace and which is not. You could do this by also adding the project root, meaning which part to strip from the path or the namespace itself, i.e. the part to keep from the path (assuming you follow the recommendations from PSR-0), which should leave you with what you want (after str_replace() a preg_replace() or something similar).
Anyway, the cleanest way to solve your problem (apart from adding a dependency), is to use Symfony Class Loader instead of hardcoding paths into your application.

Namespaces - __autoload() is requiring a wrong class

I am builded a new object in my file without namespaces:
new My\Validator();
Above, in the same file I have got __autoload():
function __autoload($className)
{
var_dump($className);
}
The __autoload() function prints
'My\My\Validator'.
Where is the double 'My' come from?
It is adding the My namespace because you are probably inside the My namespace already when you create the object with new My\Validator().
namespace My;
$obj = new My\Validator();
will be translated to:
$obj = new My\My\Validator();
Since you are inside the My namespace already you can:
either just call new Validator()
or call new \My\Validator()
The beginning \ will tell PHP to look into the global namespace.
On a side note, it is considere good practice to use spl_autoload_register instead of __autoload, because you can set multiple autoloader callbacks.

PHP namespace with Dynamic class name

Wondering if anyone else has encountered this problem when utilizing the new ability to namespace classes using PHP 5.3.
I am generating a dynamic class call utilizing a separate class for defining user types in my application. Basically the class definer takes an integer representation of types and interprets them, returning a string containing the classname to be called as the model for that user.
I have an object model for the user's type with that name defined in the global scope, but I have another object with the same name for the user's editor in the Editor namespace. For some reason, PHP won't allow me to make a namespaced dynamic call as follows.
$definition = Definer::defineProfile($_SESSION['user']->UserType);
new \Editor\$definition();
The identical syntax works for calling the global basic object model in the global namespace and I use it this way reliably throughout the application.
$definition = Definer::defineProfile($_SESSION['user']->UserType);
new $definition();
This will correctly call the dynamically desired class.
Is there a reason the two would behave differently, or has dynamic calling for namespaces not been implemented in this manor yet as this is a new feature? Is there another way to dynamically call a class from another namespace without explicitly placing its name in the code, but from within a variable?
Well, just spell out the namespace in the string:
$definition = Definer::defineProfile($_SESSION['user']->UserType);
$class = '\\Editor\\' . $definition;
$foo = new $class();
And if it's a child namespace (as indicated in the comments), simply prepend the namespace with __NAMESPACE__:
$class = __NAMESPACE__ . '\\Editor\\' . $definition;
So if the current namespace is \Foo\Bar, and $definition is "Baz", the resulting class would be \Foo\Bar\Editor\Baz

Categories