Hi, I've built something similar to this as i needed my own API to generate PDF's from templates and dynamic data.
Take a look at https://github.com/spatie/browsershot - others are available, but since this uses Chromium, i find it plays much better with bootstrap and flexbox when it comes to layout and grid systems etc. Tailwind probably works fine too.
Since you are working with templates, you could build the template in HTML and have sections for each question. You can then use text replacement to inject the answers in, like so:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>Your Template content goes here...</p>
%question_1%
%question_2%
<div>
<p>Some other content here...</p>
</div>
</body>
</html>
You can store the HTML in a database table called templates. which could look like this:
id
name
template_html
orientation // landscape / portrait
You could also have a questions table, where you can key the questions on the template. So you can say fetch me all the questions and answers where template_id = 1 and user_id = 2 etc
id
user_id
template_id
section_name // question_1, question_2 etc
question
response
So after a user has filled out all of the answers, you could either store that data or generate a PDF on the fly and pass in the answers. In your controller you could have something like this:
public function generatePdf(Request $request)
{
$template = Template::find($request->template_id);
$answers = Answer::where([
'user_id' => auth()->user()->id,
'template_id' => $request->template_id
])
->get()
->keyBy('section_name')
->toArray();
$html = convertPlaceholder($answers, $template->html);
$pdfFile = Browsershot::html($html)
->setOption($template->orientation, true)
->format('a4')
->showBackground()
->emulateMedia('print')
->pdf();
// Stream file back to browser as PDF
return response($pdfFile)->header('Content-Type', 'application/pdf');
}
public function convertPlaceholder(String $sections, String $html) : String
{
// Loop over each section and replace it with the response from the user
foreach($sections as $k => $v) {
$html = str_replace('%'.$k.'%', $v['response'], $html);
}
return $html;
}
Your HTML should now have the users responses injected in and then you can pass this HTML to browsershot and generate a PDF for you.
Note this code isn't tested, You'll need to do some refactoring to meet your needs and also sanitize user input etc.
Hope this helps!