Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

Autor wpisu: Vokiel, dodany: 21.09.2009 13:44, tagi: php

W pierwszej części Log class – klasa loggera zdarzeń rozpoczęliśmy prace nad klasą logowania zdarzeń. Utworzyliśmy interfejs klasy, który będzie implementowany. W tej części zajmiemy się implementacją tego interfejsu.

Z racji użycia interfejsu, klasy naszego loggera muszą zawierać 3 publiczne, statyczne metody: error(), warn(), info(). Najłatwiejszym, a zarazem dość przenośnym rodzajem klasy logowania do napisania jest logowanie do pliku. Zatem stwórzmy taką klasę:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
class logFile implements log_log {
	public static function error($err){
		echo 'logFile - error |'.$err;
	}
	public static function warn($err){
		echo 'logFile - warn |'.$err;
	}
	public static function info($err){
		echo 'logFile - info |'.$err;
	}
}
?>

Taki zarys musi mieć (ze względu na implementację interfejsu) nasza klasa logFile – logująca do pliku. Jednak to co mamy do tej pory nie jest zbyt użyteczne ;) Zatem zajmijmy się wypełnieniem metod:

Wszystkie z trzech metod mają za zadanie zapisać informację do logu, z tą różnicą, że są to informacją z inną flagą (błąd, ostrzeżenie, informacja). Zatem możemy je połączyć w jedną write(), która będzie zapisywać log do pliku.

<?php
/**
 * Zapis pojedynczego komunikatu
 * @param	string	$logMsg	Pojedynczy komunikat
 */
private function write($logMsg){
    file_put_contents(self::$file_name,$logMsg,FILE_APPEND | LOCK_EX);	
}
?>

Zapis do logu jak widzimy możemy przeprowadzić za pomocą file_put_contents, z ustawionymi flagami FILE_APPEND | LOCK_EX – dopisywaniem do pliku, jeśli istnieje oraz blokowaniem dostępu do pliku na czas zapisu. Dzięki temu logów w naszym pliku będzie przybywało, nie będą zastępowane, nadpisywane.

Po dodaniu metody write trzy wcześniej utworzone powinny ją wywoływać. Zatem w ciele metod dodajemy wywołanie metody write:

<?php
/**
 * Dodanie komunikatu informacyjnego do logów
 * @see log_log#info($msg)
 */
public static function info($msg){
	self::write(self::logPrefix('INFO').$msg);
}
?>

Pojawiła się tu nowa rzecz: self::logPrefix('INFO');. Otóż jest to wywołanie kolejnej metody, która ma za zadania do linii logu dodać informację o rodzaju zdarzenia, które jest logowane. Jak ta metoda wygląda w przypadku logowania do pliku? Następująco:

<?php
/**
 * Dodanie przedrostka do linijki logu
 * @param	string	$flag	Flaga określająca rodzaj zdarzenia
 * @return	string
 */
private function logPrefix($flag){
	return "\n".date('Y-m-d H:i:s')."\t|".$flag."\t|\t";
}
?>

Przyjęty format pliku logu wygląda następująco:

TIMESTAMP	|TYPE	|	MESSAGE

Przykładowo:

2009-09-02 10:50:07	|INFO	|	Pomyślnie zakończono akcję 123
2009-09-02 10:50:07	|WARN	|	Brak aktywnych zadań
2009-09-02 10:50:33	|ERROR	|	Połączenie zerwane

Wykańczając naszą klasę loggera dogramy kilka szczegółów: wybór pliku logu, ustawienie domyślnego logu w przypadku jego braku. Możemy to zrobić na kilka sposobów, jeden z nich:

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: Vokiel, dodany: 16.09.2009 13:11, tagi: css, php

W tym artykule skupimy się na szybkiej i łatwej implementacji funkcjonalności zmniejszania rozmiaru oraz łączenia wielu plików CSS w jeden.

Jeśli ktoś używa wtyczki do FF: YSlow może łatwo sprawdzić ile zewnętrznych plików css jest dołączanych do strony. Im więcej tym gorzej. Analizując dokładniej wskazania YSlow możemy zauważyć na co należy zwrócić uwagę odnośnie CSS. Są to m.in:

  • Make fewer HTTP requests – mniej żądań HTTP
  • Avoid CSS expressions – unikanie ostylowania wewnątrz kodu
  • Make JavaScript and CSS external – stworzenie zewnętrznych plików JavaScript oraz CSS
  • Minify JavaScript and CSS – zmniejszenie rozmiaru JavaScript oraz CSS
  • Put CSS at top – dołączenie zewnętrznych arkuszy stylów w nagłówku dokumentu
  • Compress components with gzip – kompresja elementów strony gzip’em
  • Add Expires headers – dodanie nagłówków informujących przeglądarkę o czasie ważności elementów

Co możemy zrobić sami na szybko? Przede wszystkim ograniczyć ilość żądań. Przeglądarki mają to do siebie, że ograniczają ilość jednoczesnych żądań do jednego serwera. Zatem jeśli przeglądarka ma domyślnie ustawione 4 żądania na serwer, a mamy zewnętrznych elementów na stronie 20, to po rozpoczęciu pobierania pierwszych czterech przeglądarka czeka, aż zostaną pobrane, zanim sięgnie po następne. Jeśli połączymy pliki CSS, JavaScript w jeden zmniejszymy tym ilość niezbędnych do wywołania żądań – dzięki temu przeglądarka szybciej pobierze resztę strony.

Zatem do dzieła! Tworzymy plik css_cache.php o takiej postaci:

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
31
32
33
34
35
36
37
38
39
< ?php 
/**
 * Tworzenie pliku cache z pobranych plików css
 * @param	string	$cache_file_name	Nazwa pliku cache
 */
function generateCache($cache_file_name){
    $dir = '.';
    if (is_dir($dir)){
        if ($handle = opendir($dir)) {
            $css_content = '/* Utworzono :'.date('Y-m-d H:i:s').' */';
            while (false !== ($file = readdir($handle))) { 
                if (strtolower(substr(strrchr($file,"."),1)) == 'css'){ 
                    $css_content .= "\n\n".'/* CSS z pliku: '.$file.' */'."\n".preg_replace('/\s+/', ' ', file_get_contents($file));
                }
            }
            closedir($handle);
            file_put_contents($cache_file_name,$css_content);
        }
    }
}
/**
 * Funkcja pobierająca plik cache
 * @param   string  $cache_file_name    Nazwa pliku
 * @param   int $cache_time Czas ważności w sekundach
 * @return unknown_type
 */
function getCache($cache_file_name,$cache_time){
    if (file_exists($cache_file_name)){
        if ($cache_time){ // jest podany termin waznosci cache
            if (filemtime($cache_file_name ) < (time() - $cache_time)) { //cache nieaktualny, pobranie od nowa i utworzenie
                generateCache($cache_file_name);
            }
        }
    }else{// brak cache - utworznie
        generateCache($cache_file_name);
    }
    return file_get_contents($cache_file_name);
}
?>

Następnie użycie plik css.php:

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
< ?php
if(array_key_exists("HTTP_IF_MODIFIED_SINCE",$_SERVER)){
    $if_modified_since = strtotime(preg_replace('/;.*$/','',$_SERVER["HTTP_IF_MODIFIED_SINCE"]));
    if($if_modified_since >= strtotime(filemtime($cache_file_name))){
        header("HTTP/1.0 304 Not Modified");
        exit();
    }
}
/**
 * Nazwa pliku cache
 * @var string
 */
$cache_file_name = 'cache_style.css';
/**
 * Czas ważności cache w sekundach
 * 0 - cache bez terminu ważności
 * @var unknown_type
 */
$cache_time = 0;
require_once 'css_cache.php';
header("Content-type: text/css; charset: UTF-8");
header("Pragma: public");
header("Cache-Control: public");
header('Expires: '.gmdate('D, d M Y H:i:s', strtotime('+1 year').' GMT'));
header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($cache_file_name)).' GMT');
ob_start("ob_gzhandler");
echo getCache($cache_file_name,$cache_time);
ob_end_flush();
?>

Krótkie omówienie: W pliku css_cache.php mamy 2 funkcje: generateCache($cache_file_name) oraz getCache($cache_file_name,$cache_time). Pierwsza z nich tworzy nam jeden zbiorczy plik cache ze wszystkich plików css znalezionych w katalogu (podanym jako parametr $dir – domyślnie obecny). Pliki oznaczane są komentarzem informującym kiedy i z jakiego pliku został utworzony dany fragment, do tego preg_replace załatwia nam sprawę zbędnych pustych znaków. Druga z nich pobiera plik cache. Jeśli został podany parametr $cache_time określający ważność cache, funkcja sprawdza, czy plik cache jest jeszcze aktualny. Jeśli plik nie jest aktualny, lub w ogóle nie istnieje jest tworzony na nowo. Następnie funkcja zwraca zawartość takiego skompresowanego pliku.

W pliku css.php mamy prosty przykład wykorzystania. Na początku sprawdzamy, czy wysłany uprzednio plik jest jeszcze aktualny (nagłówki HTTP_IF_MODIFIED_SINCE), jeśli tak – nie robimy nic – zwracamy informację, że plik nie został zmodyfikowany od czasu ostatniej wizyty. Jeśli jednak plik został zmodyfikowany, bądź jest to pierwsze wejście wysyłane są nagłówki ważności oraz odczytywany jest plik z cache.

Aby wykorzystać system na stronie wystarczy w nagłówku strony podać link do pliku css:

<link rel="stylesheet" type="text/css" href="css.php" />

Autor wpisu: cojack, dodany: 15.09.2009 16:14, tagi: php

Tak więc na phpclasses.org jakiś czas temu pojawiła się nowa klasa o nazwie sTemplate, co lepsze, jest to twór Polaka, co mnie bardzo cieszy a kolejne zdziwienie jakie mnie naszło, że jest to młody chłopak co mnie jeszcze bardziej cieszy, gdyż tacy ludzie są lub będą intelektualną śmietanką jeżeli w dalszym ciągu będą rozwijać swoją wiedzę oraz chcieć poznawać i tworzyć nowe rzeczy. Wracając do rzeczy, autorem tego systemu szablonów jest Sebastian Potasiak, link do jego blogu jest u mnie na stronie zatytułowanej Linki. Do rzeczy z czym to się je? Kolega rozwiązał w dość sprytny sposób ominięcie na wstawianie zmiennych w tpl, czyli jak w itx np {SOME_VARIABLE} lub też w smartach {$some_variable}, przykład:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-strict.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pl" lang="pl">
     <head>
          <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
          <title class="tytul"></title>
     </head>
     <body>
          <div class="tytul"></div>
          <div class="tresc"></div>
     </body>
</html>

Jak widać nie ma niczego co by można było parsować, a teraz spójrzmy na to:

1
2
3
4
5
6
7
8
9
10
11
<?php
     include('./sTemplate.class.php');
 
     $tpl = new sTemplate;
 
     $zmienne = array(
          'tytul' => 'Moja strona',
          'tresc' => 'To jest przykładowa treść mojej strony.<br />Aby zobaczyć więcej wyślij SMS o treści CHWDP na numer PREFIX_997'
     );
 
     $tpl->load('home', $zmienne);

Co nam to zwróci? A taki kod:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-strict.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pl" lang="pl">
     <head>
          <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
          <title class="tytul">Moja strona</title>
     </head>
     <body>
          <div class="tytul">Moja strona</div>
          <div class="tresc">To jest przykładowa treść mojej strony.<br />Aby zobaczyć więcej wyślij SMS o treści CHWDP na numer PREFIX_997</div>
     </body>
</html>

Takie sobie to co? Ja widzę parę problemów, dajmy na to że klasa title używamy do wylistowania artykułów, i jeżeli mielibyśmy ciągle taki sam tytuł to trochę do bani co? ;] Więc prosty system szablonów, na bardzo proste strony. Jak się mają benchmarki, a czort go wie ;] W następnym wpisie przedstawię wyniki.

Autor wpisu: Vokiel, dodany: 12.09.2009 14:16, tagi: php

WordPress ma to do siebie, że nie dba zbytnio o ograniczenie zużycia pamięci. Niestety, przy dodaniu większej ilości wtyczek (większej niż 5-7) zaczynają się problemy z wykorzystanym limitem pamięci.

Błędy pojawiają się najprędzej w panelu administracyjnym, co czynnie uniemożliwia poprawną pracę z systemem. kokpit_2009-09-12

[11-Sep-2009 15:35:01] PHP Fatal error:  Allowed memory size of 33554432 bytes exhausted (tried to allocate 170031 bytes) in /home/.../wp-includes/wp-db.php on line 501

Plugin WP-Memory-Usage pokazuje ile z dostępnej pamięci jest w użyciu.

Przyczyny

Co może być przyczyną takiego stanu rzeczy, i czy możemy coś z tym zrobić? Główną przyczyną jest funkcja inicjująca init oraz poprzedzające ją plugins_loaded i widgets_init. Funkcje te ładują do pamięci wtyczki oraz widgety, inicjują całą aplikację. Aby sprawdzić jak wygląda ładowanie strony pod względem wykorzystania pamięci możemy posłużyć się wtyczką WP Tuner. Po zainstalowaniu wtyczki przechodzimy do panelu zarządzania wtyczką wybieramy jedno z ustawień Presets: np Analyze Timing. Następnie otwieramy dowolną stronę panelu i przewijamy stronę do samego dołu: wp_tuner_2009-09-12 Jak widzimy na screenie ilość użytej pamięci skacze drastycznie do 26MB! po załadowaniu funkcji init do ponad 20MB tylko po załadowaniu pluginów! Dawno nie widziałem takiego marnotrawstwa pamięci ;)

Rozwiązania

Możliwości rozwiązania problemu mamy kilka. Zacznijmy od najprostszych: zwiększenie limitu pamięci :) Jednak w przypadku, gdy nasz wordpress nie jest postawiony na dedyku mamy małą szansę na możliwość ingerencji w to ustawienie. Możemy napisać @ do admina. Jeśli natomiast mamy możliwość zmian konfiguracji możemy zastosować kilka wpisów: php.ini:

;; set new memory limit
memory_limit = 64M

.htaccess:

# set new memory limit
php_value memory_limit 64M

lub w php:

 // set new memory limit
ini_set('memory_limit','64M');

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: Vokiel, dodany: 07.09.2009 06:58, tagi: php

Podczas pisania aplikacji internetowych ważną częścią projektu jest wiedza na temat działania owego produktu. Zdarzają się błędy wynikłe nie tylko ze złej implementacji, kodu aplikacji, ale także te niezależne od programisty. Mogą to być różnego rodzaju przerwy w działaniu innych serwisów, problemy z połączeniem internetowym, awarie. W takiej sytuacji bardzo przydatnym narzędziem jest możliwość logowania zdarzeń. W tym wpisie zajmę się opisaniem własnego pomysłu na klasę loggera.

Zacznijmy od założeń, wymagań stawianych takiej klasie.

  • elastyczność
  • możliwość umieszczania logów w różnych formatach, miejscach
  • łatwość użycia
  • umożliwienie szybkiej zmiany sposobu przechowywania

Zdarza się czasem, iż chcemy przechowywać logi w plikach, czasem w bazie danych. Nasza klasa powinna mieć możliwość łatwej zmiany silnika przechowywania logów oraz w miarę prostego sposobu przełączania się pomiędzy nimi.

Ewentualnie też, mogłaby mieć możliwość korzystania z kilku silników w jednym skrypcie. Ta opcja nie jest taka ważna, a na pewno nie jest koniecznością, jednak może się przydać w ekstremalnych sytuacjach. Załóżmy, że swoją klasę logowania ustawiliśmy na zapis do bazy. Co jednak w przypadku, gdy połączenie z bazą zostanie przerwane? W takiej sytuacji przydałoby się zapisać log w łatwiej dostępne miejsce – plik .log, .xml.

Aby móc korzystać z możliwości łatwego przełączania silnika loggera należy dobrze rozplanować struktury klas. Możemy skorzystać z klas abstrakcyjnych, interfejsów lub zwykłych klas. Aby zachować kompatybilność dodatkowych sterowników loggera postanowiłem oprzeć log class o interfejsy.

Jak podaje wikipedia: interfejs jest abstrakcyjną reprezentacją klasy pozwalającą na korzystanie z niej niezależnie od faktycznej implementacji.

Interfejs w PHP jest tak jakby tylko pomocnikiem dla programisty. Pokazuje jakie metody klasy implementujące muszą zaimplementować lecz sam ich nie udostępnia (w odróżnieniu od klasy abstrakcyjnej). Dla naszego zastosowania będzie to bardzo dobre rozwiązanie. Każdy rodzaj sterownika będzie dodawał zdarzenia do logów w inny sposób. Dodatkowo korzystając z interfesu będziemy mieli pewność, że dodatkowe sterowniki będą posiadały wymagane metody.

Jakie metody będą nam potrzebne? Jak dla mnie wystarczą 3 podstawowe: error();, warn();,info();. Schemat interfejsu będzie następujący:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
/**
 * Interfejs dla klas logów
 * @author Vokiel
 * @package log
 */
interface log_log{
	/**
	 * Dodanie błędu do logów
	 * @param	string	$msg	Komunikat
	 */
	public static function error($msg);
	/**
	 * Dodanie ostrzeżenia do logów
	 * @param	string	$msg	Komunikat
	 */
	public static function warn($msg);
	/**
	 * Dodanie komunikatu informacyjnego do logów
	 * @param	string	$msg	Komunikat
	 */
	public static function info($msg);	
}// end of logInterface
?>

Nasz interfejs posiada 3 metody do których przekazywany jest komunikat. Zapytacie czemu nie jedna metoda z flagą oznaczającą rodzaj komunikatu. Otóż wynika to z trzeciego punku założeń. Utworzyliśmy metody statyczne, dzięki temu będziemy mogli się do nich odwołać poprzez:

<?php
log::info('Wszystko ok');
log::error('Wszystko jak krew w piach!');
?>

Co dalej? W dalszych odcinkach zajmiemy się tworzeniem klas implementujących interfejs log_log oraz utworzeniem klasy trzymającej to wszystko w kupie.

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: cojack, dodany: 05.09.2009 01:22, tagi: php

Tak więc przez ostatnio miesiąc nauczyłem się dużo nowych rzeczy, i chciałbym się z Wami zdobytą wiedzą podzielić, a zaczął bym od stylu programowania, czyli standardów jakie sami sobie powinniśmy narzucić, by nasz kod był przejrzystszy i czytelniejszy nawet dla nas samych w późniejszym etapie rozwoju kodu.

Wcięcia Wcięcia powinny składać się z 4 spacji, tak spacje zamiast tabulatorów, dlaczego 4 a nie 2? Ponieważ wyraźnie zaznaczamy różnice w kodzie, i jest ona czytelniejsza dla naszego zmęczonego oka.

Składnia Zacznijmy od nazewnictwa zmiennych,

$someVariable

Tak pewnie zaraz zwrócicie uwagę mi że jest to cAmEl z Javy, i co z tego? :>

Funkcje i metody

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
someFunction($objTpl, $var) {
    // some part of code
}
 
class BigMama {
    public $variable;
    protected $_variable2;
    private $_variable;
 
    private function _setShowMeTrue() {
        $this->variable = true;
        return $this;
    }
 
    public function getShowMeTrue() {
        return $this->variable;
    }
}

Tak, nazwę klasy zaczynamy z wielkiej litery, nie robimy żadnych przerw pomiędzy nazwą a jej drugim członem tylko drugi człon z wielkiej litery. Metody w klasie protected oraz private, ich nazwy zaczynają się od dolnego podkreślenia. Z tym pod kreślnikiem to samo tyczy się zmiennych private oraz protected.

Warunek

1
2
3
4
5
if( $a == 0 ) {
    echo ':)';
} else {
    echo ':(';
}

Jak widać na załączonym obrazku, w warunku wyrażenie jest oddzielone od nawiasów spacją (białym znakiem), uwierzcie mi lub nie, ale to jest czytelniejsze!

String(c-string)

echo 'Some tekst is ' . $funnyImg . ' so much';

Widzimy że kropki łączące string są, pooddzielane spacjami (znów białe znaki) od apostrofu. Używanie cudzysłowu powinno być stosowane tylko w przypadkach koniecznych takich jak np znak nowej linii czyli \n

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: Zyx, dodany: 04.09.2009 11:27, tagi: php

Standard kodowania znaków Unicode zdobywa coraz większą popularność, co sprawia, że coraz więcej programistów pragnie go wykorzystywać również w swoich aplikacjach internetowych. Do tej pory poważnym problemem języka PHP był niemal całkowity brak wsparcia dla tego systemu. Pełne wdrożenie Unicode planowane jest na wersję 6.0, jednak już w wersji 5.3 otrzymaliśmy sporą część dodatkowego API, dzięki któremu wiele operacji staje się możliwych już teraz. W tym cyklu wpisów przyjrzymy się im bliżej.
Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.