Foros del Web » Programando para Internet » PHP »

PHP OO Evitar que PHP envie el HTML antes de tiempo

Estas en el tema de Evitar que PHP envie el HTML antes de tiempo en el foro de PHP en Foros del Web. Tengo un problema y que de momento la solución más pobre es embeber el HTML en string a una variable y devolver todo a la ...
  #1 (permalink)  
Antiguo 22/03/2015, 19:15
Avatar de guardarmicorreo  
Fecha de Ingreso: noviembre-2012
Ubicación: Córdoba
Mensajes: 1.153
Antigüedad: 12 años, 1 mes
Puntos: 84
Evitar que PHP envie el HTML antes de tiempo

Tengo un problema y que de momento la solución más pobre es embeber el HTML en string a una variable y devolver todo a la vez.

Retrocedo y comienzo desde el principio.

En mi framework personal el recorrido es el siguiente:

El usuario envia una petición GET al servidor: http://mi.direccion.com/variable/get/solicitada

Apache recibe esa petición y con el .htaccess indico que construya tres variables así:

Código:
module=variable, method=get, arguments=solicitada
Además con .htaccess también le indico que todas las peticiones vayan hacia el index.php, para que el usuario pueda obviar escribir index.php.

Con un controlador instacio al modelo y dependiendo de si el método y argumentos son indicados le paso el método y los argumentos.

El modelo instancia a otro controlador, pero en el core, que contiene las peticiones a la base de datos y todo lo que sea puramente back-end y también instancia al controlador del HTML, de manera que recibe los datos del core y del html y los retorna.

Es en este punto donde me topé con un problema a la hora de trabajar con AJAX.

Si las cabeceras del HTML (head, metas, etc.) las pongo en el index.php y en el body hago echo de lo que el usuario ha solicitado, funciona perfectamente.

Pero si hago una petición AJAX me encuentro con el problema de que la respuesta la mandará con las cabeceras HTML.

Así que probé a ver si construyendo (con el controlador del HTML) lo solicitado e incluso las cabeceras se solucionaba el problema, pero resulta que aún cuando no había echo en el index.php ni en los controladores, módulos, etc. las cabeceras se enviaban porque no estaban embebidas en PHP así

Código PHP:
Ver original
  1. function home($args=NULL){
  2. return '<p>'.$args['name'].'</p>';
  3. }

Sino que tenían este formato

Código PHP:
Ver original
  1. function home($args=NULL){
  2. <p><?php echo $args['name']; ?> </p>
  3. }

Cuando enbebí el PHP como el primer ejemplo, todo funcionaba perfecto y podía construir lo solicitado por el usuario con el orden que yo quería y meterlo en el cuerpo principal del HTML y retornarlo para mostrarlo con un echo.

El problema está en que esta forma es limitada porque no puedo entrecomillar foreach para recorrer un array y es muy lioso si quiero utilizar un condicional para mostrar una cosa que tenga dos opciones, por ejemplo

Código PHP:
Ver original
  1. ($args['message_sended']===FALSE)?'Mensaje no enviado':'Mensaje Enviado';

Y la cosa se complica si con el condicional se muestra un formulario o no.

Así que recurro a alguien que pueda orientarme en cómo es la mejor manera de poder mostrar o no HTML de manera controlada y huyendo de tener que hacer string el HTML y no limitarme en operaciones básicas que necesariamente tengo que hacer en el front-end y no en el back-end.

¿Alguien puede ayudarme?

Saludos.

P.D.: huyo de Smarty y otros, no lo veo necesario para mi, aunque sí uso otras herramientas como purecss.
__________________
Ayúdame a hacerlo por mi mismo.
  #2 (permalink)  
Antiguo 22/03/2015, 22:11
Avatar de pateketrueke
Modernizr
 
Fecha de Ingreso: abril-2008
Ubicación: Mexihco-Tenochtitlan
Mensajes: 26.399
Antigüedad: 16 años, 8 meses
Puntos: 2534
Respuesta: Evitar que PHP envie el HTML antes de tiempo

Yo haría esto:
Código PHP:
Ver original
  1. <?php
  2. function foo() {
  3.   ob_start();
  4. ?>
  5.  
  6. Acá puedo colocar el HTML/PHP que quiera, en la forma que quiera.
  7.  
  8. Al final las funciones ob_start/env_clean solo capturan toda la salida, lo que hace más fácil hacer return.
  9.  
  10. <? php
  11.   return ob_end_clean();
  12. } ?>
__________________
Y U NO RTFM? щ(ºдºщ)

No atiendo por MP nada que no sea personal.
  #3 (permalink)  
Antiguo 23/03/2015, 05:42
Avatar de dashtrash
Colaborador
 
Fecha de Ingreso: abril-2007
Ubicación: Ni en Sevilla,ni en Sanlúcar..qué más da..
Mensajes: 927
Antigüedad: 17 años, 8 meses
Puntos: 270
Respuesta: Evitar que PHP envie el HTML antes de tiempo

El problema no es que tengas que retrasar la salida HTML.
El problema es que estás pidiendo dos cosas distintas, y las tratas del mismo modo.
Una posible forma de hacerlo, es en el enrutador.
Si el path /a/b/c genera una pagina HTML, o una respuesta AJAX, lo especificas en el enrutador, e incluyes las cabeceras, o index, o lo que sea necesario.
Otra posibilidad (peor) es indicarlo via GET.Si existe un parametro "output=xxx", aplicas la salida xxx (json, etc,etc), lo cual implica unas cabeceras , controladores,etc

Y, mi consejo es: no presupongas que la salida es HTML.
  #4 (permalink)  
Antiguo 23/03/2015, 08:15
Avatar de guardarmicorreo  
Fecha de Ingreso: noviembre-2012
Ubicación: Córdoba
Mensajes: 1.153
Antigüedad: 12 años, 1 mes
Puntos: 84
Respuesta: Evitar que PHP envie el HTML antes de tiempo

Cita:
Iniciado por dashtrash Ver Mensaje
El problema no es que tengas que retrasar la salida HTML.
El problema es que estás pidiendo dos cosas distintas, y las tratas del mismo modo.
Una posible forma de hacerlo, es en el enrutador.
Si el path /a/b/c genera una pagina HTML, o una respuesta AJAX, lo especificas en el enrutador, e incluyes las cabeceras, o index, o lo que sea necesario.

Otra posibilidad (peor) es indicarlo via GET.Si existe un parametro "output=xxx", aplicas la salida xxx (json, etc,etc), lo cual implica unas cabeceras , controladores,etc

Y, mi consejo es: no presupongas que la salida es HTML.
Eso lo he intentado, el problema está en que tal cual el módulo recibe el html lo devuelve al navegador. En otras palabras: pienso que en el momento que un proceso PHP se encuentra con HTML lo devuelve al navegador y no hay forma de controlar esa salida.

Y lo he visto porque al generar el HTML con el controlador del front-end (el HTML que va dentro del body lo divido en el navegador y todo lo demás) y cargarlo en el cuerpo del HTML me devuelve primero el navegador, que es lo primero que genera el controlador, luego me devuelve la pagina en si misma y luego abajo del todo queda el cuerpo principal del HTML y las cabeceras con el body.

Eso es un despropósito a nivel semántico, aunque sí se aplican las reglas CSS y se enlazan los documentos .js

Por eso la manera de controlar la salida es primordial.

De hecho no tenía problema hasta que vi que sucedía esto y más adelante comencé a incluir AJAX, pude ver que en la salida había cabeceras y eso depurarlo en JSON es una tarea que no debería hacer, porque las cabeceras y otras tags no deberían aparecer.

No sé si me explico bien y si me estás entendiendo dashtrash.

Edito: pateketrueke gracias por tu idea, voy a investigar a ver si la puedo aplicar y cómo quedaría. Pero quedo abierto a más sugerencias.
__________________
Ayúdame a hacerlo por mi mismo.
  #5 (permalink)  
Antiguo 23/03/2015, 13:33
Avatar de guardarmicorreo  
Fecha de Ingreso: noviembre-2012
Ubicación: Córdoba
Mensajes: 1.153
Antigüedad: 12 años, 1 mes
Puntos: 84
Respuesta: Evitar que PHP envie el HTML antes de tiempo

Trabajando con tu sugerencia pateketrueke he hecho lo siguiente

Código HTML:
Ver original
  1. <?php
  2. //devuelve todo el html
  3. function controller(){
  4.    return html(content());
  5. }
  6.  
  7. //construye la estructura principal y el contenido
  8. function html($content){
  9.    \ob_start();
  10.    ?>
  11.     <html>
  12.         <head>
  13.  
  14.         </head>
  15.         <body>
  16.             <p><?php echo $content ; ?></p>
  17.         </body>
  18.     </html>
  19.     <?php
  20.    return \ob_get_contents();
  21. }
  22.  
  23. //construye el contenido
  24. function content(){
  25.    \ob_start();
  26.    ?>
  27.     Esto es una prueba del control de salida con búfer.
  28.     <?php
  29.    return \ob_get_contents();
  30. }
  31.  
  32. //llama al html
  33. echo controller();
  34. ?>

Pero me he encontrado con esta salida

Código HTML:
Ver original
  1. Esto es una prueba del control de salida con búfer.
  2.         <html>
  3.         <head>
  4.  
  5.         </head>
  6.         <body>
  7.             <p>    Esto es una prueba del control de salida con búfer.
  8.     </p>
  9.         </body>
  10.     </html>
  11.         <html>
  12.         <head>
  13.  
  14.         </head>
  15.         <body>
  16.             <p>    Esto es una prueba del control de salida con búfer.
  17.     </p>
  18.         </body>
  19.     </html>

Si hago esto otro

Código PHP:
Ver original
  1. <?php
  2. //reemplaza
  3. function replace($búfer){
  4.     return (str_replace('{content}', content(), $búfer));
  5. }
  6. //devuelve todo el html
  7. function controller(){
  8.     return html();
  9. }
  10.  
  11. //construye la estructura principal y el contenido
  12. function html(){
  13.     \ob_start('replace');
  14.     ?>
  15.     <html>
  16.         <head>
  17.  
  18.         </head>
  19.         <body>
  20.             <p>{content}</p>
  21.         </body>
  22.     </html>
  23.     <?php
  24.     \ob_end_flush();
  25. }
  26.  
  27. //construye el contenido
  28. function content(){
  29.     \ob_start();
  30.     ?>
  31.     Esto es una prueba del control de salida con búfer.
  32.     <?php
  33.     return \ob_get_contents();
  34. }
  35.  
  36. //llama al html
  37. echo controller();
  38. ?>

No obtengo salida de ningún tipo, ni tan siquiera con var_dump(controller()); al final del documento.

¿Qué está fallando en la primera forma?

Sobre la segunda no me preocupa porque no quiero terminar construyendo un sistema de templates xD
__________________
Ayúdame a hacerlo por mi mismo.
  #6 (permalink)  
Antiguo 23/03/2015, 14:04
Avatar de hhs
hhs
Colaborador
 
Fecha de Ingreso: junio-2013
Ubicación: México
Mensajes: 2.995
Antigüedad: 11 años, 5 meses
Puntos: 379
Respuesta: Evitar que PHP envie el HTML antes de tiempo

Cita:
Sobre la segunda no me preocupa porque no quiero terminar construyendo un sistema de templates xD
Eso es precisamente lo que estas haciendo.

P.D. lee el manual, no estas empleando bien el uso de ob_start y ob_get_contents
__________________
Saludos
About me
Laraveles
A class should have only one reason to change.
  #7 (permalink)  
Antiguo 23/03/2015, 14:15
Avatar de guardarmicorreo  
Fecha de Ingreso: noviembre-2012
Ubicación: Córdoba
Mensajes: 1.153
Antigüedad: 12 años, 1 mes
Puntos: 84
Respuesta: Evitar que PHP envie el HTML antes de tiempo

Cita:
Iniciado por hhs Ver Mensaje
Eso es precisamente lo que estas haciendo.

P.D. lee el manual, no estas empleando bien el uso de ob_start y ob_get_contents
Pfff ¿en qué me he metido? :D

He leído sobre las funciones ob y no encuentro nada que esté haciendo mal.

Teniendo en cuenta el primer caso:

ob_start() abre el almacenamiento en búfer y almacena lo que hay después.

ob_get_contents() obtiene el almacenamiento en búfer en el momento que es llamado y lo devuelve.

En cada función tengo ob_start, que lo podría reemplazar por un único ob_start en la función controller y haría el mismo efecto, porque son apilables.

Y en cada función retorno el ob_get_contents para devolver el búfer correspondiente a esa función.

Finalmente introduce el content en el html y retorna el html completo.

No veo que tenga nada erróneo :S
__________________
Ayúdame a hacerlo por mi mismo.
  #8 (permalink)  
Antiguo 23/03/2015, 15:17
Avatar de pateketrueke
Modernizr
 
Fecha de Ingreso: abril-2008
Ubicación: Mexihco-Tenochtitlan
Mensajes: 26.399
Antigüedad: 16 años, 8 meses
Puntos: 2534
Respuesta: Evitar que PHP envie el HTML antes de tiempo

El tema es que después de leer el buffer debes limpiarlo, pero no lo haces.

Precisamente por eso te había sugerido ob_end_clean() que hace ambas cosas, pero creo que no lees bien.
__________________
Y U NO RTFM? щ(ºдºщ)

No atiendo por MP nada que no sea personal.
  #9 (permalink)  
Antiguo 23/03/2015, 15:53
Avatar de hhs
hhs
Colaborador
 
Fecha de Ingreso: junio-2013
Ubicación: México
Mensajes: 2.995
Antigüedad: 11 años, 5 meses
Puntos: 379
Respuesta: Evitar que PHP envie el HTML antes de tiempo

Cita:
Iniciado por guardarmicorreo Ver Mensaje

He leído sobre las funciones ob y no encuentro nada que esté haciendo mal.

Teniendo en cuenta el primer caso:

ob_start() abre el almacenamiento en búfer y almacena lo que hay después.

ob_get_contents() obtiene el almacenamiento en búfer en el momento que es llamado y lo devuelve.

En cada función tengo ob_start, que lo podría reemplazar por un único ob_start en la función controller y haría el mismo efecto, porque son apilables.

Y en cada función retorno el ob_get_contents para devolver el búfer correspondiente a esa función.

Finalmente introduce el content en el html y retorna el html completo.

No veo que tenga nada erróneo :S
Un problema que tienes es que supones cosas antes de comprobarlas y por otro lado no lees bien lo que te instruye tu tutor pateketrueke.
.
Cita:
Output buffers are stackable, that is, you may call ob_start() while another ob_start() is active. Just make sure that you call ob_end_flush() the appropriate number of times. If multiple output callback functions are active, output is being filtered sequentially through each of them in nesting order.
Tienes que cerrar o vaciar el buffer tantas veces como ob_start emplees en el código. Ahora tomando tu ejemplo debiste tener algo asi:
Código PHP:
Ver original
  1. //devuelve todo el html
  2. function controller(){
  3.     html(content());
  4. }
  5.  
  6. //construye la estructura principal y el contenido
  7. function html($content){
  8.     \ob_start();
  9.     ?>
  10.     <html>
  11.     <head>
  12.  
  13.     </head>
  14.     <body>
  15.     <p><?php echo $content ;?></p>
  16.     </body>
  17.     </html>
  18.     <?php
  19.     \ob_end_flush();
  20. }
  21.  
  22. //construye el contenido
  23. function content(){
  24.     \ob_start();
  25.     ?>
  26.     Esto es una prueba del control de salida con buffer.
  27.     <?php
  28.     return \ob_get_clean();
  29. }
  30.  
  31. //llama al html
  32. controller();
__________________
Saludos
About me
Laraveles
A class should have only one reason to change.
  #10 (permalink)  
Antiguo 23/03/2015, 16:14
Avatar de guardarmicorreo  
Fecha de Ingreso: noviembre-2012
Ubicación: Córdoba
Mensajes: 1.153
Antigüedad: 12 años, 1 mes
Puntos: 84
Respuesta: Evitar que PHP envie el HTML antes de tiempo

volví a leer el manual.

Así hizo lo que yo quiero
Código PHP:
Ver original
  1. <?php    
  2. //devuelve todo el html
  3. function controller(){
  4.     $content = content();
  5.     ob_end_clean();
  6.     return html($content);
  7. }
  8.  
  9. //construye la estructura principal y el contenido
  10. function html($content){
  11.    \ob_start();
  12.    ?>
  13.     <html>
  14.         <head>
  15.  
  16.         </head>
  17.         <body>
  18.             <p><?php echo $content ; ?></p>
  19.         </body>
  20.     </html>
  21.     <?php
  22. }
  23.  
  24. //construye el contenido
  25. function content(){
  26.    \ob_start();
  27.    ?>
  28.     Esto es una prueba del control de salida con búfer.
  29.     <?php
  30.    return \ob_get_contents();
  31. }
  32.  
  33. //llama al html
  34. controller();
  35. ?>

¿Pero están bien utilizadas las funciones ob? Porque que haga lo que yo quiero no significa que esté bien jeje.
__________________
Ayúdame a hacerlo por mi mismo.
  #11 (permalink)  
Antiguo 23/03/2015, 16:27
Avatar de guardarmicorreo  
Fecha de Ingreso: noviembre-2012
Ubicación: Córdoba
Mensajes: 1.153
Antigüedad: 12 años, 1 mes
Puntos: 84
Respuesta: Evitar que PHP envie el HTML antes de tiempo

Cita:
Iniciado por hhs Ver Mensaje
Un problema que tienes es que supones cosas antes de comprobarlas y por otro lado no lees bien lo que te instruye tu tutor pateketrueke.
.
Tienes que cerrar o vaciar el buffer tantas veces como ob_start emplees en el código. Ahora tomando tu ejemplo debiste tener algo asi:
Código PHP:
Ver original
  1. //devuelve todo el html
  2. function controller(){
  3.     html(content());
  4. }
  5.  
  6. //construye la estructura principal y el contenido
  7. function html($content){
  8.     \ob_start();
  9.     ?>
  10.     <html>
  11.     <head>
  12.  
  13.     </head>
  14.     <body>
  15.     <p><?php echo $content ;?></p>
  16.     </body>
  17.     </html>
  18.     <?php
  19.     \ob_end_flush();
  20. }
  21.  
  22. //construye el contenido
  23. function content(){
  24.     \ob_start();
  25.     ?>
  26.     Esto es una prueba del control de salida con buffer.
  27.     <?php
  28.     return \ob_get_clean();
  29. }
  30.  
  31. //llama al html
  32. controller();
Gracias hhs :D
__________________
Ayúdame a hacerlo por mi mismo.

Etiquetas: formulario, html, tiempo, variable
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta

SíEste tema le ha gustado a 1 personas




La zona horaria es GMT -6. Ahora son las 13:19.