如何 运行 从对象的包含文件路径编码到对象外的函数范围?

How to run code from included filepath of object into function scope outside object?

我目前正在将代码从页面解析器函数重构为 OOP。 我在将文件中的 运行 代码包含到主函数范围时遇到困难:

对象:

class phpFragment {
    private $sData;

    function render() {
        return include $oElement->sData;
    }
}

对象容器class:

class pageData {
    protected $aPhpFragments;
    protected $aCssFragments;

    public function outputData($sTag) {
        switch($sTag) {
            case 'php':
                foreach($this->aPhpFragments as $oPhpFragment) {
                    return $oPhpFragment->render();
                }
                break;
            case 'css':
                foreach($this->aCssFragments as $oCssFragment) {
                    echo $oCssFragment->render();
                }
                break;
        }
    }
}

主要功能:

function parsePage($sLanguageCode) {
    $oTranslator = new translator($sLanguageCode);
    $aTranslations = $oTranslator->translations('page');
    $oBuilderClass = new builder($aTranslations);

    //... queries to get data and set pagedata and get the template file
    $oPageData = $oPage->getData();
    $aTemplateTags = $oTemplate->getTags(); 
    foreach($aTemplateTags as $sTag) {
       $oPageData->outputData($sTag);
    }

    //....   
}

包含代码(示例):

<?php

$oBuilderClass->build_element(.... parameters here);

?>

我只想启动构建器 -class 一次,因为它包含相当多的数据,我不想在每次包含时都重新创建。

如何return将include的代码添加到可以使用builderClass的parsePage函数中?

如果我正确理解你的问题,那么你想从 php 文件中执行整个代码作为从对象调用的方法。如果是,那么您可能想使用 eval 描述的函数 here.

使用 eval 函数,您可以将 php 文件作为字符串读取并将其计算为 php 代码,而不是包含它。

如果您的 php 文件使用 return 语句,然后是文档

eval() returns NULL unless return is called in the evaluated code, in which case the value passed to return is returned.

您可以简单地 return 来自您的方法的值。

如果您的包含文件像您在示例中显示的那样简单,那么要实现此效果,您需要替换这部分代码

class phpFragment {
    private $sData;

    function render() {
        return include $oElement->sData;
    }
}

有了这个

class phpFragment {
    private $sData;

    function render() {
        //read a file into variable as string
        $phpCode = file_get_contents($oElement->sData);                 

        //prepare code by adding return statement and '?>' at the begining (because you have an open tag in php files).
        $phpCode = '?> ' . str_replace('$oBuilderClass->build_element', 'return $oBuilderClass->build_element', $phpCode);

        //I guess that included files don't use any variables declared out of file so we need to simply escape every '$' character in file
        //that they can evaluate correctly.
        $phpCode = str_replace('$', '$', $phpCode);

        return eval($phpCode);
    }
}

听起来像是依赖注入问题:您希望 $oBuilderClassinclude 代码的范围内?

如果您有权访问应用程序依赖项容器,我会在该容器中注册该对象。通俗地说,类似于 \Application::bind('Builder', $oBuilderClass),然后再做 Builder::build_element。但是,您正在编写自己的视图渲染器表明您无权访问具有正式 IoC container.

的框架设施

假设您没有 IoC 容器,最方便的方法是:

$GLOBALS['oBuilderClass'] = new builder(...);

然后在你的后面包括:

global $oBuilderClass;
$oBuilderClass->build_element(...);

然而,这并不是特别优雅。您可能会考虑传递构建器,以便在调用井的底部有:

function render(builder $oBuilderClass) {
    return include $oElement->sData;
}

在包含时将 $oBuilderClass 置于范围内。我更喜欢首先使用正式的 IoC 容器,然后传递对象,最后如果 none 这些对你有用,然后使用全局变量。

您可以创建一个 Context class ,它将成为范围变量的容器,并帮助您在上下文中包含(执行)代码。它将是一个单例class(只会创建一个实例)。

这里是如何使用它:方法current() returns当前实例然后你可以使用export()方法将变量导出到上下文,它需要一个key/value数组。方法 execute() 将文件名作为参数并将其包含在可用的导出变量中,您可以添加临时变量作为第二个参数:

//Somewhere before execute();
oContext::current()->export([
    'variable1' => 'value1',
    'instance' => $instance
]);

//Then anywhere in your file:
oContext::current()->execute("toBeIncluded.php", [
    'tmp_variable' => 'tmp_value'
]);

//toBeIncluded.php
echo $variable1;
echo $instance->method1();
echo $tmp_variable;

你的情况:

主要功能:

function parsePage($sLanguageCode) {
    $oTranslator = new translator($sLanguageCode);
    $aTranslations = $oTranslator->translations('page');
    $oBuilderClass = new builder($aTranslations);

    //export variables to your context
    //Don't be aware of memroy usage objects are passed by reference
    oContext::current()->export(compact('oBuilderClass'));

    //... queries to get data and set pagedata and get the template file
    $oPageData = $oPage->getData();
    $aTemplateTags = $oTemplate->getTags(); 
    foreach($aTemplateTags as $sTag) {
            $oPageData->outputData($sTag);
    }

    //....   
}

对象:

class phpFragment {
    private $sData;

    function render() {
        oContext::current()->execute($oElement->sData);
    }
}

您在 class 声明下方找到:

oContext.class.php

/**
 * Class oContext
 */
class oContext {

    /**
     * The singleton instance
     * @var oContext
     */
    private static $instance = null;

    /**
     * the exported variables
     * @var array
     */
    private $variables = [];

    /**
     * Return the singleton or create one if does not exist
     *
     * @return oContext
     */
    public static function current() {
        if (!self::$instance) {
            self::$instance = new self;
        }
        return self::$instance;
    }

    /**
     * Export an array of key/value variables
     *
     * @param $variables
     * @return $this
     */
    public function export($variables) {
        foreach ($variables as $key => $value) {
            $this->variables[$key] = $value;
        }
        return $this;
    }

    /**
     * Include and execute a file in this context
     *
     * @param $file
     * @param array $variables temporary exports will not be added to the context (not available in the next call)
     * @return $this
     */
    public function execute($file, $variables = []) {
        //Populate variables
        foreach (array_merge($this->variables, $variables) as $key => $value) {
            ${$key} = $value;
        }
        include $file;
        return $this;
    }

}

希望本文能帮助您实现目标。

祝你好运。