KoolReport's Forum

Official Support Area, Q&As, Discussions, Suggestions and Bug reports.
Forum's Guidelines

Input & Export in Laravel #1655

Open David Vanacore opened this topic on on Oct 9, 2020 - 19 comments

David Vanacore commented on Oct 9, 2020

I'm having trouble getting the Input & Export example working. The select works and I'm able to see the page with the searched table. When I click Export to PDF, I get a 404 Not Found error. I'm sure I have something wrong in Laravel. Any help would be appreciated.

web.php

Auth::routes();
Route::any('/order', 'OrderController@index')->name('order');
Route::any('/export', 'ExportController@index')->name('export');

OrderController.php

<?php
namespace App\Http\Controllers;
use App\Reports\Order;
class OrderController extends Controller
{
    public function __construct()
    {
    $this->middleware('auth');
    }

    public function index()
    {
        $report = new Order;
        $report->run();
        return view("order",["order"=>$report]);

    }
}

Order.php

<?php
namespace App\Reports;
use \koolreport\processes\CalculatedColumn;
class Order extends \koolreport\KoolReport
{
    use \koolreport\laravel\Friendship;
    use \koolreport\inputs\Bindable;
    use \koolreport\inputs\POSTBinding;
    use \koolreport\export\Exportable;

    function defaultParamValues()
    {
        return array(
            "customerNumber"=>0,
        );
    }

    function bindParamsToInputs()
    {
        return array(
            "customerNumber",
        );
    }

    function settings()
    {
        return array(
            "dataSources"=>array(
                "automaker"=>array(
                    "connectionString"=>"mysql:host=xxx.xxx.xxx.xxx70;dbname=automaker",
                    "username"=>"user",
                    "password"=>"user",
                    "charset"=>"utf8"
                ),
            )
        );
    }

    function setup()
    {

        $this->src('automaker')
        ->query("
            SELECT *
            FROM customers
            ORDER BY customerName
        ")
        ->pipe($this->dataStore("customers"));

        $this->src('automaker')
        ->query("
            SELECT products.productName,orderdetails.priceEach,orderdetails.quantityOrdered
            FROM orders
            JOIN orderdetails
            ON
                orders.orderNumber = orderdetails.orderNumber
            JOIN products
            ON
                products.productCode = orderdetails.productCode
            WHERE customerNumber = :customerNumber
        ")->params(array(
            ":customerNumber"=>$this->params["customerNumber"]
        ))
        ->pipe(new CalculatedColumn(array(
            "amount"=>"{priceEach}*{quantityOrdered}"
        )))
        ->pipe($this->dataStore("orders"));
    }
}

Order.view.php

<?php
    use \koolreport\inputs\Select;
    use \koolreport\widgets\koolphp\Table;

    $customerName = "";
    $this->dataStore("customers")->popStart();
    while($row = $this->dataStore("customers")->pop())
    {
        if($row["customerNumber"]==$this->params["customerNumber"])
        {
            $customerName =$row["customerName"];
        }
    }
?>
<div class="report-content">
    <form method="post">
    <?php echo csrf_field() ?>
        <div class="text-center">
            <h1>Customer Orders</h1>
            <div class="row form-group">
                <div class="col-md-6 offset-md-3">
                    <?php
                    Select::create(array(
                        "name"=>"customerNumber",
                        "dataStore"=>$this->dataStore("customers"),
                        "dataBind"=>array(
                            "text"=>"customerName",
                            "value"=>"customerNumber",
                        ),
                        "attributes"=>array(
                            "class"=>"form-control"
                        )
                    ));
                    ?>
                </div>
            </div>
            <div class="form-group">
                <button class="btn btn-primary">Look up</button>
            </div>
        </div>
    </form>
    <?php
        if($this->dataStore("orders")->countData()>0)
        {
        ?>
            <?php
            Table::create(array(
                "dataStore"=>$this->dataStore("orders"),
                "columns"=>array(
                    "productName"=>array(
                        "label"=>"Product",
                    ),
                    "priceEach"=>array(
                        "label"=>"Price",
                        "prefix"=>"$",
                    ),
                    "quantityOrdered"=>array(
                        "label"=>"Quantity"
                    ),
                    "amount"=>array(
                        "label"=>"Total",
                        "prefix"=>"$",
                    )
                ),
                "class"=>array(
                    "table"=>"table table-striped"
                )
            ));
            ?>
            <div class="text-center">
                <form method="post" action="export.php">
                    <input type="hidden" value="<?php echo $this->params["customerNumber"]; ?>"    name="customerNumber" />
                    <button class="btn btn-primary">Export to PDF</button>
                    </form>
                </div>
        <?php
        }
    ?>
</div>

ExportController.php

<?php

namespace App\Http\Controllers;

use App\Reports\Export;

class ExportController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function index()
    {
        $export = new Export;
        $export ->run();
        return view("export",["export"=>$export]);
    }
}

export.php

<?php
require_once "Order.php";
$report = new Order;
$report->run()
->export('OrderPdf')
->pdf(array(
    "format"=>"A4",
    "orientation"=>"portrait",
    //"zoom"=>2,
    "margin"=>"1in"
))
->toBrowser("orders.pdf");

export.blade.php

@extends('layouts.app')

@section('content')
<?php
require_once "Order.php";
$report = new Order;
$report->run()->render();
?>
@endsection

OrderPdf.view.php

<?php
    use \koolreport\widgets\koolphp\Table;
    $this->dataStore("customers")->popStart();
    $customerName = "";
    while($row = $this->dataStore("customers")->pop())
    {
        if($row["customerNumber"]==$this->params["customerNumber"])
        {
            $customerName =$row["customerName"];
        }
    }
?>

<!DOCTYPE html>
<html>
    <head>
        <title>Order details of customer</title>
        <link rel="stylesheet" href="../../../assets/bs3/bootstrap.min.css" />
        <link rel="stylesheet" href="../../../assets/bs3/bootstrap-theme.min.css" />
    </head>
    <body>
        <div class="container box-container">
                <div class="text-center">
                    <h1><?php echo $customerName; ?></h1>
                </div>
            <hr/>
            <?php
                if($this->dataStore("orders")->countData()>0)
                {
                ?>
                    <?php
                    Table::create(array(
                        "dataStore"=>$this->dataStore("orders"),
                        "columns"=>array(
                            "productName"=>array(
                                "label"=>"Product",
                            ),
                            "priceEach"=>array(
                                "label"=>"Price",
                                "prefix"=>"$",
                            ),
                            "quantityOrdered"=>array(
                                "label"=>"Quantity"
                            ),
                            "amount"=>array(
                                "label"=>"Total",
                                "prefix"=>"$",
                            )
                        ),
                        "class"=>array(
                            "table"=>"table table-striped"
                        )
                    ));
                    ?>
                <?php
                }
            ?>
        </div>
    </body>
</html>
David Vanacore commented on Oct 9, 2020

I realized that the button was pointing to the wrong place, so I fixed that.

...
            <form method="post" action="export">
...

Now I'm getting a 419 Page Expired error.

David Winterburn commented on Oct 12, 2020

Hi David,

If you use Laravel please put csrf token in your form before submitting. Thanks!

David Vanacore commented on Oct 14, 2020

Thank you for the information. That got me a little further.

I've added the csrf token, but now I'm getting the Exception "Could not save content to temporary folder" error. I've searched the forums and I have tried the following:

1) I downloaded and installed the phantomjs file in the /vendor/koolreport/export/bin/. It's permissions are set to 755.

2) The /vendor/koolreport/export/tmp directory is set to 755.

3) I've tried adding this to the export.php file

->settings(array(
"useLocalTempFolder"=>true,))

It creates a .tmp file when I run the export, but the file is empty.

I'm running a VM of ubuntu server 18.04 with Apache 2.4.29

Thank you for you help.

David Winterburn commented on Oct 16, 2020

Hi David,

Please open the .tmp file with a text editor (it's just a html file) and let us know if there's any content inside. By the way, do you run any php -S or php artisan serve command? Thanks!

David Vanacore commented on Oct 16, 2020

The .tmp file is empty. I run php artisan serve --host=XXX.XXX.XXX.XXX --port=XXXX

David Winterburn commented on Oct 19, 2020

Hi David,

If you ran php artisan server you were using PHP development server and not Apache. Export package uses PhantomJS headless browser, which PHP build-in web server, a development server, not a production one like Apache, nginx, etc, is not compatible with.

Therefore I would suggest you server your project/reports on Apache service for pdf export to work correctly.

David Vanacore commented on Oct 19, 2020

That makes sense. Thanks you for the information and I'll get that changed and see what happens.

KoolReport commented on Oct 19, 2020

@David Vanacore Thank you so much for your tips. We really appreciate!

David Vanacore commented on Oct 25, 2020

Okay, I moved the project folder to the /var/www/html of the server and set it up without the artisan server. I'm still getting the same message though

David Winterburn commented on Oct 26, 2020

Hi David,

Please repeat steps 1, 2, 3 of this post of yours:

https://www.koolreport.com/forum/topics/1655#p8940

Then open the .tmp file with a text editor and let us know if there's any content in it. Thanks!

David Vanacore commented on Oct 27, 2020

I repeated the 3 steps above, but I'm still getting the same error message "Could not save content to temporary folder". The tmp file that is created is blank.

David Winterburn commented on Oct 27, 2020

Please create a php file at your current project's location with this content:

<?php        
        if (file_put_contents($pathToLocalTmpFile, "Hello world")) {
            echo "Saved tmp content";
        } else {
            throw new \Exception("Could not save content to temporary folder");
            return false;
        }

Then open it on your browser and let us know the result. Thanks!

David Vanacore commented on Oct 27, 2020

I had to add this to the code:

...
if (file_put_contents(($pathToLocalTmpFile ?? 'test'), "Hello world")) {
...

It gives the output "Saved tmp content" and it says "Hello World" inside the test file. It also saves the file in the /project/public folder.

David Winterburn commented on Oct 27, 2020

That's a good result. Please set $pathToLocalTmpFile to be the path to a file in your local temp folder and run it again.

David Vanacore commented on Oct 27, 2020

That seems to work. I'm able to save it to the tmp directory

    if (file_put_contents("/var/www/html/project/vendor/koolreport/export/tmp/test", "Hello world")) {
David Winterburn commented on Oct 28, 2020

Please open the file koolreport/export/Handler.php and go to this part:

         if (file_put_contents($source, $content)) {
            return $source;
        } else {
            throw new \Exception("Could not save content to temporary folder");
            return false;
        }

and replace it with this:

        echo "file path = $source<br>";
        echo "file content = " . htmlspecialchars($content); echo  "<br>";
        if (file_put_contents($source, $content)) {
            echo "$source saved<br>";
            return $source;
        } else {
            echo "file_put_contents error<br>";
            throw new \Exception("Could not save content to temporary folder");
            return false;
        }

Then run export again and let us know the result. Thanks!

David Vanacore commented on Oct 28, 2020

I get the same error "Could not save content to temporary folder", but now I have the debug info:

file path = /var/www/html/project/vendor/koolreport/export/tmp/5f99de06b458a3.tmp
file content =
file_put_contents error
David Vanacore commented on Nov 6, 2020

Any other ideas of what might be causing this or is there something else that I can test? Thank you.

David Winterburn commented on Nov 6, 2020

Please send us an email to support@koolphp.net regarding this topic. We will guide you to arrange for a remote debugging session. Thanks!

Build Your Excellent Data Report

Let KoolReport help you to make great reports. It's free & open-source released under MIT license.

Download KoolReport View demo
None yet

None