Search code examples
laravelexportexport-to-csvlaravel-9

Exporting all clients does not work, the file is saved with no name and no extension


I am trying to export the data in my database; in particular all the customers present but also a single chosen customer.

I tried to set the code only that when I click the button to export all clients a file with no name and no extension is saved.

ClientsExport Class

class ClientsExport implements FromCollection
{
    private $client = null;

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

    public function collection(Client $client=NULL)
    {
        if ($this->client) {
            return collect([$this->client]);
        }

        return Client::all();
    }

}

Taking a few tries I found that if I remove the if in the code below, then leaving it alone

return Excel::download(new ClientsExport, 'clients.xlsx');

it works properly, So it seems that the problem is giving it the if

ClientController

public function export(Client $client) 
    {
        if($client){
            return Excel::download(new ClientsExport($client), $client->surname . ' ' .  $client->name . '.xlsx');
        } else {
            return Excel::download(new ClientsExport, 'clients.xlsx');   
        } 
    }

Routes

Route::get('client-export/{client?}', [ClientController::class,'export'])->name('client.export');

View Blade

Button where I want to export all clients

<a class="btn btn-warning mb-5 py-3 px-4 mt-3 me-3 fs-5" href="{{ route('client.export') }}">Export all clients</a>

Button where I want to export the individual client

<a class="btn btn-warning" href="{{ route('client.export' , compact('client')) }}">Export</a> 

Solution

  • The issue is that when using route model binding, defining your controller method as: public function export(Client $client) will supply you with a new "empty" instance of \App\Models\Client when the client id in your route definition is "empty". Hence, the check below in your controller method will always be truthy.

    ClientController::export(\App\Models\Client $client)

           if($client){
                // ...
            } else {
                // ...  
            } 
    

    To fix that, you will have to explicitly set the Controller method's parameter to NULL. This will instruct Laravel's route model binding system to supply you with a NULL $client variable instead of an "empty" instance of the Client model (new \App\Models\Client) when the client id in your route definition is "empty". ie:

    ClientController class

    // ...
        public function export(\App\Models\Client $client = null)
        {
    
        }
    // ...
    

    FULL SOLUTION

    ClientsExport Class

    
    class ClientsExport implements FromCollection
    {
        public function __construct(private ?\App\Models\Client $client = null)
        {
        }
    
        public function collection()
        {
            return is_null($this->client)
                ? Client::all()
                : collect([
                    $this->client
                ]);
        }
    
    }
    

    ClientController class

    // ...
        public function export(\App\Models\Client $client = null)
        {
            return Excel::download(new ClientsExport($client),
                is_null($client)
                    ? 'clients.xlsx'
                    : $client->surname . ' ' . $client->name . '.xlsx'
            );
        }
    // ...