Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP define scope for included file

Tags:

scope

include

php

I have quite a lot of PHP view files, which I used to include in my controllers using simple include statements. They all use methods declared in a view class which they get like $view->method(); However I recently decided that it would be better if the including would also be done by this view class. This however changes the scope of the included file so that $view is no longer defined. Here is a code example:

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

Right now I hacked my way around the problem using this in the view class:

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

Is there anyway to declare the scope of the inluded file or is this the best way of solving the problem?

These examples are off coarse simplified.

like image 349
Pim Jager Avatar asked Feb 09 '09 20:02

Pim Jager


4 Answers

Here' a simplified but functional view class that I've seen around quite a lot and use quite a lot.
As you can see in the code below: you instantiate a view with the filename of the template file.
The client code, probably a controller, can send data into the view. This data can be of any type you need even other views.
Nested views will be automatically rendered when the parent is rendered.
Hope this helps.

// 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 = false ) {
        ob_start();
        include( $this->filename );
        $rendered = ob_get_clean();
        if( $print ) {
            echo $rendered;
            return;
        }
        return $rendered;
    }
    
    function __toString() {
        return $this->render();
    }
}

Usage

// 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;

The templates

//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 ?>
like image 119
meouw Avatar answered Oct 18 '22 22:10

meouw


You can't change include() scope, no, so your method is probably about as good as it gets in the situation you're describing. Though I'd skip the ugly PHP4-compat ampersand, myself.

like image 30
chaos Avatar answered Oct 18 '22 22:10

chaos


What i do, ( i don't know how OK it is) is simply

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

Sure as hell works

Cheers!

like image 29
Pedro Avatar answered Oct 19 '22 00:10

Pedro


An even more simplified version of a View class:

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;
    }

}

In controller:

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

In the template/view file:

echo $this->page_title;
like image 35
Andrew Avatar answered Oct 19 '22 00:10

Andrew