Utilisation de l'impression R et var dump avec référence circulaire

j'utilise le MVC framework Symfony , et il semble que beaucoup des objets intégrés que je veux déboguer ont des références circulaires. Cela rend impossible l'impression des variables avec print_r() ou var_dump() (puisqu'elles suivent des références circulaires à l'infini ou jusqu'à ce que le processus s'épuise, selon la première éventualité).

au lieu d'écrire mon propre clone print_r avec un peu d'intelligence, y a-t-il de meilleures alternatives il y a? Je veux seulement être capable d'imprimer une variable (objet, tableau ou scalaire), soit vers un fichier log, un en-tête http ou la page Web elle-même.

Edit: pour clarifier ce qu'est le problème, essayez ce code:

<?php

class A
{
    public $b;
    public $c;

    public function __construct()
    {
        $this->b = new B();
        $this->c = new C();
    }
}

class B
{
    public $a;

    public function __construct()
    {
        $this->a = new A();
    }
}

class C
{
}

ini_set('memory_limit', '128M');
set_time_limit(5);

print_r(new A());
#var_dump(new A());
#var_export(new A());

ça ne marche pas avec print_r() , var_dump() ou var_export() . Le message d'erreur est:

PHP erreur fatale: taille de mémoire autorisée de 134217728 octets épuisés (essayé d'allouer 523800 octets) en print_r_test.php sur la ligne 10

34
demandé sur Christian Davén 2011-06-09 15:36:28

8 réponses

nous utilisons le cadre PRADO et il a un construit dans la classe appelée" TVarDumper " qui peut gérer de tels objets complexes assez bien - il peut même le formater en HTML agréable incl. syntaxique. Vous pouvez obtenir cette classe de ici .

11
répondu ChrFin 2016-04-08 01:03:00

Doctrine ont la même classe de service.

exemple d'usage:

<?php echo "<pre>"; \Doctrine\Common\Util\Debug::dump($result, 4); echo "</pre>";?>
12
répondu Alorian 2016-04-07 15:12:27

Vous pourriez utiliser var_export() .

var_export () ne traite pas les circulaires les références qu'il serait proche de impossible de générer du PHP parsable code pour cela. Si vous voulez faire quelque chose avec la représentation complète d'un tableau ou d'un objet, utilisez la sérialiser.)(

mise à JOUR: Semble que j'avais tort. J'ai pensé que j'ai utilisé ce il y a quelque temps, c'était dans ce but, mais ça devait être une sorte d'imagination ivre.

de cette façon, le seul conseil que je puisse donner est d'installer Xdebug .

4
répondu kapa 2011-06-09 12:36:36

TVarDumper

TVarDumper est destiné à remplacer la fonction buggy PHP var_dump et print_r , car il peut identifier correctement les objets référencés récursivement dans une structure d'objet complexe. Il a également un contrôle de profondeur récursif pour éviter l'affichage récursif indéfinie de certaines variables particulières.

Vérifier TVarDumper.php :

<?php
/**
 * TVarDumper class file
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @link http://www.pradosoft.com/
 * @copyright Copyright &copy; 2005-2013 PradoSoft
 * @license http://www.pradosoft.com/license/
 * @version $Id$
 * @package System.Util
 */

/**
 * TVarDumper class.
 *
 * TVarDumper is intended to replace the buggy PHP function var_dump and print_r.
 * It can correctly identify the recursively referenced objects in a complex
 * object structure. It also has a recursive depth control to avoid indefinite
 * recursive display of some peculiar variables.
 *
 * TVarDumper can be used as follows,
 * <code>
 *   echo TVarDumper::dump($var);
 * </code>
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @version $Id$
 * @package System.Util
 * @since 3.0
 */
class TVarDumper
{
    private static $_objects;
    private static $_output;
    private static $_depth;

    /**
     * Converts a variable into a string representation.
     * This method achieves the similar functionality as var_dump and print_r
     * but is more robust when handling complex objects such as PRADO controls.
     * @param mixed variable to be dumped
     * @param integer maximum depth that the dumper should go into the variable. Defaults to 10.
     * @return string the string representation of the variable
     */
    public static function dump($var,$depth=10,$highlight=false)
    {
        self::$_output='';
        self::$_objects=array();
        self::$_depth=$depth;
        self::dumpInternal($var,0);
        if($highlight)
        {
            $result=highlight_string("<?php\n".self::$_output,true);
            return preg_replace('/&lt;\?php<br \/>/','',$result,1);
        }
        else
            return self::$_output;
    }

    private static function dumpInternal($var,$level)
    {
        switch(gettype($var))
        {
            case 'boolean':
                self::$_output.=$var?'true':'false';
                break;
            case 'integer':
                self::$_output.="$var";
                break;
            case 'double':
                self::$_output.="$var";
                break;
            case 'string':
                self::$_output.="'$var'";
                break;
            case 'resource':
                self::$_output.='{resource}';
                break;
            case 'NULL':
                self::$_output.="null";
                break;
            case 'unknown type':
                self::$_output.='{unknown}';
                break;
            case 'array':
                if(self::$_depth<=$level)
                    self::$_output.='array(...)';
                else if(empty($var))
                    self::$_output.='array()';
                else
                {
                    $keys=array_keys($var);
                    $spaces=str_repeat(' ',$level*4);
                    self::$_output.="array\n".$spaces.'(';
                    foreach($keys as $key)
                    {
                        self::$_output.="\n".$spaces."    [$key] => ";
                        self::$_output.=self::dumpInternal($var[$key],$level+1);
                    }
                    self::$_output.="\n".$spaces.')';
                }
                break;
            case 'object':
                if(($id=array_search($var,self::$_objects,true))!==false)
                    self::$_output.=get_class($var).'#'.($id+1).'(...)';
                else if(self::$_depth<=$level)
                    self::$_output.=get_class($var).'(...)';
                else
                {
                    $id=array_push(self::$_objects,$var);
                    $className=get_class($var);
                    $members=(array)$var;
                    $keys=array_keys($members);
                    $spaces=str_repeat(' ',$level*4);
                    self::$_output.="$className#$id\n".$spaces.'(';
                    foreach($keys as $key)
                    {
                        $keyDisplay=strtr(trim($key),array(""151900920""=>':'));
                        self::$_output.="\n".$spaces."    [$keyDisplay] => ";
                        self::$_output.=self::dumpInternal($members[$key],$level+1);
                    }
                    self::$_output.="\n".$spaces.')';
                }
                break;
        }
    }
}

XDebug var_dump

utilisez l'extension Xdebug PHP, et il détectera et ignorera les références circulaires, par exemple:

echo xdebug_var_dump($object);

print_r + array_slice

comme dans ce post , vous pouvez essayer:

print_r(array_slice($desiredArray, 0, 4));

features_var_export

utilisez la fonction suivante qui fait partie du module caractéristiques pour Drupal ( features.export.inc ):

/**
 * Export var function
 */
function features_var_export($var, $prefix = '', $init = TRUE, $count = 0) {
  if ($count > 50) {
    // Recursion depth reached.
    return '...';
  }

  if (is_object($var)) {
    $output = method_exists($var, 'export') ? $var->export() : features_var_export((array) $var, '', FALSE, $count+1);
  }
  else if (is_array($var)) {
    if (empty($var)) {
      $output = 'array()';
    }
    else {
      $output = "array(\n";
      foreach ($var as $key => $value) {
        // Using normal var_export on the key to ensure correct quoting.
        $output .= "  " . var_export($key, TRUE) . " => " . features_var_export($value, '  ', FALSE, $count+1) . ",\n";
      }
      $output .= ')';
    }
  }
  else if (is_bool($var)) {
    $output = $var ? 'TRUE' : 'FALSE';
  }
  else if (is_int($var)) {
    $output = intval($var);
  }
  else if (is_numeric($var)) {
    $floatval = floatval($var);
    if (is_string($var) && ((string) $floatval !== $var)) {
      // Do not convert a string to a number if the string
      // representation of that number is not identical to the
      // original value.
      $output = var_export($var, TRUE);
    }
    else {
      $output = $floatval;
    }
  }
  else if (is_string($var) && strpos($var, "\n") !== FALSE) {
    // Replace line breaks in strings with a token for replacement
    // at the very end. This protects whitespace in strings from
    // unintentional indentation.
    $var = str_replace("\n", "***BREAK***", $var);
    $output = var_export($var, TRUE);
  }
  else {
    $output = var_export($var, TRUE);
  }

  if ($prefix) {
    $output = str_replace("\n", "\n$prefix", $output);
  }

  if ($init) {
    $output = str_replace("***BREAK***", "\n", $output);
  }

  return $output;
}

Utilisation:

echo features_var_export($object);

Sérialiser

utiliser serialize pour décharger l'objet dans une représentation sérialisée, p.ex.:

echo serialize($object);

JSON Encode

utiliser json_encode pour le convertir en format JSON, p.ex.:

echo json_encode($object);

Voir aussi: Test if la variable contient les références circulaires

4
répondu kenorb 2017-05-23 11:46:38
class Test {
    public $obj;
}
$obj = new Test();
$obj->obj = $obj;
print_r($obj);
var_dump($obj);

sortie:

Test Object
(
    [obj] => Test Object
 *RECURSION*
)

object(Test)[1]
  public 'obj' => 
    &object(Test)[1]

il me semble que les deux print_r() et var_dump() peuvent gérer la récursion sans problème. Utiliser PHP 5.3.5 sur Windows.


var_export() ne détecte pas la récursion, qui entraîne une erreur fatale instantanée:

Fatal error:  Nesting level too deep - recursive dependency? in \sandbox\index.php on line 28
2
répondu binaryLV 2011-06-09 11:47:28

j'ai eu ce problème aussi et je l'ai résolu en mettant en œuvre la méthode __get() pour briser le cercle de référence. La méthode _ _ get () est appelée après qu'un attribut n'est pas trouvé dans la déclaration de classe. La méthode _ _ get () obtient aussi le nom de l'attribut manquant. En utilisant cela, vous pouvez définir "les attributs virtuels" qui fonctionnent de la même manière que d'habitude, mais ne sont pas mentionnés par la fonction print_r. Voici un exemple:

public function __get($name)
{
    if ($name=="echo") {
        return Zend_Registry::get('textConfig');
    }

}

1
répondu Lucian Depold 2012-09-21 11:01:27

Cela semblait faire le travail pour moi:

print_r(json_decode(json_encode($value)));
0
répondu fcrick 2017-03-01 21:16:06

Symfony de nos jours a également composante VarDumer: https://symfony.com/doc/current/components/var_dumper.html

il gère les références circulaires et supporte le serveur de dump distant.

L'Installation est assez facile:

composer require symfony/var-dumper --dev

alors vous pouvez utiliser la fonction globale dump (je suppose que composer autoload.php est déjà inclus):

<?php
/* ... */
dump($someVar);
0
répondu Ostin 2018-09-19 07:56:24