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.
ReadSession::sheet()ReadSession::withHeaderRow()ReadSession::withOptions()ReadSession::rows()ReadSession::toArray()ReadSession::first()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.
MnbExcel::read() gives you a ReadSession.
Choose sheet, headers, columns, options, skip, and limit.
Call one terminal method such as rows() or toArray().
Switch to generator, array, scalar, or cell-value operations.
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.
$session = MnbExcel::read('orders.xlsx')
->sheet('Orders')
->withHeaderRow(1)
->selectColumns(['Order ID', 'Customer'])
->withOptions(['skip_empty_rows' => true]);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.
sheet()Choose the worksheet context.ReadSessionwithHeaderRow()Define how row keys are normalized.ReadSessionselectColumns()Project only the columns the workflow needs.ReadSessionwithOptions()Apply reader policy without executing the read.ReadSessionskip() / limit()Shape the later terminal operation.ReadSessionrows()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.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.
Array operations after toArray().
Iterate, index, count, filter, or transform the returned PHP array.
$rows = $session->toArray();
foreach ($rows as $row) {
echo $row['Order ID'] . PHP_EOL;
}Iteration after rows().
Consume rows as they are yielded without first materializing the complete result.
foreach ($session->rows() as $row) {
echo $row['Order ID'] . PHP_EOL;
}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.
$data = $session->toArray();
$data->rows(); // Invalid: $data is now an array.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.
Convenient, but potentially duplicate work.
$count = $session->countRows(); // First read pass.
$rows = $session->toArray(); // Second read pass.Collect simple counters while processing rows.
$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.