Il costruttore PHP viene eseguito prima che possano essere forniti argomenti per variabili nidificate

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

  •  03-07-2019
  •  | 
  •  

Domanda

Per prima cosa, ecco un piccolo frammento di codice per spiegare il mio problema:

<?php
class foo {

    public $title;

    __construct{

        echo "<html>\n";
        echo "<head>\n";
        echo "<title>".$this->title."</title>\n";
        echo "</head>\n";
        echo "<body>\n";

    }

    /**
    *
    * I get $title from index.php
    *
    */
    public function setTitle( $title )
    {

        $this->title = $title;

    }


    __destruct{

        echo "</body>\n";
        echo "</html>\n";

    }

}
?>

Probabilmente hai già notato che questo codice produrrà un titolo di bene,. Sì, c'è uno spazio vuoto lì. : -)

Per me questo in realtà ha perfettamente senso (anche se non me lo aspettavo) perché il costruttore di classi viene eseguito sulla creazione dell'oggetto foo, il che significa che non aspetta che index.php fornisca l'argomento per setTitle () che a sua volta restituisce la stringa che riempie $ this- > title .

Quindi, se ho davvero capito cosa sta succedendo qui, cosa posso fare per aggirare questo problema? Devo eseguire il buffering dell'output utilizzando le funzioni buffer integrate e quindi modificare l'output memorizzato con la stringa del titolo fornita? Qualche idea?

Vorrei davvero, davvero, davvero mantenere questa struttura in cui il costruttore e il distruttore contengono questo codice ripetitivo. È bello che queste funzioni non debbano essere chiamate da nessuna parte. Capisco che alcuni sviluppatori potrebbero considerare questa cattiva pratica, ma lo farò comunque in questo modo perché lo voglio perché penso che sia bello. Quindi non sto davvero cercando consigli in questo aspetto, a meno che non ti senta estremamente motivato a informarmi sulla mia stupidità.

Quindi, se hai qualche consiglio / idea / conoscenza da condividere con me, sarebbe fantastico.

Grazie, e sentiti libero di prenderti il ??tuo tempo perché immagino che sarò costretto a rimanere nascosto per nascondermi dall'influenza suina malvagia che è arrivata nella mia città, quindi niente fretta!

È stato utile?

Soluzione

teh_noob. Ascoltami. Queste parole che sto scrivendo proprio qui. Fai finta di dirli e ascolta le parole che mi escono dalla bocca. No. NO NO NO NO NO ! E no, non do un calcio di topo come " cool " pensi che lo sia.

Questo è uno di quegli sfortunati scenari in cui sarebbe più breve elencare il "giusto" cose su questo approccio che il "sbagliato" cose. Vale a dire, i tuoi problemi sono numerosi. Detto questo, esaminerò solo alcune delle cose che sono cattive in questa idea.

Per prima cosa, discutiamo di OOP in generale. Quello che stai facendo qui è la mia cosa meno preferita da vedere in assoluto: ciò che chiamo "programmazione con le classi". Vale a dire, programmazione strutturata nelle vesti di OOP perché è stata utilizzata una parola chiave class. Se lo farai, non preoccuparti. Usa solo le funzioni. Questo è un abuso di classe semplice e chiaro.

Le classi sono progetti di oggetti. Gli oggetti si prestano all'incapsulamento e alla istanziazione . A meno che tu non sia davvero un fan del modello Singleton , perché creare una classe che sia chiaramente progettata essere istanziato una sola volta? E prima di dire "Ma Peter, il modello Singleton ci aiuta !!! 1one" prova a capire che in realtà non è poi così eccezionale . Inoltre, quello che stai facendo qui non è nemmeno un motivo per cui le persone si rivolgono al modello Singleton in primo luogo.

Il secondo è l'argomento delle sottoclassi. Forse ad un certo punto in futuro vorrai alcune pagine popup per il tuo sito. Oppure vorrai versioni di sola stampa che non siano solo basate su CSS. Forse vorrai anche qualcosa che non sia affatto HTML come un feed RSS. E adesso? Quanto altro funziona in questo costruttore, dovrai duplicare per far funzionare questi nuovi tipi di pagina? Ma cosa succede se hai già iniziato a fare affidamento su sottoclassi per creare singole pagine? Adesso sei fottuto. Certo, puoi tornare indietro e collegare il motivo decorativo , ma perché passare attraverso tutto quel lavoro quando questo problema può essere evitato dal design di classe non stupido in primo luogo?

In terzo luogo, è l'idea di fare eco all'HTML in primo luogo. Sto bene con l'eco per una parola o due qui, un tag o tre lì. Ma per grossi blocchi HTML, è solo idiozia. Abbi la decenza di sfuggire alla modalità di output e usa HTML non bloccato in una stringa. Non solo è più facile modificarlo e leggerlo, ma puoi anche usarlo in un WYSIWYG se lo desideri.

Quarto, questo male, male rompe la SRP .

Quinto: questo tipo di design ridicolo porta al tipo di problemi che stai cercando di risolvere qui. Solo tu non vuoi sapere che la soluzione è rimuovere le dichiarazioni di eco dal tuo costruttore. C'è un modo per aggirarlo? Sicuro. In effetti, ce n'è anche più di uno. Raccomando qualcuno di loro? No, non proprio.

Infine, discutiamo delle intestazioni. Forse non hai ancora imparato a conoscerli. Forse hai e non ti interessa. Ma cosa succederà quando, tra 6 mesi, stai lavorando a un problema e stai lavorando all'interno di un metodo che prevede 10 chiamate in profondità nello stack e ti rendi conto di una semplice funzione header () risolverà il tuo problema. Forse hai bisogno di regolare il controllo della cache o devi impostare manualmente il codice di risposta - qualunque cosa. Ma indovina un po ', non puoi. Perché? Perché il tuo stupido costruttore restituisce al browser il millisecondo in cui è stato creato.

Quindi, per ricapitolare: NO! A meno che il tuo obiettivo reale e ultimo sia quello di vedere alcuni dei tuoi lavori su The Daily WTF .

Cosa posso offrire oltre all'ammonimento? Forse parte di una nuova direzione? Bene, il debug dell'output è abbastanza difficile in sistemi ben costruiti, quindi non iniziare sparandoti nel piede che lo fa implicitamente. Tutto l'output dal tuo sistema dovrebbe essere esplicito . Se vuoi creare una "pagina" tipo di classe, va bene. Basta non farlo come quello .

class foo
{
    protected $title;
    protected $headers;

    public function setTitle( $title )
    {
        $this->title = $title;
    }

    public function addHeader( $header )
    {
        $this->headers[] = $header;
    }

    public function sendHeaders()
    {
        foreach ( $this->headers as $header )
        {
            header( $header );
        }
    }

    public function printPageHeader()
    {
        $this->sendHeaders();
        ?>
            <html>
                <head>
                    <title><?php echo $this->title; ?></title>
                </head>
                <body>
        <?php
    }

    public function printPageFooter()
    {
        ?>
                </body>
            </html>
        <?php
    }

    public function printPage()
    {
        $this->printPageHeader();
        $this->printPageFooter();
    }
}

$p = new foo;
$p->setTitle( 'Just Testing' );
$p->addHeader( 'Cache-control: no-cache' );
$p->printPage();

Altri suggerimenti

Potresti fare tutte le stampe nel distruttore. Lì sono note tutte le variabili. Tuttavia (come hai detto tu stesso) penso che sia davvero una brutta pratica. Suggerirei di usare il tipo di file view / template (hai comunque abbastanza tempo :)).

Potresti passare il titolo come argomento nel costruttore?

  

schnalle: questa è una cattiva pratica. questa è follia.
   the_noob: follia ...?
   the_noob: (grida) QUESTO ... È ... LITTLEFRAMEWORKIMBUILDING!
   the_noob: (calcia la separazione del codice e la presentazione nel pozzo)

Non ho davvero quello che vuoi fare, ma ho semplicemente passato il titolo come parametro al costruttore ...

<?php

class Title {
    public function __construct($title) {

        echo '<html><head><title>' . htmlspecialchars($title) . '</title></head><body>';
    }

    public function __destruct() {
        echo '</body></html>';
    }
}

?>

se vuoi davvero che i tuoi oggetti stampino qualcosa, suggerirei il metodo magico __tostring (), così puoi semplicemente echo il tuo oggetto. ma per i tag HTML ... ancora non utile.

Ti auguro buona fortuna con il tuo framework, ma sei o un geniale (non probabile) o un ragazzo che fa gli stessi errori (quasi) tutti i principianti (prima dell'arrivo di MVC).

  

modifica: non posso aiutarti. si desidera l'output diretto quando viene creato l'oggetto, ma è necessario ottenere i dati nell'oggetto prima che venga creato. quindi cerchi di aggirare qualcosa di brutto nel renderlo ancora più brutto. semplicemente non funziona così!
  stai cercando di costruire un nuovo tipo di auto migliore attaccando le ruote a un asino vivente, poi ti lamenti perché in qualche modo non ha funzionato come ti aspettavi (asino su ruote! wheooo!), e ora chiedi alla comunità come per attaccare i fanali posteriori in modo da rendere più veloce l'asino / l'auto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top