当需要页面通过另一个类方法时,函数变量不可用

时间:2014-11-24 07:51:11

标签: php oop

我希望能够通过类方法要求页面。问题是,当我通过普通的require语句要求页面时,所有变量都可以在所需页面上访问,但如果我使用另一个类来要求该页面,则不再可以访问变量。

我有两个页面,index.php和other.php。

的index.php:
    

class Myclass {
    public function test(){
        $test='hello World';
        $other=new other;
        $other->other_page('other.php'); //if I change this line to require 'other.php' variables are accessible.
    }
}


class other {
    public function other_page($page){
        require $page;
    }
}

$class=new Myclass;
$class->test();

other.php

<?php
echo $test;

index.php给出了未定义的索引错误。但如果我改变了:

$other->other_page('other.php'); 

require 'other.php';

一切正常。我可以通过将它们传递给

来使这些变量可用
other::other_page()

在这两种情况下,一切都是一样的。那么为什么类的行为不同,除了将变量传递给

之外,还有其他方法可以使变量可访问
other::other_page()

2 个答案:

答案 0 :(得分:2)

如有疑问,请始终参考docs

  

在大多数情况下,所有PHP变量只有一个范围。这个单一范围跨越包含和所需文件......但是,在用户定义的函数中引入了本地函数范围。函数内使用的任何变量默认都限制在本地函数范围内。

And

  

当包含文件时,它包含的代码将继承发生包含的行的变量范围。从那时起,调用文件中该行可用的任何变量都将在被调用文件中可用。但是,包含文件中定义的所有函数和类都具有全局范围。

问题是您的脚本other.php继承了other_page()方法的范围。在此方法内部,没有定义局部变量$test。这就是你的错误所在的地方。现在,为什么MyClass es test()方法中的直接要求有效,这应该是合乎逻辑的。包含的文件继承了方法的范围,并且在其范围内确实存在$test变量。

这是一般问题。我建议你重新考虑你的设计。

显式地将范围传递给您想要包含的脚本,而不是随机依赖某个范围
<?php

// Controller.php
class Controller {

    public function test()
    {
        $test = 'Hello World';
        // You would probably want to pass that via Dependency-Injection and
        // not as a hardcoded dependecny
        $retriever = new PageRetriever;

        // Only the contents of the second argument are passed
        // to the getPage() method
        echo $retriever->getPage('page.php', ['test' => $test]);
    }

}

// PageRetriever.php
class PageRetriever {

    public function getPage( $page, $args = [] )
    {
        $contents = null;

        // Extract the contents of the $args array into
        // the methods local scope
        extract($args);

        // Initiate output buffering, so that the contents
        // of the script is not immediately displayed
        ob_start();
        require $page;
        $contents = ob_get_contents();
        ob_end_clean();

        return $contents;
    }

}

这只是一个简单的实现,用来演示我在说什么。在这里你有一个干净的分离范围。您知道只有PageRetriever中已明确传递的变量才可用。

答案 1 :(得分:0)

我将给你一个简单的例子,你可以理解访问机制

first.php

<?php    
class first {    
    private $name;
    function __construct() {
        $this->name="name";
    }

    function  changeName(){
        $this->name="newName";
    }

    function getName()
    {
        return $this->name;
    }    
}    
?>

second.php

<?php
    include 'first.php';
    $firstObject=new first;
    echo $firstObject->getName().'<br>';
    $firstObject->changeName();
    echo $firstObject->getName();

?>

在您使用require 'other.php'的情况下,该内容包含在Myclass班级test()功能中。在该位置$test已定义。

但是当您使用$other->other_page('other.php');时,该内容将包含在other类的other_page($page)功能中。在该位置$test未定义。