Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ElectroBuddha's avatar

Row num instead of db ID ?

Hi, is it possible to somehow show row num instead of ID field on the resources index page? My admin users don't really need to see real database id for each row, and I also don't want to reveal these ids to everyone. I could hide it, but then table feels empty, so it would be really nice to just show simple row numbers (from 1 to num of rows) on each table. Any suggestions how could I achieve this?

0 likes
8 replies
jlrdw's avatar

Just derive a row number field. I am guessing it is just for looks. But you don't need to show the id field anyway, just skip that field in a foreach, can still be part of the query.

ElectroBuddha's avatar

I tried defining resource field like this:

Text::make('#', function () {
    return view('partials.rownum')->render();
})->asHtml(),

And in the 'partials/rownum.blade.php' I put {{ $loop->index + 1 }}, but the page returns error: Undefined variable: loop;

Is there any way I could hook into index table foreach loop, or is it accessible just within frontend Vue component?

Is it maybe possible to override indexQuery(NovaRequest $request, $query) and to somehow append row num column to the query?

ElectroBuddha's avatar
ElectroBuddha
OP
Best Answer
Level 3

In case someone needs this, I've managed to solve this by using MySql's query session variables feature explained here.

First you have to override indexQuery method like this:

...
use Illuminate\Support\Facades\DB;
...

public static function indexQuery(NovaRequest $request, $query)
{
        // Needed for proper row nums when using pagination
        $offset = $request->input('perPage', 0) * ($request->input('page', 1) - 1); 

        DB::statement(DB::raw('set @row_number = 0'));

        return $query->select([
                DB::raw("(@row_number:=@row_number + 1) + $offset AS num"),
                'your_table_name.*'
        ]);
}

Then, define 'rownum' field in resource $fields array:

Text::make('#', 'num')->sortable()

That's it.

1 like
Cronix's avatar

@electrobuddha @siangboon was meaning in a for/foreach loop in blade while displaying the data. $loop only exists within a blade loop. instead of using index + 1 you can just use iteration, which starts at 1 instead of 0 for the loop count so it wouldn't need to be manually incremented.

@foreach ($collections as $collection)
    {{ $loop->iteration }}  // starts at 1

    {{ $collection->name }}
    {{ $collection->description }}
@endforeach
1 like
ElectroBuddha's avatar

@CRONIX - This is Laravel Nova related, there are no blade templates here (when rendering resource index page).

Cronix's avatar

@electrobuddha I didn't say there was. I was clarifying what he was meaning and that $loop only exists within blade loops. You were getting an error when using $loop. I was stating why.

1 like
jangan's avatar

Sorry to bump a 3 year old post but since this is the #1 result on google for this search, I wanted to post an updated solution without touching the indexQuery since we have many other uses for indexQuery.

This solution handles pagination as well

 /**
     * Get the fields displayed by the resource.
     *
     * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
     * @return array
     */
    public function fields(NovaRequest $request)
    {
        if (!$request->count) {
            $request->count = 0;
        }
        return [
            Text::make('#', function () use ($request) {
                $request->count += 1;
                $rowNumber = $request->page == 1 ? $request->count : $request->count + ($request->perPage * ($request->page - 1));
                return $rowNumber;
            })->asHtml()->textAlign('center')->onlyOnIndex(),
        ];
    }

Please or to participate in this conversation.