substr

Returns a portion of a string starting at a given offset, optionally limited to a length.

Signature
substr(string $string, int $offset, ?int $length = null): string
  • Added in PHP 4.0

Parameters

ParameterTypeDescription
$stringstringThe input string.
$offsetintWhere the returned substring starts. Non-negative offsets count from the beginning; negative offsets count back from the end of the string.
$lengthoptional?int= nullMaximum number of bytes to return. Negative values stop that many bytes before the end; 0 returns an empty string; null runs to the end of the string.

Return value

stringThe extracted part of the string, or an empty string if nothing matches the requested range.

Changelog

  • PHP 8.0.0length is nullable now. Passing null explicitly returns the substring up to the end of the string, where it previously returned an empty string.
  • PHP 8.0.0The function now returns an empty string where it previously returned false (for example when offset is past the end of the string).

substr slices a string by byte offset. Positive offsets count from the start, negative offsets count from the end, and the length may be positive (how much to take), negative (how much to leave off the end) or null (take everything remaining).

When to reach for it

Use it whenever you already know the position: taking a fixed-width field out of a record, reading a prefix code, chopping a known extension off a filename, or pairing it with strpos to extract the text between two markers. The negative-length form is particularly handy — substr($s, 0, -4) drops the last four bytes without you needing to compute the length.

What trips people up

It counts bytes, not characters. Cutting a UTF-8 string at an arbitrary offset can land in the middle of a multibyte sequence and produce a broken character, which is why truncating user text should use mb_substr.

The other change to remember is that since PHP 8.0 an out-of-range request returns "" rather than false. Old code that checked if (substr(...) === false) no longer detects anything — check the length of the input instead. And do not use substr($s, 0, 1) === 'x' to test a prefix; str_starts_with says it more clearly.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Pull a fixed-width field out of a legacy flat-file record.
  • Drop a known suffix, such as substr($file, 0, -4) to remove '.csv'.
  • Take the first N characters of a description for a list preview.
  • Extract the text between two markers found with strpos.

Frequently asked questions

Why does substr return an empty string instead of false?

Since PHP 8.0 substr always returns a string; an offset past the end of the input yields "" rather than false. Code that tested for false should check the input length instead.

What is the difference between substr and mb_substr?

substr counts bytes and mb_substr counts characters in a given encoding. For UTF-8 text with accented or non-Latin characters, only mb_substr is guaranteed not to split a character.

How do I get the last N characters of a string?

Pass a negative offset: substr($s, -3) returns the last three bytes. Use mb_substr($s, -3) if the string may contain multibyte characters.

More examples

Extracting text between two markers

Prints 'Release notes'. The length argument is the distance between the two positions, which is the usual way substr and strpos are combined. In real code you would guard against strpos returning false first.

Example · php
<?php
$html  = '<title>Release notes</title>';
$start = strpos($html, '<title>') + 7;
$end   = strpos($html, '</title>');

echo substr($html, $start, $end - $start), "\n";

Byte slicing versus character slicing

The strlen/mb_strlen line prints '12 bytes, 10 chars', which is why the two slices differ: substr took 4 bytes and landed inside the two-byte ï, while mb_substr took 4 whole characters.

Example · php
<?php
$text = 'naïve café';

echo substr($text, 0, 4), "|\n";     // may cut the ï in half
echo mb_substr($text, 0, 4), "|\n";  // naïv
echo strlen($text), ' bytes, ', mb_strlen($text), " chars\n";

Truncating with an ellipsis

Prints 'Short' unchanged and 'A considerably longe…' for the second. The length check first matters — without it, short strings would get a pointless ellipsis appended even though nothing was cut.

Example · php
<?php
function preview(string $text, int $max = 20): string {
    return strlen($text) <= $max ? $text : substr($text, 0, $max - 1) . '…';
}

echo preview('Short'), "\n";
echo preview('A considerably longer description here'), "\n";

Discussion

  • Be the first to comment on this lesson.