Newsgroup: it.comp.www.php
Titolo: Di OOP, di templating, e di idee nat alle 2 di notte.

Premessa: idea nata dopo una notte insonne e dopo essere stato
stracciato tre volte di fila da gnuChess in modalità facile, non sò
fino a che punto ha senso.
Allora, immaginatevi la classe più semplice che possa esistere per
gestire il templating con i file php:
Esempio 1: ( 
http://pastie.org/692083
 nel caso la formattazzione venga
stravolta)
<?php
class MyNode{
    public $title;
    public $body;
    public $template;
    public function __construct($title, $body, $template){
        $this->title = $title;
        $this->body = $body;
        $this->template = $template;
    }
    private function capitalize(){
        $this->title = ucwords($this->title);
    }
}
class NodeLoader{
    public $nodi;
    public function getNodes($array){
        foreach($array AS $singolonodo){
            $nodi[] = new MyNode($singolonodo['title'], $singolonodo
['body'], $singolonodo['template']);
        }
        return $nodi;
    }
}
$valori = array(
    '0' => array(
        'title' => 'Primo nodo',
        'body' => 'testo del primo nodo',
        'template' => 'node.tpl.php'
    ),
    '1' => array(
        'title' => 'secondo nodo',
        'body' => 'corpo del secondo nodo',
        'template' => 'node.tpl.php'
    )
);
$nodi = NodeLoader::getNodes($valori);
foreach($nodi AS $nodo){
    include($nodo->template);
}
/*
 *file node.tpl.php:
 *<h2><?php echo $nodo->title; ?></h2>
 *<div class="body"><?php echo $nodo->body; ?></div>
*/
?>
Io vorrei evitare si inserire quel include($nodo->template); ogni
volta che voglio stamparlo in quel metodo (foreach, o stampa singolo
nodo).
Quindi ho inserito un semplice metodo output() nella classe MyNode:
Esempio 2: ( 
http://pastie.org/692090
 )
<?php
class MyNode{
    public $title;
    public $body;
    public $template;
    public function __construct($title, $body, $template){
        $this->title = $title;
        $this->body = $body;
        $this->template = $template;
    }
    private function capitalize(){
        $this->title = ucwords($this->title);
    }
    public function output(){
        /*
         * Volendo continuare a utilizzare la sintassi
         * $node->title invece che $this->title nel file.tpl.php,
         * pensavo di fare $node = $this;
         * Funzionerebbe, ma incrementerei inutilmente la memoria
         * utilizzata da php (raddoppiandola per quel che riguarda
         * tutte le proprieta' dell'istanza)
        */
        include($this->template);
    }
}
class NodeLoader{
    public $nodi;
    public function getNodes($array){
        foreach($array AS $singolonodo){
            $nodi[] = new MyNode($singolonodo['title'], $singolonodo
['body'], $singolonodo['template']);
        }
        return $nodi;
    }
}
$valori = array(
    '0' => array(
        'title' => 'Primo nodo',
        'body' => 'testo del primo nodo',
        'template' => 'node2.tpl.php'
    ),
    '1' => array(
        'title' => 'secondo nodo',
        'body' => 'corpo del secondo nodo',
        'template' => 'node2.tpl.php'
    )
);
$nodi = NodeLoader::getNodes($valori);
foreach($nodi AS $nodo){
    $nodo->output();
}
/*
 *file node2.tpl.php
 *<h2><?php echo $this->title; ?></h2>
 *<div class="body"><?php echo $this->body; ?></div>
*/
?>
Ma questo mi porta ad avere da un lato il vantaggio che, quando si
vuole stampare un nodo, bisogna utilizzare l'apposito metodo (più
ordinato quindi, nel metodo output() volendo posso fare ulteriori
controlli prima di stampare il nodo); Ma alza due problemi:
1.il
 file node.tpl.php dovrà fare riferimento non più a $node, o al
nome che darò all'istanza di MyNode, ma a $this.
In primis non mi piace usare $this al di fuori della classe (anche se
logicamente in questo caso è all'interno), ma si potrebbe comunque
risolvere (vedere commento apposito nel metodo output());
2. In questo modo, visto che la renderizzazione avviene all'interno
della classe, tramite al template si può accedere indisturbati a tutti
i metodi privati della classe MyNode, cosa che non accade nel primo
esempio.
La mia domanda quindi è così fatta: è possibile utilizzare un metodo
per caricare e stampare il template all'interno della classe
'madre' (cioè MyNode), ma facendo si che il file di template
(node.tpl.php) abbia accesso solo ai metodi pubblici della classe
stessa?
p.s: una soluzione potrebbe essere mettere il metodo output() dentro
la classe NodeLoader invece che in MyNode, ma non sarebbe la stessa
cosa

 accesso solo ai metodi pubblici della classe stessa?
Mi vengono in mente due sistemi.
Il primo e` praticamente di fare un'altra classe a cui passi solo le 
variabili pubbliche e che fa solo l'include, senza alcuna altra 
informazione (vedi nota subito sopra).
Il secondo e` uguale a questo, ma usi eval()
Il terzo (ho detto due?? :) ) sarebbe di farti un sistema di templating 
grezzo che prima elimina tutto il codice php dalla pagina, poi trasforma, 
per esempio "[[foreach lista as elemento]]" in "<?php foreach ($lista as 
$elemento): ?>, e poi passarlo a eval().
Io, al massimo, userei il primo. Ho l'orticaria a sentir nominare eval() :)
 
Bye.

 Bye.
ciao e grazie!

 gli importi.
Occhio a non mischiare anche il controller, nella view e nel model. ;)
Questi calcoli li fai nel controller (richiamando metodi di MyInvoice) 
prima di passare $fattura alla view/template (vedi sopra).
 
Bye.