Filtering and Sorting
How to narrow a loaded result down to the rows you want, and put them in the right order.
Matching Rows: where()
Section titled “Matching Rows: where()”Choosing which rows to load is the query’s job (SQL’s WHERE clause); there’s no point fetching rows you won’t use. These methods are for the result you already have: one loaded collection sliced different ways for different parts of the page, with no extra queries.
where() keeps the rows where a field matches a value. Chain it to match on
more than one field:
use Itools\SmartArray\SmartArrayHtml;
$users = SmartArrayHtml::new([ ['name' => 'Jean', 'status' => 'Active', 'role' => 'admin', 'newsletter' => 1], ['name' => 'Tom', 'status' => 'Inactive', 'role' => 'admin', 'newsletter' => 0], ['name' => 'Sam', 'status' => 'Active', 'role' => 'editor', 'newsletter' => 1],]);
$active = $users->where('status', 'Active'); // Jean and Sam$admins = $users->where('status', 'Active')->where('role', 'admin'); // just JeanThe rule behind every case: where() gives the same answers a SQL WHERE
does, with two exceptions - strings stay case-sensitive, and a non-numeric
string never equals 0. In practice:
- Numbers match numeric strings:
'1'matches1, andwhere('price', 1)matches a DECIMAL column’s'1.00'(databases and forms often hand numbers back as strings). - Two strings must match exactly.
- Null only matches null.
- True/false mean 1/0.
When you need full type-sensitive matching, filter() (below) takes a
callback where you can compare with ===.
With just a field name, where() keeps the rows where that field has a
truthy value, following PHP’s empty() rules (NULL, false, 0, "0", and
"" don’t count), which fits checkbox fields:
$subscribed = $users->where('newsletter'); // Jean and SamExcluding Rows: whereNot()
Section titled “Excluding Rows: whereNot()”The whereNot() method drops the matching rows and keeps everything else,
the inverse of where():
$nonAdmins = $users->whereNot('role', 'admin'); // just SamIt mirrors the single-argument form too: whereNot('newsletter') keeps
the rows where the field is empty by PHP’s empty() rules, meaning NULL,
false, 0, "0", "", or the field missing from the row entirely.
CMS Builder List Fields: whereInList()
Section titled “CMS Builder List Fields: whereInList()”This one is specific to CMS Builder, which stores checkbox groups and
multi-select fields as tab-separated lists in a single column (a page shown
in two places stores "\tmenu\tfooter\t"). The whereInList() method matches
one value inside those fields, whole values only, never substrings.
The whole where-family chains on one loaded result:
$pages = SmartArrayHtml::new([ ['num' => 1, 'title' => 'Home', 'hidden' => 0, 'showIn' => "\tmenu\tfooter\t"], ['num' => 2, 'title' => 'About', 'hidden' => 0, 'showIn' => "\tmenu\t"], ['num' => 3, 'title' => 'Login', 'hidden' => 0, 'showIn' => "\tmenu\t"], ['num' => 4, 'title' => 'Old News', 'hidden' => 1, 'showIn' => "\tmenu\t"],]);
$menuPages = $pages->where('hidden', 0)->whereNot('title', 'Login')->whereInList('showIn', 'menu');
foreach ($menuPages as $page) { echo "<li>$page->title</li>\n";}// <li>Home</li>// <li>About</li>Custom Tests: filter()
Section titled “Custom Tests: filter()”When the test is more than field-equals-value, filter() takes a callback.
The callback receives plain PHP values (row arrays, strings, numbers), so
you write ordinary PHP inside it:
$tables = SmartArrayHtml::new(['cms_accounts', 'wp_posts', 'cms_orders']);
$ours = $tables->filter(fn($name) => str_starts_with($name, 'cms_')); // cms_accounts, cms_ordersCalled with no callback, filter() removes empty values ("", "0", 0,
NULL, false). That includes zeros that are real data (a $0 price, a sort
order of 0, an unchecked tinyint MySQL handed back as "0"); pass a callback
when zeros should stay. Like PHP’s array_filter(), kept rows keep their
original keys; chain values() when you want them renumbered.
Sorting: sortBy() and sort()
Section titled “Sorting: sortBy() and sort()”sortBy() orders rows by a field. It returns a new sorted collection and
never modifies the original (PHP’s own sort() modifies arrays in place;
SmartArray methods don’t), so your result stays in query order and can be
sorted different ways for different spots on the page:
$funds = SmartArrayHtml::new([ ['name' => 'Fund 10'], ['name' => 'Fund 2'], ['name' => 'Fund 1'],]);
$textOrder = $funds->sortBy('name'); // Fund 1, Fund 10, Fund 2$realOrder = $funds->sortBy('name', SORT_NATURAL); // Fund 1, Fund 2, Fund 10Plain text sorting compares character by character, which puts “Fund 10”
before “Fund 2”; SORT_NATURAL sorts numbers the way people read them.
For flat lists (no rows, just values), use sort():
$tags = SmartArrayHtml::new(['PHP', 'MySQL', 'Apache']);
echo $tags->sort()->implode(', '); // Apache, MySQL, PHPDuplicates and Membership: unique() and contains()
Section titled “Duplicates and Membership: unique() and contains()”unique() drops repeated values from a flat list, keeping the first of each,
and contains() to ask whether a value is in the list at all. Both treat 1
and '1' as the same value (contains() follows the same matching rules as
where()):
$tags = SmartArrayHtml::new(['PHP', 'MySQL', 'PHP', 'Apache']);
echo $tags->unique()->implode(', '); // PHP, MySQL, Apachevar_export($tags->contains('MySQL')); // true