Prawidłowa odpowiedź to mysqli_set_charset(), bo właśnie ta funkcja ustawia zestaw znaków (charset) dla połączenia z bazą danych w rozszerzeniu mysqli. W praktyce oznacza to, że dzięki niej PHP i serwer bazy danych (np. MySQL) „dogadują się”, w jakim kodowaniu mają być przesyłane i zapisywane teksty – w tym polskie znaki typu ą, ę, ł, ś itd. Bez poprawnie ustawionego charsetu bardzo łatwo o krzaczki, znaki zapytania zamiast liter albo problemy z sortowaniem tekstu. Moim zdaniem dobrą praktyką jest zawsze po nawiązaniu połączenia mysqli_connect natychmiast wywołać mysqli_set_charset($conn, 'utf8mb4'). Ten konkretny charset (utf8mb4) jest obecnie standardem de facto: obsługuje pełne Unicode, w tym emotikony, różne alfabety, a przy okazji bez problemu radzi sobie z polskimi znakami. Przykładowy, poprawny fragment kodu może wyglądać tak: $conn = mysqli_connect('localhost', 'user', 'haslo', 'baza'); mysqli_set_charset($conn, 'utf8mb4'); Dzięki temu każda instrukcja mysqli_query, każde pobieranie danych mysqli_fetch_assoc będzie już działać w odpowiednim kodowaniu. Warto pamiętać, że ustawienie charsetu powinno być spójne na wszystkich poziomach: konfiguracja bazy (collation i charset tabel), ustawienia połączenia (właśnie mysqli_set_charset) oraz nagłówki HTTP/HTML (meta charset="utf-8"). Dopiero takie podejście zgodne z dobrymi praktykami branżowymi zmniejsza ryzyko błędów związanych z kodowaniem tekstu, zwłaszcza w większych aplikacjach webowych. Jeśli robi się projekty komercyjne, to ignorowanie tej funkcji bardzo szybko mści się przy migracjach danych czy integracjach z innymi systemami.
W tym pytaniu łatwo się pomylić, bo wszystkie podane funkcje należą do rozszerzenia mysqli i często pojawiają się obok siebie w kodzie. Kluczowe jest jednak zrozumienie, która z nich faktycznie odpowiada za ustawienie kodowania znaków, a które służą do zupełnie innych zadań. W praktyce większość problemów z polskimi znakami wynika z braku świadomości, że samo połączenie z bazą to za mało – trzeba jeszcze jasno powiedzieć, w jakim zestawie znaków ma odbywać się komunikacja. Funkcja mysqli_query() służy wyłącznie do wykonywania zapytań SQL na już istniejącym połączeniu. Można przez nią wysłać SELECT, INSERT, UPDATE, a nawet ręcznie wykonać polecenie typu SET NAMES, ale to jest obejście, a nie dobra praktyka. W nowoczesnym kodzie właśnie mysqli_set_charset() jest rekomendowaną metodą ustawiania kodowania, a używanie do tego zwykłego zapytania SQL jest uznawane za rozwiązanie przestarzałe i bardziej podatne na błędy konfiguracyjne. Z kolei mysqli_connect() tworzy samo połączenie z serwerem bazy danych. Ona nie ustawia domyślnie właściwego kodowania dla aplikacji – to, jakie będzie kodowanie po połączeniu, zależy od konfiguracji serwera MySQL i może się różnić między środowiskami (lokalnie coś działa, na serwerze produkcyjnym już nie). Typowy błąd początkujących polega na założeniu, że skoro połączenie działa, to problem kodowania „sam się ogarnie”. Niestety nie, bez jawnego mysqli_set_charset() często kończy się to krzaczkami. Natomiast mysqli_fetch_assoc() odpowiada tylko za pobieranie kolejnych wierszy wyniku zapytania w postaci tablicy asocjacyjnej. Ona nie ma żadnego wpływu na to, w jakim kodowaniu dane zostały przysłane z serwera. Jeśli połączenie działa w złym charsetcie, to mysqli_fetch_assoc() po prostu zwróci już zepsute ciągi znaków. Próby „naprawiania” tego na tym etapie zwykle prowadzą do jeszcze większego chaosu. Typowy błąd myślowy przy tym pytaniu polega na mieszaniu pojęć: skoro funkcja jest związana z zapytaniami lub z pobieraniem danych, to część osób intuicyjnie wiąże ją też z kodowaniem. W rzeczywistości kwestia charsetu jest konfiguracją połączenia z bazą, a nie pojedynczego zapytania czy sposobu pobierania wyników. Właśnie dlatego jedyną poprawną odpowiedzią w tym zestawie jest mysqli_set_charset(), bo to ona wprost i formalnie ustawia zestaw znaków dla danego połączenia zgodnie z dobrymi praktykami programowania w PHP.