String Macros¶
Text manipulation in question control code.
Most PHP string functions are not available
Control code runs through the engine's own interpreter against a fixed
allowlist. strlen, trim, strpos, implode, join, str_repeat,
str_pad and htmlspecialchars are not on it — calling any of them is a
hard error, not a warning. Earlier versions of this page documented all of
them. The engine's own equivalents are below.
The engine's string macros¶
stringlen($str)¶
Length of a string in bytes (it is PHP's strlen). A non-ASCII character such as é, π or ° counts as 2 or more.
$length = stringlen("hello") // 5
stringpos($needle, $haystack)¶
Position of $needle within $haystack, or -1 if it does not occur.
Needle first, haystack second
This is the opposite order from PHP's strpos, and the opposite of what
earlier versions of this page showed. Getting it backwards silently returns
-1 rather than erroring.
$position = stringpos("world", "hello world") // 6
$found = stringpos("x", "hello") // -1
Because a miss is -1 and not false, test it as a number:
$given = getstuans($stuanswers, $thisq)
$hasUnit = ($given !== null && stringpos("cm", $given) >= 0)
stringclean($str, $mode)¶
Strips characters. $mode selects how much:
$mode |
Effect |
|---|---|
0 (default) |
trim leading and trailing whitespace |
1 |
remove all whitespace, inside as well as out |
2 |
remove every non-word character (keeps ASCII letters, digits, underscore; accented letters such as é are removed too) |
$cleaned = stringclean(" hello world ") // "hello world"
$tight = stringclean("1 234 567", 1) // "1234567"
$bare = stringclean("(3, 4)", 2) // "34"
Mode 1 is the usual way to compare a typed answer while ignoring spacing.
stringappend($value, $suffix) and stringprepend($value, $prefix)¶
Add text to the end or the start. Both are array-aware: given an array, they apply to every element and return the new array, which is the compact way to attach units to a whole set of options.
$labelled = stringappend(array(2, 4, 6), " cm") // "2 cm", "4 cm", "6 cm"
$money = stringprepend($amounts, "$")
Native functions the engine does expose¶
These are ordinary PHP functions the engine deliberately allowlists, so they behave exactly as PHP documents them:
| Available | Use for |
|---|---|
substr($s, $start, $len) |
extract part of a string |
str_replace($find, $repl, $s) |
replace all occurrences |
strtolower($s), strtoupper($s) |
change case |
ucfirst($s), lcfirst($s) |
change the first character only |
explode($sep, $s) |
split into an array |
substr_count($s, $needle) |
count occurrences |
sprintf($fmt, …) |
formatted output |
preg_match, preg_match_all, preg_replace |
regular expressions |
htmlentities($s) |
escape for HTML display |
rawurlencode($s) |
escape for a URL |
Joining and splitting¶
There is no implode. Use the array macros:
joinarray($array, $separator, $ksort)¶
$items = array("apple", "banana", "orange")
$list = joinarray($items, ", ") // "apple, banana, orange"
$separator defaults to ",". Pass true as the third argument to sort by key before joining.
arraytolist($array, $spaced)¶
A shorthand for the common case: joins with ",", or with ", " when $spaced is true.
$list = arraytolist($items, true) // "apple, banana, orange"
listtoarray($list)¶
The inverse — splits a comma-separated string and trims each piece.
$colors = listtoarray("red, blue, green") // "red", "blue", "green"
explode($sep, $s) is available when the separator is not a comma, but it does not trim.
stringtoarray($str)¶
Splits into individual bytes, not words. That is one element per character for plain ASCII text, but a non-ASCII character such as é is split into broken pieces.
$chars = stringtoarray("abc") // "a", "b", "c"
Examples¶
Build a sentence¶
$name = "Alice"
$number = 5
$sentence = ucfirst($name) . " has " . $number . " apples."
Concatenation is ., as in PHP.
Check the length of a typed answer¶
$given = getstuans($stuanswers, $thisq)
$fb = ""
$fb = "Your answer is too long." if ($given !== null && stringlen($given) > 10)
$fb = "Your answer is too short." if ($given !== null && stringlen($given) < 2)
Compare ignoring case and spacing¶
$given = getstuans($stuanswers, $thisq)
$correct = stringclean(strtolower("New York"), 1)
$ismatch = ($given !== null && stringclean(strtolower($given), 1) == $correct)
Format a list for display¶
$values = array(10, 20, 30)
$formatted = "Values: " . joinarray($values, " | ") // "Values: 10 | 20 | 30"
Interpolating an array prints Array
"Values: $values" renders the literal word Array. Join it first, as above.
Tips¶
stringposreturns-1, notfalse— compare with>= 0.- Arguments to
stringposare needle-then-haystack — the reverse of PHP. stringappend/stringprependwork on whole arrays, which is usually shorter than looping.- Use
htmlentities, nothtmlspecialchars, when putting student input into HTML. - A student's last submitted answer is
$stuanswers[$thisq]. It isnullbefore the first submission, and in a multipart question it is an array of parts. Usegetstuans($stuanswers, $thisq, $part)(part defaults to0), which returnsnullfor a missing or blank answer, and test fornullbefore using the result.
See Also¶
- Array Macros — array operations, including
joinarrayandlisttoarray - Format Macros — number formatting and display
- Feedback Macros — building feedback messages
- Control Syntax — conditionals and loops