Artykuły jmail's software

[PHP] Dane aplikacji [en] Application data in PHP

by on sty.29, 2010, under PHP / CF / .NET / Java

Wszyscy, którzy mieli do czynienia z ColdFusion albo z ASP.NET wiedzą co to są dane aplikacyjne, albo jak miłe one są w użyciu. Ustawienie jednej zmiennej powoduje, że każdy użytkownik widzi ją w taki sam sposób. Wszyscy użytkownicy współdzielą dane w jeden identyczny sposób. Jeżeli użytkownik X ustawi zmienną aplikacyjną na 1 wtedy wszyscy użytkownicy widzą ją jako 1. W tym artykule zajmiemy się wykonaniem pseudo takiego rozwiązania w PHP.

Na początku należy się parę słów wyjaśnienia po co nam.

1. Łatwa komunikacja z wszystkimi klientami
2. Nie chcemy utrzymywać wszystkiego w bazie danych
3. Wstawianie w zmienne sesyjne zabiera więcej miejsca na dysku a pamięci operacyjnej jakby tyle samo ubywa
4. Niekoniecznie musimy chcieć, żeby dane aplikacyjne były zapisywane na komputerze klienta. Na przykład jako dana aplikacyjna może być użyty numer licencji jaką wystawiliśmy klientowi. Oczywiście można ją zdefiniować jako stałą w aplikacji, czasami jednak chcielibyśmy zmienić taką zmienną. Jak to zrobić? Stałą jest ciężko ponownie zdefiniować.



Jakie warunki musi spełnić rozwiązanie.

1. Łatwy dostęp skryptu do zmiennych
2. Łatwy do zmiennych w skrypcie na przykład z klas.
3. Samozapisujące się (bez naszego udziału najlepiej)
4. Możliwość zrzucenia danych w dowolnym miejscu naszego skryptu.



A więc do dzieła!

1. Łatwy dostęp skryptu do zmiennych

Na początek trzeba zdać sobie sprawę, ze rozwiązanie musi działać na dowolnym serwerze. Nie możemy go więc uzależnić od żadnej bazy danych. Oczywiście baza danych może przechowywać nasze zmienne, ale nic nie będzie tak proste jak zapis danych do pliku. Więc zapiszemy nasze dane w pliku textowym. Nazwiemy go application.data

2. Łatwy do zmiennych w skrypcie na przykład z klas.

Z moich badań nad takim rozwiązaniem wyszło niestety, że w PHP nie ma możliwości utworzenia własnych zmiennych superglobalnych takich jak $_SESSION czy $_POST, które wszędzie byłyby widoczne. Na szczęście PHP przynosi nam coś innego co się bardzo przydaje. Zmienna $_SESSION jest zrzucana do pliku i odtwarzana kiedy następuje do niej ponowne odwołanie. Dlatego jest to problem – po co nam to zapisane w 100.000 plików jeżeli tylu ludzi wejdzie na stronę?

Jest jedna zmienna superglabalna, która jest napełniana przy starcie skryptu i zwalniana przy jego zakończeniu to zmienna $_ENV dlatego właśnie z niej skorzystamy.

3. Samozapisujące się (bez naszego udziału najlepiej)

Istnieje możliwość wywoływania dynamicznych funkcji. W dalszej części pokażę jak tego dokonać.

4. Możliwość zrzucenia danych w dowolnym miejscu naszego skryptu.

Punkt 3 i 4 są powiązane ze sobą dlatego zostaną omówione w jednym miejscu.

Zacznijmy od przygotowania sobie środowiska.

Jeżeli Twój serwer daje Ci możliwość ustawienia zmiennych w pliku .htaccess ustaw to w prosty sposób

1
2
php_value auto_prepend_file appStart.php
php_value auto_append_file appEnd.php

W pliku appStart.php zawrzemy wszystko co niezbędne do działania rozwiązania, natomiast w pliku appEnd.php zawrzemy jedynie zapis zmiennych aplikacyjnych.

Jeżeli Twój serwer nie ma możliwości wstawiania dyrektyw php_value w pliku .htaccess musisz zadbać o to, żeby te pliki zostały dołączone na początku i na końcu każdego skryptu.

Ustawiamy sobie dwie zmienne globalne (w php), które nam posłużą do działania.

1
2
define('APP_DATA_FILE', 'some/path/application.data');
define('APP_NAME', 'ApplicationName');

Teraz zainicjujmy naszą przestrzeń aplikacyjną

1
$_ENV[APP_NAME] = array();

Jak widzimy powyżej stała APP_NAME została użyta tylko i wyłącznie w jednym celu. Zainicjowania podtablicy w zmiennej superglobalnej $_ENV. Dzięki temu mamy już wszystko gotowe.

Odczyt danych aplikacyjnych

1
2
3
4
5
6
7
8
9
10
11
12
function application_start(){
    if (!file_exists(APP_DATA_FILE)){
        $AppFileHandler = fopen(APP_DATA_FILE, 'w') or die('I can\'t read application data!');
        fclose($AppFileHandler);
    }
    $file = fopen(APP_DATA_FILE, "r");
    if ($file){
        $data = fread($file, filesize(APP_DATA_FILE));
        fclose($file);
    }
    $_ENV[APP_NAME] = unserialize($data);
}

I po wszystkim. Dane aplikacyjne zostały utworzone. Teraz w dowolnym miejscu skryptu (w klasie, poza nią, gdzie Ci się żywnie podoba), możesz z niej korzystać używając takiego odniesienia

1
$_ENV[APP_NAME]['ApplicationVarName']

Łatwo można poznać przewagę takiego rozwiązania. Załóżmy, że konfiguracja aplikacji jest zapisywana w pliku. Oczywiście standardowo używamy mozolnie podstawiania do tablicy $config i w każdej funkcji musimy na początku dopisywać

1
global $config;

Przy rozwiązaniu powyżej nie musimy juz tego robić. Żadnych zmiennych globalnych do klas nie trzeba przekazywać, gdyż zmienna $_ENV jest superglobalna.

Funkcję application_start wrzucamy do pliku appStart.php dodajemy w tym pliku ustawienie dwóch stałych globalnych (o czym była mowa wyżej) i dodajemy w dowolnym miejscu appStart.php

1
application_start();

Oczywiście najsensowniej byłoby to zrobić za inicjacją zmiennych aplikacyjnych ;)

Pierwsze dwa punkty naszych założeń mamy spełnione. Teraz pora zabrać się za punkt 3 i 4.

Mówiłem wcześniej o dynamicznie wywoływanych funkcjach. Tak to nie problem wywołać funkcję z dynamicznej nazwy. Ale po kolei. Teraz potrzebowalibyśmy funkcję, która nam te dane zapisze.

Nasza funkcja zapisująca dane aplikacyjne, będzie wyglądać tak

1
2
3
4
5
6
$data = serialize($_ENV[APP_NAME]);
$file = fopen(APP_DATA_FILE, "w");
if ($file){
    fwrite($file, $data);
    fclose($file);
}

Dlaczego nie objąłem jej function nazwa_funkcji? Z prostej przyczyny. Chcąc uczynić rozwiązanie bardziej niezależnym zdecydowałem się użyć dynamicznej funkcji, która zapisuje dane gdzie sobie zażyczę.

Teraz w pełni dopisujemy naszę funkcję

1
2
3
4
5
6
$_ENV['application_func'] = create_function('', '$data = serialize($_ENV[APP_NAME]);
    $file = fopen(APP_DATA_FILE, "w");
    if ($file){
        fwrite($file, $data);
        fclose($file);
    }'
);

Mamy utworzoną dynamiczną funkcję. Teraz jeszcze pora coś dodać do naszego pliku appEnd.php . Jak mówiliśmy tam ma być zapisywanie zmiennych do pliku. Proszę bardzo.

1
$_ENV['application_func']();

Zmienne zostały zapisane! Czego więcej chcieć? ;) Koniec z global przy przekazywaniu configów ;)

Jeżeli gdzieś zmienisz dane aplikacyjne najlepiej od razu je zrzucać wywołując funkcję jak pokazałem powyżej.

Życzę miłej pracy wszystkim developerom

:, , ,

3 Comments for this entry

  • kallosz

    hmm… Ciekawe rozwiązanie ;]
    raczej często nie potrzebujemy stosowania zmiennych globalnych ale na przyszłość – kto wie ;]

  • mateusz93k

    Bardzo ciekawy artykuł. Z pewnością po coś się to kiedyś przyda, jednak na razie nie mam pomysłu na zastosowanie tego gdzieś u siebie :)

  • jmail

    najprostsze wykorzystanie.

    Prosta sytuacja. User Ci zgłasza, ze mu się długo wykonywał skrypt. Nie wiesz kiedy nie wiesz dlaczego i tak dalej ;)

    robisz sobie zmienne

    $_ENV[APP_NAME]['script_time']
    $_ENV[APP_NAME]['script_time_when']

    i dostawiasz do zapisu

    1
    2
    3
    4
    5
    if($script_execution_time > $_ENV[APP_NAME]['script_time']){

    $_ENV[APP_NAME]['script_time'] = $script_execution_time;
    $_ENV[APP_NAME]['script_time_when'] = time();
    }

    i już wiesz kiedy i ile najdłużej wykonywał się skrypt. Teraz możesz z logami porównać co w tym czasie jeszcze się działo na serwerze. Jeżeli do bazy byś chciał to zapisywać to:
    a/ miałbyś dużą tabelę w bazie :F
    b/ zużywałbyś niepotrzebne zasoby na połączenie itd.

Leave a Reply

Kalendarz

Styczeń 2010
P W Ś C P S N
« gru   lut »
 123
45678910
11121314151617
18192021222324
25262728293031
Linki sponsorowane:
ethica * katalog * rss * perfumy