Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

Autor wpisu: sokzzuka, dodany: 12.01.2011 09:29, tagi: php

Marcin Babij z naszej klasy w swoim wpisie na php.internals poinformował społeczność php, o wykonanych przez nich optymalizacjach interpretera. Dotyczą one implementacji hash table czyli znanych nam wszystkim php-owych „arrayów”. Jako, że są one wykorzystywane wszędzie, nie tylko w kodzie napisanym przez użytkowników ale również w wielu miejscach w samym interpreterze, każda poprawka, która przyspiesza funkcje operujące na tej strukturze danych jest mile widziana (jak podaje Babij średnio ich wywołania zajmują 10%-20% czasu każdego skryptu).

Nie wgłębiając się zbytnio w techniczne szczegóły, które można znaleźć w oryginalnym wpisie, programistom nk.pl udało się zmniejszyć obciążenie procesora przy operacjach na tablicach o 4% do 6% przy niewielkim wzroście użycia pamięci. Patch, który dostarczył został sprawdzony względem php 5.3.4 i apc-3.1.3p1 i można go ściągnąć z githuba.

Wypada tylko podziękować programistom naszej klasy, że są tak uprzejmi i dzielą się swoimi osiągnięciami. Może to zachęci inne osoby z naszego pięknego kraju do przyłączenia się do projektu.

Autor wpisu: widmogrod, dodany: 11.01.2011 21:58, tagi: php, eclipse

Eclipse, dla wielu może być ociężałą kobyłą – zgodzę się – ale jej ociężałóść znika po 15min uruchamiania i gdy zacznie się wykorzystywać moc jaką daje Eclipse.

Pracując w Eclipse od ok 3lat z przerwami na wypróbowanie Netbeans. Dopiero niedawno zdałem sobie sprawę że zapomniałem nie tylko o myszce ale również o bloku navigacji projektu.

Skróty klawiaturowe, których używam kilka razy dziennie:

  • Ctrl + Shift + R – znajdź i otwórz plik (można używać *. by znaleźć wszystkie możliwości gdy nie pamięta się nazwy pliku)
  • Ctrl + Shift  + T – znajdź i otwórz typ pliku (rozpoznaje skrócone nazwy np.: ZVH -> Zend_View_Helper)
  • Ctrl + Shift + M – znajdź i otwórz metodę – bez komentarza ;)
  • Zanacz tekst i Ctrl + Alt + G – wyszukaj w projekcie wszystkie wystąpienia zaznaczonego tekstu

Jak widać tylko cztery skróty wystarczą by nawigacja po projekcie była błyskawiczna i bez potrzeby sięgania myszki by coś odgrzebać :)

Czy też macie swoje ulubione skróty klawiaturowe w Eclipsie?

Autor wpisu: batman, dodany: 10.01.2011 08:00, tagi: php

Poprzedni tekst traktujący o SPL rozpoczął serię wpisów poświęconych standardowej bibliotece PHP (Standard PHP Library). Poznaliśmy w nim trzy klasy ułatwiające pracę z plikiem. Podczas poznawania tych klas, okazało się, że korzystają z dobrodziejstw iteratorów oraz wbudowanych interfejsów. Dzisiaj skupimy się jedynie na interfejsach dostarczanych razem z SPL z wyłączeniem SplObserver oraz SplSubject. O obserwatorze napiszę innym razem. Obok interfejsów dostępnych w ramach SPL, PHP oferuje kilka dodatkowych interfejsów, o których również dzisiaj napiszę.

Traversable

Jest to pusty interfejs służący do oznaczenia klasy jako “iterowalnej”. Każdy obiekt klasy implementującej interfejs Traversalbe może zostać użyty w pętli foreach jako wyrażenie. Interfejs ten nie może zostać użyty bezpośrednio w klasie. Zamiast tego należy skorzystać z interfejsu dziedziczącego po Traversable, np Iterator lub IteratorAggregate.

Iterator

Interfejs ten służy jako rozwinięcie idei interfejsu Traversable. Wprowadza on metody, które zostaną wykorzystane przez pętlę foreach podczas iteracji po obiekcie. Domyślnie pętla foreach przejdzie po wszystkich właściwościach publicznych obiektu. W przypadku użycia interfejsu wykorzystane zostaną metody:

  • current – zwraca bieżący element
  • key – zwraca klucz aktualnego elementu
  • next – przesuwa wewnętrzny wskaźnik na kolejny element
  • rewind – przesuwa wewnętrzny wskaźnik na pierwszy element
  • valid – sprawdza czy bieżąca pozycja jest poprawna

Zobaczmy przykład prostej klasy korzystającej z tego interfejsu

class Foo implements Iterator
{
    protected $_position;
    protected $_someData = array('123', 'abc', 'qwe');

    public function __construct()
    {
        $this->_position = 0;
    }

    public function current()
    {
        return $this->_someData[$this->_position];
    }

    public function key()
    {
        return $this->_position;
    }

    public function next()
    {
        ++$this->_position;
    }

    public function rewind()
    {
        $this->_position = 0;
    }

    public function valid()
    {
        return isset($this->_someData[$this->_position]);
    }
}

$foo = new Foo();
foreach($foo as $key => $value) {
    echo $key . ' = ' . $value;
}

Zgodnie z oczekiwaniami, wynikiem działania będzie

0 = 123
1 = abc
2 = qwe

Po co nam klasa, która robi to samo co tablica? Odpowiedź jest tylko jedna – po nic. Interfejs ten ma zastosowanie wszędzie tam, gdzie mamy do czynienia z kolekcjami obiektów, na których będziemy wykonywać dodatkowe operacje. Może to być na przykład kolekcja złożona z obiektów, gdzie każdy z nich odpowiada wierszowi w bazie danych.

IteratorAggregate

Interfejs ten jest o tyle ciekawy, że pozwala “oddelegować” iterowanie po danym obiekcie do innej klasy implementującej interfejs Traversable (lub inny interfejs po nim dziedziczący).

class Foo implements Iterator
{
    protected $_position = 0;
    protected $_someData = array();

    public function __construct($data)
    {
        $this->_someData = $data;
        $this->rewind();
    }

    public function current()
    {
        return $this->_someData[$this->_position];
    }

    public function key()
    {
        return $this->_position;
    }

    public function next()
    {
        $this->_position = $this->_position + 1;
    }

    public function rewind()
    {
        $this->_position = 0;
    }

    public function valid()
    {
        return isset($this->_someData[$this->_position]);
    }
}

class Bar implements IteratorAggregate
{
    protected $_data = array('123', 'abc', 'qwe');

    public function getIterator()
    {
        return new Foo($this->_data);
    }
}

$bar = new Bar();
foreach($bar as $key => $value) {
    echo $key . ' = ' . $value;
}

Do czego jest to nam potrzebne? Przykładów zastosowania jest co najmniej kilka. Najprostszym z nich jest udostępnienie chronionych lub prywatnych danych na zewnątrz.

class Foo implements IteratorAggregate
{
    protected $_data = array(123, 'abc', 'qwe');

    public function getIterator()
    {
        return new ArrayIterator($this->_data);
    }
}

$foo = new Foo();
foreach($foo as $key => $value) {
    echo $key . ' = ' . $value;
}

Nie przejmujcie się klasą ArrayIterator, omówię ją przy okazji iteratorów. Wystarczy, że będziecie wiedzieć, iż klasa ta pozwala na modyfikowanie i usuwanie kluczy i wartości tablic oraz obiektów.

Countable

Implementacja tego interfejsu oznacza, iż naszą klasę można policzyć. Interfejs definiuje tylko jedną publiczną metodę, która zwraca liczbę opisującą ilość elementów w naszej klasie.

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

Autor wpisu: Athlan, dodany: 10.01.2011 00:36, tagi: mysql, sql, internet

We wpisie Chmura tagów w PHP, w którym został przedstawiony problem budowy chmury tagów zapisałem przykładowe zapytanie prezentujące przykładowe dane dla klasy, które dosłownie zabija bazę danych zliczając za każdym razem ilość występowań tagów. Dostając feedbacki, zauważyłem, że problem ten jest bagatelizowany przez wiele osób. Spróbujmy zbudować bardziej optymalne rozwiązanie zarządzania strukturą danych w taki sposób, aby dane wyciągać bardzo bezboleśnie.

Zbudujmy przykładową strukturę bazy danych tagów, do której będziemy przypinać różne rzeczy – newsy, artykuły, galerie zdjęć, zdjęcia, cokolwiek.

Najprostsza tabela db_tags o polach:

  • tag_id, UNSIGNED, aby zwiększyć zakres INT – wartości ujemne nie są nam porzebne. Oczywiście primary key oraz auto increment.
  • tag_name, chociażby varchar(255)
  • tag_count, UNSIGNED, INT, ponownie bez znaku, aby zwiększyć zakres, wartości ujemne są nam niepotrzebne. Tutaj będziemy przechowywać liczbę reprezentującą, ile razy użyto tagu do oznaczenia dowolnego zestawu informacji.
CREATE TABLE db_tags (
  tag_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
  tag_name VARCHAR(255) NOT NULL ,
  tag_count INT UNSIGNED NOT NULL
) ENGINE = INNODB;

Zastanówmy się, po czym będziemy sortować tagi. Warto założyć klucz na pole tag_count, znacznie przyspieszy późniejsze sortowanie wyników po najpopularniejszych tagach. Jeżeli chcemy sortować po liczbie występowań tagu oraz nazwie (aby chmura była alfabetycznie), warto założyć wspólny klucz na tag_name oraz tag_count. Osobiście sortowanie alfabetyczne zostawiam implementacji klasie tagów dla ksort(), bowiem zapytanie wyciągające tagi jest obarczone limitem, zatem wspólny klucz w bazie danych nie jest mi potrzebny – mniej danych w indeksach.

ALTER TABLE db_tags ADD INDEX (tag_count);

Tworzymy dowolną strukturę danych, która będzie podpinała się do naszych tagów. Pamiętajmy, że do tagów może podpinać się (a przynajmniej powinno, zależy od założeń początkowych projektu) wiele struktur jednocześnie. Wybrałem najbardziej pospolite – newsy w tabeli db_news.

CREATE TABLE db_news (
  news_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  news_title TEXT NOT NULL,
  news_content TEXT NOT NULL
) ENGINE = INNODB;

Pozostało nam stworzyć tabelę wiążącą nasze newsy z tagami (nie tagi z newsami). Tabelę nazwałem db_news_tags. Zawierać ona będzie tylko dwa pola przechowujące identyfikator newsa oraz przypisanego do niego tagu, zachowując typ danych wiążących, czyli INT UNSIGNED. Zakładam wspólny primary key dla obu pól.

  • handler_item – klucz ID newsa,
  • handler_node – klucz ID tagu.
CREATE TABLE db_news_tags (
  handler_item INT UNSIGNED NOT NULL,
  handler_node INT UNSIGNED NOT NULL,
PRIMARY KEY (handler_item, handler_node)
) ENGINE = INNODB;

Buduję relacyjną bazę danych. Gdy jakiś tag zostanie usunięty, bądź gdy jakiś news zostanie usunięty, automatycznie powinien zniknąć wpis z tabeli db_news_tags, zatem używamy kluczy obcych:

ALTER TABLE db_news_tags ADD FOREIGN KEY (handler_item) REFERENCES db_news (news_id) ON DELETE CASCADE;
ALTER TABLE db_news_tags ADD FOREIGN KEY (handler_node) REFERENCES db_tags (tag_id) ON DELETE CASCADE;

Tak zaprojektowaną strukturę danych mogę spokojnie używać do przechowywania danych. Pozostaje kwestia obliczania ilości występowań tagów. Istnieją co najmniej dwie szkoły.

  1. Każda zmiana danych w db_news_handler wywołuje procedurę liczącą tagi. Trzeba mieć na uwadze, że tagi są przeliczane od początku mielenie bazy, ale de facto proces odbywa się po kluczach. Zaletą rozwiązania jest to, że przy bardzo rozbudowanych strukturach (np. liczymy tylko aktywne i widoczne tagi) procedura uwspólnia nam warunki podliczania, używając jej w wielu miejscach nie musimy się martwić o redefiniowanie triggerów.
  2. Dla przedstawionego przykładu w tym poście wystarczy inkrementacja licznika przy dodaniu i dekrementacja przy usunięciu tagu. W większości przypadków właśnie takiego rozwiązania powinno się używać.

Luźny komentarz techniczny (problems, tips & tricks): Aby ominąć problemy wynikłe z założenia w punkcie pierwszym, równie dobrze możemy napisać procedury, które inkrementują/dekrementują liczbę tagów w zależności od warunków (np. tylko wtedy, kiedy tag jest aktywny i widoczny w serwisie). Nikt nie powiedział, że procedury muszą liczyć wszystko od początku możemy się na takie rozwiązanie zgodzić, rezygnujemy natomiast z synchronizacji licznika podczas zmiany warunków, wówczas podczas każdej zmiany warunków, trzeba przekręcić licznik od początku, zliczając wszystkie rekordy wg. ustalonych warunków ręcznie. Triggera należałoby również umieścić w UPDATE (zmiana stanu tagu, np. z niewidocznego na widoczny, z aktywnego na nieaktywny). I to jest najrozsądniejsze rozwiązanie.

W naszym przypadku ograniczymy się do dwóch triggerów, które będą trzymały rękę na pulsie w momencie przypisania tagu do struktury INSERT oraz zerwaniu przypisania DELETE. Zatem:

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

Autor wpisu: JoShiMa, dodany: 07.01.2011 23:56, tagi: php

Pracując ostatnio nad pewnym projektem przyszło mi zaprogramować niezliczoną ilość formularzy. No taka niestety jest specyfika paneli administracyjnych. Postanowiłam więc przy tej okazji pokazać jak można tworzyć formularze za pomocą modułu formo, jak przekazać formularz do widoku oraz jak w widoku wykorzystać jego elementy. Instalacja modułu formo Moduł formo to dość wygodne narzędzie choć ma pewne niedoróbki. [...]

Autor wpisu: matipl, dodany: 07.01.2011 08:09, tagi: php

php-logo30 grudnia 2010 świat obiegła wiadomość, że PHP jest podatny na dość trywialny błąd. Podczas konwersji stringa do liczby double wartości 2.2250738585072011e-308 przy pomocy rejestrów x87 FPU nasz PHP był w stanie powiesić całą maszynę.

Mimo wszystko dla większości osób ten PHP Remote Exploit nie był zbytnio straszny. Wystarczy, że nasza aplikacja zaopatrzona jest w walidatory formularzy (np. Zend Framework lub Symfony) albo PHP operuje na systemie 64 bitowym, którego błąd nie dotyczył.

Wczoraj, 6 stycznia społeczność PHP, który jest open source (jeśli nie pamiętasz) załatała błąd wydając tym samym wersję PHP 5.3.5 oraz 5.2.17. Dzięki. Zachęcam do aktualizacji albo kompilacji :)

Źródło: PHP 5.3.5 and 5.2.17 Released!

Autor wpisu: batman, dodany: 07.01.2011 08:00, tagi: php

Większość programistów PHP zapytana o SPL albo nie wiedziałaby o co chodzi, albo kojarzyłaby “jakieś klasy do listowania katalogów”. A szkoda, ponieważ SPL oferuje programistom struktury, często wynajdywane przez nich na nowo. Do szerokiego wachlarza możliwości dostępnych w ramach SPL można zaliczyć zestaw klas wyjątków, klasy iteratorów, struktury danych, funkcje autoloadera oraz zestaw interfejsów. W ramach popularyzowania SPL będę opisywał kolejne zagadnienia z nim związane. Dzisiaj poznamy możliwości oferowane przez klasy służące do obsługi plików. Będą to SplFileInfo, SplFileObject oraz SplTempFIleObject.

SplFileInfo

Klasa SplFileInfo stanowi obiektowy interfejs dostępu do informacji o pliku i wygląda nastęująco

SplFileInfo
{
	/* Methods */
	__construct ( string $file_name )
	public int getATime ( void )
	public string getBasename ([ string $suffix ] )
	public int getCTime ( void )
	public SplFileInfo getFileInfo ([ string $class_name ] )
	public string getFilename ( void )
	public int getGroup ( void )
	public int getInode ( void )
	public string getLinkTarget ( void )
	public int getMTime ( void )
	public int getOwner ( void )
	public string getPath ( void )
	public SplFileInfo getPathInfo ([ string $class_name ] )
	public string getPathname ( void )
	public int getPerms ( void )
	public string getRealPath ( void )
	public int getSize ( void )
	public string getType ( void )
	public bool isDir ( void )
	public bool isExecutable ( void )
	public bool isFile ( void )
	public bool isLink ( void )
	public bool isReadable ( void )
	public bool isWritable ( void )
	public SplFileObject openFile ([ string $open_mode = r [, bool $use_include_path = false [, resource $context = NULL ]]] )
	public void setFileClass ([ string $class_name ] )
	public void setInfoClass ([ string $class_name ] )
	public void __toString ( void )
}

Duża ilość metod przekłada się na praktyczne zastosowania klasy, w zupełności wystarczające do uzyskania wszystkich informacji o pliku.

Do czego jest nam potrzebna ta klasa? Przede wszystkim zamyka w jednym pojemniku wszystkie metody zwracające informacje o pliku. Dzięki temu stanowi doskonałą bazę dla wszystkich klas operujących na plikach i katalogach – tak, przekazanie do SplFileInfo nazwy katalogu też zadziała.

SplFileObject

Klasa SplFileObject dziedziczy bezpośrednio po SplFileInfo i uzupełnia ją o metody manipulujące plikiem. Ponadto implementuje interfejsy RecursiveIterator, Traversable, Iterator, SeekableIterator, które dodatkowo zwiększają jej możliwości. O interfejsach napiszę w jednym z kolejnych wpisów. Na teraz wystarczy wiedzieć, że dzięki tym interfejsom można iterować po obiekcie SplFileObject np. pętlą foreach i w każdej iteracji mieć dostęp do kolejnego wiersza z pliku oraz uzyskiwać dostęp do dowolnego miejsca w pliku.

Klasa składa się z następujących metod (plus te, które dziedziczy po SplFileInfo)

SplFileObject extends SplFileInfo implements RecursiveIterator , Traversable , Iterator , SeekableIterator
{
    /* Constants */
    const integer SplFileObject::DROP_NEW_LINE = 1 ;
    const integer SplFileObject::READ_AHEAD = 2 ;
    const integer SplFileObject::SKIP_EMPTY = 6 ;
    const integer SplFileObject::READ_CSV = 8 ;
    /* Methods */
    __construct ( string $filename [, string $open_mode = "r" [, bool $use_include_path = false [, resource $context ]]] )
    public string|array current ( void )
    public boolean eof ( void )
    public boolean fflush ( void )
    public string fgetc ( void )
    public array fgetcsv ([ string $delimiter = "," [, string $enclosure = "\"" [, string $escape = "\\" ]]] )
    public string fgets ( void )
    public string fgetss ([ string $allowable_tags ] )
    public bool flock ( int $operation [, int &$wouldblock ] )
    public int fpassthru ( void )
    public mixed fscanf ( string $format [, mixed &$... ] )
    public int fseek ( int $offset [, int $whence = SEEK_SET ] )
    public array fstat ( void )
    public int ftell ( void )
    public bool ftruncate ( int $size )
    public int fwrite ( string $str [, int $length ] )
    public void getChildren ( void )
    public array getCsvControl ( void )
    public int getFlags ( void )
    public int getMaxLineLen ( void )
    public bool hasChildren ( void )
    public int key ( void )
    public void next ( void )
    public void rewind ( void )
    public void seek ( int $line_pos )
    public void setCsvControl ([ string $delimiter = "," [, string $enclosure = "\"" [, string $escape = "\\" ]]] )
    public void setFlags ( int $flags )
    public void setMaxLineLen ( int $max_len )
    public bool valid ( void )
}

Jeśli się dokładnie przyjrzycie, zauważycie iż większość metod pokrywa się ze znanymi funkcjami, takimi jak fwrite, fgets, eof, fseek, itd. Stosowanie tych metod niczym się nie różni od ich odpowiedników poza tym, że są wywoływane w kontekście obiektu i nie wymagają ciągłego przekazywania uchwytu do pliku.

SplTempFileObject

Ostatnią klasą z grupy obsługi plików jest SplTempFileObject, która umożliwia tworzenie tymczasowych plików w pamięci lub w katalogu tymczasowym. Klasa dziedziczy po SplFileObject i jedyną metodą jaką zawiera jest konstruktor.

SplTempFileObject extends SplFileObject
{
    /* Methods */
    __construct ([ integer $max_memory ] )
}

 

Praktyczne zastosowanie

Głównym celem opisanych powyżej klas jest dostarczenie obiektowego interfejsu do obsługi plików. Wraz z obiektowością dostajemy wyjątki, które są używane zamiast typowych dla standardowych funkcji warningów. Nic nie stoi na przeszkodzie aby rozszerzać funkcjonalność tych klas i dodać np. możliwość serializacji SplFileObject.

Ponieważ dobry przykład wart jest więcej niż tysiąc słów, przejdę bez dalszej zwłoki do konkretnych przypadków użycia.

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

Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.