PHP Instance object with path - php

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.

Related

Why can't I instantiate a new object from a string without a full namespace

Why is it that when I want to instantiate a new object from a string like so
use Foo\Bar\Test
$name = "Test";
$test = new $name();
I get an exception since Test is not found in the global namespace.
I know I could simply use the full namespace when instantiating :
$name = "Foo\\Bar\\Test";
$test = new $name();
But it kind of doesn't fit the use I planned to make out of it. I know it's probably a design flaw on my part for the "doesn't fit" but it still raised the question as to why this cannot be done. Also, if it exists, are there alternatives to this approach? (beside __NAMESPACE__ as in this example I am not currently in Foo\Bar).
You have to differentiate between the information, the compiler resolves at compile and at runtime. At compiletime he resolves alias resolution.
use Foo\Bar\Test
So every occurance of Test would be resolved to \Foo\Bar\Test.
Creating new objects instead is an runtime operation. At this point, there isn't any alias or namespace resolution. The only thing the runtime (new operator) knows at this time, is the given name. If you pass a class, it must always be the full qualified name.

make NAMESPACE declaration conditional?

I include myfile.php file 2 times.. I want to know if there is way to put in the start of myfile.php something like this:
if($authorized){
Namespace MyProject;
}
function ABC(){}
function EFG(){}
(I do this to avoid function-redefine errors. Please dont ask me why I do such thing.. I know there are if function_exists and etc.. but I need answers to what I ask).
update:
I do this, because I need to define function XYZ() and using that before other framework is loaded (which newly defines globally function XYZ()). So I want to use that function (with different functionality) before framework loads, and after framework loads, it should behave as framework decides.
Is there a way to make namespace's conditional?
Although this is impossible directly, I could suggest using the define() method to create this yourself. Where the file requiring the class needs to have a allowed definition to access the file.
define('IN_NAMESPACE', 0);
if(defined('IN_NAMESPACE')) {
// authorized
}
But if you're worrying about a class name being repeated, namespaces are for the declaration of environments so you do not get duplicates, for example:
namespace Environments\One;
class Example { }
namespace Environments\Two;
Class Example { }
use Environments\One\Example as ExampleOne;
use Environments\Two\Example as ExampleTwo;
$e_o = new ExampleOne();
$e_t = new ExampleTwo();
Or simply, directly say you will use this environment like so:
$e_o = new Environments\One\Example();
$e_t = new Environments\Two\Example();
But again, this issue is not canonical to PHP. Use MVC methodologies to over-come these issues and Singleton/Dependency Injection design patterns.

How to reference the desired constant when two classes have the same name in PHP?

I am maintaining an old Zend 1.12 application. This application has two classes named Document (application/models/Document.php), one of which holds a set of constants I need to reference.
Normally this works just fine. However, in one helper (library/App/Helper/Action/Docusign.php) a different Document class (library/Docusign/APIService.php) is being referenced for some reason I can't suss out, and of course it does not have the needed constants.
How can I specify which class it should be using in referencing the constant?
$documentType = Document::DOCUMENT_TYPE_OTHER;
Fatal error: Access to undeclared static property: Document::$DOCUMENT_TYPES in ...
I've tried messing around with various namespaces as well but no luck. Zend seems to be doing something behind the scenes to screw that up :P
Any advice out there for me?
If, as you say, you aren't using any other namespaces, stick this at the very top of library/Docusign/APIService.php:
<?php
namespace Docusign;
...
Then, when referring to that different class, use this code:
$doc = new \Docusign\Document();
$documentType = Document::DOCUMENT_TYPE_OTHER;
Note that any object code within library/Docusign/APIService.php will need to be namespaced as well. So if you have a line like this:
$date = new DateTime();
You'd need to change it to:
$date = new \DateTime();
There is no namespace based solution without tearing everything up and re-doing it to use namespaces properly throughout the app.
Instead, I refactored by changing one of the class names to DocumentModel from Document in order to force differentiation explicitly.

namespaces and autoload - the right way

I want to use Facebook's PHP SDK and want to implement __autoload with it and I'm having problems.
At first I thought that this will work:
function __autoload($class) {
if(file_exists(APPPATH."libraries/facebook/".$class.EXT)) {
require_once(APPPATH."libraries/facebook/".$class.EXT);
}
}
The path is correct by the way.
Now I wanted to use:
$fb = new FacebookSession();
And it didn't work (unknown class), I then discovered this is FacebookSession.php:
namespace Facebook;
I'm not experienced with namespaces in PHP, but I tried this:
$fb = new Facebook\FacebookSession();
My autoloader stopped working, because now $class in __autoload is equal to "Facebook\FacebookSession"
How to handle this? I can't simply do explode or something similar on "\" because, I believe, there can be more such elements, right? Or maybe it's enough to do explode and take the last element, which fill be the final class name to look for? It does work, but is this the right way?

PHP Problems with constructing classes (variables and namespaces)

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;

Categories