Takie Same Oddzielne Serwisy

Witam. Mój współpracownik chce, by serwis był dla wielu krajów i żeby każdy był osobny tj. dla każdego osobna baza. Poza tym kod będzie taki sam.

1.Czy najlepszym rozwiązaniem jest skopiowanie ileś razy folderu z aplikacją i dla każdego w configu zmienienie języka?

Dodatkowo czas jest brany z serwera i przez to nie zgodny z lokalnym czasem użytkownika. Rozwiązaniem dla PHP jest ustawienie w configu ‘timeZone’ i wtedy time() zwraca czas zgodny ze strefą, ale zostaje MySQL.

2.Teraz mam poprawiać każde zapytanie na stronie w którym jest NOW() albo CURRENT_TIMESTAMP, czy może jest sposób by dla danej strefy Yii je podmieniał?

Moim zdaniem powinien być jeden folder z kodem aplikacji i tylko różna konfiguracja zależnie od wybranego kraju (różne połączenia, różny język). Mam takie rozwiązanie w moim demku, źródła na Githubie.

Czas powinien być przechowywany w aplikacji zawsze bezwzględnie, czyli w UTC (bez offsetu). Powinien być formatowany przy wyświetlaniu zależnie od strefy czasowej użytkownika.

Nie polecam też stosowania funkcji date() i time() tylko klasy DateTime wbudowanej w PHP.

Jak mogłem na to nie wpaść że, może być to jedna aplikacja i różne połączenia do bazy… Naprawdę dużo to ułatwia sprawę przyszłych modyfikacji serwisu.

Czyli że wszędzie przy zapisywaniu czasu używam:


$time = new DateTime('NOW', new DateTimeZone('UTC'));

,a do formatowania i offsetu przy wyświetlaniu:


$time = new DateTime($model->time, new DateTimeZone('Europe/Warsaw');

?

P.s Jak z obiektu DateTime wypisać czas? $object[‘date’] nie działa, a nie potrafię odnaleźć się w dokumentacji.

DateTime.format()

Ok dzięki. Teraz została jeszcze jedna kwestia: skąd brać strefę czasową usera i gdzie ją przechowywać? Lokalizacja przez IP nie jest zawsze prawidłowa, więc trzeba ustalać strefę na podstawie tego co poda użytkownik. Tylko czy lepiej zrobić dropdownlist na stronie i zapisywać wartość w ciasteczku czy może jednak przy rejestracji dać możliwość wyboru kraju i na podstawie jego pobierać strefę z bazy?

Ja bym to zrobił jawnie, przy rejestracji, i zapisał na stałe, z możliwością zmiany później.

W kodzie mam dość dużo wyrażenia ‘NOW()’. Zamiast bindować to:


$time = new DateTime('NOW', new DateTimeZone('UTC'));

lepiej dać po prostu w zapytaniu ‘UTC_TIMESTAMP()’ ?

I czy mógłbyś mi powiedzieć gdzie trzymać informacje o strefie po pobraniu jej z bazy? Cookies czy może jakoś da się załadować to do configa?

Pobierz z bazy i trzymaj w sesji lub w $this->user jeśli masz to zapisane w tabeli użytkowników.

Jeżeli nie chcesz tworzyć tysiąca baz danych, tylko jedną, to możesz skorzystać z opcji prefiksów do nazw tabel w modelu ActiveRecord. Załóżmy, że masz tabelę, w której chcesz przechowywać użytkowników. Wtedy definiujesz w modelu tabeli nazwę jako {{user}} a prefiks ustalasz w zależności od języka i tak, np. dla Polski będziesz miał tabelę pl_user, dla Niemiec {{de_user}} i tak dalej a tylko 1 model do obsługi i łatwiejsze zarządzanie bazami

Dobry trik z tymi prefiksami, chociaż jeśli niektóre tabele byłyby wspólne dla wszystkich języków to może dodawać taki prefiks wg. bieżącego języka aplikacji w metodzie tableName() w modelach.

Dobry pomysł z prefiksami, tylko że na jednym modelu tego nie zrobię, gdyż użytkownicy z zagranicy będą musieli podać inne informacje przy rejestracji(np. nie mają PESEL’u).

Jest pewna rozbieżność pomiędzy UTC_TIMESTAMP, a klasą z php DateTime ktora wynosi około 1,5minuty. Wszystko stoi na jednym serwerze, ale i tak jedno i drugie zwraca czas od tego 1970 roku więc powinno się zgadzać, a tak nie jest. Czy jest jakiś sposób, aby to ujednolicić?

Po to ktos wymyslil cos takiego jak http://www.yiiframework.com/doc/api/1.1/CModel/#scenario-detail

No dobra ale jak załatwić kwestię rozbieżności UTC_TIMESTAMP i klasy DateTime? Bo tak to było by dużo roboty żeby wszędzie bindować czas z php. A i jak odczytać czas mając sam offset?

Wycinek z man 8 hwclock:

Być może baza i PHP używają dwóch różnych zegarów. Tak czy inaczej, polecam używać ntp do synchronizacji zegara w systemie.

Co do drugiego pytania to chodzi o to jak sformatować czas UTC z użyciem offsetu czyli strefy czasowej?

Podpowiem jeszcze, że w Yii mamy CTimestampBehavior, który zautomatyzuje Ci wstawianie dat do bazy. W szczególności przyjrzyj się timestampExpression

Tak, o to chodziło. Próbowałem używać timezone_name_from_abbr(), ale dla UTC i offsetu 3, nie wiadomo czemu dawało 4 godziny przesunięcia, a dla offsetu 2 - 2 godziny czyli tutaj prawidłowo.

Do configa do bazy dodałem taką linijkę:


'initSQLs'=>array("set time_zone='+00:00';")

a do komponentu Controller dodałem funkcję:


public function getTime($time, $timeZone='UTC', $pattern='Y-m-d H:i:s')

        {

            $czas = new DateTime($time, new DateTimeZone($timeZone));

            return $czas->format($pattern);

        }

Nie wiem czy akurat w tym pliku to umiescić, ale przynajmniej już nie musze w kodzie zmieniać żadnych zapytań i przerabiać wyrażeń NOW(). Wszystkie godziny działają poprawnie ze strefą, a jedynym mankamentem jest to że w bazie czasy nie są zapisane w formacie utc, lecz serwerowym. Mam dostęp do plików phpmyadmina, więc może dało by się to dopieścić?