views:

898

answers:

5

Current situation:

  • I have the current version of my MVC Framework which uses classes as controllers.
  • I have some "vintage" modules from my old MVC Framework which uses simple, flat includes as controllers.

Much simplified that means:

New Version:

<?PHP
class blaController extends baseController {
    private $intVar;

    function dosomethingFunction() {
        $this->intVar = 123;
        $this->view('myView');
    }
}
?>

Old Version:

<?PHP
$globalVar = 123;
// view "controllername" is automatically shown
?>

I'm now trying to write a wrapper to be able to use my old controllers in my new MVC without having to rewrite everything. To do so, I have a "wrapper" controller:

class wrapController extends baseController {
    function dosomethingFunction() {
        require 'old_dosomething.function.php';
        $this->view('old_dosomething_view');
    }
}

(Once again: This is VERY, VERY simplified - just to get the idea over. Not actual code.)

The problem with that approach is, that the previously global variable $globalVar now only exists inside of the method "dosomethingFunction" and cannot be accessed by the view.

This wouldn't be the case if I could force the require to behave as "in global scope" so that $globalVar would once again be available in global scope.

So: Is there some way to achieve "require_global" or something similar?

(One solution for my problem would be to modify my old controllers to start with a bunch of "global" commands, but I'd prefer a solution where I don't have to change so much of that old code.)

(Note: Please don't tell me that GLOBALS are bad. It totally misses the point of this question. Just accept that it is a requirement to keep some old code working in a newer, cleaner environment.)

+1  A: 

Hmmm, this is an issue I've never before seen. I suppose you could do this

class wrapController extends baseController {
    function dosomethingFunction() {
        require 'old_dosomething.function.php';

        // Force "old" globals into global scope
        $GLOBALS['globalVar'] = $globalVar;

        $this->view('old_dosomething_view');
    }
}

But that's a pretty tedious, manual process as well, depending on how many globals we're talking about. I'll think about this, but I don't know of any "auto-magic" solution off the top of my head.

Peter Bailey
"$GLOBALS['globalVar'] = $globalVar;" would be an option if I could iterate through all local variables, but is there an "automated" way to find all of those?
BlaM
+3  A: 

You can add local variables defined within dosomethingFunction() to global scope:

class wrapController extends baseController {
    function dosomethingFunction() {
        require 'old_dosomething.function.php';
        //begin added code  
        $vararr = get_defined_vars();
        foreach($vararr as $varName => $varValue) 
              $GLOBALS[$varName] = $varValue;            
        //end added code          
        $this->view('old_dosomething_view');
    }
}

Note, that for this to work as expected, you should call require before using any other thing in the function. get_defined_vars() returns only variables from the current scope, so no array_diff hacks are needed.

vartec
I'm not yet sure why, but somehow array_merge doesn't work in my scenario while merging the array "manually" with foreach works.
BlaM
well, $GLOBAL is not really "normal" array. Rolled back to foreach version.
vartec
+4  A: 

This is the easiest solution I can think of.

Use the get_defined_vars() function twice and get a diff of each call to determine what variables were introduced by the required file.

Example:

$__defined_vars       = get_defined_vars();
require('old_dosomething.function.php');
$__newly_defined_vars = array_diff_assoc($__defined_vars, get_defined_vars());
$GLOBALS = array_merge($GLOBALS, $__newly_defined_vars);
$this->view('old_dosomething_view');
Matt
no need to do array_diff if you're calling that from within a function. get_defined_vars() only returns variables within the current scope.
vartec
Good point. Though it's certainly possible that someone later adds variables to that function.
Matt
array_diff_assoc fails if one of the variables is an object that cannot be converted to string.
BlaM
@mcreenan: but if you call get_defined_vars() *before* more variables are added, they you'll get only the ones from included file.
vartec
A: 

Hi

Have you tried Zend_Registry from Zend Framework?

The registry is a container for storing objects and values in the application space. By storing the value in the registry, the same object is always available throughout your application. This mechanism is an alternative to using global storage.

http://framework.zend.com/manual/en/zend.registry.html

uuɐɯǝʃǝs
That would require modifying the old code which is just what I try to avoid.
BlaM
... and I don't see how Zend_Registry is better than a simple global array to store stuff...
BlaM
A: 

For anybody interested: My (so far) final version:

class wrapController extends baseController {
    function dosomethingFunction() {
        // ... do some initialisation stuff ...

        $__defined_vars = array_keys(get_defined_vars());

        require 'old_dosomething.function.php';

        $__newly_defined_vars = array_diff(
                                    array_keys(get_defined_vars()),
                                    $__defined_vars, 
                                    array('__defined_vars')
                                );
        foreach ($__newly_defined_vars as $var) {
            $GLOBALS[$var] = &$$var;
        }

        $this->view('old_dosomething_view');
    }
}

Ugly, but it works. Thanks for all your great help!

BlaM