Praca w kilku środowiskach
Pracując nad aplikacją w środowisku PHP (choć dotyczy to także innych środowisk server-side), nieraz skrypty tworzymy na lokalnym serwerze, po czym gotowe i przetestowane skrypty kopiujemy na docelowy serwer. Nie sposób uniknąć przy tym konieczności zmiany niektórych parametrów (np. login i hasło do bazy danych, ścieżek do plików). Jak pozbyć się kłopotliwego obowiązku zmiany fragmentów kodu przed skopiowaniem na serwer?
Podstawowa zasada, to wartości różne dla obu środowisk, zapisywać w zmiennych w jednym pliku (np. settings.inc.php). Taki plik - różny na obu serwerach (testowym i produkcyjnym) - można include()’ować i spokojnie używać zdefiniowanych zmiennych.
Innym, prawdopodobnie bezpieczniejszym sposobem, jest definiowanie stałych zawierających odpowiednie parametry, np:
< ?php
define('_MYSQL_SERVER', 'localhost');
define('_MYSQL_USER', 'ecome');
define('_MYSQL_PASSWD', '1234');
$rDB = @mysql_connect(_MYSQL_SERVER, _MYSQL_USER, _MYSQL_PASSWD) or die('db1cf');
?>
Dzięki temu unikniemy niebezpieczeństwa nadpisania zmiennych przez źle skonfigurowane php zmiennymi z tablic $_GET, $_POST lub $_COOKIE. Co więcej, takie wartości są globalne, nie musimy więc przejmować się zasięgiem zmiennych.
Co jednak zrobić, gdy w zależności od serwera należy wykonać - bądź nie - całe fragmenty kodu?
Tutaj także z pomocą przychodzi nam mechanizm definiowania stałych. Rozwiązanie z którego korzystam polega na zdefiniowaniu w środowisku testowym stałej __THIS_DEVELOP_MODE. Następnie, w kodzie stosuję instrukcję warunkową:
< ?php
define('__THIS_DEVELOP_MODE', true);
if(defined('__THIS_DEVELOP_MODE')){
$rDB = mysql_connect(_MYSQL_SERVER, _MYSQL_USER, _MYSQL_PASSWD);
}else{
if($rDB = @mysql_connect(_MYSQL_SERVER, _MYSQL_USER, _MYSQL_PASSWD)){
//połączenie udane...
}else{
//połączenie nieudane
header('Location: http://www.example.com/blad.htm');
die();
}
}
?>
W przypadku, gdy stała __THIS_DEVELOP_MODE jest zdefiniowana, to wykonana zostanie tylko instrukcja łączenia z serwerem MySql. Jej niepowodzenie spowoduje wyświetlenie błędu (zależnie od konfiguracji serwera). W środowisku testowym jest to jak najbardziej pożądane.
W przypadku, gdy stała nie jest zdefiniowana, wykonana zostanie część kodu zawarta w bloku else. Ważne jest istnienie drugiej instrukcji warunkowej która sprawdza, czy połączenie zostało pomyślnie ustanowione.
Warto zwrócić uwagę na trzy rzeczy:
- przed instrukcją mysql_connect() umieściłem operator @ który zapobiegnie wyświetlaniu błędu
- po wystąpieniu błędu użytkownik zostaje przekierowany na inną stronę
- po instrukcji header() następuje instrukcja die()
Ad 1: Jest to dobry zwyczaj gdyż ujawnianie użytkownikom informacji o błędach może także ujawnić szczegóły pracy systemu (tu: adres serwera MySql i/lub login). W przypadku błędu zapytania sql, może zostać ujawniona np. struktura bazy danych.
Ad2: Po wystąpieniu błędu najlepiej jest przerwać działanie skryptu.
Ad3: Należy pamiętać, że instrukcja header() nie przerywa działania skryptu. Jeżeli więc chcemy natychmiast przekierować użytkownika na stronę z informacją o błędzie, należy użyć także instrukcji die()