Skip to content
MNB PHPExcelDeveloper Guide
AI

Core concepts

Fluent and Terminal Methods

Understand which reading calls keep configuring a ReadSession and which calls execute work and return generators, arrays, counts, rows, or cell values.

Level
Beginner
Reading time
9 min
Package
mnb/mnb-phpexcel or a format package
Updated
Full packageIndividual packagesReadSession
ReadSession::sheet()ReadSession::withHeaderRow()ReadSession::withOptions()ReadSession::rows()ReadSession::toArray()ReadSession::first()
Method boundary

A read chain has two phases: configure the session, then execute one terminal operation.

The important change is not the method name—it is the return type. Fluent calls keep returning ReadSession; a terminal call returns the data or scalar your application asked for.

01Create

MnbExcel::read() gives you a ReadSession.

02Configure

Choose sheet, headers, columns, options, skip, and limit.

03Execute

Call one terminal method such as rows() or toArray().

04Use the result type

Switch to generator, array, scalar, or cell-value operations.

Still fluent

No rows are read just because the session is being configured.

Each configuration call returns the session again, so the chain can continue until the application chooses a terminal result.

Configure a ReadSession
$session = MnbExcel::read('orders.xlsx')
    ->sheet('Orders')
    ->withHeaderRow(1)
    ->selectColumns(['Order ID', 'Customer'])
    ->withOptions(['skip_empty_rows' => true]);
Method map

Know what each category returns before you chain another call.

Use fluent methods to describe the read. Use terminal methods to obtain the result. After a terminal call, the next valid operations belong to the returned PHP type.

Fluent configurationReturns ReadSession
sheet()Choose the worksheet context.ReadSession
withHeaderRow()Define how row keys are normalized.ReadSession
selectColumns()Project only the columns the workflow needs.ReadSession
withOptions()Apply reader policy without executing the read.ReadSession
skip() / limit()Shape the later terminal operation.ReadSession
Terminal executionReturns another type
rows()GeneratorForward-only row processing.
toArray()arrayMaterialize the returned rows in memory.
first()?arrayRead only the first normalized data row.
countRows()intReturn the normalized row count.
hasRows()boolCheck whether selected data exists.
toStructuredSheetArray()arrayReturn rows plus structured source/count metadata.
cell("B2")mixedRead one worksheet coordinate directly.
After execution

Use the result you actually received—not the session API you had before.

toArray() gives you a native array; rows() gives you a generator. Both are correct, but they support different next steps.

Materialized result

Array operations after toArray().

Iterate, index, count, filter, or transform the returned PHP array.

Array result
$rows = $session->toArray();

foreach ($rows as $row) {
    echo $row['Order ID'] . PHP_EOL;
}
Incremental result

Iteration after rows().

Consume rows as they are yielded without first materializing the complete result.

Generator result
foreach ($session->rows() as $row) {
    echo $row['Order ID'] . PHP_EOL;
}
Common mistake

A terminal return value is not a ReadSession.

Once toArray() returns, the fluent chain has ended. Calling session methods on that array is a return-type error, not a spreadsheet-data problem.

Return-type mistake
$data = $session->toArray();
$data->rows(); // Invalid: $data is now an array.
Read passes

Treat each terminal method as a separate operation unless the API explicitly documents otherwise.

Calling one terminal method for a count and another for the rows can read the selected worksheet twice. That may be acceptable for small files, but it is easy to make large-file work unnecessarily expensive.

Two passes

Convenient, but potentially duplicate work.

Two terminal operations
$count = $session->countRows(); // First read pass.
$rows  = $session->toArray();   // Second read pass.
One pass

Collect simple counters while processing rows.

One streaming pass
$count = 0;

foreach ($session->rows() as $row) {
    $count++;
    // Process the row here.
}

Review rule: choose the smallest terminal result the workflow needs. If a streaming pass already processes every row, collect simple counts or aggregates during that same pass when practical.