I'm building a script that got a static class used to load few things including files and views.
class load
{
public static function view($file_path, $area)
{
debug::log('getting view <b>' . $area . $file_path . '</b>.');
ob_start();
self::file($file_path, 'areas/' . $area . '/views');
debug::log('flushing view <b>' . $area . $file_path . '</b>.');
eturn ob_get_clean();
}
public static function file($file, $folder)
{
if(is_file($file_path = ROOT . '/' . $folder . '/' . $file))
{
if(require_once $file_path)
{
debug::log('file <b>' . $file_path . '</b> included.');
return true;
}
}
else
debug::kill('requested file <b>' . $file_path . '</b> does not exist.');
}
}
In the controller Im calling the view method to get a view:
$html = load::view('public', 'path/to/view/file.php');
Obviously, Im not able to access the variables from the controller at the view file using this practice, so I did a small modification on the view class to capture the vars:
public static function view($file_path, $area, $vars = array())
And added the following lines of codes to get the keys into vars:
while(list($n_list_var,$v_list_var)=each($vars))
$$n_list_var = $v_list_var;
But again I can't access the vars since Im using a method to load a file.
I have a method to load the files because I wanna test and log each file include attempt and not repeat the code every time I need include a file. And I have the loader view inside the loader class so I have all the methods of this kind together. Should I give up on using a class to load files? Should I use the loader view method on a extendable class from my controller?
Instead of going ahead and modify my entire script I would like to hear some opinions ... what would be the best practice to go? Or is there a way to solve my problem? Maybe using __set and __get magic methods?
Thanks,
Why not just pass a $vars argument to load::file() and extract( $vars ) (possibly moving the vars you use inside file() into class variables to prevent them from being overwritten)?
I'm suggesting using extract() instead of:
while(list($n_list_var,$v_list_var)=each($vars))
$$n_list_var = $v_list_var;
By the way, it would be a good idea to name your class Load.
Related
I have a custom module, and now want to call the add() function from checkout/cart. How do I call the controller and function?
I have tried $this->load->controller('checkout/cart'); but this returns a fatal exception.
I am using OpenCart v 1.5.6.4
In OpenCart 1.5.*, getChild is used to load other controllers. Specifically, it is running a route to the desired controller and function. For example, common/home would load the home controller from the common group/folder. By adding a third option we specify a function. In this case, 'add' - checkout/cart/add.
class ControllerModuleModule1 extends Controller {
protected function index() {
ob_start();
$this->getChild('checkout/cart/add');
$this->response->output();
$response = ob_get_clean();
}
}
Most controllers don't return or echo anything, but specify what to output in the $this->response object. To get what is being rendered you need to call $this->response->output();. In the above code $response is the json string that checkout/cart/add echos.
To solve the same issue, I use $this->load->controller("checkout/cart/add").
If I use getChild, this exception get thrown : "Call to undefined method Loader::getChild()".
What is the difference between the 2 methods? Is getChild better?
The problem with getChild() is it only works if the controller calls $this->response->setOutput() or echo at the end - producing actual output. If on the other hand, you want to call a controller method that returns a variable response, it isn't going to work. There is also no way to pass more than one argument since getChild() accepts only one argument to pass, $args.
My solution was to add this bit in 1.5.6.4 to system/engine/loader.php which allows you to load a controller and call it's methods in the same way as you would a model:
public function controller($controller) {
$file = DIR_APPLICATION . 'controller/' . $controller . '.php';
$class = 'controller' . preg_replace('/[^a-zA-Z0-9]/', '', $controller);
if (file_exists($file)) {
include_once($file);
$this->registry->set('controller_' . str_replace('/', '_', $controller), new $class($this->registry));
} else {
trigger_error('Error: Could not load controller ' . $controller . '!');
exit();
}
}
Now you can do this:
$this->load->controller('catalog/example');
$result = $this->controller_catalog_example->myMethod($var1, $var2, $var3);
I have the follow code snippet and works well:
<?php
require_once(FOLDER_ROOT . "/lib/transaction/RetornoBanco.php");
require_once(FOLDER_ROOT . "/lib/transaction/RetornoFactory.php");
$fileName = 'test.txt';
function rowProcess($self, $numLn, $vrow) {
print ($numLn . ' - ' . $vrow);
}
$test = RetornoFactory::getRetorno($fileName, 'rowProcess');
$retorno = new RetornoBanco($test);
$retorno->process();
The getRetorno function uses 'rowProcess' as a handler function.
But now I'm trying do it in my custom controller (on my own Magento Extension, looks like Zend Controllers).
For each line of my file (test.txt), rowProcess runs.
But now, in my controller, rowProcess has a class.
My controller:
class MY_CLASS_HERE extends Mage_Adminhtml_Controller_Action
{
public function uploadAction()
{
//just to simplify, this uploaded file exists
$fileName = '/home/user/public_html/app/files/file.RET';
$test = RetornoFactory::getRetorno($fileName, "rowProcess");
$retorno = new RetornoBanco($test);
$retorno->process();
echo 'My Controller Here';
}
public function rowProcess($self, $numLn, $vrow)
{
print ($numLn . ' - ' . $vrow);
//I'm creating log to prevent it is not a problem for standard output
Mage::log($numLn . ' - ' . $vrow);
//This function log is default in Magento and works without problems.
}
}
My controller works well but now the handler doesn't print nothing!
I think it's wrong because now my function handler inside a class and getRetorno function can not use it. What could I do to fix this?
How about using like this? Can you try it?
$test = RetornoFactory::getRetorno($fileName, $this->rowProcess);
Currently, I have a pretty average php auto loader loading in my classes. I've come to a point in development where I will need to override a class with another class based on a variable. I'm running a custom SaaS application, and we have the occasional organization that will demand some weird change to the way the system functions. In the past, we've filled up our code with garbage by massive IF statements for orgs, such as
if(ORGID == 'ABCD'){
//do this insane thing
}else{
//Normal code here.
}
So, I've been toying with the idea of a dynamic auto loader. ORGID is one of the very first defines in the application. The entire application is running under a fixed namespace of COMPANY\PRODUCT; Here's a code sample of what I was thinking I could do.
class MyLoader {
static public function load($name) {
$temp = explode('\\',$name);
$class = array_pop($temp);
$name = str_replace('_',DIRECTORY_SEPARATOR,$class);
if(file_exists(ROOT.'includes/_classes/' . $name . '.php')){
include(ROOT.'includes/_classes/' . $name . '.php');
}
}
}
spl_autoload_register(__NAMESPACE__ .'\MyLoader::load');
Since ROOT and ORGID are defined before the autoloader comes into play, I thought about doing this
class MyLoader {
static public function load($name) {
$temp = explode('\\',$name);
$class = array_pop($temp);
$name = str_replace('_',DIRECTORY_SEPARATOR,$class);
if(file_exists(ROOT.'includes/_classes/' . ORGID . '/' . $name . '.php')){
include(ROOT.'includes/_classes/' . ORGID . '/' . $name . '.php');
}elseif(file_exists(ROOT.'includes/_classes/' . $name . '.php')){
include(ROOT.'includes/_classes/' . $name . '.php');
}
}
}
spl_autoload_register(__NAMESPACE__ .'\MyLoader::load');
While this works, I have to copy/paste my entire class into the org specific class file, then make changes. I can't extend the primary class, because the classes share the same name. The only option I've been able to come up with that would allow me to extend my classes in such a way is to never load the base class.
Instead of
$myObj = new myClass();
I call
$myObj = new customMyClass();
and I have a file called customMyClass(); which simply extends myClass without making any changes to it. This way, the auto loader will load customMyClass and then load myClass. If an organization has their own customMyClass in their organization folder, then it will load in that class, which will then properly load in myClass.
While this works, we have hundreds of class files, which would double if we had a custom file for each.
I've seen a couple of examples that use eval to handle similar situations. Is that really the only way to do this type of thing?
UPDATE:
Just so I'm clear, the end goal is so that the thousands of places we've called $myObj = new myClass(); doesn't need to be rewritten.
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.
I'm getting a "Call to a member function process_data() on a non-object in page.class.php on line 35" even though the object has been called.
Here is the index.php extraction showing the object being instantised
// require our common files
require("modules/module.php");
require("registry/objects/datetime.class.php");
require("registry/objects/page.class.php");
// load in all the objects
$datetime = new dateandtime;
$page = new page;
$module = new module;
It then passes to the Process class
require("template.class.php");
$template = new template($php_path . "controllers/themes/adm/" . $page . ".html");
// Place in both commonly used language and page specific language
$template->language($php_path . "controllers/language/en/adm/common.php");
$template->language($php_path . "controllers/language/en/adm/" . $page . ".php");
// Tell the page's module to load in data it needs
$module->process_data("module_" . $page);
// Output the final result
$template->output();
It's at this point PHP is throwing the error. The contents of the module.php file is as follows
class module {
public function process_data ($child) {
require($child . ".php");
read_data();
return true;
}
}
I've tried moving the instance declaration to within the second pasted code, but that generates more errors, because the class that "module" calls in then uses some of the "template" classes as well - so the same issue occurs just further down the line.
What am I getting wrong her, or completely missing, I'm sure it's the latter but I really need help here. Thanks
It looks to me as if variable $module was not in the scope when you try to call object method. Could you try var_dump($module) before $module->process_data("module_" . $page). What is the result of this function? Quick solution may be declaring $module global, but globals are not a very good idea anyway (but you may check if it works).