Skip to content

Latest commit

 

History

History
148 lines (108 loc) · 6.35 KB

File metadata and controls

148 lines (108 loc) · 6.35 KB

Troubleshooting

Common error messages and how to fix them, plus the gotchas that don't produce an error at all. Headings quote the message or symptom so you can find them by search.

Contents:

empty() and if() checks on fields don't work as expected

In HTML mode a field is an object wrapping your value, and PHP's empty() answers by object rules, not by what's stored. Missing values pass, but a stored "" or 0 is an object, and objects are always truthy:

use Itools\SmartArray\SmartArrayHtml;

$user = SmartArrayHtml::new([['name' => 'Jean', 'nickname' => '', 'logins' => 0, 'phone' => null]])->first();

empty($user->phone);     // true  - stored NULL reads as missing
empty($user->missing);   // true  - keys that don't exist do too
empty($user->nickname);  // false - "" is stored, so the check sees an object, and objects are truthy
empty($user->logins);    // false - same for 0

Ask the field instead; the answers are about the value:

$user->nickname->isEmpty();  // true - "", NULL, 0, and "0" all count as empty
$user->phone->isMissing();   // true - NULL or "" (zero counts as present)

The same goes for comparisons: $user->logins > 5 compares the object, not the number. Unwrap with value() (or int(), float()) first. SmartString's troubleshooting page covers every variation of this.

Raw mode has one version of the same trap: existing fields are plain values, but a missing or misspelled field returns a SmartNull placeholder, which is an object and therefore truthy, so a bare if ($user->is_admin) runs when the field doesn't exist. PHP's isset() and ?? treat missing keys as missing, so $user->is_admin ?? 0 is a safe guard. Comparing without one isn't: $user->is_admin == 1 is true for a missing field too, because PHP casts the placeholder object to 1 (and raises its own object-to-int notice).

A === null check never matches

In HTML mode, fields are always objects: a stored NULL comes back as a SmartString wrapping null, and a missing key comes back as a SmartNull placeholder. Neither is PHP's null:

$user->phone === null;           // false - the field is an object
$user->phone->value() === null;  // true  - the original value is null
$user->phone->isMissing();       // true  - NULL or "" (usually what you meant)

In raw mode (SmartArray), stored values come back as plain PHP types, so a stored NULL there really is null and === works directly.

Warning: Can't convert SmartArrayHtml to string

Something echoed a whole collection or row where a single value belongs. The two usual causes: echoing the collection itself, or calling a method inside a double-quoted string without curly braces:

$cities = SmartArrayHtml::new(['Vancouver', 'Ottawa']);

echo "Cities: $cities";                   // WRONG - prints the warning above and nothing for the array
echo "Cities: {$cities->implode(', ')}";  // RIGHT - Cities: Vancouver, Ottawa

Warning: some_field is undefined in listings.php:12

A row from your results was asked for a column it doesn't have. Usually one of two things: the column name is misspelled, or the query didn't select that column, so check the spelling first and the SELECT list second. For a key that legitimately may not exist, read it with ??, which never warns: $row->some_field ?? ''. Watch for two gotchas with ??. It doesn't fire on a stored "" (an empty string is a value), and the fallback skips HTML encoding, so keep fallbacks plain text.

Only rows inside a result set warn. Lookups on keyed maps (from indexBy() or column()) and standalone arrays render blank silently, because a miss there is a normal no-match.

Casting with (array) returns internal object data

PHP's (array) cast exposes an object's internal properties (the engine offers no way to override it), so the result is mangled keys instead of your data. Use toArray():

$cities = SmartArrayHtml::new(['Vancouver', 'Ottawa']);

$plain = (array)$cities;      // WRONG - internal properties with unusable keys
$plain = $cities->toArray();  // RIGHT - plain array, original values

$flat = [...$cities];         // spread works for flat lists but keeps element mode: SmartStrings in HTML mode

json_encode() returns an object instead of an array

Filtering keeps original keys, like PHP's array_filter(), and JSON turns any array with key gaps into an object. Chain values() to renumber first:

$cities = SmartArrayHtml::new(['Vancouver', 'Ottawa']);

header('Content-Type: application/json');
$json = json_encode($cities->filter(fn($c) => $c !== 'Vancouver'));            // {"1":"Ottawa"}
$json = json_encode($cities->filter(fn($c) => $c !== 'Vancouver')->values());  // ["Ottawa"]

A lookup using a field as the key renders blank

Inside braces, a field converts to its HTML-encoded text, so a text key with an apostrophe or ampersand encodes into something that doesn't match. Pass the original with value():

$facts = SmartArrayHtml::new(["St. John's" => 'Oldest city in North America']);
$city  = SmartArrayHtml::new(['city' => "St. John's"])->city;

echo $facts->{$city};           // WRONG - looks up "St. John&​apos;s", renders blank
echo $facts->{$city->value()};  // RIGHT - Oldest city in North America

Numeric ids aren't affected (digits encode to themselves), which is why id lookups work either way.


← Documentation Index | ← Prev: Method Reference | Next: Performance →