2
votes

I am trying to export to excel using PHP 7, Laravel 5.8, Maatwebsite Excel 3.1. I successfully display on the view blade and also perform the filter.

Model: use App\UserResponse;

Controller

public function userresponseReport(Request $request,$export=false)
{
    $data['title'] = 'User Response';

    $userresponses = DB::table('user_response as g')
        ->select(
        //DB::raw('DATE(g.created_at) as created_date'),
            DB::raw('g.created_at as created_date'),
            'g.msisdn',
            'g.game_code',
            'g.answer',
            'g.answer_code',
            'g.Amount_charged',
            'g.payment_ref',
            'g.status',
            'g.user_channel'
        )
        ->orderByRaw('g.created_at DESC');

    $start_date = $request->start_date;
    $end_date = $request->end_date;

    $render=[];
    if(isset($request->start_date) && isset($request->end_date))
    {
        $userresponses=$userresponses->whereBetween('created_at',[$start_date.' 00:00:00',$end_date.' 23:59:59']);
        $render['start_date']=$request->start_date;
        $render['end_date']=$request->end_date;
    }elseif(isset($request->start_date))
    {
        $userresponses=$userresponses->where('created_at',$request->start_date);
        $render['start_date']=$request->start_date;
    }
    if(isset($request->msisdn))
    {
        $userresponses=$userresponses->where('msisdn','like','%'.$request->msisdn.'%');
        $render['msisdn']=$request->msisdn;
    }
    if(isset($request->game_code))
    {
        $userresponses=$userresponses->where('game_code','like','%'.$request->game_code.'%');
        $render['game_code']=$request->game_code;
    }
    if(isset($request->user_channel))
    {
        $userresponses=$userresponses->where('user_channel','like','%'.$request->user_channel.'%');
        $render['user_channel']=$request->user_channel;
    }

    if(!empty($export))
    {
        return Excel::download(new UserresponseExport($userresponses->get()), 'userresponse.xlsx');
    }
    $userresponses= $userresponses->orderBy('created_at','DESC');
    $userresponses= $userresponses->paginate(15);
    $userresponses= $userresponses->appends($render);
    $data['userresponses'] = $userresponses;

    return view('report.userresponseReport',$data);
}

Then after that, the view blade:

userresponseReport.blade.php

    <div class="row" style="margin-bottom: 10px">
        {{ Form::model(request(),['method'=>'get']) }}
        <div class="col-sm-2">
             {{ Form::text('msisdn',null,['class'=>'form-control','placeholder'=>'MSISDN']) }}
        </div>
        <div class="col-sm-2">
             {{ Form::text('game_code',null,['class'=>'form-control','placeholder'=>'Game Code']) }}
        </div>   
        <div class="col-sm-2">
             {{ Form::text('user_channel',null,['class'=>'form-control','placeholder'=>'Channel']) }}
        </div>          
        <div class="col-sm-2">
            {{ Form::date('start_date',null,['class'=>'form-control','placeholder'=>'Date']) }}
        </div>
        <div class="col-sm-2">
            {{ Form::date('end_date',null,['class'=>'form-control','placeholder'=>'Date']) }}
        </div>          
        <div class="col-xs-2">
            {{ Form::submit('Search',['class'=>'btn btn-warning']) }}
            <a href="{{ route('userresponseReport',['export']) }}" class="btn btn-primary"><i class="fa fa-file-excel-o"></i> Excel</a>
        </div>
        {{ Form::close() }}
    </div>


<div class="box box-primary">
        <div class="box-header with-border">
<table class="table table-bordered table-hover table-striped table-condesed" id="commenter_info_table">
    <caption></caption>
    <thead>
        <tr>
            <td>#</td>
            <td>Date</td>
            <td>MSISDN</td>
            <td>Game Code</td>
            <td>Game Name</td>
            <td>Answer</td>
            <td>Channel</td>
        </tr>
    </thead>
    <tbody>
        @foreach($userresponses as $key => $userresponse)
            <tr>
                <td>{{ ++$key }}</td>
<!--                <td>{{ $userresponse->created_date }}</td>-->
                <td>{{ date('Y-m-d h:i:s A', strtotime($userresponse->created_date)) }}</td>
                <td>{{ $userresponse->msisdn }}</td>
                <td>{{ $userresponse->game_code }}</td>
                <td> 
                    @if($userresponse->game_code=='101')
                       Trivia
                    @elseif($userresponse->game_code=='102')
                       Predict and Win 
                    @elseif($userresponse->game_code=='103')
                       Party With the BBN 
                    @elseif($userresponse->game_code=='104')
                       Grand Prize  
                    @elseif($userresponse->game_code=='105')
                       Happy Hour    
                    @elseif($userresponse->game_code=='106')
                       Power Boost                         
                    @endif                       
                </td>                
                <td>{{ $userresponse->answer }}</td>
                <td>{{ $userresponse->user_channel }}</td>                                    
            </tr>          
        @endforeach
            <tr>
            <td colspan="14">
                {{ $userresponses->links() }}
            </td>
            </tr>         
    </tbody>

</table>   

Then the Export

UserresponseExport


class UserresponseExport implements FromView, WithHeadings, ShouldAutoSize, WithEvents, WithMapping
{
    protected $userresponses;

    public function __construct($userresponses = null)
    {
        $this->userresponses = $userresponses;
    }

    public function view(): View
    {
        return view('report.userresponseReport', [
            'userresponses' => $this->userresponses ?: DB::table('user_response as g')
                ->select(
                    DB::raw('g.created_at as created_date'),
                    'g.msisdn',
                    'g.game_code',
                    'g.answer',
                    'g.answer_code',
                    'g.Amount_charged',
                    'g.payment_ref',
                    'g.status',
                    'g.user_channel'
                )
                ->orderByRaw('g.created_at DESC')
        ]);
    }

    private $headings = [
        'Date Created',
        'MSISDN',
        'game_code',
        'Answer',
        'Channel'
    ];
    public function headings(): array
    {
        return $this->headings;
    }


    public function registerEvents(): array
    {
        return [
            AfterSheet::class    => function(AfterSheet $event) {
                $cellRange = 'A1:E1'; // All headers
                $event->sheet->getDelegate()->getStyle($cellRange)->getFont()->setSize(14);

            },


        ];
    }

}

Route

Route::get('/report/userresponse-report/{export?}', ['as' => 'userresponseReport', 'uses' => 'ReportController@userresponseReport']);

On the view blade, when I clicked on search everything was okay. But when I click on export, I got this error:

Symfony \ Component \ Debug \ Exception \ FatalErrorException (E_UNKNOWN) Declaration of App\Exports\UserresponseExport::view(): App\Exports\View must be compatible with Maatwebsite\Excel\Concerns\FromView::view(): Illuminate\Contracts\View\View

export_error

  1. What could have caused this error?
  2. How do I resolve it?
1

1 Answers

7
votes

This error indicates that your class App\Exports\UserresponseExport is not following the interface correctly.

By the error we can see that you need to have a method named view which you have, but your method have typehinted App\Exports\View as the return type instead of Illuminate\Contracts\View\View.

To fix this simply change your view method return type to Illuminate\Contracts\View\View.


Your code right now most likely says

public function view(): View 
{
  ...
}

But as you are missing use Illuminate\Contracts\View\View; in your import statements, View is getting resolved to the current namespace of your class + the class you are trying to typehint, which results in App\Exports\View.

So another solution to this instead of typehinting the full namespace is to import Illuminate\Contracts\View\View, in your class by adding use Illuminate\Contracts\View\View; at the top of your file.