PHP определить область для включенного файла - PullRequest
4 голосов
/ 09 февраля 2009

У меня довольно много файлов вида 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");
}

Есть ли способ объявить объем включенного файла или это лучший способ решения проблемы?

Эти примеры грубо упрощены.

Ответы [ 8 ]

12 голосов
/ 09 февраля 2009

Вот 'упрощенный, но функциональный класс представления, который я видел довольно часто и довольно часто использую.
Как вы можете видеть из кода ниже: вы создаете экземпляр представления с именем файла шаблона.
Код клиента, возможно, контроллер, может отправлять данные в представление. Эти данные могут быть любого типа, вам нужны даже другие представления.
Вложенные представления будут автоматически отображаться при отображении родительского элемента.
Надеюсь, это поможет.

// 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 ?>
1 голос
/ 02 апреля 2015

Еще более упрощенная версия класса 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;
1 голос
/ 20 октября 2010

То, что я делаю, (я не знаю, как это нормально) просто

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

Конечно, как работает ад

ура!

1 голос
/ 09 февраля 2009

Вы не можете изменить область действия include (), нет, поэтому ваш метод, вероятно, примерно так же хорош, как и в ситуации, которую вы описываете. Хотя я бы и сам пропустил уродливый амперсанд с поддержкой PHP4.

0 голосов
/ 18 ноября 2018

Я нашел отличное решение. Просто создайте анонимную функцию и вызовите ее. Только для 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!
0 голосов
/ 25 марта 2016

Вы можете отправить get_defined_vars () в качестве параметра функции просмотра. Это создает массив, содержащий все определенные переменные в текущей области видимости. В вашем методе «view» вы вызовете PHP «extract» для полученного массива.

0 голосов
/ 15 февраля 2013

Расширение возможностей Quano:

Сделайте еще один шаг вперед и включите переменные в глобальную область выполнения (которые в противном случае должны были бы вызываться с помощью 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 как произвольную переменную, но мои чувства паука говорят мне , что это не сработает (предупреждение) .

0 голосов
/ 15 февраля 2011

Возможно, это связано с моими настройками php или чем-то, но если я включу файл в функцию, этот включенный файл будет иметь только область действия переменных этой функции.

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