wtorek, 16 września 2014

PHP: czy wielkość liter ma znaczenie?

Kolega zadał mi "rekrutacyjne" pytanie z języka PHP. Jako osoba pracująca w tym języku od lat powinienem się w nim orientować na tyle, by odpowiedzieć bez pudła. Pytanie brzmi:
Czy PHP jest case-sensitive?
I wiecie co? Odpowiedź wcale nie jest taka prosta jak mi się dotąd zdawało. Choć swoją rzuciłem bez zastanowienia, a z odpowiedzią czułem chęć kłucić się od razu, zainspirowało mnie to do wykonania serii eksperymentów.

Odpowiedź kolegi brzmi:
Zależy od systemu operacyjnego.

Ciężko mi się z tym osobiście zgodzić. Trudno mi sobie wyobrazić, aby było to w pełni zależne od systemu operacyjnego. Rozumiem kwestie dostępu do plików, ale tworzenie przestrzeni nazw nie powinno być z tym w żaden sposób powiązane.

Zanim przeprowadziłem kilka sprawdzeń, sam stwierdziłem:
Dla elementów zdefiniowanych przez użytkownika jest.

Po kilku sprawdzeniach jestem chętny stwierdzić, że byłem bliższy poprawnej odpowiedzi, ale również przesadziłem. Wygląda na to, że niezależnie od systemu PHP zwraca uwagę na wielkość liter tylko w nazwach zmiennych. Poniżej przykład:
$foo = 'bar';
$Foo = 'Bar';
var_dump($foo)
var_dump($Foo)
Wynikiem powyższego jest:
string 'bar' (length=3)
string 'Bar' (length=3)
Ten banalny test wykonałem zarówno na Windows jak i Linux. W obu przypadkach wynik był identyczny. Pewnie dla zwiększenia wiarygodności powinienem wykonać 40 sprawdzeń na różnych systemach, serwerach i wersjach PHP, ale jestem na to co nieco za leniwy.

W przypadku innych elementów języka, moje testy wykazały, że wielkość liter nie ma żadnego znaczenia. Wielkość liter nie ma żadnego znaczenia w nazwach klas. Przykładowo kod:
class TestClass {
 private $foo = 'bar';
}

class testClass {
  private $foo = 'baz';
}

$fooObj = new TestClass();
var_dump($fooObj);
Powoduje fatalny błąd:
Fatal error: Cannot redeclare class testClass
Dla klas zalecane jest, aby zachowywać pierwotną formę nazwy. Powodem jest stosowanie automatycznego ładowania klas w wielu aplikacjach, które może być wyczulone na wielkość liter w nazwie klasy, czy interfejsu. Dla pewności przeprowadziłem jeszcze test dla interfejsu i uzyskałem taki sam wynik. Z resztą PHP interfejsy traktuje jako klasy, więc czegóż innego ja się spodziewałem?

W przypadku funkcji wbudowanych PHP nie interesuje się wielkością liter. Jest całkowicie nieczułe na tym punkcie. Poniższy kod:
$foo = 'BaR';
$bar = StrToLower($foo);
var_dump($foo, $bar);
Generuje wynik:
string 'BaR' (length=3)
string 'bar' (length=3)
choć ja spodziewałbym się raczej:
Fatal error: Call to undefined function StrToLower()
A jak się zachowa PHP dla klas wbudowanych? Zacząłem się już całkiem przyzwyczajać do jego ignorancji, więc nie zdziwiło mnie, że wywołanie:
$foo = new DateTime();
$bar = new datetime();

var_dump($foo, $bar);
Nie powoduje błędu, ale zwraca:
object(DateTime)[1]
  public 'date' => string '2014-09-16 19:17:11' (length=19)
  public 'timezone_type' => int 3
  public 'timezone' => string 'UTC' (length=3)
object(DateTime)[2]
  public 'date' => string '2014-09-16 19:17:11' (length=19)
  public 'timezone_type' => int 3
  public 'timezone' => string 'UTC' (length=3)
PHP wykazuje się również brakiem czułości przy wywołaniu metod z wbudowanych klas. Przykładowo kod:
$foo = new DateTime();
$bar = $foo->getTimestamp();
$baz = $foo->gettimestamp();

var_dump($bar, $baz);
również nie generuje żadnego błędu, ale zwraca:
int 1410895210
int 1410895210
Na koniec pozwólmy sobie jeszcze raz na bardziej złożony test. Pierwotnie uważałem, że PHP jest case-sensitive dla wszystkich elementów zdefiniowanych przez programistę. Spróbujmy więc zadeklarować dwie metody o zbliżonych nazwach w jednej klasie:
class TestClass {
  public function testMethod() {
    return $foo;
  }

  public function Testmethod() {
    return $bar;
  }

  private $foo = 'foo';
  private $bar = 'bar'
}

$fooObj = new TestClass();
var_dump($fooObj);
Wywołanie tego skryptu kończy się fatalnym błędem:
Fatal error: Cannot redeclare TestClass::Testmethod()
Po wcześniejszych sprawdzeniach nie byłem już tym w ogóle zaskoczony.

Wnioski

Niezależnie od systemu operacyjnego PHP nie jest case-sensitive, czyli jest case-insensitive. Jedyne odstępstwo od reguły to zmienne. W tym przypadku nie ma znaczenia, czy są to zmienne lokalne, globalne, pola czy pola statyczne. Dla mnie to niewiele zmienia. Dalej będę zwracał uwagę na wielkość liter pisząc w PHP, ale tak jakby troszeczkę się zawiodłem. W pewnym okresie języki case-sensitive uważałem za znacznie wyżej rozwinięte.

Brak komentarzy:

Prześlij komentarz