5

我有很多 PHP 视图文件,我曾经使用简单的包含语句将它们包含在我的控制器中。它们都使用在视图类中声明的方法,它们就像 $view->method(); 但是,我最近决定,如果包含也由这个视图类完成会更好。但是,这会更改包含文件的范围,因此不再定义 $view。这是一个代码示例:

in someViewFile.php (BOTH siuations)
    <html>
    <head><title><?php echo $view->getAppTitle(); ?></title>
    etc.
OLD SITUATION in controller:
    $view = new view;
    include('someViewFile.php'); //$view is defined in someViewFile.php
NEW SITUATION in controller:
    $view = new view;
    $view->show('someViewFile'); //$view is not defined in someViewFile.php

现在我在视图类中使用它解决了这个问题:

public function show($file){
    $view = &$this;
    include($file.".php");
}

无论如何要声明包含文件的范围,还是这是解决问题的最佳方法?

这些例子是粗略的简化。

4

7 回答 7

12

这是一个简化但功能强大的视图类,我已经看到很多并使用了很多。
正如您在下面的代码中看到的:您使用模板文件的文件名实例化一个视图。
客户端代码(可能是控制器)可以将数据发送到视图中。此数据可以是您需要的任何类型,甚至可以是其他视图。
渲染父级时将自动渲染嵌套视图。
希望这可以帮助。

// simple view class
class View {
    protected $filename;
    protected $data;

    function __construct( $filename ) {
        $this->filename = $filename;
    }

    function escape( $str ) {
        return htmlspecialchars( $str ); //for example
    }

    function __get( $name ) {
        if( isset( $this->data[$name] ) {
            return $this->data[$name];
        }
        return false;
    }

    function __set( $name, $value ) {
        $this->data[$name] = $value;
    }

    function render( $print = true ) {
        ob_start();
        include( $this->filename );
        $rendered = ob_get_clean();
        if( $print ) {
            echo $rendered;
            return;
        }
        return $rendered;
    }

    function __toString() {
        return $this->render();
    }
}

用法

// usage
$view = new View( 'template.phtml' );
$view->title = 'My Title';
$view->text = 'Some text';

$nav = new View( 'nav.phtml' );
$nav->links = array( 'http://www.google.com' => 'Google', 'http://www.yahoo.com' => 'Yahoo' );

$view->nav = $nav;

echo $view;

模板

//template.phtml
<html>
    <head>
        <title><?php echo $this->title ?></title>
    </head>
    <body>
        <?php echo $this->nav ?>
        <?php echo $this->escape( $this->text ) ?>
    </body>
</html>

//nav.phtml
<?php foreach( $this->links as $url => $link ): ?>
    <a href="<?php echo $url ?>"><?php echo $link ?></a> 
<?php endforeach ?>
于 2009-02-09T20:58:29.487 回答
3

您无法更改 include() 范围,不,因此您的方法可能与您描述的情况一样好。虽然我自己会跳过丑陋的 PHP4 兼容 & 符号。

于 2009-02-09T20:25:43.810 回答
1

我做什么,(我不知道它有多好)很简单

extract($GLOBALS);
include $view.".php";

确实有效

干杯!

于 2010-10-20T16:56:03.393 回答
1

View 类的更简化版本:

Class View {

    protected $filename;

    function __construct($filename){
        $this->filename = $filename;
    }

    function display(){
        global $session; //put global variables here

        include Cfg::ROOT . '/views/' . $this->filename;    
    }

    function assign($key, $val){
        $this->$key = $val;
    }

}

在控制器中:

$view = new View('homepage.php');
$view->assign('page_title',$page_title); //assign all needed variables from controller
$view->display();

在模板/视图文件中:

echo $this->page_title;
于 2015-04-02T17:22:14.437 回答
0

也许这与我的 php-settings 或其他东西有关,但如果我在函数中包含一个文件,则包含的文件将只具有该函数变量的范围。

$a = 1; // This variable isn't visible for the included file

function render()
{
    $b = 2; // This variable is
    include('template.php');
}


// ----------------------------------------
// template.php

<html>
<body>
<?=$a?> // wont show
<?=$b?> // will show
</body>
</html>

我想我会选择这样的东西:

function render($template, $variables)
{
    extract($variables);
    include($template);
}

用法:

render('templates/mytemplate.php', array(a=>1, b=>2));
于 2011-02-15T09:25:01.063 回答
0

扩展 Quano 所提供的功能:

更进一步,在全局执行范围内包含变量(否则必须在 include 的内部使用 global 调用)。这个想法是,您希望 include 像包含在您的主应用程序范围或定义的范围中一样工作。

考虑这个类:

class PHPInclude {
    private static $globalsList = array(
            'GLOBALS','_SERVER','_GET','_POST','_FILES',
            '_REQUEST','_SESSION','_ENV','_COOKIE'
        );
    public static function phpInclude($file,$variables=array()) {
        if ( file_exists($file) ) {
            $globs = array();
            foreach ( $GLOBALS as $key => $value ) {
                if ( !in_array($key,sefl::$globalsList) ) {
                    array_push($globs,$key);
                }
            }
            foreach ( $globs as $key ) {
                global $$key;
            }
            foreach ( $variables as $variable ) {
                global $$variable;
            }
            unset($globs,$key,$value);
            ob_start();
            include $file;
            return ob_get_clean();
        }
        return '';
    }
}

按如下方式使用它:

$foo = 'bar';
function testScope() {
    $woo = 'sah';
    PHPInclude::phpInclude('file.phtml',array($woo));
}

该示例将自动包含$foo,因为它在全局范围内,并且$woo由于它在本地范围内而被添加。

我没有$this作为任意变量进行测试,但我的蜘蛛感觉告诉我它不起作用(警告)

于 2013-02-15T17:24:16.723 回答
0

我找到了一个很好的解决方案。只需创建一个匿名函数并调用它。仅适用于 PHP 7+。

$arg1=1;
call_user_func(function()use($arg1,$arg2,...){
 $values=$arg1+$arg2;
 // $values is limited in scope inside this function
}

例如:

$values='HEY!';

//included code
$arg1=1;
$arg2=2;
call_user_func(function()use($arg1,$arg2,...){
 $values=$arg1+$arg2;
 // $values is limited in scope inside this function
}

echo $values;
// echos HEY!
于 2018-11-18T02:33:14.153 回答