El constructor de PHP se ejecuta antes de que se puedan proporcionar argumentos para variables anidadas

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

  •  03-07-2019
  •  | 
  •  

Pregunta

Lo primero es lo primero, aquí hay un pequeño código de código para ayudar a explicar mi 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";

    }

}
?>

Es probable que ya hayas notado que este código producirá un título de bien,. Yah, hay un espacio vacío allí. : -)

Para mí, esto realmente tiene mucho sentido (incluso si no lo esperaba) porque el constructor de la clase se está ejecutando en la creación del objeto foo, lo que significa que no espera el index.php para proporcionar el argumento. para setTitle () que a su vez devuelve la cadena que llena $ this- > title .

Entonces, si realmente entiendo qué está pasando aquí, ¿qué puedo hacer para solucionar este problema? ¿Debería almacenar en búfer la salida utilizando las funciones de búfer integradas y luego modificar la salida almacenada con la cadena de título suministrada? ¿Alguna idea?

Realmente me gustaría mantener esta estructura donde el constructor y el destructor contienen este código repetitivo. Es bueno que estas funciones no tengan que ser llamadas en ninguna parte. Entiendo que algunos desarrolladores pueden considerar esta mala práctica, pero voy a hacerlo de todos modos porque quiero porque creo que es genial. Así que realmente no estoy buscando consejos en ese aspecto, a menos que te sientas extremadamente motivado para informarme sobre mi estupidez.

Entonces, si tienes algún consejo / idea / conocimiento para compartir conmigo, sería genial.

Gracias, y siéntase libre de tomarse su tiempo porque supongo que me veré obligado a permanecer escondido de la malvada gripe porcina que ha llegado a mi ciudad, ¡así que no hay prisa!

¿Fue útil?

Solución

teh_noob. Escúchame. Estas palabras que estoy escribiendo aquí. Finge que los estoy diciendo y escucha las palabras que salen de mi boca. No. NO NO NO NO NO ! Y no, no le doy el trasero a una rata de cómo " cool " crees que es.

Este es uno de esos escenarios desafortunados en los que sería más corto enumerar el " derecha " cosas sobre este enfoque que el " mal " cosas. Es decir, sus problemas son numerosos. Dicho esto, voy a repasar solo algunas de las cosas malas de esta idea.

Primero, solo discutamos OOP en general. Lo que estás haciendo aquí es lo que menos me gusta ver: lo que llamo "programación con clases". Es decir, programación estructurada en forma de OOP porque se usó una palabra clave de clase. Si vas a hacer esto, no te molestes. Solo usa las funciones. Esto es abuso de clase simple y simple.

Las clases son planos de objetos. Los objetos se prestan para encapsulación y creación de instancias . A menos que sea realmente un fan del patrón Singleton , ¿por qué crear una clase que esté claramente diseñada? para ser instanciado una sola vez? Y antes de que digas " ¡Pero Peter, el patrón Singleton nos ayuda! Trate de entender que en realidad no es tan bueno . Además, lo que estás haciendo aquí no es ni siquiera una razón por la que las personas recurran al patrón de Singleton en primer lugar.

Segundo es el tema de las subclases. Tal vez en algún momento en el futuro querrá algunas páginas emergentes para su sitio. O querrá versiones de solo impresión que sean más que simplemente basadas en CSS. Tal vez incluso querrás algo que no sea HTML, como un feed RSS. ¿Ahora que? ¿Cuánto otro trabajo que se realiza en este constructor va a tener que duplicar para que estos nuevos tipos de páginas funcionen? ¿Pero qué sucede si ya ha comenzado a confiar en las subclases para crear páginas individuales? Ahora estás jodido. Claro, puedes volver y conectar el patrón de decoración , pero ¿por qué pasar por todo ese trabajo? ¿Cuándo se puede evitar este problema mediante un diseño de clase no estúpido en primer lugar?

En tercer lugar, es la idea de hacer eco de HTML en primer lugar. Estoy bien con el eco de una palabra o dos aquí, una etiqueta o tres allí. Pero para grandes trozos de HTML, es solo idiotez. Tenga la decencia de escapar al modo de salida y use HTML que no esté bloqueado en una cadena. No solo es más fácil de editar y leer, sino que también puede trabajar con él en un WYSIWYG si así lo desea.

Cuarto, esto mal, mal rompe el SRP .

Quinto: este tipo de diseño ridículo conduce al tipo de problemas que intentas resolver aquí. Solo que no quiere saber que la solución es eliminar las declaraciones de eco de su constructor. ¿Hay alguna manera de evitarlo? Por supuesto. De hecho, hay incluso más de uno. ¿Recomiendo alguno de ellos? No, en realidad no.

Por último, vamos a discutir los encabezados. Quizás todavía no hayas aprendido sobre ellos. Tal vez tienes y no te importa. Pero, ¿qué ocurrirá cuando, dentro de 6 meses, esté trabajando en un problema y esté trabajando dentro de un método que tenga 10 llamadas en la pila y se dé cuenta de una función simple de header () resolverá tu problema Tal vez necesite ajustar el control de caché o configurar manualmente el código de respuesta, lo que sea. Pero adivina qué, no puedes. ¿Por qué? Debido a que su tonto constructor envía al navegador el milisegundo que se creó.

Por lo tanto, para recapitular: NO! A menos que su objetivo final y real sea ver algunos de sus trabajos manuales en The Daily WTF .

¿Qué puedo ofrecer además de la amonestación? Tal vez parte de una nueva dirección? Bueno, la salida de depuración es bastante difícil en sistemas bien construidos, así que no empieces a dispararte en el pie que lo hace de manera implícita. Todos los resultados de su sistema deben ser explícitos . Si quieres hacer una " página " tipo de clase, eso está bien. Simplemente no lo hagas como that.

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

Otros consejos

Podrías hacer toda la impresión en el destructor. Allí se conocen todas las variables. Sin embargo (como usted mismo ha dicho), creo que esto es realmente una mala práctica. Yo sugeriría usar tipos de archivos de vista / plantilla (de todos modos, tienes suficiente tiempo :)).

¿Podría pasar el título como un argumento en el constructor?

  

schnalle: esto es una mala práctica. esto es una locura.
   the_noob: madness ...?
   the_noob: (shouts) ESTO ... ES ... LITTLEFRAMEWORKIMBUILDING!
   the_noob: (elimina la separación del código y la presentación en el pozo)

Realmente no obtengo lo que quieres hacer, pero solo le doy el título como parámetro al constructor ...

<?php

class Title {
    public function __construct($title) {

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

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

?>

Si realmente quieres que tus objetos impriman algo, sugiero el método magic __tostring (), para que puedas simplemente repetir tu objeto. pero para las etiquetas html ... aún no es útil.

te deseo suerte con tu marco, pero o eres un genio (no es probable) o un chico que comete los mismos errores (casi) todos los principiantes (antes de que llegara MVC).

  

editar: no puedo ayudarte. desea una salida directa cuando se crea el objeto, pero necesita obtener datos en el objeto antes de crearlo. así que tratas de solucionar algo feo para hacerlo aún más feo. ¡Simplemente no funciona de esa manera!
  estás tratando de construir un nuevo y mejor tipo de automóvil uniendo ruedas a un burro viviente, luego te quejas porque de alguna manera no funcionó como lo esperabas (burro sobre ruedas, ¡vaya!), y ahora le preguntas a la comunidad cómo para conectar las luces traseras de una manera que haga que el burro / automóvil vaya más rápido.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top