Laravel 5 Zipp invoices files using zipper

Requirements Install chumper/zipper Package

composer require chumper/zipper

Config define providers and aliases

Find the providers in config folder in app.php file and register the ZipperServiceProvider.

'providers' => [
        // ...
       'Chumper\Zipper\ZipperServiceProvider',
    ]

Locate the aliases in config >> app.php file and designate the aliases.

'aliases' => [
        // ...
        'Zipper' => 'Chumper\Zipper\Zipper',
    ]

Controller

We are creating an export function that will return download link with zipped PDF invoices files. For this controller we will use classes :

use Request;
use App\Http\Requests;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\File;
use PDF;

 

public function export()
{           
    $inputs = Request::all();

    //Clean directory
    // Get all files in a directory
    $files =   Storage::allFiles('public/invoices/');
    // Delete Files
    Storage::delete($files);

    try { 

            // take invoices ids
            $invoices = \DB::table('invoices')
                ->select('id')
                ->get();

            // for each invoiuce we will generate PDF file from view and storage into disk path
            foreach ($invoices as $invoice){
   
                $pdf = invoice($invoice->id);
                $file = $pdf[0]->output();
                Storage::put('public/invoices/inv_'.$pdf[1].'.pdf', $file);   
            }
        }
         // zip all files into temp
            $files = glob(storage_path('app/public/invoices/*'));
            if ($files) {
              \Zipper::make(storage_path('app/public/invoices/invoices_'.date('Y-m-d').'.zip'))->add($files)->close();
              // return link
              return Storage::download('public/invoices/invoices_'.date('Y-m-d').'.zip');
            }
            return back();   
    } 
    catch(\Illuminate\Database\QueryException $ex){ 
      return $ex->getMessage(); 
    }
}

Helper function to generate PDF file from view.

This helper function will return an array with pdf object and invoice number.

function invoice($id){

    $items = \DB::table('invoice_items')
        ->select('service', 'gross', 'net', 'vat', 'pst')
        ->where('id_invoice', $id)
        ->get();
    
    $pdf = PDF::loadView('invoice', compact('items'));
    return [$pdf, $inv_number];
}

Invoice View

We are creating the simple HTML view invoice blade file: invoice.blade.php for this example. You can update this HTML as per your requirement.

!DOCTYPE html>
<html lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Invoice - 1000</title>
    <style>
        .clearfix:after {
            content: "";
            display: table;
            clear: both;
          }
          .place {
            text-align: right;
            margin-top: 30px;
          }
          .bank {
            width: 100%;
            height: 70%;
            background: #ffff;
            border: none;
            font-size: 14px;
            font-family: Arial;
            color: black;
            overflow:hidden; 
            resize:none;
          }
          a {
            color: #5D6975;
            text-decoration: underline;
          }
          
          body {
            position: relative;
            width: 19cm;  
            height: 26cm;
            margin: 0 auto; 
            color: black;
            background: #FFFFFF; 
            font-family: DejaVu Sans, sans-serif; 
            font-size: 12px;
          }
          header {
            padding: 10px 0;
          }
          
          #logo {
            float: left;
            margin-bottom: 10px;
          }
          
          #logo img {
            height: 80px;
          }
          
          h1 {
            border-top: 1px solid  #5D6975;
            border-bottom: 1px solid  #5D6975;
            color: black;
            font-size: 2.4em;
            line-height: 1.4em;
            font-weight: normal;
            text-align: left;
            margin: 0 0 20px 0;
          }
          h2 {
            color: black;
            font-size: 1.4em;
            line-height: 1.4em;
            font-weight: normal;
            margin: 10px 10px 20px 0;
            text-align: center;
          }
          .inv {
          }
          .users {
            display: block;
            margin-right: 30px;
            margin-left: 30px;
          }
          .seller {
            float: left;
            font-size: 16px;
            margin-bottom: 30px;
          }
          .company {
            float: right;
            font-size: 16px;
            margin-bottom: 30px;
          }
          
          #seller div,
          #company div {
            white-space: nowrap;        
          }
          table {
            width: 100%;
            border-collapse: collapse;
            border-spacing: 0;
            margin-bottom: 20px;
          }
          table tr:nth-child(2n-1) td {
            background: #F5F5F5;
          }
          table th,
          table td {
            text-align: right;
          }
          table th {
            padding: 5px 5px;
            color: #5D6975;
            border-bottom: 1px solid #C1CED9;
            white-space: nowrap;        
            font-weight: normal;
          }
          table .service,
          table .desc {
            text-align: left;
          }
          table td {
            padding: 5px;
            text-align: right;
          }
          table td.service,
          table td.desc {
            vertical-align: top;
          }
          table td.unit,
          table td.qty,
          table td.total {
            font-size: 1.2em;
          }
          table td.grand {
            border-top: 1px solid #5D6975;;
          }
          #notices .notice {
            color: #5D6975;
            font-size: 1.2em;
            margin-bottom: 20px;
          }
          footer {
            color: #5D6975;
            width: 100%;
            height: 30px;
            position: absolute;
            bottom: 0;
            border-top: 1px solid #C1CED9;
            padding: 8px 0;
            text-align: center;
          }
          .total {
            font-family: Arial; 
            font-size: 14px;
          }
    </style>
  </head>
  <body>
    <header class="clearfix">
      <div id="logo">
        <img src="/logo.png">
      </div>
      <div class="place">
        <div>Place of issue: Country, City</div>
        <div>Date of issue: 2019-05-06 12:00:00</div>
        <div>Date of sale: 2019-05-06 12:00:00</div>
      </div>
      <div class="inv">
          <h2 style="float: right"><strong>ORYGINAL/COPY</strong></h2>
          <h1>INVOICE Nr - <strong>1000</strong></h1>
          <div class="users">
            <div class="company">
              <div><strong>SELLER: </strong></div>
              <div>Company name</div>
              <div>Address</div>
              <div>Country, City</div>
              <div>Tax ID</div>
            </div>
            <div class="seller">
              <div><strong>BUYER: </strong></div>
              <div>Company Name</div>
              <div>Address</div>
              <div>Country, City</div>
              <div>Tax ID</div>
            </div>
          </div>
      </div>
    </header>
    <main>
      <table>
        <thead>
          <tr>
            <th>PRODUCT</th>
            <th>NET</th>
            <th>VAT %</th>
            <th>VAT AMOUNT</th>
            <th>PST %</th>
            <th>PST AMOUNT</th>
            <th>GROSS</th>
          </tr>
        </thead>
        <tbody>
          @foreach ($items as $item)
          <tr>
            <td class="desc">{{ $item->service }}</td>
            <td class="total">{{ $item->net }}</td>
            <td class="qty total">24</td>
            <td class="total">{{ $item->vat }}</td>
            <td class="unit total">5</td>
            <td class="total">{{ $item->pst }}</td>
            <td class="total">{{ $item->gross }}</td>
          </tr>
          @endforeach
          <tr>
            <td colspan="6" class="grand total">TOTAL NET</td>
            <td class="grand total">USD {{ $invoice->total_net }}</td>
          </tr>
          <tr>
            <td colspan="6">VAT 24%</td>
            <td class="total">USD {{ $invoice->total_vat }}</td>
          </tr>
          <tr>
            <td colspan="6">PST 5%</td>
            <td class="total">USD {{ $invoice->total_pst }}</td>
          </tr>
          <tr>
            <td colspan="6" class="grand total"><strong>TOTAL DUE</strong></td>
            <td class="grand total"><strong>USD {{ $invoice->total_gross }}</strong></td>
          </tr>
        </tbody>
      </table>
      <!--Payment Terms -->
      <div id="notices">
          <div class="notice"><strong>Terms of Payment: payment terms</strong></div>
      </div>
      <!--Bank details -->
      <div>
        <div><strong>Bank Details:</strong></div>
        <textarea class="bank" disabled rows='17'>bank details</textarea>
      </div>
    </main>
    <footer>
      Invoice was created on a computer and is valid without the signature and seal.
    </footer>
  </body>
</html>

Route

Now we need to add the route in /routes/web.php for export zipped invoices.

Route::get('/invoices_export', 'InvoicesController@export');

Finally, everything’s ready now when you execute GET https://localhost//invoices_export to download the Zipped PDF files. Feel free to comment if any query.

Related articles

Laravel 5 Custom Authentication Setup

In this article, we will focus on how to...

Laravel 5 Export To PDF Using Laravel-Dompdf

In this article, we will discuss Laravel 5 Export...

Laraver 5 Image upload to BLOB mysql

In this article, we will discuss Laravel 5 save...

Laravel 5 OAuth2 for REST API

In this article, I will show you how to...

Case Studies

Psycholog dziecięcy Olsztyn
Search engine optimization

SEO for Child Psychologist Olsztyn

In this case study, we explore how we improved the online presence of a child psychologist in Olsztyn through an effective SEO strategy. The...
Content & copywriting

Personal Trainer Shop

A clothing brand wanted to launch a new e-commerce website that would allow customers to browse and purchase their products online. We developed a...
E-commerce development

Tech & Gadgets Shop

A clothing brand wanted to launch a new e-commerce website that would allow customers to browse and purchase their products online. We developed a...