PHP

Strings em Profundidade Já leu

13 min de leitura

Strings em Profundidade
Strings são o tipo de dado mais presente em qualquer aplicação web. Toda entrada de usuário chega como string. Todo HTML gerado &eac

Strings são o tipo de dado mais presente em qualquer aplicação web. Toda entrada de usuário chega como string. Todo HTML gerado é uma string. Todo JSON enviado e recebido passa por strings. Manipular texto com precisão, segurança e eficiência é uma habilidade central do desenvolvimento PHP.

Neste artigo vamos além do básico — cobrimos as funções mais importantes da biblioteca de strings do PHP, formatação de números e datas, e uma introdução prática às expressões regulares com preg_match e preg_replace.


Revisão rápida: aspas simples vs duplas

Antes de avançar, vale consolidar um ponto do Artigo 04:

<?php
declare(strict_types=1);

$nome = "Ricardo";

// Aspas simples — literal, sem interpolação, mais rápido
echo 'Olá, $nome';       // Olá, $nome (literal)
echo 'Ela disse: "oi"';  // sem necessidade de escapar aspas duplas

// Aspas duplas — interpola variáveis e sequências de escape
echo "Olá, $nome";          // Olá, Ricardo
echo "Olá, {$nome}!";       // Olá, Ricardo! — chaves delimitam a variável
echo "Linha 1\nLinha 2";    // \n = quebra de linha
echo "Coluna1\tColuna2";    // \t = tabulação

// Heredoc — para strings longas com interpolação
$html = <<<HTML
    <div class="perfil">
        <h1>$nome</h1>
    </div>
    HTML;

// Nowdoc — como heredoc mas sem interpolação (equivalente às aspas simples)
$sql = <<<'SQL'
    SELECT * FROM usuarios WHERE nome = '$nome'
    SQL;
// $nome não é interpolado — útil para SQL, templates, etc.

A regra prática: use aspas simples quando não precisar de interpolação. O código fica mais rápido e deixa claro que a string é literal.


Funções fundamentais de string

<?php
declare(strict_types=1);

$texto = "  Dominando o PHP em 1 Ano  ";
$frase = "O rato roeu a roupa do rei de Roma";

// Tamanho e limpeza
echo strlen($texto);          // 28 — inclui os espaços
echo mb_strlen($texto);       // 28 — versão multibyte (use para Unicode)
echo trim($texto);            // "Dominando o PHP em 1 Ano"
echo ltrim($texto);           // remove espaços só da esquerda
echo rtrim($texto);           // remove espaços só da direita
echo trim($texto, " D");      // remove " " e "D" das bordas

// Capitalização
echo strtolower($frase);      // tudo minúsculo
echo strtoupper($frase);      // TUDO MAIÚSCULO
echo ucfirst("olá mundo");    // Olá mundo — primeira letra maiúscula
echo ucwords("olá mundo php");// Olá Mundo Php — primeira de cada palavra
echo mb_strtolower("AÇÃO");   // ação — versão multibyte para acentos

// Busca e posição
echo strpos($frase, "rato");     // 3 — posição da primeira ocorrência
echo strrpos($frase, "ro");      // 27 — posição da última ocorrência
echo substr_count($frase, "ro"); // 4 — quantas vezes "ro" aparece

// Atenção: strpos pode retornar 0 (início da string) — use !== false
$pos = strpos($frase, "O");
if ($pos !== false) {
    echo "Encontrado na posição $pos\n"; // 0
}

// substr — extrai parte da string
echo substr($frase, 3, 4);    // "rato" — começa na pos 3, pega 4 chars
echo substr($frase, -4);      // "Roma" — 4 caracteres do final
echo mb_substr($frase, 3, 4); // versão multibyte

// Substituição
echo str_replace("rato", "gato", $frase);
// "O gato roeu a roupa do rei de Roma"

// Substituição case-insensitive
echo str_ireplace("RAtO", "gato", $frase);
// "O gato roeu a roupa do rei de Roma"

// Múltiplas substituições de uma vez
echo str_replace(
    ["rato", "roupa", "rei"],    // buscar
    ["gato", "calça", "dono"],   // substituir por
    $frase
);

Divisão e junção

<?php
declare(strict_types=1);

$csv      = "Ana,Bruno,Carla,David";
$frase    = "PHP é incrível";
$nomes    = ["Ana", "Bruno", "Carla"];

// explode — divide string em array pelo separador
$partes = explode(",", $csv);
// ["Ana", "Bruno", "Carla", "David"]

// Terceiro argumento limita o número de partes
$limitado = explode(",", $csv, 2);
// ["Ana", "Bruno,Carla,David"] — divide no máximo em 2 partes

// implode — une array em string com separador
echo implode(", ", $nomes);     // "Ana, Bruno, Carla"
echo implode(" | ", $nomes);    // "Ana | Bruno | Carla"
echo implode("", $nomes);       // "AnaBrunoCarla"

// str_split — divide em pedaços de N caracteres
$chars = str_split("PHP", 1);   // ["P", "H", "P"]
$pares = str_split("ABCDEF", 2); // ["AB", "CD", "EF"]

// wordwrap — quebra string em linhas com largura máxima
$texto = "Este é um texto longo que precisa ser quebrado em múltiplas linhas para exibição.";
echo wordwrap($texto, 40, "\n", true);

Formatação

<?php
declare(strict_types=1);

// number_format — formata números para exibição
$preco    = 1234567.891;

echo number_format($preco);              // 1,234,568 — padrão americano
echo number_format($preco, 2);           // 1,234,567.89
echo number_format($preco, 2, ',', '.'); // 1.234.567,89 — padrão brasileiro

// sprintf — formata string com placeholders
$nome  = "Ana";
$nota  = 9.75;
$media = 8.423;

echo sprintf("Aluna: %s | Nota: %.2f", $nome, $nota);
// "Aluna: Ana | Nota: 9.75"

echo sprintf("Média: %.1f", $media);  // "Média: 8.4"
echo sprintf("Código: %05d", 42);     // "Código: 00042" — zero-padded
echo sprintf("Hex: %x", 255);         // "Hex: ff"
echo sprintf("Porcentagem: %.1f%%", 94.567); // "Porcentagem: 94.6%"

// printf — como sprintf mas já imprime
printf("%-15s %5.2f\n", "Produto A", 129.9);  // alinhamento
printf("%-15s %5.2f\n", "Produto B", 49.5);

// number_format vs sprintf para moeda
$valor = 1500.5;
$formatadoNF  = "R$ " . number_format($valor, 2, ',', '.');   // R$ 1.500,50
$formatadoSPF = sprintf("R$ %.2f", $valor);                    // R$ 1500.50

Datas e horas

<?php
declare(strict_types=1);

// date() — formata a data/hora atual
echo date("d/m/Y");       // 08/03/2026
echo date("H:i:s");       // 14:35:20
echo date("d/m/Y H:i");   // 08/03/2026 14:35
echo date("l, d F Y");    // Saturday, 08 March 2026
echo date("U");           // Unix timestamp atual

// Caracteres de formato mais usados
// d = dia com zero | j = dia sem zero
// m = mês com zero | n = mês sem zero
// Y = ano 4 dígitos | y = ano 2 dígitos
// H = hora 24h | h = hora 12h
// i = minutos | s = segundos
// D = dia abreviado | l = dia completo
// M = mês abreviado | F = mês completo
// N = dia da semana (1=seg, 7=dom)
// U = Unix timestamp

// mktime() — cria um timestamp a partir de componentes
$natal = mktime(0, 0, 0, 12, 25, 2026); // hora, min, seg, mês, dia, ano
echo date("d/m/Y", $natal); // 25/12/2026

// strtotime() — converte string para timestamp
$amanha    = strtotime("+1 day");
$semanaPassada = strtotime("-1 week");
$proximaMes = strtotime("+1 month");
$dataEspecifica = strtotime("2026-06-15");

echo date("d/m/Y", $amanha);         // data de amanhã
echo date("d/m/Y", $semanaPassada);  // data de uma semana atrás
echo date("d/m/Y", $dataEspecifica); // 15/06/2026

// DateTime — classe orientada a objetos (mais recomendada para projetos modernos)
$hoje   = new DateTime();
$futuro = new DateTime("+30 days");
$fixa   = new DateTime("2026-12-31");

echo $hoje->format("d/m/Y H:i");     // data e hora atual formatada
echo $fixa->format("l, d F Y");      // "Thursday, 31 December 2026"

// Diferença entre datas
$inicio = new DateTime("2026-01-01");
$fim    = new DateTime("2026-12-31");
$diff   = $inicio->diff($fim);

echo $diff->days;    // 364
echo $diff->months;  // 11

// DateTimeImmutable — versão que não modifica o objeto original
// Preferida em código funcional e quando você precisa preservar a data original
$base      = new DateTimeImmutable("2026-03-01");
$mais30    = $base->modify("+30 days"); // retorna NOVO objeto
$mais60    = $base->modify("+60 days"); // $base ainda é 01/03

echo $base->format("d/m/Y");    // 01/03/2026 — não modificado
echo $mais30->format("d/m/Y");  // 31/03/2026
echo $mais60->format("d/m/Y");  // 30/04/2026

Expressões regulares

Expressões regulares (regex) são padrões de busca que permitem encontrar, validar e extrair texto com uma precisão impossível de alcançar com funções simples de string. O PHP usa funções preg_* que implementam o padrão PCRE (Perl Compatible Regular Expressions):

<?php
declare(strict_types=1);

// preg_match — verifica se o padrão existe e captura grupos
// Retorna 1 se encontrou, 0 se não encontrou, false em erro
$email = "ana@email.com";

// Delimitadores: / no início e fim. Flags após o delimitador final.
$padrao = '/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/';

if (preg_match($padrao, $email)) {
    echo "E-mail válido\n";
}

// Capturando grupos com parênteses
$data = "Hoje é 08/03/2026";
preg_match('/(\d{2})\/(\d{2})\/(\d{4})/', $data, $matches);

// $matches[0] = string completa correspondida
// $matches[1] = primeiro grupo capturado
// $matches[2] = segundo grupo
// $matches[3] = terceiro grupo
echo $matches[0]; // "08/03/2026"
echo $matches[1]; // "08"
echo $matches[2]; // "03"
echo $matches[3]; // "2026"

// Grupos nomeados — mais legível que índices numéricos
preg_match('/(?P<dia>\d{2})\/(?P<mes>\d{2})\/(?P<ano>\d{4})/', $data, $m);
echo $m["dia"]; // "08"
echo $m["mes"]; // "03"
echo $m["ano"]; // "2026"
<?php
declare(strict_types=1);

// preg_match_all — encontra TODAS as ocorrências
$html    = '<a href="https://php.net">PHP</a> e <a href="https://laravel.com">Laravel</a>';
$padrao  = '/<a href="([^"]+)">([^<]+)<\/a>/';

preg_match_all($padrao, $html, $matches);

// $matches[0] = array com as strings completas
// $matches[1] = array com o grupo 1 (URLs)
// $matches[2] = array com o grupo 2 (textos dos links)
print_r($matches[1]); // ["https://php.net", "https://laravel.com"]
print_r($matches[2]); // ["PHP", "Laravel"]

// preg_replace — substitui com regex
$telefone = "(11) 9 8765-4321";

// Remove tudo que não for dígito
$somenteDigitos = preg_replace('/\D/', '', $telefone);
echo $somenteDigitos; // "11987654321"

// preg_replace com referência de grupo ($1, $2...)
$data = "2026-03-08";
$dataFormatada = preg_replace('/(\d{4})-(\d{2})-(\d{2})/', '$3/$2/$1', $data);
echo $dataFormatada; // "08/03/2026"

// preg_split — divide string usando regex como separador
$texto  = "um  dois   três    quatro"; // múltiplos espaços
$partes = preg_split('/\s+/', $texto); // divide por um ou mais espaços
print_r($partes); // ["um", "dois", "três", "quatro"]

Referência rápida de metacaracteres regex

<?php
declare(strict_types=1);

// METACARACTERES ESSENCIAIS
// .   = qualquer caractere (exceto \n)
// \d  = dígito [0-9]
// \D  = não-dígito
// \w  = palavra [a-zA-Z0-9_]
// \W  = não-palavra
// \s  = espaço em branco (espaço, tab, newline)
// \S  = não-espaço

// QUANTIFICADORES
// *   = zero ou mais
// +   = um ou mais
// ?   = zero ou um (opcional)
// {n} = exatamente n vezes
// {n,} = n ou mais vezes
// {n,m} = entre n e m vezes

// ÂNCORAS
// ^   = início da string
// $   = fim da string
// \b  = limite de palavra

// CLASSES DE CARACTERE
// [abc]  = a, b ou c
// [^abc] = qualquer coisa exceto a, b ou c
// [a-z]  = qualquer letra minúscula

// FLAGS (após o delimitador)
// i = case-insensitive
// m = multiline (^ e $ por linha)
// s = . inclui \n
// u = modo Unicode

// Exemplos práticos de validação
$padroes = [
    "cep"      => '/^\d{5}-?\d{3}$/',
    "cpf"      => '/^\d{3}\.\d{3}\.\d{3}-\d{2}$/',
    "telefone" => '/^\(?\d{2}\)?\s?9?\d{4}-?\d{4}$/',
    "url"      => '/^https?:\/\/[\w\-]+(\.[\w\-]+)+/',
    "cor_hex"  => '/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/',
];

$testes = [
    "cep"      => "01310-100",
    "cpf"      => "123.456.789-09",
    "telefone" => "(11) 98765-4321",
    "url"      => "https://php.net",
    "cor_hex"  => "#FF5733",
];

foreach ($padroes as $tipo => $padrao) {
    $valido = preg_match($padrao, $testes[$tipo]) ? "válido" : "inválido";
    echo "$tipo: $valido\n";
}

Segurança com strings

<?php
declare(strict_types=1);

// htmlspecialchars — escapa caracteres HTML
// SEMPRE use ao exibir dados do usuário em HTML
$entrada = '<script>alert("XSS")</script>';
echo htmlspecialchars($entrada, ENT_QUOTES, 'UTF-8');
// &lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;

// htmlspecialchars_decode — inverte a operação
// strip_tags — remove todas as tags HTML
$html   = '<p>Texto <strong>importante</strong></p>';
$limpo  = strip_tags($html);         // "Texto importante"
$comP   = strip_tags($html, '<p>');  // "<p>Texto importante</p>" — permite <p>

// Verificando e convertindo encoding
$utf8 = mb_convert_encoding("Ação", "UTF-8", "ISO-8859-1");

// mb_strlen e mb_substr para strings com acentos
$palavra = "Programação";
echo strlen($palavra);     // pode dar 12 em UTF-8 (bytes, não chars)
echo mb_strlen($palavra);  // 11 — caracteres reais
echo mb_substr($palavra, 0, 7); // "Program"

Boas práticas com strings

Use sempre mb_* para strings com caracteres não-ASCII. Em qualquer aplicação brasileira, mb_strlen, mb_strtolower, mb_substr são obrigatórios. As funções sem mb_ operam em bytes, não em caracteres.

Escape sempre entradas de usuário com htmlspecialchars. Nunca exiba dados de formulário ou banco de dados diretamente no HTML — isso abre vetores de ataque XSS.

Prefira sprintf a concatenações longas. sprintf("Olá, %s! Você tem %d mensagens.", $nome, $total) é muito mais legível do que "Olá, " . $nome . "! Você tem " . $total . " mensagens.".

Use DateTimeImmutable em código novo. Objetos imutáveis são mais seguros do que DateTime mutável — você não corre o risco de modificar acidentalmente uma data compartilhada.

Teste regex em ferramentas online antes de colocar no código. Sites como regex101.com permitem testar padrões com visualização em tempo real, o que economiza muito tempo de debugging.


Resumo

Função / Recurso O que faz
mb_strlen() / mb_substr() Tamanho e extração com suporte Unicode
trim() / ltrim() / rtrim() Remove espaços (ou chars) das bordas
str_replace() Substituição simples de string
explode() / implode() Divide string em array / une array em string
sprintf() Formata string com placeholders tipados
number_format() Formata número para exibição
date() / DateTime Formata datas — prefira DateTime em código novo
DateTimeImmutable Datas imutáveis — prefira em código funcional
strtotime() Converte string para timestamp
preg_match() Verifica padrão e captura grupos
preg_match_all() Encontra todas as ocorrências
preg_replace() Substitui com regex
htmlspecialchars() Escapa HTML — obrigatório ao exibir entradas

Referências e leituras para aprofundar

Comentários

Mais em PHP

Exceções Avançadas
Exceções Avançadas

Tratamento de erros &eacute; onde c&oacute;digo bom se separa de c&oacute;dig...

Estruturas de Controle
Estruturas de Controle

Um programa que executa sempre as mesmas instru&ccedil;&otilde;es na mesma or...

Orientação a Objetos: Fundamentos
Orientação a Objetos: Fundamentos

Orienta&ccedil;&atilde;o a Objetos &eacute; o paradigma que organiza o c&oacu...