PHP jest językiem, którego opanowanie w stopniu podstawowym nie jest trudne, jednakże ma to swoje konsekwencje w tym, że początkujący programiści, często idąc na łatwizne piszą kod, który nie jest najwyższej jakości. Często winą tego są poradniki z czasów kiedy wiądącym trendem było PHP 3-4. Te poradniki mają się ni jak do rzeczywistości programistycznej i PHP 7, które zostanie wypuszczone w tym roku. Według mnie oto najczęstsze błędy programistów:

Używanie funkcji z rodziny mysql_*

większość tutoriali używa funkcji mysql_* w swoich przykładach. Jednakże funkcje te od jakiegoś czasu oznaczone są jako deprecated to oznacza, że zostaną usunięte w kolejnej wersji PHP. Komunikat ze strony manuala php opisującego funkcję mysql_connect()

Warning

This extension was deprecated in PHP 5.5.0, and it was removed in PHP 7.0.0. Instead, the MySQLi or PDO_MySQL extension should be used. See also MySQL: choosing an API guide and related FAQ for more information.

Zgodnie z dokumentacją zamiast mysql_* używaj funkcji z rodziny mysqli lub PDO.

Mylenie funkcji, isset(), empty(), array_key_exists()

Funkcja isset(), sprawdza czy element jest ustawiony w tablicy, tj istnieje i jego wartość nie jest równa null.

Funkcja empty(), sprawdza czy element nie jest pusty. To oznacza, że wartość musi być ustawiona, nie może być nullem oraz nie może być pusta w zależności od typu. Np pusty string to ”, pusta tablica to `[]`, wartość ‚false’ też jest traktowana jako pusta.

Funkcja array_key_exists() sprawdza czy klucz tablicy istnieje, różnica pomiędzy isset() jest taka, że klucz może mieć przypisaną wartość null, a funkcja zwróci true.

Zobacz na poniższy kod

$array = [
    'a' => null,
    'b' => '',
    'c' => 4	
];


echo (int)isset($array['a']);              //false
echo (int)array_key_exists('a', $array);   //true
echo (int)empty($array['a']);              //false


echo (int)isset($array['b']);              //true
echo (int)array_key_exists('b', $array);   //true
echo (int)empty($array['b']);              //true


echo (int)isset($array['c']);              //true
echo (int)array_key_exists('c', $array);   //true
echo (int)empty($array['c']);              //false


echo (int)isset($array['d']);              //false
echo (int)array_key_exists('d', $array);   //false
echo (int)empty($array['d']);              //true
echo (int)empty([]);                       //true

 

Ignorowanie Notice

Notice są to wskazkówki dla programisty, że coś może być nie tak z jego kodem i nie powinny być ignorowane. Najczęstsze notice możemy dostać gdy np odwołujemy się do elementu tablicy, który nie istnieje. Klasycznym przykłądem jest wywołanie skryptu, który obsługuję metode post, bez przekazania danych do tej metody. Dobrą praktyką w takim przypadku jest sprawdzenie, czy żadanie HTTP jest typu POST. Co możemy zrobić za pomocą poniższego kodu

if  ($_SERVER['REQUEST_METHOD'] === 'POST')  {
  //żadanie typu POST
}

Oraz sprawdzenie każdej zmiennej formularza czy istnieje i/lub nie jest pusta za pomocą funkcji isset() oraz empty()

Referencje, a wartości

To bardzo szeroki temat. Należy pamiętać, że w PHP obiekty przekazywane są przez referencje, a typy wbudowane przez wartość. Należy również pamiętać o zasięgu obiektów w PHP.

<?php

$array = [
'a' => 1,
'b' => 2,
'c' => 3	
];

//loop array via reference
foreach($array as &$row) {}
var_dump($array); //array(3) { ["a"]=> int(1) ["b"]=> int(2) ["c"]=> &int(3) }

//loop array via copying 
foreach($array as $row) {}
var_dump($array); //array(3) { ["a"]=> int(1) ["b"]=> int(2) ["c"]=> &int(2) }

 

Powyższy kod wbrew pozorom powinien dwa razy wyświetlić tablicę 1,2,3 jednakże, zwracana druga tablica ma wartości 1, 2, 2. Zwróć uwagę na typ zwracanej wartości, którą nie jest 2 ale jest referencja do int-a wskazującego na element posiadający wartość 2.

Co się dzieje w tym kodzie?

Na początku mamy zwykłą pętle, która nic nie robi oprócz tego, że wartość do pętli jest przekazywana przez referencje. Druga pętla natomiast ma przekazywaną wartość przez kopie.

W drugiej pętli w kolejnych przebiegach dzieją się następujące rzeczy.

$array[‚a’] kopiowana jest wartość do zmiennej $row, która jest referencją do $array[‚c’], po pierwszym przebiegu tablica wygląda następująco: 1,2,1

$array[‚b’] kopiowana jest wartość do zmiennej $row, która teraz jest referncją do $array[‚c’], $array[‚c’] jest równe 2 więc zostaje.  Tablica wygląda następująco 1,2,2

$array[‚c’] kopiowana jest wartość do zmiennej $row, która jest referencją do $array[‚c’]. W tablicy się nic nie zmienia.

Co zrobić, aby temu zapobiec? Wystarczy po użyciu referencji ją zwolnić poprzez użycie funkcji unset() na zmiennej, którą używamy w foreach() { }

Pamiętaj, że gdy w pętli foreach przekazywane są obiekty, nie musimy jawnie używać operatora referencji &, a działanie jest identyczne z powyższym.

Ignorowanie PSR

PSR jest to zbiór standardów obowiązujących programistów PHP. Najważniejsze, rzeczy które pownieneś wiedzieć to

Jeśli używasz edytora wspierającego PSR, przestaw tryb autoformatowania kodu tak abyś w łatwy sposób mógł zreformatować kod i widzieć jakie błędy jeszcze popełniasz. Dzięki PSR patrząc na cudzy kod nie widzimy chaosu, a spójną całość, która jest identyczna pomiędzy frameworkami i pracą programistów. O ile na początku może być Ci ciężko po przyzwyczajeniu się będziesz z automatu pisał kod, który jest poprawnie sformatowany. Tutaj warto wspomnieć również o tym by używać spacji zamiast tabów oraz kodowania plików w UTF-8 o czym wielu programistów zapomina.

Programowanie obiektowe

Wielu programistów używa klas jako ładnego zbioru do statycznych funkcji. Mija się to z celem programowania obiektowego. Jeśli naprawdę chcesz zacząć programować obiektowo, poczytaj o polimorfizmie, wzorcach projektowych, SOLID. Programowanie obiektowe to bardzo szeroki temat, na moim blogu znajdziesz wiele informacji na temat dobrych praktych i wzorców.

Przypisywanie wartości zamiast porówania oraz problemy z ifami

wielu programistów PHP popełnia prosty przypisania w klauzurze if.

<?php

$a = 2;

if ($a = 1) {
  //zmienna $a = 1 przypisanie sie powiodlo wiec jestemy w tym bloku
} else {
   echo $a;
}

na pierwszy rzut oka wszystko jest ok, tyle że zamiast operatora porówniania został wykorzystany operator przypisania, który zwróci wartość 1, a zmienna $a od teraz będzie miała wartość 1. Istnieje prosta metoda by ustrzec  się tego błędu

if (1 = $a)  { 
  //blad
}

 

w tym przypadku dostaniemy błąd natomiast gdy użyjemy

$a = 1;
if (1 == $a)  { 
   //porowanie poprawne
}

wszystko będzie działało tak jak powinno.

Kolejny problem z ifami to operator porówania == a operator identyczności przykłady

echo (int)(1 == 1); //true
echo (int)(1 === 1); //true
echo (int)(1 == '1'); //true
echo (int)(1 === '1'); //false
echo (int)(1 == '1 abc'); // true ponieważ string jest zamieniany na 1
echo (int)(1 == 1.0); //true
echo (int)(1 === 1.0); //false

Używanie operatora ‚==’ może doprowadzić do niespodziewanych sytuacji podczas używania oprogramowania, tak więc warto zwrócić uwagę na typy i rzutowanie niejawne.

Podsumowanie

To tyle jeśli chodzi o początkujące błędy i pułapki języka. Mam nadzieję, że przybliżyłem Ci temat i w jakimś stopniu zobaczyłeś, że rzeczy, które są oczywiste mogą zachowywać się inaczej niż przypuszczasz. Jeśli chcesz bardziej zgłębić temat poczytaj o pierwszeństwie i kolejności wykonywania operatorów gdyż jest to kolejna rzecz, która może Cię zaskoczyć. Powodzenia!