array must be compatible with Maatwebsite\Excel\Concerns\WithMapping::map($row) in - Laravel

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Mastering Data Mapping in Laravel Excel: Solving the WithMapping Compatibility Error

As developers working with data export solutions in Laravel, one of the most powerful tools we turn to is Maatwebsite\Excel. It allows us to transform complex Eloquent collections or database results directly into professional-looking Excel files. A key feature that simplifies this process is the WithMapping concern, which lets you define how a collection should be transformed row by row.

However, when dealing with complex data structures—like those involving multiple related queries and custom logic—developers often run into compatibility issues when trying to use the map($row) method. This post will dive into the specific error you encountered while exporting your student and teacher data, explain why it happens, and provide the correct, robust solution.

The Compatibility Conflict: Why WithMapping::map($row) Fails

You are using the WithMapping concern, which expects the map method to receive a single row of data (an array or object) at a time. The signature you defined was:

public function map($published_goals, $current_terms): array

The error message clearly states that this signature is incompatible with what WithMapping::map($row) expects. This incompatibility arises because the Excel library iterates over your collection and passes each item as $row to the mapping function. If you define your map method to accept multiple variables, the underlying mechanism doesn't know how to associate the incoming single row ($row) with those separate variables.

In essence, map() is designed for a one-to-one transformation of a row. When your data preparation involves fetching related data (like student details and teacher names) in the collection() method, you need to ensure that all the necessary information for a single output row is consolidated before it hits the mapping phase.

The Solution: Consolidating Data in the Collection Method

The fix is to restructure your collection() method so that it returns a collection where each element is an array containing all the data points required for that specific Excel row. This way, the $row passed to the map function will contain everything it needs.

Let's refactor your export class to achieve the desired result cleanly. We need to merge the results from your separate queries ($published_goals and $current_terms) into a single structure for each student record.

Refactored Code Example

Here is how you can restructure your StudentExport class to correctly utilize WithMapping:

<?php

namespace App\Exports;

use Illuminate\Database\Eloquent\Builder;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithMapping;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;

class StudentExport implements FromCollection, WithMapping
{
    private $headings = [
        'Student ID', 
        'Name',
        'Class',
        'Status',
        'Teacher'
    ];

    public function collection()
    {
        // 1. Fetch current term data
        $current_term_data = DB::table('appraisal_identity')
            ->select('term_name')
            ->where('company_id', $this->userCompany)
            ->where('is_current', 1)
            ->first()
            ->pluck('term_name'); // Get just the single term name

        // 2. Fetch published goals and join teacher data in a single query for efficiency
        $goals = DB::table('hr_students AS e')
            ->join('hr_employees AS em', 'em.id', '=', 'e.teacher_id')
            ->select(
                'e.student_id',
                DB::raw('CONCAT(e.first_name, \' \', e.last_name) AS full_name'),
                'e.student_class',
                DB::raw('(CASE WHEN e.is_status = 3 THEN \'Excellent\') WHEN e.is_status = 2 THEN \'Good\') AS student_status',
                DB::raw('CONCAT(em.first_name, \' \', em.last_name) AS teacher_name')
            )
            ->whereIn('e.student_id', DB::table('hr_students')->where('is_published', 1)->where('company_id', $this->userCompany)->pluck('employee_code'))
            ->distinct()
            ->get();

        // 3. Combine the results into a structure suitable for mapping
        $data = [];
        foreach ($goals as $goal) {
            // Find the current term name (assuming only one exists)
            $currentTermName = $current_term_data->first() ?? 'N/A';

            $data[] = [
                $goal->student_id,
                $goal->full_name,           // Concatenated Name
                $goal->student_class,
                $goal->student_status,     // Calculated Status
                $goal->teacher_name,       // Concatenated Teacher Name
                $currentTermName          // The term name we want to display
            ];
        }

        return $data;
    } 

    /**
     * Map the collected data to the desired Excel output structure.
     * Since collection() now returns an array of arrays, map($row) works perfectly.
     */
    public function map($row): array
{
    // The order here must match the order in the $data array returned by collection()
    return [
       $row[0], // Student ID
       $row[1], // Full Name
       $row[2], // Class
       $row[3], // Status
       $row[4], // Teacher
   ];
}

// ... (startCell, headings, registerEvents methods remain the same)

Conclusion

The error you faced is a classic example of understanding the contract between your data preparation layer (collection()) and your transformation layer (map()). When employing WithMapping in Laravel Excel, remember that the map method operates on a single row. By ensuring your collection() method returns an array where each element is a complete, flat row containing all necessary fields (student details, teacher names, and term information), you satisfy the requirements of WithMapping::map($row).

This approach leads to cleaner, more maintainable code. It aligns perfectly with the principles of robust application design, much like adhering to the SOLID principles that underpin great Laravel development. For further insights into leveraging the full power of the Laravel ecosystem and Eloquent for complex data handling, I highly recommend exploring official documentation and resources from laravelcompany.com. Happy exporting!