PDO ma swoje minusy (wydaje mi się, że nie ma wszystkich typowych dla MySQL opcji).
Ale może niedobrze uczyć się kododawania MySQL-specific? Heh, w takim układzie, w ogóle czemu PHP, są inne języki, nie będę pokazywał palcem...
Ale używanie MySQL bez MySQLi ? Bezcelowe.
MySQLi ma swoje ograniczenia, i owszem, ale jeśli już coś rozszerzać, to właśnie MySQLi aż się prosi o rozszerzenie. Oczywiście bez sensu dopisywać do niego już istniejącą funkcjonalność, ale są ciekawsze sposoby rozszerzania. Mój lib na przykład implementuje interfejs Countable i Iterator, co pozwala na całkiem przyjemne posługiwanie się zapytaniami w kodzie:
foreach (db::$cc->query('select * from my_table') as $n => $record) { ... }
Ale do takiego skrótu potrzebna jest opcja, w jakiej postaci mają być zwracane rzędy wyniku, u mnie defaultowo zwraca jako obiekty, ale można przełączyć na coś innego.
Co do zabezpieczania, to oczywiście mysqli::real_escape_string(). Podobno prawidłowe działanie tej funkcji wymaga ustawienia locale:
@setlocale('LC_ALL', 'pl_PL.UTF-8');
Jeśli oczywiście używasz UTF-8. Jeśli czegoś innego, ustawiasz na coś innego.
Żeby nie musieć PAMIĘTAĆ o escapowaniu każdego stringa zapodawanego do zapytania, w kodzie inicjującym swoją aplikację zrobiłem escapowanie tablic $_GET, $_POST i $_REQUEST. Tak na wszelki wypadek. Działa. Po włączeniu tego injecty do bazy już mi nie przechodziły

O co jeszcze rozszerzam MySQLi? Na przykład poprawiam buga w odczycie wartości pól bitowych. Jeśli sprawdzisz je na true albo false to się zdziwisz. Nie zawierają nawet 0 ani 1. Próba "podglądnięcia" co takiego zwraca php dla takich pól zwróci dziwne rzeczy. A tak na prawdę to chr(0) i chr(1). "Bez sęsu", prawda?

Co jeszcze się przydaje? Lepsza obsługa wartości typu set i enum, funkcje kopiowania i przenoszenia tabel, tworzenia widoków, importowania i eksportowania danych... Ale nie będę wklejał kodu, toż to sama przyjemność sobie to napisać

A co do tematu zabezpieczania, niech Ci tylko do głowy nie strzeli sprawdzać każdego zapytania przed wysłaniem! TO JEST ZŁE, bo po co sprawdzać coś za każdym wywołaniem funkcji, co może być sprawdzone JEDNORAZOWO, przy uruchomieniu.