strtok
Splits a string into tokens one at a time, using any of the given delimiter characters.
strtok(string $string, string $token): string|false
strtok(string $token): string|false- Added in PHP 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$string | string | The string being split into tokens. Supplied only on the first call; subsequent calls omit it and continue through the string held in internal state. |
$token | string | The delimiters. Every character in this string is treated as a separate delimiter, and it may differ between calls. |
Return value
string|falseThe next token found in the string, or false when no tokens remain.
Errors
Emits E_WARNING as of PHP 8.3.0 when called without a token argument.
Changelog
- PHP 8.3.0Calling strtok() with no token argument now emits E_WARNING.
strtok walks through a string one token at a time. The first call passes both the string and the delimiter characters; every call after that passes only the delimiters and picks up where the previous call stopped. It returns false once the string is exhausted.
When to reach for it
It is worth using when you want to stop early — pulling only the first two fields off a long line, or scanning a large buffer without materialising every piece as explode would. It also collapses runs of delimiters, so "a;;;b" with ; yields just a and b, and leading or trailing delimiters are ignored. That makes it convenient for whitespace-separated input where explode would hand you empty strings.
What trips people up
The parser state is global to the process, so a function that calls strtok in the middle of your loop silently steals your position. Never nest two strtok loops, and be careful calling any function that might use it internally. The second argument is a set of single characters, not a delimiter string: strtok($s, "; ") splits on semicolons and spaces, it does not look for the two-character sequence.
For anything reentrant or structured, explode or preg_split is the safer choice.
Example
When to use it
- Read only the first few whitespace-separated fields of a long log line without splitting the whole thing.
- Parse a semicolon-and-space separated list where consecutive delimiters should be collapsed rather than producing empty entries.
- Walk a large in-memory buffer token by token and break out as soon as a match is found.
Frequently asked questions
What is the difference between strtok and explode?
explode returns every piece at once, including empty strings between consecutive delimiters, while strtok returns one token per call and skips empty tokens entirely. Use explode unless you need to stop early or change delimiters partway through.
Why does strtok return the wrong token inside a loop?
Because strtok stores its position in one process-wide state. Any nested strtok call — including one hidden inside a function you call in the loop — moves that shared pointer and breaks the outer loop.
Can strtok split on a multi-character delimiter like '::'?
No. Every character in the token argument is treated as its own delimiter, so '::' just means 'split on colons'. Use explode or preg_split for a true multi-character separator.
More examples
Changing delimiters mid-parse
Prints 'GET', '/index.php' and 'a=1'. Each call may use a different delimiter set, so you can switch the rule as you move through the string — something explode() cannot do in one pass.
<?php
$line = 'GET /index.php?a=1 HTTP/1.1';
$method = strtok($line, ' ');
$path = strtok('?'); // now split on '?' instead
$query = strtok(' ');
echo $method, "\n";
echo $path, "\n";
echo $query, "\n";Stopping early on a big string
Prints 'sum of first values: 15'. Only five tokens are ever produced — the remaining 995 are never built as separate strings, which is the memory advantage over explode(). The strtok('', '') call clears the stored string.
<?php
$csv = implode(',', range(1, 1000));
$sum = 0;
$t = strtok($csv, ',');
while ($t !== false && $t <= 5) {
$sum += (int) $t;
$t = strtok(',');
}
echo "sum of first values: $sum\n";
strtok('', ''); // release the internal reference
echo "done\n";
Discussion