How to achieve “require_global”?

2020-07-18 08:35发布

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

标签: php
5条回答
何必那么认真
2楼-- · 2020-07-18 09:16

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');
查看更多
劫难
3楼-- · 2020-07-18 09:17

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.

查看更多
迷人小祖宗
4楼-- · 2020-07-18 09:29

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!

查看更多
闹够了就滚
5楼-- · 2020-07-18 09:29

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

查看更多
对你真心纯属浪费
6楼-- · 2020-07-18 09:34

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.

查看更多
登录 后发表回答