Autor wpisu: thejw23, dodany: 14.10.2009 20:24, tagi: php
Autor wpisu: m1chu, dodany: 13.10.2009 22:23, tagi: css, php
W pewnym stadium zaawansowania wyrażenia regularne stają się potężnym narzędziem każdego programisty PHP (i nie tylko). A to dlatego, że pozwalają na wykonywanie operacji, których często nie sposób dokonać w prosty sposób przy pomocy standardowych funkcji zawartych w tym języku. Walidacja zawartości zmiennych, czy podmienianie specyficznej części ich zawartości - na to pozwalają wyrażenia regularne. 15-ście przykładowych, najbardziej niezbędnych dla każdego web developera, skompletowałem w dalszej części artykułu. Do Waszej dyspozycji oddaję także prosty serwis sprawdzający poprawność wprowadzanych wzorców.
1. Walidacja adresu e-mail opartego na hoście
Wzorzec:
PLAIN TEXT CODE:- /^([a-z0-9]{1})([^\s\t\.@]*)((\.[^\s\t\.@]+)*)@([a-z0-9]{1})((([a-z0-9-]*[-]{2})|([a-z0-9])*|([a-z0-9-]*[-]{1}[a-z0-9]+))*)((\.[a-z0-9](([a-z0-9-]*[-]{2})|([a-z0-9]*)|([a-z0-9-]*[-]{1}[a-z0-9]+))+)*)\.([a-z0-9]{2,6})([.]?)$/Diu
Opis:
Wyrażenie ma za zadanie sprawdzać, czy wprowadzony przez użytkownika adres e-mail ma poprawną formę. Aby test zakończył się sukcesem muszą zostać spełnione następujące warunki:
- nazwa użytkownika musi zaczynać się od znaku litery lub cyfry, nie może zawierać spacji, tabulatorów, aty, za to mogą się znajdować w nim kropki, pod warunkiem, że nie występują jedna, po drugiej,
- po nazwie użytkownika musi pojawiać się znak małpy,
- domena, podobnie jak nazwa użytkownika, musi rozpoczynać się od litery, bądź cyfry, po czym do znaków dozwolonych dochodzą - oraz ., pod warunkiem, że pierwszy z wcześniej wymienionych znaków nie znajduje się na początku lub na końcu nazwy subdomeny (wyjątkiem są dwa myślniki na jej końcu odpowiadające często prefiksom xn--), a drugi nie jest poprzedzany swoim odpowiednikiem. TLD może mieć długość od dwóch do sześciu znaków,
- domena może być zakończona kropką,
- rozwiązanie nie sprawdza jak długi jest wprowadzony adres e-mail.
Strona testowa:
Tekst spełniający warunki:
2.a_a-d@n-do.x-d.pl
Tekst nie spełniający warunków:
2.a_a-d@n-do.x-d.v-.pl (część domeny kończąca się nieprawidłowym znakiem)
Uwagi:
Jeżeli rozwiązanie w jakimkolwiek stopniu zawiedzie można pokusić się o użycie wyrażenia z ostatniej aktualizacji pliku logical_filters.c ze źródeł PHP.
Rozwiązanie oparte o wyrażenie regularne:
PLAIN TEXT PHP:- $email = trim('adres@domena.pl');
- if ( !preg_match('/^([a-z0-9]{1})([^\s\t\.@]*)((\.[^\s\t\.@]+)*)@([a-z0-9]{1})((([a-z0-9-]*[-]{2})|([a-z0-9])*|([a-z0-9-]*[-]{1}[a-z0-9]+))*)((\.[a-z0-9](([a-z0-9-]*[-]{2})|([a-z0-9]*)|([a-z0-9-]*[-]{1}[a-z0-9]+))+)*)\.([a-z0-9]{2,6})([.]?)$/Diu', $email) )
- {
- print 'Nieprawidłowy adres e-mail';
- }
Autor wpisu: cojack, dodany: 09.10.2009 18:11, tagi: php
Od jakiegoś czasu jak sobie przeglądam różne fora, cały czas widzę że ludzie mają problemy z kodowaniem na stronie, a to nie widzą co jest tego przyczyną, a to znowu ustawiają kodowanie w nagłówku html inne niż w pliku, a to do bazy danych podczas połączenia zapominają ustawić kodowania znaków. Jest to trochę smutne a rzecz jest tak prosta, że mógłbym rzec trywialna. Co należy zrobić by tego uniknąć.
Kodowanie w pliku
I tutaj chciałbym Wam wszystkim powiedzieć że iso-8859-2 nie jest standardem kodowania, tak nie jest! Są dwa standardy kodowania pliku, jeden to iso-8859-1 a drugi to mój ulubiony utf-8. O każdym z nich możecie sobie przeczytać na wiki. Jeżeli pracujecie na systemach z rodziny windows, to od razu Wam współczuje, ponieważ słabe edytory plików są ustawione defaultowo na kodowanie windowsowkie czyli cp 1250, co jest bardzo złym podejściem dla programistów, oraz złym nawykiem jeżeli się do tego przyzwyczaimy. Ci którzy pracują na linuxie, mogą sobie darować resztę tego paragrafu ponieważ u nas domyślnie wszystko jest w utf-8 (wyjątkiem od tej reguły jest slackware), ale co tam.
O co chodzi, dajmy na to że używamy notatnika do edycji plików php czy html. W nagłówku head ustawiamy kodowanie strony np dla iso-8859-2, zapisujemy, przeglądamy treść i co? I błędy! Tak Polskie znaki diakrytyczne (mowa o znakach alfabetu z ogonkami) są w postaci tzw. krzaków. Spowodowane jest to tym iż plik jest zapisany w formacie cp 1250 (czyli windowsowskim). Nie pamiętam w tej chwili czy notatnik pozwala nam na zmianę kodowania, ale wydaję mi się że nie, i w cale bym się nie zdziwił gdyby tak było.
Co należy zrobić, otóż sprawa jest prosta, pobrać jakiś edytor tekstu, który pozwala nam na zmianę formatu zapisu pliku, jednym który znam, oraz w pełni darmowym jest Notepad++, pewnie nie jeden z Was już o nim słyszał lub go używa. Nie będę nikogo nakłaniał na żadne z IDE, ponieważ DE ma pomagać a nie przeszkadzać a początkującemu programiście może utrudniać życie. Wracając do Notepad++, ustawiamy w nim kodowanie na UTF-8, ustawiamy w nagłówku dokumentu html charset również na utf-8 i odświeżamy stronę. Proszę jak ładnie wyglądają teraz nasze Polskie literki.
Kodowanie bazy danych
W komentarz pewnie zostanę zlinczowany za to co tutaj napiszę, ale to mój blog i mogę sobie pisać co chce ;] A więc nawiązując do powyższego paragrafu, w dalszym ciągu będę się upierał przy kodowaniu w UTF-8, sprawa ma się tak iż dostępnych mamy b.dużo baz danych, a hostingi przeważnie udostępniają nam jedną w porywach do dwóch typów baz danych są nimi MySQL oraz PostgreSQL. Co do drugiej sprawa ma się krótko, defaultowo kodowanie ustawione na utf-8, sprawa zamknięta, ale że Postgres w naszym kraju jest jakimś małym procentem (nie wiadomo czemu), przejdźmy do MySQL. Przykładowy kod do utworzenia tabeli w bazie danych.
CREATE TABLE `users` ( `id` int(4) NOT NULL AUTO_INCREMENT, `slogin` varchar(128), `shaslo` varchar(32), PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
Jak widać po zamknięciu definicji kolumn w tabeli, mamy ustawiony typ tabeli na InnoDB oraz ustawiony domyślny typ zapisu danych do bazy na kodowanie utf-8, i na samym końcu o ile ma być zwiększany id przy nowym rekordzie.
Gdybyśmy się pozbyli wpisu dotyczącego CHARSET, najprawdopodobniej domyślnym kodowaniem zostałby iso-1, tak 1 nie 2. A my gupie polaczki jedziemy ostrona na 2 jakby to było spełnieniem naszych marzeń. NIE! I jeszcze raz nie! Tak jak pisałem wyżej Standardami są iso-1 oraz utf-8.
Następnym krokiem jest ustawienie typu kodowania podczas połączenia się z bazą danych, zróbmy tak:
$link = mysql_connect('host', 'user', 'password'); $charset = mysql_client_encoding($link); if ( $charset != 'utf8' ) { mysql_set_charset('utf8',$link); }
Co tutaj robimy, łączymy się z bazą danych w najprostszy z możliwych sposobów, pobieramy kodowanie bazy danych, jeżeli jest inne niż utf8, ustawiamy je na właśnie ten typ kodowania. Wymagania co do komendy mysql_set_charset, manual przedstawia nam: mysql >= 5.0.7, oraz jednoznacznie jest napisane że SET NAMES nie powinno się wykonywać poprzez mysql_query, przykład:
$result = mysql_query("set names 'utf8'";);
Dobrym też nawykiem, bynajmniej dla mnie jest też stosowanie htmlspecialchars (oczywiście z utf-8 i ENT_QUOTES) przy zapisie danych do bazy, powoduje to konwersję znaków na encje, przy czym kodowanie tego typu znaków nie powinno się burzyć. Kolejnym dobrym nawykiem podczas walidacji danych z formularza powinno być z Waszej strony sprawdzanie typu kodowania znaków przesyłanych przez formularz do Waszego skryptu, poprzez mb_check_encoding, używamy:
Autor wpisu: thejw23, dodany: 30.09.2009 19:02, tagi: framework, php
Autor wpisu: Vokiel, dodany: 28.09.2009 10:56, tagi: php
Ostatnia część tworzenia projektu loggera zdarzeń – klasy Log. Skupimy się na wykończeniu projektu, który naprawi powstałe wcześniej niedociągnięcia, trudności w korzystaniu. Utworzona klasa połączy nam wszystkie funkcjonalności w jedno. Doda kilka funkcjonalności, wprowadzi wygodę w użytkowaniu, łatwość zmian. W pierwszej części ustaliliśmy wymagania klasy Log, ustaliliśmy strukturę, zasady funkcjonowania klasy oraz napisaliśmy interfejs. W drugiej części rozwinęliśmy nasz projekt o klasę logFile implementującą wcześniej utworzony interfejs, omówiliśmy możliwość rozszerzeń funkcjonalności o nowe klasy (LogDB) oraz spotkaliśmy się z problemem szybkiej zmiany rodzaju wykorzystywanej klasy.
Tworzenie klasy
Stwórzmy klasę, która połączy w sobie możliwość używania różnych klas loggera (logFile, logDb). Aby zachować ustalone na początku wymagania, dać możliwość łatwego wykorzystania, szybkiej zmiany silnika bez potrzeby wielu zmian w kodzie oraz maksymalnie skrócić zapis, musimy skorzystać z kilku technologi OOP.
Pierwsza z nich – klasa statyczna, druga – singleton. Czemu tak? Klasa statyczna + singleton załatwi nam szybkie i wygodnie użycie:
log::info('Szybko i sprawnie');
. Dzięki temu, po ustaleniu na początku skryptu silnika przechowywania logów w dalszej części możemy wygodnie korzystać z w/w zapisu. Dodatkowo przejście z logowania do pliku na logowanie do bazy nastąpi tylko w jednym miejscu. Jak zapewne zauważyliście nawet nazwa klasy została maksymalnie skrócona log
, aby użycie było jak najbardziej wygodne.
Zatem do dzieła. Wzór klasy będzie następujący:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?php class log implements log_log{ private static $driver; private static $drivers = array(); private static $defaultDriverName = 'log_logFile'; protected function __construct(){} protected function __clone(){} public static function instance(){} public static function addDriver(log_log $driver){} public static function useDriver($drivername=''){} public static function error($err,$driverName=''){} public static function warn($err,$driverName=''){} public static function info($err,$driverName=''){} } ?> |
Zmienne klasy
W klasie log mamy zadeklarowane 3 zmienne. Każda z nich ma swoje, łatwe do odgadnięcia, zastosowanie:
private static $driver;
– aktualny sterownik klasy loggera
private static $drivers = array();
– tablica dostępnych (dodanych) sterowników
private static $defaultDriverName = 'log_logFile';
– nazwa domyślnego sterownika
Statyczna zmienna klasy $driver;
przechowuje aktualnie wybrany sterownik, do którego następuje zapis logów. W trakcie korzystania z klasy będzie możliwa zmiana sterownika, dzięki temu, nawet w jednym skrypcie zachowamy możliwość wybrania innego sterownika do zapisu logu konkretnego zdarzenia.
Kolejna zmienna $drivers;
jest tablicą przechowującą obiekty klas poszczególnych sterowników. Dzięki temu po jednokrotnym wykorzystaniu konkretnego sterownika, w przypadku jego ponownego użycia obiekt nie jest tworzony na nowo.
Trzecia zmienna $defaultDriverName;
jak sama nazwa wskazuje, przechowuje nazwę domyślnego sterownika klasy loggera. Dzięki temu klasa jest gotowa do użycia bez ustawiania sterownika przy każdym, pierwszym, uruchomieniu skryptu.
Metody
Trzech ostatnich metod error(), warn(), info()
nie muszę omawiać, zostało to już przedstawione w poprzednich częściach. Jedyną różnicą względem poprzednich implementacji jest dodanie nowego parametru: $driverName =''
. Parametr ten, jak nazwa wskazuje, podaje nazwę sterownika, którego należy użyć do zapisu danego komunikatu. Domyślnie nie jest zdefiniowany, a w przypadku jego nie podania, wykorzystywany jest domyślny sterownik. Istnieje jednak możliwość podania innego sterownika do zapisu konkretnego komunikatu. Dzięki temu rozszerzamy funkcjonalność naszej klasy, o wybór sterownika dla konkretnego komunikatu, lub pojedynczego wystąpienia.
Utworzyliśmy dwie metody z dostępem ustawionym na protected:
protected function __construct(){} protected function __clone(){}
Ich zadaniem jest pilnowanie, aby nasza klasa była rzeczywiście singletonem. Zabezpiecza przed utworzeniem nowego obiektu klasy log z poza niej samej oraz przed utworzeniem kopii takiego obiektu.
Autor wpisu: Vokiel, dodany: 26.09.2009 16:56, tagi: php
W pierwszej części na temat optymalizacji bloga opartego na WordPress skupiliśmy się na kilku elementach:
Zmianie memory_limit()
poprzez php.ini, .htaccess, lub ini_set() w php. Następnie zapoznaliśmy się z częścią możliwości optymalizacji po stronie front-end’u (cache).
W dzisiejszej części będziemy kontynuować proces optymalizacji do tego stopnia, aby możliwym było bezproblemowe korzystanie z platformy blogowej. Zacznijmy od optymalizacji bazy danych.
Nieużywane szablony
Jeśli uruchamiając blog nie mogliśmy się zdecydować na konkretny szablon (theme), próbowaliśmy kliku z nich, do tego ustawialiśmy w nich jakieś opcje, dodatki, konfiguracje – to po zmianie na inny szablo wpisy dokonane dla poprzednich szablonów pozostaną zapisane w bazie. Jest to dobre rozwiązanie w przypadku, gdy zechcemy zmienić szablon (powrócić do wcześniej ustawionego) – konfiguracja zostaje przywrócona do etapu na jakim ją pozostawiliśmy. Jednak jeśli zdecydujemy się już na ten jedyny, wybrany szablon, zwykle nie będziemy go zmieniać, raczej upiększać, modyfikować. Możemy zatem śmiało usunąć pozostałe, oraz wszystkie wpisy w bazie danych które po nich pozostały. W tym celu logujemy się do menedżera MySQl (SQLyog, PMA) przeglądamy tabelę wp_options
w poszukiwaniu wpisów odnoszących się do starych szablonów, wtyczek, które odinstalowaliśmy i usuwamy je.
Nieaktualne ustawienia wtyczek
W moim przypadku usunięcie nieaktualnych wpisów odnoszących do ustawień kilku szablonów oraz wpisów pozostałych po wtyczkach zmniejszyło ilość wierszy w tabeli wp_options
o około 80 rekordów (wszystkie z ustawionym autoload
na 'yes'
). Dodatkowo postanowiłem zmienić opcję autoload
dla wybranych wpisów (po uprzednim pełnym backupie bazy). Ustawienia zostały zmienione tylko dla tych wpisów, odnośnie których znaczenia byłem pewien, oraz tych, które nie miały wartości. Samo zużycie pamięci zostało nieznacznie zmienione – w granicach błędu statystycznego. Jednak ilość zwróconych wyników uległa lekkiemu zmniejszeniu oraz zmniejszył się czas trwania zapytań – zatem przyśpieszenie już jakieś nastąpiło.
Indeksy
Przeglądając wyniki z WP Tuner (włączone ustawienia: Show Everything) natknąłem się na kilka niepoprawnych zapytań, na zapytania z narzutem, bez odpowiednio ustawionych indeksów. Niezbędnym okazało się ponowne zalogowanie do MySQL’a celem naniesienia poprawek poprzez dodanie indeksów. Zwykle brak indeksów występuje w przypadku wtyczek.
Szkice, wpisy autosave
Jeśli zakończyliśmy edycję wpisów, oraz wszystkie szkice zostały opublikowane, bądź są nam już niepotrzebne możemy je usunąć. Upewnijmy się tylko uprzednio, czy opublikowane wpisy są już ostateczne i nie będziemy chcieli wracać do poprzednich wersji. Funkcjonalność WordPress’a jaką jest automatyczne zapisywanie szkiców bywa bardzo przydatna. Jednak po zakończonej edycji wpisu, opublikowania go w wersji, która nie wymaga zmian, pozostałe wersje wpisu są już niepotrzebne. Usuniemy je za pomocą zapytania sql:
DELETE FROM wp_posts WHERE post_type = "revision";
Cache
W pierwszej części wspomniałem o systemach cache dostępnych jako wtyczki, a także o możliwości napisania własnych. Poza cache generowanych plików warto ustawiać czas ważności cache takich elementów jak pliki js, css, grafiki, dla przeglądarki. Tak, aby w przypadku braku modyfikacji przeglądarka nie pobierała ponownie tych plików, nawet nie zgłaszała potrzeby ich pobrania.
Jedną z opcji będzie wydłużenie domyślnego czasu ważności plików w zależności od ich rozszerzenia. Do tego celu posłużą nam dyrektywy apache oraz plik .htaccess. Odnajdujemy plik .htaccess w lokalizacji wp-content/cache
, edytujemy:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | # BEGIN supercache <IfModule mod_mime.c> <FilesMatch "\.html\.gz$"> ForceType text/html FileETag None </FilesMatch> AddEncoding gzip .gz AddType text/html .gz </IfModule> <IfModule mod_deflate.c> SetEnvIfNoCase Request_URI \.gz$ no-gzip </IfModule> <IfModule mod_headers.c> Header set Cache-Control 'max-age=300, must-revalidate' </IfModule> <IfModule mod_expires.c> ExpiresActive On ExpiresDefault A300 ExpiresByType application/x-javascript A3600 ExpiresByType text/css A3600 ExpiresByType image/gif A3600 ExpiresByType image/png A3600 ExpiresByType image/jpeg A3600 ExpiresByType text/plain A300 ExpiresByType application/x-shockwave-flash A3600 ExpiresByType video/x-flv A3600 ExpiresByType application/pdf A3600 ExpiresByType text/html A300 </IfModule> # END supercache |
Interesują nas wpisy od linii 16, czyli w momencie gdy moduł mod_expires.c
jest dostępny. Wraz z nim dostajemy możliwość ustawienia domyślnego czasu ważności elementów strony w zależności od ich typu. Jak widzimy domyślnie ustawiony jest na A3600 – czyli 3600 sec = 1 godz. W przypadku, gdy grafiki nie będą się zbyt często zmieniać śmiało możemy wydłużyć ten okres do miesiąca czyli: A2592000. Zatem w liniach 19-23 możemy wpisać nowy czas aktualności plików dla przeglądarki.
Poza określaniem czasu w sekundach mod_expires
daje możliwość określania czasu za pomocą słownych określeń, np:
1 2 3 4 5 6 | # Słowne określenia czasu ważności cache <IfModule mod_expires.c> ExpiresActive On ExpiresDefault "access plus 1 week" ExpiresByType application/x-javascript "access plus 1 month" ExpiresByType text/css "modification plus 5 hours" |
Więcej szczegółów na stronie apache – module mod_expires