在php中包含from/with函数

在php中包含from/with函数,php,function,include,Php,Function,Include,我一直在努力使用一个php脚本,包括另一个,所以我想我可能需要一些帮助 基本上,我希望在base.php中包含一个名为content-1.php的php文件,并在functions.php中包含一个函数 我的想法是根据$\u GET-variables包含不同的文件。我在找这样的东西: function getContent($content) { $api = $this; // The rest of the code } base.php include("func

我一直在努力使用一个php脚本,包括另一个,所以我想我可能需要一些帮助

基本上,我希望在base.php中包含一个名为content-1.php的php文件,并在functions.php中包含一个函数

我的想法是根据$\u GET-variables包含不同的文件。我在找这样的东西:

function getContent($content) {

    $api = $this;

    // The rest of the code

}
base.php

include("functions.php");
$api->getContent($_GET["content"]);
include("functions.php");
include("/content/content-1.php");
functions.php

class api {
function getContent($content) {
    if (isset($content)) {
        if (file_exists("/content/" . $content . ".php")) {
              return include("/content/" . $content . ".php");
        }
    }

    return include("/content/content-1.php");
}

function getName() {
   //Some function...
}

}
$api = new api;
content-1.php

echo "Hello world.";
echo $api->getName();
echo "Hello world.";
echo $this->getName();
一切似乎都在呼应着你好世界。直到我尝试从content-1.php访问$api。我遇到一个致命错误:调用非对象的成员函数

但是如果我将content-1.php直接包含到base.php中,那么它看起来就像这样:

function getContent($content) {

    $api = $this;

    // The rest of the code

}
base.php

include("functions.php");
$api->getContent($_GET["content"]);
include("functions.php");
include("/content/content-1.php");
调用$api和所有东西都可以工作

因此,如果我没有太混乱,我想知道如何使用getContent函数包含内容,并且仍然能够像立即包含文件那样传递变量


对于复杂的描述,我很抱歉,我试图简化我真正使用的代码,所以如果路径或语法中有任何错误,那不是真正的问题,只是一些粘贴错误而已

尝试$this而不是$api:

content-1.php

echo "Hello world.";
echo $api->getName();
echo "Hello world.";
echo $this->getName();
content-1.php$api的内部实际上是$this


发生这种情况的原因是$api变量仅在函数范围外可见。您可以向函数中添加一行,如下所示:

function getContent($content) {

    $api = $this;

    // The rest of the code

}
旁注

函数中的代码存在严重的安全问题!可以像现在这样包含任何文件。如果$_GET['content']的值等于'../../../../passwords.txt',例如,将包含passwords.txt文件,访问者将能够查看您的所有密码

为了帮助解决这个问题,您应该构建一个可用文件的列表,以便选择可以包含哪些文件。为了使这更容易,可以动态地进行

function getContent($content) {

    $api = $this;  // Make the $api avaiable to included file.

    $path  = 'path/to/contents/directory';
    $files = scandir($path);

    // Remove the two 'dot' directories
    $files = array_diff($files, ['.', '..']);

    // Now you check if the provided $content file name exists and in fact is a file.
    $filename = trim($content, '/.') . '.php';

    if(in_array($filename, $files) && is_file($filename)) {

         return include('/content/' . $filename);

    }

    return include('/content/content-1.php');
}
现在,您可以确定攻击者只能包含目录中的文件

更新

问题:

如何在包含的文件中声明新变量,并在执行getContent函数的脚本中使用它们

有一种方法可以在不使用任何脆弱代码的情况下实现您的要求。您可以通过引用将另一个声明数组的变量传递给函数。该函数如下所示:

function getContent($content, array &$variables = []) {...
$variables['new_variable_name'] = 'new_variable_value';
这种方法的限制是,只能声明如下所示的新变量:

function getContent($content, array &$variables = []) {...
$variables['new_variable_name'] = 'new_variable_value';
现在,当您调用函数时,您可以选择向其传递另一个声明数组的参数。此数组将保存包含文件中声明的变量

$variables = [];

$api->getContent($content, $variables);
现在您可以像这样访问变量:

$variables['new_variable'];
您还可以将它们提取到当前范围中。这可能会导致问题,因此我添加了EXTR_SKIP标志,以指示PHP应该忽略具有相同名称的现有变量。您可以设置标志EXTR_PREFIX_ALL,并提供第三个参数来提取$variables,EXTR_PREFIX_ALL,'PREFIX'。这将为所有提取的变量添加前缀,并帮助您避免命名冲突

extract($variables, EXTR_SKIP);
使用函数包含文件时有一些限制,但我首先介绍的方法no extract可以帮助您区分哪些变量与包含的内容相关


希望有用。

啊,谢谢!但是,与包含在content-1.php中的真正区别是什么?如果我想在content-1.php中定义一个变量,以便以后在base.php中使用,我该怎么办?我不理解你的第一个问题。至于你的第二个问题,这将有点棘手,但你要做的是不渲染父模板,直到你渲染子模板。这有点复杂,而且已经有解决方案可以做到这一点。比如zend framework 2。回答得真棒!非常感谢您在安全方面的投入!虽然我有办法,但你的更好!但是如何以另一种方式传递变量呢?如果我想声明或设置一个变量以供以后在base.php中使用?谢谢,我只是想确定您是否意识到安全问题,因为这可能会在以后的开发过程中导致严重的问题。我已经更新了答案,为您的问题提供了解决方案。