Strings7 min readExamples run on PHP 8.5.10

chop()

Learn how PHP chop() works as an alias of rtrim(), including default characters, custom lists, ranges, edge cases and the Perl naming trap.

Signature

chop(string $string, string $characters = " \n\r\t\v\x00"): string

Purpose

chop() removes characters from the end of a string and returns the shortened copy. In PHP it is simply another name for rtrim(): the two functions accept the same arguments and behave identically. Because of that, most modern code uses rtrim(), which says what it does more plainly. You will still run into chop() in older code bases, so it helps to read it fluently.

The name is a trap for developers who know Perl. Perl's chop removes exactly one character from the end of a string. PHP's chop() does nothing of the sort: it removes a whole run of trailing characters taken from a set, and by default that set is whitespace-like.

Signature

Parameters and defaults

  • $string: the input string. It is not modified in place; PHP strings are passed by value, so you must use the return value.
  • $characters: an optional list of characters to strip. When omitted, PHP strips the space, newline, carriage return, tab, vertical tab and the NUL byte (\0).

The $characters argument is a set, not a suffix. Every character in it is a candidate for removal, in any order, and removal continues from the right until a character not in the set is found. You can also write a range with two dots, such as "0..9", to mean every character from 0 to 9.

Return value and failure cases

The function returns a string. If nothing at the end matches, you get the original content back unchanged. If every character matches, you get an empty string. It does not return false and does not throw for ordinary input. A malformed .. range in the character list can produce a warning, so build range lists carefully rather than from untrusted input.

Example 1: cleaning trailing whitespace

The most common use is dropping a trailing newline or stray spaces from a line of text.

Example
<?php
$line = "Report ready \n\t ";
$clean = chop($line);
echo json_encode($clean, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";
Output
"Report ready"

All the trailing spaces, the newline and the tab are removed in one call, because each of them belongs to the default set.

Example 2: custom characters and ranges

Pass a second argument to strip something other than whitespace. Only the characters you list are removed, and only from the right-hand end.

Example
<?php
$results = [
    chop("Hello!!!", "!"),
    chop("Item A123456", "0..9"),
    chop("abcxyx", "xy"),
];
echo json_encode($results, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";
Output
["Hello","Item A","abc"]

The third call shows the set behavior: both x and y are in the list, so the trailing xyx disappears even though xyx is not written as a unit. Scanning stops at c, which is not in the set.

Example 3: left side untouched, and not Perl's chop

Example
<?php
$text = "  keep left  ";
$a = chop($text);
$b = rtrim($text);
echo json_encode([
    'chop' => $a,
    'rtrim' => $b,
    'same' => $a === $b,
    'removedLastChar' => chop("PHP"),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";
Output
{"chop":"  keep left","rtrim":"  keep left","same":true,"removedLastChar":"PHP"}

Leading spaces survive, the result is identical to rtrim(), and chop("PHP") still returns PHP, because the final P is not whitespace.

Edge cases

  • An empty input string returns an empty string.
  • A string made only of removable characters becomes "".
  • Whitespace in the middle of the string is never touched; only the trailing run is examined.
  • Passing an empty $characters string means no characters are eligible, so the input is returned unchanged.
  • The default set includes the NUL byte and vertical tab, which many people forget when they expect only visible spaces and newlines.
  • Bytes, not Unicode characters, are processed. For plain ASCII lists this is fine, but a multibyte character inside the list is treated as separate bytes and can lead to surprising results.

Common mistakes

  1. Expecting Perl behavior. If you want to remove exactly one final character, use substr($string, 0, -1) instead, taking care with empty strings.
  2. Ignoring the return value. Calling chop($s); on its own statement changes nothing; assign the result.
  3. Thinking the list is a suffix. chop($s, ".php") removes any trailing ., p or h characters, not the literal extension. That can eat into a filename such as graph.php and beyond. To remove a specific suffix, check it with str_ends_with() and then cut it off.
  4. Expecting both ends to be trimmed. Use trim() for both sides or ltrim() for the left side only.
  5. Choosing the obscure name. In new code, rtrim() communicates intent better and avoids confusion with other languages.
  • rtrim(): the primary name that chop() aliases.
  • trim() and ltrim(): strip both ends or the start.
  • substr(): remove a fixed number of characters.
  • str_ends_with(): test for a literal suffix before removing it.
  • str_replace() and preg_replace(): remove content anywhere in a string.

Recap

chop() is an alias of rtrim(). It returns a new string with trailing characters removed, using whitespace and NUL by default or a custom set and .. ranges when you provide one. It does not remove just the last character as Perl's version does, and it leaves the start and middle of the string alone.

Tested examples

Remove trailing whitespace with the default character set
<?php
$line = "Report ready \n\t ";
$clean = chop($line);
echo json_encode($clean, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";
Output
"Report ready"
Custom character lists and ranges
<?php
$results = [
    chop("Hello!!!", "!"),
    chop("Item A123456", "0..9"),
    chop("abcxyx", "xy"),
];
echo json_encode($results, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";
Output
["Hello","Item A","abc"]
chop() equals rtrim() and does not remove one character
<?php
$text = "  keep left  ";
$a = chop($text);
$b = rtrim($text);
echo json_encode([
    'chop' => $a,
    'rtrim' => $b,
    'same' => $a === $b,
    'removedLastChar' => chop("PHP"),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";
Output
{"chop":"  keep left","rtrim":"  keep left","same":true,"removedLastChar":"PHP"}