How to use defined data as function or class name? - php

I defined a data like below..
define('INDEX_CONTROLLER', 'test');
And I want to use that like below..
require_once 'controllers/' . INDEX_CONTROLLER . '.php';
$this->controller = new INDEX_CONTROLLER();
I'm getting error that below..
Fatal error: Class 'INDEX_CONTROLLER' not found in
/var/www/own/boot.php on line 13

You can set it equal to a variable and then call it:
$controller = INDEX_CONTROLLER;
$this->controller = new $controller();

Better use Reflections
DEFINE('INDEX_CONTROLLER', 'test');
$rc= new ReflectionClass(INDEX_CONTROLLER);
$this->controller = $rc->newInstance();
or in one line if you use php5.4+
$this->controller = (new ReflectionClass(INDEX_CONTROLLER))->newInstance();
You can read more about Reflections here: http://php.net/manual/en/book.reflection.php

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

Dynamically call a method from a dynamically called class

I'm trying to call a controller and method pulled from the URI site.com/controller/method
Here is my current working code:
$__REQUEST__ = new URI_Request($_SERVER["REQUEST_URI"]);
$this->prepareController($__REQUEST__);
if($this->checkClass()) {
$this->controller = new $this->controller();
if($this->checkMethod($__REQUEST__)) {
$method = $__REQUEST__->getMethod();
$this->method = $method;
$this->controller->$method();
}
}
However, I want this line
$this->controller->$method();
To work as similarly to this
$this->controller = new $this->controller();
//achieves something like $this->controller = new IndexController();
//if the URL was something like site.com/index/test (/index/ gets manipulated)
i.e. something like
$this->controller->$this->method
I can see why this wouldn't work, however - is there a way to chain this or get it to reference the $method variable from the object characteristics rather than a stray variable?
$this->controller->{$this->method}();

PHP autoloader with namespaces [duplicate]

This question already has answers here:
How do I use PHP namespaces with autoload?
(13 answers)
Closed 6 years ago.
I am trying to understand how to define a working autoloader for a trivial application with namespaces.
I created following structure:
public
index.php
src
Models
WordGenerator.php
Obviously, later it will grow. The WordGenerator.php file is following:
<?php
namespace Models;
class WordGenerator {
public $filename;
public function __construct($filename) {
$this->_filename = $filename;
}
}
Now I try to create instance of this object in index.php:
<?php
use \Models;
$wg = new WordGenerator("words.english");
Obviously I get fatal error because I did not define autoloader. However though, according to documentation all I can pass is $classname. How should I define the autoloader function to take namespace declared by use statement then??
[edit]
I was wrong understood a moment ago. So here's my code for index.php:
spl_autoload_register(function ($className) {
$className = ltrim($className, '\\');
$prepend = "..\\src\\";
$fileName = "{$prepend}";
$namespace = '';
if ($lastNsPos = strrpos($className, '\\')) {
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$fileName = $prepend.str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
}
$fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
require $fileName;
});
//require '../src/Models/WordGenerator.php';
use Models;
$wg = new WordGenerator("words.english");
echo $wg->getRandomWord();
Now, this does not work and I get:
Warning: The use statement with non-compound name 'Models' has no effect in C:\xampp\htdocs\Hangman\public\index.php on line 22
Warning: require(..\src\WordGenerator.php): failed to open stream: No such file or directory in C:\xampp\htdocs\Hangman\public\index.php on line 16
Fatal error: require(): Failed opening required '..\src\WordGenerator.php' (include_path='.;C:\xampp\php\PEAR') in C:\xampp\htdocs\Hangman\public\index.php on line 16
However when I change new WordGenerator to new \Models\WordGenerator it works. Now, the question is: how can I pass namespaces declared by use statement to autoloader function to make it work properly?
Your use statement is incorrect. You want use Models\WordGenerator;
The use operator doesn't declare anything but an alias. Consider the expanded form:
use Models\WordGenerator as WordGenerator;
Which is equivalent.
You can alias a namespace rather than a class, but it doesn't work in the way you're attempting. For example:
use Models as Foo;
$wg = new Foo\WordGenerator("words.english");
Would work. However:
use Models;
Is equivalent to:
use Models as Models;
Which effectively does nothing.
For more information see Using namespaces: Aliasing/Importing in the PHP manual.
Please look at documentation. Autoloader must be defined by you at beginning of you script. At provided link there is example autoloader and more complex solution

generate class name?

how can you do something like this?
require_once 'class.Table_'.$table.'.php';
$class = new Table_$table();
$className = $var.'someString'.$var2;
$obj = new $className();
In your case
$className = 'Table_'.$table;
$obj = new $className();
Pretty much the way you did it.
The variable has to be the whole class name.
So:
<?php
$clsName = "Table_a";
require_once "class.{$clsName}.php";
$class = new $clsName();
?>
This is supported since PHP 5.2.

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