You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Construction: all-scalar rows (typical database rows) clone a shared
template child and assign their data in one copy-on-write step instead of
running the constructor and storing field by field. Mixed rows keep the
full conversion path.
foreach: getIterator() returns a C-level ArrayIterator when nothing needs
wrapping - raw mode, or when every value is a row, tracked by a rowsOnly
flag that flips false wherever a scalar or null is stored. HTML arrays
with scalar values keep the wrapping generator, so foreach yields
SmartStrings exactly as before.
25-row record set: 19.0 -> 6.6 microseconds to construct; a rendered
25-row list page now runs 1.15x vs hand-written htmlspecialchars code
(was 1.59x). Side effect: deprecated SmartArrayRaw logs its constructor
deprecation twice per result set (outer + row template) instead of once
per row.
Copy file name to clipboardExpand all lines: CHANGELOG.md
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -32,7 +32,8 @@
32
32
- Array-syntax deprecation notices suggest one replacement style across reads, writes, `isset()`, and `unset()`: `->key` and `->key = $value` for property-safe names, `->{0}` for integer keys, `->{'users.id'}` for other keys. Reads used to suggest `->get(0)` while existence checks suggested `->{0}`, so one `empty()` call printed two notices with different advice, and writes suggested the now-deprecated `->set()`. Null and `''` keys are the exception and suggest `->get('')` / `->set('', $value)` - the brace form is a fatal error for an empty property name.
33
33
-`isset($array['key'])` and `empty($array['key'])` now follow `$onOffsetAccess` like reads, writes, and `unset()` - notice by default, exception in `'throw'` mode. Existence checks were the one silent form of the deprecated `[]` syntax; if `[]` support is removed in a future version, `isset()` on the object would silently return false instead of erroring, so these call sites need migrating with the rest. Property-syntax checks (`isset($array->key)`) are unaffected and stay signal-free. Internal existence checks now call `array_key_exists()` directly, removing two method calls from every `get()`.
34
34
-`isset()`, `empty()`, and `??` treat a stored null as missing, matching plain PHP arrays: on a NULL column, `isset($row->field)` is now false and `$row->field ?? 'none'` returns `'none'`. Previously they answered "does the column exist", so in HTML mode `??` fallbacks never fired on NULL columns (the wrapped null echoed as `""`). Bracket syntax (`isset($row['field'])`) matches. Direct access is unchanged: `$row->field` still returns the stored null, wrapped in HTML mode, with no warning. Ask `$row->keys()->contains('field')` when you need "does the key exist, even if NULL". Note `??` substitutes its fallback before the library runs, so the fallback skips HTML encoding - use `->or()` for display fallbacks that carry user data. See UPGRADING.md.
35
-
- Array construction is ~1.6x faster (local benchmark, 25-row record set: 19.0 → 11.9 microseconds). Three changes: internal properties assign from a fixed key list instead of `property_exists()` checks per key, child rows share one properties array instead of rebuilding it per row, and scalar values store directly in the constructor loop instead of dispatching through `setElement()`. The fixed key list also means constructor `$properties` can no longer name arbitrary internal properties like `$data` - unknown keys are ignored, same as before.
35
+
- Array construction is ~2.9x faster (local benchmark, 25-row record set: 19.0 → 6.6 microseconds). Internal properties assign from a fixed key list instead of `property_exists()` checks per key; all-scalar rows (typical database rows) clone a shared template child and assign their data in one copy-on-write step instead of running the constructor and storing field by field; scalars store directly in the constructor loop instead of dispatching through `setElement()`. The fixed key list also means constructor `$properties` can no longer name arbitrary internal properties like `$data` - unknown keys are ignored, same as before. One visible side effect: deprecated `SmartArrayRaw` logs its constructor deprecation twice per result set (outer array + row template) instead of once per row.
36
+
-`foreach` is 1.2-1.3x faster when nothing needs wrapping: `getIterator()` returns a C-level `ArrayIterator` in raw mode and for record sets where every value is a row, instead of stepping through a generator per element. HTML-mode arrays with scalar values keep the wrapping generator, so foreach yields SmartStrings exactly as before.
36
37
-`help()` and `debug()` print plain text on the command line instead of wrapping output in literal `<xmp>` tags. Terminal detection checks `PHP_SAPI` plus two fallbacks (Windows console `SESSIONNAME`, missing `SCRIPT_NAME`) because some hosts' CGI builds misreport SAPI. Web responses are unchanged. Matches SmartString.
37
38
-`or404()` outputs `<html>` instead of `<html lang>` - an empty `lang` reads as an invalid value to accessibility checkers, and the message language is caller-supplied so it can't be declared. Matches SmartString.
38
39
-`orDie()` and `or404()` now exit with status 1 instead of 0, so shell scripts and cron jobs see the failure. Output is unchanged. Matches SmartString.
0 commit comments