Across this section you've inspected form arrays with `kint()`, logged validation and submission failures, and traced AJAX callbacks through the browser's Network tab — each technique aimed at one specific kind of problem. The Devel module is what ties all of that together into a single toolkit you keep enabled throughout a whole development cycle, rather than reaching for a different tool every time.
What you'll learn in this lesson
- What Devel actually bundles beyond the `kint()` function you've already used
- How the Devel toolbar gives you route, permission, and cache information for free on every page
- Why Devel should never be enabled on a production site
- How everything from this section — array inspection, logging, AJAX tracing — fits together as one debugging workflow
Installing and enabling Devel
composer require drupal/devel
drush en devel -y
Same install path you used back in the first lesson of this section — Devel is one module, but it ships several distinct tools under that one package, and `kint()` is only the most-used of them.
Beyond kint(): the Devel toolbar
Enable Devel's toolbar (a separate sub-module, `devel_toolbar`) and every page on your site gains a menu showing you, without writing a single line of debug code: the current route name, the controller or form class handling it, session information, and a live cache-clear link. When a form isn't behaving as expected, checking "is this route even hitting the class I think it is" via the toolbar is often faster than adding a `kint()` call at all.
Bringing it together in one form
namespace Drupal\my_module\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
class InspectForm extends FormBase {
public function getFormId() {
return 'inspect_form';
}
public function buildForm(array $form, FormStateInterface $form_state) {
$form['example'] = [
'#type' => 'textfield',
'#title' => $this->t('Example Textfield'),
];
$form['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Submit'),
];
// Structure debugging, from the first lesson in this section.
kint($form);
return $form;
}
public function submitForm(array &$form, FormStateInterface $form_state) {
// Execution-flow debugging, from two lessons ago.
kint($form_state->getValues());
$this->messenger()->addMessage($this->t('Form submitted successfully.'));
// Failure logging, exactly like the validation-logging lesson.
\Drupal::logger('my_module')->notice('Form @form_id submitted.', [
'@form_id' => $this->getFormId(),
]);
}
}
Nothing here is a new technique — it's the same `kint()` and `\Drupal::logger()` calls from earlier in this section, just placed at both the structure-inspection point (`buildForm()`) and the execution-flow point (`submitForm()`) in the same form. That's the real skill this whole section has been building: knowing *which* tool answers *which* question, not memorizing a longer and longer list of debug functions.
Quick check: you're debugging a form and you're not sure whether the problem is in the route configuration, the form class being invoked, or the form's own logic. Which Devel tool do you check first — `kint()`, the Devel toolbar, or the log? (Answer: the Devel toolbar — it tells you the route and controller/form class actually being used on this page, before you've written a single `kint()` call, which is exactly the "am I even hitting the code I think I am" question you need answered first.)
Key takeaways
- Devel bundles several distinct tools — `kint()` is the most-used, but the toolbar's route/controller info is often the faster first check.
- The right debugging technique depends on the question: structure (`kint($form)`), execution flow (`kint($form_state->getValues())` + logging), or the client/server boundary (Network tab).
- Devel is always a `--dev` dependency — require it that way, and confirm it's disabled before any deploy to production.
- The Devel toolbar answers "am I even hitting the code I think I am" faster than adding debug calls to code you're not yet sure is running.
Coming up next
That closes out the Drupal Form Api path — from your very first `buildForm()` all the way through validation, submission, AJAX, theming, security, performance, testing, and now debugging every one of those pieces when something goes wrong. You've now got the full toolkit for building forms that are correct, secure, fast, and maintainable — the rest is practice.