A recent challenge that I faced on a project was to generate the HTML of a full Drupal page, from within a Drupal request. The project called for a template to be rendered within the structure of a Drupal theme and also to include the styles associated with that theme.
At first, this doesn’t seem like a big problem, but once I started trying to figure things out it became much more complex than I was expecting.
The problem is that you can’t just render a page using the ‘html’ and ‘page’ templates as there is a lot of context surrounding those templates. Without this context in place Drupal produces a page of markup that contains no styles or blocks. The context is how Drupal knows what theme to load, what libraries to add to the page, what preprocess hooks to call, what menu items to generate, and so on.
I found a couple of different solutions to this problem that work quite well.
In both of these situations I will generate the page render and then send it back to the user using a new Response object from a controller. This essentially replaces the response from the Drupal controller with our custom markup.
Solution 1: Render A Page Using A Get Request
Since we are trying to render a page it sort of makes sense that we ask Drupal to render that full page for us through a sub-request. This means making a secondary request using the Guzzle HTTP Client to the page we want to render and then returning the result of that request in the Response object.
This is perhaps the simplest approach as we just need to figure out the page we want to go to and then make the request to that page.
Here is the action method for a normal Drupal controller where we are rendering node 123 in the full context of a page response. I’ve left out a bit of boilerplate code here, but you’ll want to inject the ‘http_client‘ service into your controller and store it in the objects httpClient property.