2009-02-09 12 views
4

J'ai beaucoup de fichiers de vue PHP, que j'avais l'habitude d'inclure dans mes contrôleurs en utilisant des instructions simples d'inclusion. Ils utilisent tous des méthodes déclarées dans une classe de vue, comme $ view-> method(); Cependant, j'ai récemment décidé qu'il serait préférable que l'inclusion soit également faite par cette classe de vue. Cela modifie toutefois la portée du fichier inclus afin que $ view ne soit plus défini. Voici un exemple de code:PHP définir la portée pour le fichier inclus

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 

En ce moment je piraté mon chemin autour du problème en utilisant ce dans la classe de vue:

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

Y at-il de toute façon de déclarer la portée du fichier Inclu ou est c'est la meilleure façon de résoudre le problème?

Ces exemples sont grossièrement simplifiés.

Répondre

1

Vous ne pouvez pas modifier la portée include(), non, donc votre méthode est probablement à peu près aussi bonne que dans la situation que vous décrivez. Bien que je passerais l'esperluette PHP4-compat, moi-même.

11

Voici une classe de vue simplifiée mais fonctionnelle que j'ai beaucoup vue et que j'utilise beaucoup.
Comme vous pouvez le voir dans le code ci-dessous: vous instanciez une vue avec le nom de fichier du fichier modèle.
Le code client, probablement un contrôleur, peut envoyer des données dans la vue. Ces données peuvent être de tout type dont vous avez besoin même d'autres vues.
Les vues imbriquées sont automatiquement affichées lorsque le parent est rendu.
Espérons que cela aide.

// 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(); 
    } 
} 

Utilisation

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

Les modèles

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

Je pense qu'il ya une petite faute de frappe où il est dit "nom de fichier"? – noio

+0

En effet, le membre et son utilisation sont 'nomfichier' où l'affectation est' nomfichier'. J'ai essayé de l'éditer, mais une édition nécessite 6 caractères de changement. _roll eyes_ – Travis

+0

Correction de faute de frappe - merci de l'avoir signalé – meouw

1

Qu'est-ce que je fais, (je ne sais pas comment il est OK) est tout simplement

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

Bien sûr que l'enfer fonctionne

À la votre!

0

Peut-être que cela a à voir avec mes paramètres php ou quelque chose, mais si j'inclue un fichier dans une fonction, ce fichier inclus aura seulement la portée des variables de cette fonction.

$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> 

Je pense que je partirais avec quelque chose comme ceci:

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

Utilisation:

render('templates/mytemplate.php', array(a=>1, b=>2)); 
0

sur ce Quano Expansion a à offrir:

Prenez une étape plus loin et inclure des variables dans la portée globale de l'exécution (qui devrait autrement être appelée avec global sur les internes d'inc lude). L'idée est que vous souhaitiez que l'inclusion fonctionne comme si elle était incluse dans la portée de votre application principale ou dans une portée de votre définition.

Considérez cette classe:

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

utiliser comme suit:

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

L'exemple inclut automatiquement $foo car il est dans la portée mondiale et $woo est ajouté, car il est dans la portée locale .

Je n'ai pas testé $this comme variable arbitraire, mais mes sens araignées me disent it won't work (warning).

+0

darn, réponse est à http://stackoverflow.com/questions/2211877/giving-php-included-files-parent-variable-scope – zamnuts

1

Une version encore plus simplifiée d'une classe de Vue:

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

} 

Contrôleur:

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

Dans le fichier modèle/vue:

echo $this->page_title; 
-1

Vous pouvez envoyer get_defined_vars () en tant que paramètre de la fonction de vue. Cela produit un tableau contenant toutes les variables définies dans la portée actuelle. Dans votre méthode "view", vous appelerez "extract" de PHP sur le tableau reçu.

+0

N'a pas regardé la question mais imho un petit exemple augmenterait la qualité de votre répondre. – m02ph3u5