Edit PDF Form fields with PHP
- Home
- Engineering Blog
- Edit PDF Form fields with PHP
Intro
Today I’m going to present a use case of a client who requires a PHP application that can export PDF files filled with collected data.
To illustrate, I will present and small example project in Laravel.
Setting environment up
Let’s start creating a Laravel project
composer create-project laravel/laravel PDFTest
The next step is create a docker container for this project.
version: '3.6'
services:
webserver:
image: nginx:latest
container_name: pdf_web
env_file: ./docker/environment.env
volumes:
- ./:/code
- ./docker/nginx/site.conf:/etc/nginx/conf.d/site.conf
- ./docker/nginx/laravel.site.conf:/etc/nginx/conf.d/api.conf
- ./docker/nginx/fastcgi.conf:/etc/nginx/fastcgi.conf
ports:
- "80:80"
- "8888:80"
php:
image: erdiko/php-fpm:latest
container_name: pdf_php
env_file: ./docker/environment.env
volumes:
- ./:/code
ports:
- "9000:9000"
PDF library
After some research, I opted for pdftk, since it seems to be the most widely used.
Pdftk is a cross-platform binary that provides a bunch of handy command line options to manipulate PDFs like get plain text content, list fields, list fields data, fill in forms, etc.
A simple entrypoint.sh script is used to install the pdftk.
#!/bin/bash
apt update && apt install -y pdftk;
php-fpm
that has to vi mapped and executed in the php services, getting something like this
php:
image: erdiko/php-fpm:latest
container_name: pdf_php
env_file: ./docker/environment.env
volumes:
- ./:/code
- ./docker/entrypoint.sh:/usr/local/etc/php/entrypoint.sh
ports:
- "9000:9000"
entrypoint: /usr/local/etc/php/entrypoint.sh
How to integrate in PHP
Here we will install php-pdftk package. Php-pdftk is a php package that relays on pdftk to manipulate PDF documents from php applications.
composer require mikehaertl/php-pdft
that provides a PHP class, named PDF, with all needed methods to work with PDF files.
Let’s put hands on the code
The first step is create controller, which I named it PdfEditor.
Below is how the implementation looks like,
<?php
namespace App\Http\Controllers;
use mikehaertl\pdftk\Pdf;
class PdfEditor extends Controller
{
/**
* Show the application dashboard.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return view('pdftest.upload');
}
public function store(Request $request)
{
$uploadedFile = $request->file('pdf_file');
$filename = $uploadedFile->getClientOriginalName();
$request->session()->put('current_pdf', $filename);
Storage::disk('local')->putFileAs(
'files/'.$filename,
$uploadedFile,
$filename
);
return redirect()->back()->with('success', 'Your file is submitted Successfully');
}
public function preview()
{
if(Session::has('current_pdf')) {
$filepath = Storage::disk('local')->getDriver()->getAdapter()->getPathPrefix() . 'files/'. Session::get('current_pdf');
$filename = $filepath . '/' . Session::get('current_pdf');
return response(file_get_contents($filename))->withHeaders([\
'Content-Type' => 'application/pdf'\
]);
}
return redirect()->back()->with('error', 'Sorry. File not found.');
}
public function edit()
{
$filepath = Storage::disk('local')->getDriver()->getAdapter()->getPathPrefix() . 'files/'. Session::get('current_pdf');
$filename = $filepath . '/' . Session::get('current_pdf');
$pdf = new Pdf($filename);
$fields = $pdf->getDataFields(true)->__toArray();
return view('pdftest.edit')->with('fields',$fields);
}
public function save(Request $request)
{
$filepath = Storage::disk('local')->getDriver()->getAdapter()->getPathPrefix() . 'files/'. Session::get('current_pdf');
$filename = $filepath . '/' . Session::get('current_pdf');
$target = $filepath . '/filled_' . Session::get('current_pdf');
$pdf = new Pdf($filename);
$inputs = $request->all();
unset($inputs['_token']);
foreach ($inputs as $field=>$value) {
$data[str_replace('_',' ',$field)] = $value;
}
$pdf->fillForm($data)
->needAppearances();
if (!$pdf->saveAs($target)) {
$error = $pdf->getError();
dd($error);
}
return response(file_get_contents($target))->withHeaders([\
'Content-Type' => 'application/pdf'\
]);
}
}
We will also need two views, one to upload the PDF and the other to create a dynamic form that will allow us to edit the content of the PDF form.
Below is how the edit form looks like
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">PDF Test</div>
<div class="card-body">
@if (session('status'))
<div class="alert alert-success" role="alert">
{{ session('status') }}
</div>
@endif
@if (session()->has('success'))
<div class="alert alert-success">
<ul>
<li>{!! session()->get('success') !!}</li>
</ul>
</div>
@endif
<form method="POST" action="/pdftest/save" aria-label="{{ __('Save Changes') }}">
@csrf
<table class="table table-bordered table-striped">
<thead>
<tr>
<td>Name</td>
<td>Type</td>
<td>Value</td>
</tr>
</thead>
@foreach($fields as $field)
<tbody>
<tr>
<td>{{$field['FieldName']}}</td>
<td>{{$field['FieldType']}}</td>
<td>{{json_encode($field['FieldValue'])}}</td>
</tr>
</tbody>
@endforeach
</table>
{{--@foreach($fields as $field)--}}
{{--<div class="form-group row">--}}
{{--<label for="{{$field['FieldName']}}">{{ __($field['FieldName']) }}</label>--}}
{{--@switch($field['FieldType'])--}}
{{--@case('Text')--}}
{{--<div class="col-md-6">--}}
{{--<input type="text" id="{{$field['FieldName']}}" name="{{$field['FieldName']}}" value="{{json_encode($field['FieldValue'])}}">--}}
{{--</div>--}}
{{--@break--}}
{{--@case('Choice')--}}
{{--<div class="col-md-6">--}}
{{--<select id="{{$field['FieldName']}}" name="{{$field['FieldName']}}" value="{{json_encode($field['FieldValue'])}}">--}}
{{--<option value="{{$field['FieldValue']}}">{{$field['FieldValue']}}</option>--}}
{{--@foreach($field["FieldStateOption"] as $option)--}}
{{--<option value="{{$option}}" >{{__($option)}}</option>--}}
{{--@endforeach--}}
{{--</select>--}}
{{--</div>--}}
{{--@break--}}
{{--@case('Button')--}}
{{--<div class="col-md-6">--}}
{{--@if($field['FieldValue']=="1")--}}
{{--<input type="checkbox" id="{{$field['FieldName']}}" name="{{$field['FieldName']}}" value="{{$field['FieldValue']}}" checked>--}}
{{--@else--}}
{{--<input type="checkbox" id="{{$field['FieldName']}}" name="{{$field['FieldName']}}" value="{{$field['FieldValue']}}">--}}
{{--@endif--}}
{{--</div>--}}
{{--@break--}}
{{--@endswitch--}}
{{--</div>--}}
{{--@endforeach--}}
<div class="form-group row mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Save changes') }}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
Once you finish just click on Save Changes button that will fill the form and save a new filled PDF.
Final thoughts
I hope this simple example illustrate on how to handle projects that requires PDF form edition.
Thank you for reading and see in the next post.
Tags: Laravel, pdf, pdf forms, pdf-tk, php, programming
Categories: PHP, Programming
Comments
Disqus Recommendations
We were unable to load Disqus Recommendations. If you are a moderator please see our troubleshooting guide.
❮
- 8 years ago
- 4 comments
An overview and examples of debugging your PHP application with the use of …
- 9 years ago
- 1 comment
In the second part of our NPM & Angular CLI series we discuss how we turned …
- 8 years ago
- 1 comment
A real world example of an Angular observable
- 9 years ago
- 3 comments
Creating a custom application with Angular CLI is easy and fun. …
- 9 years ago
- 10 comments
Using components is a fantastic way to include 3rd party libraries like …
- 7 years ago
- 3 comments
The future of jQuery
- 8 years ago
- 1 comment
Videojs component with Vuejs
- 10 years ago
- 1 comment
Remote PHP Debugging with Xdebug
❯
Disqus Comments
We were unable to load Disqus. If you are a moderator please see our troubleshooting guide.
What do you think?
4 Responses
Upvote
Funny
Love
Surprised
Angry
Sad
G
Join the discussion…
Comment
Log in with
or sign up with Disqus or pick a name
Disqus is a discussion network
- Don't be a jerk or do anything illegal. Everything is easier that way.
Read full terms and conditions
This comment platform is hosted by Disqus, Inc. I authorize Disqus and its affiliates to:
- Use, sell, and share my information to enable me to use its comment services and for marketing purposes, including cross-context behavioral advertising, as described in our Terms of Service and Privacy Policy, including supplementing that information with other data about me, such as my browsing and location data.
- Contact me or enable others to contact me by email with offers for goods or services
- Process any sensitive personal information that I submit in a comment. See our Privacy Policy for more information
Acknowledge I am 18 or older
Discussion Favorited!
Favoriting means this is a discussion worth sharing. It gets shared to your followers' Disqus feeds, and gives the creator kudos!
Tweet this discussion
- Share this discussion on Facebook
- Share this discussion via email
- Copy link to discussion
K
I tried to achive what state in this tutorial.
But i have a main issue that the pdftk can not write into the tmp folder:
Warning: copy(filled.pdf): failed to open stream:
Permission denied in /var/www/html/pdfa/vendor/mikehaertl/php-pdftk/src/Pdf.php on line 555
its seem tmp dolder is not writable but it has 777 chmod so totally dont understand whats the issue with it.
Do you have any idea?
see more
live.rezync.com
live.rezync.com is blocked
This page has been blocked by an extension
- Try disabling your extensions.
ERR_BLOCKED_BY_CLIENT
Reload
This page has been blocked by an extension
pippio.com
pippio.com is blocked
This page has been blocked by an extension
- Try disabling your extensions.
ERR_BLOCKED_BY_CLIENT
Reload
This page has been blocked by an extension
See how we can help
Lets talk!
Contact Us
Stay up to date on the latest technologies
Join our mailing list, we promise not to spam.
Email AddressJoin