VarDumpFormatter.io: How I Created an Online Tool that Didn’t Exist Yet
By: Alexandre Daubois
Tags: Symfony, Beautifier, Vardump, Parse, PHP

The Core: the algorithm behind everything

The model we’ll use

Because yes, our output is a tree with at least one node (for example, when we parse a string as simple as int(5) ), and at most a nested tree with multiple nodes with objects and arrays. I’ve been straight forward with the model. Also, I defined every possible Node type with constants. Again, PHP doesn’t have much variable types.

Note that TYPE_NONE is only used for initialization purpose.

That’s it! This is the only model class we need to parse our var_dump output. The second things I had to create is of course a Symfony service that will format any var_dump string.

Let’s dive into the algorithm itself

Parsing things like an int , float , boolean is super simple. I used a lot the String component of Symfony. I never had the opportunity to do so, and given that we’re going to deal with Strings a lot, I thought it would be a good idea to experiment with them. In order to parse simple types, I just have to add two methods in the service. The first one checks if the given type is “simple” to parse and then creates a new node before returning it. It sets the node type, and then call the second method named extractValue , which will simply return the value of the variable. We can see the use of Symfony Strings with after and before methods.

These methods are straightforward, and will of course only work if the var_dump output hasn’t been altered in any way. We’ll see later in this article how we can deal with errors, for example if the user badly pasted its output or changed things inside of it before passing it to the beautifier.

Strings and resources parsing

These two are also easy to parse. Resources are dumped like this:

resource(internal_php_indentifier) of type (resource_type)

A few lines of code and you’re good to go:

Strings parsing is a bit trickier. Why? Because strings can contain absolutely everything. Parenthesis, brackets, why not another var_dump output! I had to find another way to do this, more than just take everything between quotes ( var_dump doesn’t escape quotes!). Then I realized something: var_dump also outputs string length. Perfect! We can use this to parse exactly the number of characters we need, without having to take care of any special character.

Now the hardest part: parse arrays and objects

That’s the part that took me the most sweat and tears, because of two reasons:

Arrays and objects can contain n-levels of depth (alright, this one’s pretty easy with our tree and nodes model) ;

Arrays and objects can contain strings of dumped arrays, for example. We want our tool to work for every case (or at least all cases I could think of…), and man, that wasn’t as easy as I thought when starting this project.

The little bright side is if our parser works for arrays, it works for objects too.

So, first of all, let’s check if our var_dump output contains an array, and let’s create a node that represents it:

Note that we’re using setDepth methods of node. This will be super useful when we will be displaying the formatted output to the user. This way we will be able to add tabulations in front of nodes display depending on their depth.

After doing this, let’s explore the processProperties method. The extractProperties simply returns the content between the first and last brackets of the array, and in this case, $node->getValue() return the number between parenthesis just after the word array , in another words: the properties count of this array. Having this information allows us to know of many properties we need to parse.

First, we need to check if the properties count is greater than 0. If it’s equal to zero, we’re done with this part. Otherwise, we’ll first trim the string we just received in order to get rid of blank spaces, tabulations or whatever at beginning or end of the array content. The next part is “string sanitizing”.

We want to process every array’s depth individually, and then iterate through them thanks to recursion. But in order to only process the current depth level, we have to get rid of deeper levels.

The solution I found is: count opening and closing brackets (this way, strings in deeper levels can contain brackets without problems), and replace deeper arrays’ content with something our parser won’t interpret, let’s say the underscore symbol. It will give something like this:

There is just one problem with this part of code. If a string contains an opening bracket and not its closing one, result will be unpredictable. But let’s say it is enough for now, and that it’ill cover the vast majority of cases.

This part will result on something like this:

{ [0]=> int(5) [1]=> array(3) { __________________ } }

Note: underscore symbol count is exactly the same as characters count of array’s content.

Hurray! We now have a single depth string to parse. This is super convenient because we can now recursively call our parser. It will process the first property as an int , then the next one as an array. So we’ll send the non-sanitized string to the parser for property [1] , and then we will repeat this process again and again. To extract property name and pass recursively non-sanitized data to the parser, we retrieve every property with a big regex (seems complicated but it’s really not) that extracts each property and parse them individually:

That’s truly the most complex part of the whole project. First regex catch every possible variable type of PHP, and the second one extracts properties keys in the current array. Note we’re calling processContent with $value , which is the non-sanitized string. Then, if another array is found, processContent will call the method to parse arrays, and so on.

That’s it! We now have a beautifier capable of parsing arrays. And objects too! Remember, objects are displayed the same way arrays are.

We have our tree with its nodes. It is now super trivial to display it with something like Twig, with again a recursive template whenever you print an array, and a display behavior by variable type. Remember, we stored everything in our Node model, from variable type to extra-data like strings length, properties names in arrays, PHP internal identifier for objects or resources, etc.

A bit of Twig, a bit of CSS, and we’re good: