Przejdź do treści

Przyjazne adresy URL — generowanie slugów

  • Przydatne narzędzia
  • poziom: początkujący
  • aktualizacja: 12 lipca 2026

Adres /artykul/zolta-lodz-podwodna wygląda lepiej i pozycjonuje się lepiej niż /artykul.php?id=147. Sercem takich adresów jest slug — uproszczona wersja tytułu. Ta funkcja poprawnie zamienia wszystkie polskie znaki diakrytyczne i radzi sobie także ze znakami z innych języków.

PHP 74 linii Pobierz .php
<?php
/**
 * Generowanie slugów (przyjaznych adresów URL) — skryptyPHP.com
 * Zapisz jako: slug.php i dołączaj przez require 'slug.php';
 */

/**
 * Zamienia tekst na slug: małe litery, bez polskich znaków,
 * spacje i znaki specjalne na myślniki.
 *
 *   utworz_slug('Żółta łódź podwodna!')  ->  'zolta-lodz-podwodna'
 */
function utworz_slug(string $tekst): string
{
    // Małe litery (mb_strtolower poprawnie obsługuje Ż -> ż itd.)
    $tekst = mb_strtolower(trim($tekst), 'UTF-8');

    // Polskie znaki diakrytyczne
    $polskie = [
        'ą' => 'a', 'ć' => 'c', 'ę' => 'e', 'ł' => 'l', 'ń' => 'n',
        'ó' => 'o', 'ś' => 's', 'ź' => 'z', 'ż' => 'z',
    ];
    $tekst = strtr($tekst, $polskie);

    // Znaki diakrytyczne z innych języków (é, ü, č...) — jeśli dostępne iconv
    if (function_exists('iconv')) {
        $przetworzony = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $tekst);
        if ($przetworzony !== false) {
            $tekst = $przetworzony;
        }
    }

    // Wszystko, co nie jest literą a-z ani cyfrą, zamieniamy na myślnik
    $tekst = preg_replace('~[^a-z0-9]+~', '-', $tekst);

    // Myślniki z początku i końca precz
    $tekst = trim($tekst, '-');

    return $tekst !== '' ? $tekst : 'wpis';
}

/**
 * Zapewnia unikalność sluga w ramach istniejącej listy:
 * gdy 'moj-artykul' zajęty, zwróci 'moj-artykul-2', potem '-3' itd.
 *
 * @param string[] $istniejace lista zajętych slugów (np. z bazy danych)
 */
function unikalny_slug(string $slug, array $istniejace): string
{
    if (!in_array($slug, $istniejace, true)) {
        return $slug;
    }
    $numer = 2;
    while (in_array($slug . '-' . $numer, $istniejace, true)) {
        $numer++;
    }
    return $slug . '-' . $numer;
}

// ── PRZYKŁADY ───────────────────────────────────────────────
echo utworz_slug('Żółta łódź podwodna!');            // zolta-lodz-podwodna
echo "\n";
echo utworz_slug('  PHP 8.4 — co nowego?  ');        // php-8-4-co-nowego
echo "\n";
echo utworz_slug('Crème brûlée & spółka');           // creme-brulee-spolka
echo "\n";

// Unikalność względem slugów zajętych w bazie:
$zajete = ['moj-artykul', 'moj-artykul-2'];
echo unikalny_slug('moj-artykul', $zajete);          // moj-artykul-3

// Z bazą danych (przykład):
// $zajete = $pdo->query('SELECT slug FROM artykuly')->fetchAll(PDO::FETCH_COLUMN);
// $slug   = unikalny_slug(utworz_slug($tytul), $zajete);

Jak użyć tego skryptu

  1. Skopiuj obie funkcje do projektu i wywołuj utworz_slug($tytul) przy zapisywaniu artykułu/produktu.
  2. Slug zapisz w bazie w osobnej kolumnie z indeksem UNIQUE i używaj go w adresach zamiast ID.
  3. Przed zapisem przepuść slug przez unikalny_slug() z listą slugów już istniejących w bazie.
  4. Ładne adresy w stylu /artykul/moj-slug/ włączysz regułą mod_rewrite: RewriteRule ^artykul/([a-z0-9-]+)/?$ artykul.php?slug=$1 [L].

Warto wiedzieć

  • Mapę polskich znaków stosujemy zawsze, a iconv jest tylko uzupełnieniem dla obcych znaków — na niektórych serwerach transliteracja iconv zależy od ustawień systemowych, więc nie można na niej polegać w kwestii polskich liter.
  • Slug raz opublikowanego artykułu lepiej zostawić w spokoju — zmiana adresu psuje linki z innych stron. Jeśli musisz zmienić, ustaw przekierowanie 301 ze starego adresu.
  • Wyszukiwanie po slugu w bazie rób tak samo jak po każdej innej wartości: zapytaniem przygotowanym.
#slug #url #seo #mod_rewrite #polskie znaki

Podobne skrypty