Mage :: el registro escribe en la pantalla

21

Tengo un sistema de desarrollo, display_errors está activado, Magento está en modo desarrollador e intenté

Mage::log($layered_navigation_filter_block); // Mage_Catalog_Block_Layer_Filter_Attribute

Y todo fue escrito en la pantalla en lugar del archivo de registro, ¿por qué?

Se parece a este caso:

// app/Mage.php:837
if (is_array($message) || is_object($message)) {
    $message = print_r($message, true);
}

pero el segundo argumento de print_r se ignora:

Mage_Catalog_Block_Layer_Filter_Category Object ( [_filter:protected] => ...

 

[28-Jan-2013 22:48:43 UTC] PHP Fatal error:  Allowed memory size of 268435456 bytes exhausted (tried to allocate 241434624 bytes) in /var/www/app/code/local/MyCompany/Motif/Model/Observer.php on line 47
[28-Jan-2013 22:48:43 UTC] PHP Stack trace:
[28-Jan-2013 22:48:43 UTC] PHP   1. {main}() /var/www/index.php:0
[28-Jan-2013 22:48:43 UTC] PHP   2. Mage::run() /var/www/index.php:87
[28-Jan-2013 22:48:43 UTC] PHP   3. Mage_Core_Model_App->run() /var/www/app/Mage.php:683
[28-Jan-2013 22:48:43 UTC] PHP   4. Mage_Core_Controller_Varien_Front->dispatch() /var/www/app/code/core/Mage/Core/Model/App.php:354
[28-Jan-2013 22:48:43 UTC] PHP   5. Mage_Core_Controller_Varien_Router_Standard->match() /var/www/app/code/core/Mage/Core/Controller/Varien/Front.php:176
[28-Jan-2013 22:48:43 UTC] PHP   6. Mage_Core_Controller_Varien_Action->dispatch() /var/www/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php:250
[28-Jan-2013 22:48:43 UTC] PHP   7. Mage_Catalog_CategoryController->viewAction() /var/www/app/code/core/Mage/Core/Controller/Varien/Action.php:419
[28-Jan-2013 22:48:43 UTC] PHP   8. Mage_Core_Controller_Varien_Action->generateLayoutBlocks() /var/www/app/code/core/Mage/Catalog/controllers/CategoryController.php:146
[28-Jan-2013 22:48:43 UTC] PHP   9. Mage_Core_Model_Layout->generateBlocks() /var/www/app/code/core/Mage/Core/Controller/Varien/Action.php:344
[28-Jan-2013 22:48:43 UTC] PHP  10. Mage_Core_Model_Layout->generateBlocks() /var/www/app/code/core/Mage/Core/Model/Layout.php:210
[28-Jan-2013 22:48:43 UTC] PHP  11. Mage_Core_Model_Layout->_generateBlock() /var/www/app/code/core/Mage/Core/Model/Layout.php:205
[28-Jan-2013 22:48:43 UTC] PHP  12. Mage_Core_Model_Layout->addBlock() /var/www/app/code/core/Mage/Core/Model/Layout.php:239
[28-Jan-2013 22:48:43 UTC] PHP  13. Mage_Core_Model_Layout->createBlock() /var/www/app/code/core/Mage/Core/Model/Layout.php:472
[28-Jan-2013 22:48:43 UTC] PHP  14. Mage_Core_Block_Abstract->setLayout() /var/www/app/code/core/Mage/Core/Model/Layout.php:456
[28-Jan-2013 22:48:43 UTC] PHP  15. Mage::dispatchEvent() /var/www/app/code/core/Mage/Core/Block/Abstract.php:239
[28-Jan-2013 22:48:43 UTC] PHP  16. Mage_Core_Model_App->dispatchEvent() /var/www/app/Mage.php:447
[28-Jan-2013 22:48:43 UTC] PHP  17. Mage_Core_Model_App->_callObserverMethod() /var/www/app/code/core/Mage/Core/Model/App.php:1317
[28-Jan-2013 22:48:43 UTC] PHP  18. MyCompany_Motif_Model_Observer->coreBlockAbstractPrepareLayoutAfter() /var/www/app/code/core/Mage/Core/Model/App.php:1338
[28-Jan-2013 22:48:43 UTC] PHP  19. print_r() /var/www/app/code/local/MyCompany/Motif/Model/Observer.php:47

Ok, ocurre un error fatal, no se registra ninguna función de apagado, entonces ¿por qué se hace eco de print_r? :-) Todavía no entiendo lo que está sucediendo.

Fabian Blechschmidt
fuente
¿El resultado que está obteniendo en la pantalla es el volcado del objeto de bloque o es una excepción? Podría estar detectando una excepción antes de que se llame a Mage :: log.
mybluevan
¿Qué es exactamente lo que está escrito en la pantalla?
Alan Storm
actualizó la pregunta
Fabian Blechschmidt
¿Qué versión de Stack, Magento y / o PHP estás usando?
B00MER
MAMP PRO (Apache / 2.2.22, PHP 5.4.3) magento 1.7.0.2
Fabian Blechschmidt

Respuestas:

29

Creé un caso de prueba reproducible realmente corto y dulce para esto:

<?php

error_reporting(-1);
ini_set('display_errors', true);
ini_set('memory_limit', '1M');

$chunk = base64_encode(openssl_random_pseudo_bytes(1024));

while (true) {
    $a[] = print_r($chunk, true);
}

La razón por la que está viendo la información se debe al print_ruso interno de la memoria intermedia de salida para capturar su información. Eche un vistazo a la definición de la print_rfunción desde la fuente PHP:

/* {{{ proto mixed print_r(mixed var [, bool return])
   Prints out or returns information about the specified variable */
PHP_FUNCTION(print_r)
{
    zval *var;
    zend_bool do_return = 0;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &var, &do_return) == FAILURE) {
        RETURN_FALSE;
    }

    if (do_return) {
        php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC);
    }

    zend_print_zval_r(var, 0 TSRMLS_CC);

    if (do_return) {
        php_ob_get_buffer (return_value TSRMLS_CC);
        php_end_ob_buffer (0, 0 TSRMLS_CC);
    } else {
        RETURN_TRUE;
    }
}

Debido a que PHP se está quedando sin memoria y está muriendo, el búfer de salida se vacía antes de print_rborrarlo a través de su llamada aphp_ob_get_buffer

No estoy seguro de que va a haber de todos modos alrededor de esto. Solo asegúrese de deshabilitar ese inicio de sesión en producción, o ejecute mod_security para evitar que este tipo de salida vaya a la página.

davidalger
fuente
Muchas gracias por esta respuesta detallada. Debería reiniciar el aprendizaje de C y leer el código fuente de PHP :)
Fabian Blechschmidt
6

Lo que davidalger señala es importante. El objeto que intenta registrar es demasiado grande y hace que PHP se quede sin memoria. Dependiendo de su límite de memoria y del tamaño de su bloque, puede usar:

Mage::log($layered_navigation_filter_block->debug());

Todos los objetos que extienden Varien_Object pueden usar debug () para generar la propiedad subyacente _data de forma recursiva.

Consulte esta publicación de blog de uno de mis compañeros de trabajo para obtener una explicación más detallada.

mybluevan
fuente
2

¿Podría ser ésta la razón?

/programming/9329877/using-print-r-in-ob-start

"De la documentación de PHP: cuando se utiliza el parámetro de retorno, esta función utiliza el almacenamiento intermedio de salida interno, por lo que no se puede utilizar dentro de una función de devolución de llamada ob_start ()". Más información aquí: [php.net/manual/en/function.print-r.php]

ProxiBlue
fuente