-
Appears in:
- Laravel Basics
Dirty Debugging with dd()
Published on 14/07/2023Sometimes it's useful to get a bit more information on the data you're dealing with - does your variable actually contain the data you expect? If not, where did things go wrong?
There are various debugging tools available, such as Xdebug, which provide some really sophisticated ways to drill into your data. However, most of these require some amount of setup before you can start using them.
If you just need a really quick way to peek at your data, Laravel's dd() can do the trick, with no configuration necessary.
What does dd() do?
dd() doesn't actually stand for "dirty debug" (but it makes a good title). It actually stands for dump and die.
It's a built-in Laravel function, and you use it by passing in some variable to the parenthesis like below:
$cat = "Tibbles";
dd($cat);
It tells PHP to print out (dump) the contents of the variable(s) you passed in, and then, stop running (die). It's not sophisticated, but it's a quick and easy way to see what the variable contains.

We can see here that the value of our variable $cat is the sting "Tibbles", just as we expected.
Notice that Laravel also tells us which file and line the dd is coming from.
Example use-cases
Mysterious errors
If your code for some reason refuses to run, and you just get a blank page, or an error that you can't quite track down, dd() can help. Because the code stops running at the dd line, anything dodgy after this point is less likely to have an impact (missing brackets etc might still cause problems).
A really simple way to debug this is to put a few strings in a dd in various sections of your code, then comment them out from the top, testing each time to see where things break - this helps you to isolate the block of code where the error happens
public function dodgyFunction()
{
dd('Test 1 - First line');
// some code here
dd('Test 2');
// some more code here
}
Unexpected / Missing data
It's happened to us all. You pull some data from the database, and then you try to use it...and Laravel is telling you off because whatever you're trying to do apparently isn't allowed.
You can use dd() to tell you what data you actually have. From there, you can figure out why things aren't working. See the How to use dd section for a worked example.
Spaghetti Code
Imagine you've got some super-duper complex code, with some badly named methods, and some really messy inheritance. It's really hard to know which chunks of code are actually doing what.
You can place a dd - maybe with just a string dd("I'm the BobsUncle method!") in a few of the files you're trying to figure out, and by seeing which message gets printed out, as well as the filename and line number, you can see which files and methods are being used.
How to use dd()
Firstly, you'll need to be working on a file that can be accessed (directly or indirectly) from a web browser, or API client*. For instance, a Controller method with a Route pointing to it.
Open your browser/client, and navigate to the relevant URL. Then, open up the relevant section of code that powers this page. This could be code directly in the Controller, or any code that the Controller uses, like Models or helper functions the code calls - you can place a dd() within any of the code powering the page.
Let's look at an example:
$name = 'Tibbles';
$cat = Cat::where('name', $name)->get();
$colour = $cat->color;
return "The colour of the cat named $name is $colour";
In this example, I'm expecting to have retrieved an instance of my Cat model, specifically, the cat named Tibbles, and then I want to find out what colour fur he has.
But I've got an error:
Property [colour] does not exist on this collection instance
Collection instance? What? Where's Tibbles?
Add a dd() to the line before the error, and we can see what's going on. (Laravel helpfully displays your code on the error page, with the offending line highlighted)
Here's our dd():

Oops, looks like we actually have a collection, instead of our model instance (Tibbles the Cat). We can see Tibbles in the collection though, so we know we're on the right track.
To resolve this, we need to make sure we just ask for the first matching result, instead of all matching results. We should use ->first() instead of ->get()
$name = 'Tibbles';
$cat = Cat::where('name', $name)->first();
dd($cat);
$colour = $cat->color;
return "The colour of the cat named $name is $colour";

Our latest dd shows us that our data is an instance of the Cat Model, and we can see Tibbles' data in there - including the 'color' property.
If we take out the dd, our next lines of code should now run fine, and the color attribute should be accessible.
We see our returned string, "The colour of the cat named Tibbles is Black and White"
Limitations
Whilst it's not that dirty, dd() does have a number of limitations you should bear in mind:
Loops
The code will stop as soon as it hits a dd() - if this is within a loop, then only that first iteration of the loop will go ahead before the code stops. If your code is breaking in the second, third, fourth iteration... you'll have stopped before you got there.
One way around this is to use an if() statement - a dd() won't do anything if it's inside a false if. If you know something about the data in the loop that breaks - eg you know the code breaks on the cat named "Sid", you could wrap the dd() as below.
if ($cat->name === 'Sid'){
dd($cat);
}
dd() has a cousin - dump() - which works in much the same way, but without the code dying. You could add dump($cat) into the loop to get the data within every iteration. If Laravel throws an error later on, you'll often still be able to see the output from dump() at the bottom of the error page.
One-at-a-time debugging
Because the code stops at the first dd(), you can't view multiple of them at once. However, you can pass multiple params to one dd, all of which will be printed out, so if variables are close together, you can put them in the same dd to see both - eg dd($name, $cat)
No "Resume" functionality
Unlike more sophisticated debugging tools, once you've hit a dd(), that's it, the code stops. This can be annoying if you've had to do multiple steps to get to the relevant point, because you have to reload and start again rather than just picking up where you left off. Proper debugging tools like Xdebug allow you to place multiple breakpoints, and hop from one to the next.
Harder to debug "deeper" code
To view the results of a dd(), you'll need to be able to reach the output of the code, either using a browser to access it via a web route, or an API client to access it from an API route. If your code isn't called by something that returns something to user - eg it's in a background job, it can be harder to get at this code. This isn't insurmountable, but it might need you to temporarily copy code to somewhere accessible, or make some methods public so that you can call them from a controller
Understanding the data dump
You'll have seen that there are quite a lot of sections to the outputted data. Here's a summary of the key ones you might want to use:
Line 1
If you've got some simple data, like a string, you'll just see the value here. Eg in the example above, if you did dd($name), you'd see "Tibbles" returned.
Next to this, you'll also see a filename and line number - this tells you where in the code the dd was
If you've got more complex data, like a Collection or a Model instance, you'll see the path to the relevant class. You'll likely also see a little arrow, to expand the data.
"Items" Key
If you've got something containing multiple results, like a Collection or an Array, you'll see an "items" key. You can expand this, and you'll see 0 or more keys, with an expand arrow beside each one. Expand each item to see what it contains
What you see within each item (or at the top level, if you only had one item), will depend on what sort of data you have. Some of the ones you might be most likely to use are below:
"Attributes" and "Original"
If you've pulled data from the database, this is where your actual data lives. These two may be the same, but if you've modified the data in any way, "original" will contain the data as it is in the database, and "attributes" will contain your modifications
"Casts"
Determined by the model, whether Laravel treats any fields as a specific data type - eg date fields might be cast to a Carbon Date instance. See Laravel Docs - attribute casting
"With"
Details of any related data that was eager-loaded from other tables. See Laravel Docs - eager loading
"Fillable" and "Guarded"
Properties set on the model which determine which fields can be updated en-masse by the end user. See Laravel Docs - mass assignment
This is by no means an exhaustive list, and there are many more headings you'll see within a data dump, depending on the type of data you're dealing with. Checking what class is being dumped (line 1) is a good place to start when trying to figure out what data structure to expect.
Be careful!
Make sure you never push any code containing a dd() to your live site. Unlike proper debugging tools, a dd() in the code will execute wherever it is, even on a live website.
This could mean a broken website for your user, as the code will stop running where the dd() is placed, and they won't be able to get any further.
At worst, it could also reveal sensitive information about the inner workings of your site, or confidential data from your database.
dd() can be a useful tool, but always remember to clean up after yourself!
In summary...
Whilst using dd() is a pretty blunt-object type of debugging, it can be pretty useful when you just want to quickly see the data you're dealing with. Bear in mind its limitations, and take care to clean up when you're done. Happy debugging!