Strings7 min readExamples run on PHP 8.5.10

chunk_split()

Learn how PHP 8.4 chunk_split() inserts a separator after every fixed number of bytes, with examples, edge cases and common mistakes.

Signature

chunk_split(string $string, int $length = 76, string $separator = "\r\n"): string

Purpose

chunk_split() walks through a string and inserts a separator after every fixed number of characters. The classic use is wrapping base64_encode() output into lines that follow the RFC 2045 style used in email. It is also handy for visually grouping long identifiers, such as card numbers or hexadecimal digests, into readable blocks.

The key thing to remember is that the separator is added after every chunk, including the last one. The function therefore does not work like implode(), which only puts a glue string between items.

Signature

Parameters and defaults

  • $string is the input to be chunked.
  • $length is the chunk size. The default is 76, the line length commonly used for base64 in mail. It must be greater than zero.
  • $separator is the sequence inserted after each chunk. The default is "\r\n" (carriage return plus line feed). Pass "\n", a space, a dash or any other string if you need something different.

Return value and failure cases

The function returns a new string; the original is not modified. A string shorter than $length is not left untouched: it comes back with one separator appended. The same applies to an empty string, which is shorter than any positive length.

If $length is zero or negative, PHP 8 throws a ValueError. There is no false return to check. Because the arguments are typed, passing a non-numeric value for $length raises a TypeError in the normal way.

Example 1: the trailing separator

The first example shows both a string that does not divide evenly and one that does. In each case the separator also ends the result.

Example
<?php
echo json_encode([
    chunk_split('abcdefgh', 3, '-'),
    chunk_split('abcdef', 3, '-'),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
Output
["abc-def-gh-","abc-def-"]

The eight-letter string yields abc-def-gh-, with the short final chunk followed by a separator. The six-letter string yields abc-def-.

Example 2: wrapping base64 output

This is the use the function was designed for. Encoding first and chunking second keeps every line within a predictable width. Here json_encode() is used only so the newline characters are visible in the output.

Example
<?php
$encoded = base64_encode('Hello, World!');
echo json_encode(chunk_split($encoded, 8, "\n"), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
Output
"SGVsbG8s\nIFdvcmxk\nIQ==\n"

The encoded text is SGVsbG8sIFdvcmxkIQ==, which is twenty characters long. It is cut into lines of eight, eight and four characters, and each line ends with a newline.

Example 3: grouping digits for display

Because of the trailing separator, display formatting usually needs one extra step. Removing the final space with rtrim() gives a clean result.

Example
<?php
$card = '4111111111111111';
echo rtrim(chunk_split($card, 4, ' ')), PHP_EOL;
Output
4111 1111 1111 1111

The sixteen digits become four groups of four, separated by single spaces, with no trailing space left over.

Edge cases

  • Exact multiples. A string whose length divides evenly by $length still ends with the separator. There is no special case that skips it.
  • Short input. If the string is no longer than the chunk length, you get the original text plus one separator.
  • Bytes, not characters. The function counts bytes. For ASCII text, bytes and characters are the same thing, but a multibyte UTF-8 character can be cut in the middle. Splitting a two-byte letter with a length of 1 produces two invalid fragments. For text in a multibyte encoding, use a multibyte-aware approach such as mb_str_split() and join the pieces yourself.
  • Empty separator. An empty separator is allowed, and the output is then identical to the input, so there is little point in doing it.
  • Line endings. The default "\r\n" is correct for email-style data but surprising if you print the result to a Unix terminal or compare it against text that only uses "\n".

Common mistakes

  1. Forgetting the trailing separator. Code that compares the result with an expected string, or displays it to users, often has an unwanted final dash, space or newline. Trim it when you need only separators between chunks.
  2. Passing a zero length. Computing the chunk size from user input or a division can yield 0, which throws a ValueError. Validate it first.
  3. Expecting an array. The function returns one string. If you want the pieces as separate items, str_split() is the right tool.
  4. Using it for word wrapping. chunk_split() cuts at fixed positions regardless of word boundaries. For natural text, use wordwrap().
  5. Chunking before encoding. Chunk the base64 text, not the raw bytes. Splitting the original data and encoding the pieces separately produces different output.
  6. Assuming characters in UTF-8. As noted above, the length counts bytes, so accented letters and emoji can be broken.
  • str_split() converts a string into an array of fixed-size pieces.
  • explode() splits a string on a delimiter you supply.
  • wordwrap() wraps text to a line width at word boundaries.
  • base64_encode() produces the text that chunk_split() is most often used to format.
  • rtrim() removes the trailing separator when you do not want it.

Recap

chunk_split() returns a string in which a separator follows every $length bytes, including the last chunk. Its defaults, 76 and "\r\n", suit base64 for email. Use a positive length, trim the final separator when formatting for display, and prefer str_split() or multibyte-aware code when you need an array or have non-ASCII text.

Tested examples

The separator also follows the final chunk
<?php
echo json_encode([
    chunk_split('abcdefgh', 3, '-'),
    chunk_split('abcdef', 3, '-'),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
Output
["abc-def-gh-","abc-def-"]
Wrapping base64 output into short lines
<?php
$encoded = base64_encode('Hello, World!');
echo json_encode(chunk_split($encoded, 8, "\n"), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
Output
"SGVsbG8s\nIFdvcmxk\nIQ==\n"
Grouping digits and trimming the trailing space
<?php
$card = '4111111111111111';
echo rtrim(chunk_split($card, 4, ' ')), PHP_EOL;
Output
4111 1111 1111 1111