skip to Main Content

i have a problem to load the data from database , the system give me an error

Maximum Execution time off 60 seconds exceeded

i realize i need to optimze my code to shrink the time to load the data, I nearly have 10K of data in the table.

this is my code

public function export(Request $request){
    $fotoOutcomes= new FotoOutcomeCollection(FotoOutcome::with('user','outcomeCategory','paymentMethod')->select('name','cost','date','pcs')->get());  
    $pdf = PDF::loadView('FotoOutcomeExport/FotoOutcomeExport', compact('fotoOutcomes'));
    return $pdf->download('Foto-Outcome.pdf');

}

please help me to optimize this code, i have no idea about what should i do to optimize this code.
thankyou in advance

UPDATE
this is my view code

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>

</head>
<body>
<div className="overflow-x-auto">
    <table className="table table-zebra w-full">
        <thead>
            <tr>
                <th>No</th>
                <th>Name</th>
                <th>Date</th>
                <th>Pcs</th>
                <th>Cost</th>
            </tr>
        </thead>
        <tbody>
            @php $i=1 @endphp
            @foreach ($fotoOutcomes as $fotoOutcome)
            
            <tr>
                <th>{{$i}}</th>
                <td>{{$fotoOutcome->name}}</td>
                <td>{{$fotoOutcome->date}}</td>
                <td>{{$fotoOutcome->pcs}}</td>
                <td>{{$fotoOutcome->cost}}</td>
            </tr>
            @php $i++; @endphp
            @endforeach
        </tbody>
    </table>
</div>

3

Answers


  1. Please show the view from which you generate the pdf, I have the same issue when I try to use some Laravel helper function (In my case, I try to use the asset() function).

    Try to use the loop variable instead of the $i variable

    <tr>
     <th>{{$loop->index}}</th>
     <td>{{$fotoOutcome->name}}</td>
     <td>{{$fotoOutcome->date}}</td>
     <td>{{$fotoOutcome->pcs}}</td>
     <td>{{$fotoOutcome->cost}}</td>
    </tr>
    

    Or you can test with a smaller amount of data, if its fails the error is in the view

    public function export(Request $request){
        $fotoOutcomes= new FotoOutcomeCollection(FotoOutcome::with('user','outcomeCategory','paymentMethod')->select('name','cost','date','pcs')->take(10)->get());  
        $pdf = PDF::loadView('FotoOutcomeExport/FotoOutcomeExport', compact('fotoOutcomes'));
        return $pdf->download('Foto-Outcome.pdf');
    
    }
    
    Login or Signup to reply.
  2. If you have 10K of items, you are hydrating a ton of models in that query. That takes time and memory. Probably the most efficient way to reduce this would be to use a DB query and not fully hydrate the models. Assuming your table is foto_outcomes:

    $fotoOutcomes = DB::table('foto_outcomes')->get();
    

    However, this is still pulling in all of the information from that table. You can further reduce the query time by not selecting *, and only applying the fields you need:

    $fotoOutcomes = DB::table('foto_outcomes')->select('name', 'date', 'pcs', 'cost')->get();
    

    I see you have included three relationships in your original query. If those are necessary, you will have to add them to the above query. You can also add a select statement for those relations to save calling * on those relations. However, if those items are on the original foto_outcomes table, you can skip them for a big jump in efficiency, using the query above.

    Login or Signup to reply.
  3. You can use pagination to load data in small amount instead of loading all data at once.

    public function export(Request $request){
        $pageSize = 100; // set the number of records to load per page
        $fotoOutcomes = FotoOutcome::with('user', 'outcomeCategory', 'paymentMethod')
            ->select('name', 'cost', 'date', 'pcs')
            ->paginate($pageSize); // use pagination to load data in smaller chunks
        $fotoOutcomes = new FotoOutcomeCollection($fotoOutcomes);
        $pdf = PDF::loadView('FotoOutcomeExport/FotoOutcomeExport', compact('fotoOutcomes'));
        return $pdf->download('Foto-Outcome.pdf');
    }
    

    you can change your for loop like this in view code.

    @foreach ($fotoOutcomes as $fotoOutcome)
    <tr>
        <th>{{ $fotoOutcomes->firstItem() + $loop->index }}</th>
        <td>{{ $fotoOutcome->name }}</td>
        <td>{{ $fotoOutcome->date }}</td>
        <td>{{ $fotoOutcome->pcs }}</td>
        <td>{{ $fotoOutcome->cost }}</td>
    </tr>
    @endforeach
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search