PHP:Como implementar um método __get-like para variáveis ​​de função local

StackOverflow https://stackoverflow.com/questions/2669195

  •  28-09-2019
  •  | 
  •  

Pergunta

Não sou estranho ao __get() e já o usei para criar algumas bibliotecas muito convenientes no passado.Porém, me deparo com um novo desafio (PHP 5.3, abreviou e simplificou meu código para esta questão):

<?php
namespace test;

class View {
    function __construct($filename, $varArray) {
        $this->filename = $filename;
        $this->varArray = $varArray;
    }

    function display() {
        include($this->filename);
    }

    function __get($varName) {
        if (isset($this->varArray[$varName]))
            return $this->varArray[$varName];
        return "?? $varname ??";
    }
}

?>

Acima está um sistema muito, muito simplificado para carregar uma View.Este código chamaria a visualização e a exibiria:

<?php

require_once("View.php");

use test\View;

$view = new View("views/myview.php", array("user" => "Tom"));
$view->display();

?>

Meu objetivo com este código é permitir que a visualização "myview.php" contenha código como este:

<p>
    Hello <?php echo $user; ?>!  Your E-mail is <?php echo $email; ?>
</p>

E, usado com o código acima, geraria "Olá Tom!Seu e-mail é ??e-mail ??"

No entanto, isso não funcionará.A visualização está sendo incluída em um método de classe, portanto, quando se refere a $user e $email, está procurando variáveis ​​de função locais - não variáveis ​​pertencentes à classe View.Por esse motivo, __get nunca é acionado.

Eu poderia mudar todas as variáveis ​​da minha visão para coisas como $this->user e $this->email, mas isso seria uma solução confusa e pouco intuitiva.Eu adoraria encontrar uma maneira de referenciar variáveis ​​​​diretamente, SEM que o PHP gere um erro quando uma variável indefinida for usada.

Pensamentos?Existe uma maneira limpa de fazer isso ou sou forçado a recorrer a soluções hacky?

Foi útil?

Solução

EDITANDO MINHA RESPOSTA.Um pouco como um "hackear", mas uma solução potencial.Pode querer "redefinir" o error_handler para uma funcionalidade mais genérica.

visualizar.php

<?php
error_reporting(E_ALL);
ini_set("display_errors", 0);
class View {
    function display($file, $values) {        
        set_error_handler(array($this, '__get'), E_NOTICE);        
        extract($values);
        include($file);
    }

    function __get($vaule)
    {
        echo '<i>Unknown</i>';
    }
}

$View = new View;
$values = array('user' => 'Tom',
               'email' => 'email@host.com');

$View->display('/filename.php', $values);
?>

nome do arquivo.php

Hello <?php echo $user; ?>, your email is <?php echo $email; ?> and your are <?php echo $age; ?> years old.

Saída

Hello Tom, your email is email@host.com and your are Desconhecido years old.

Outras dicas

Você pode usar extrair para colocar todas as variáveis ​​no escopo local:

function display() {
    extract($this->varArray);
    include($this->filename);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top