Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM    Subskrybuj kanał ATOM dla tagu php Kanał ATOM (tag: php)

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...

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

Najnowsza wersja PHP oznaczona numerem 5.3 wprowadziła do języka szereg usprawnień, o których programiści jeszcze niedawno mogli jedynie marzyć. Jednym z takich usprawnień są funkcje anonimowe, nazywane również domknięciami (closures). Mimo swoich wad znacząco wpływają na sposób programowania, wprowadzając do słownika programisty PHP konstrukcje określane mianem funkcji zwrotnych.

Najprostsza funkcja anonimowa ma postać

$funkcja = function()
{
	echo 'Jestem funkcja anonimowa';
};

$funkcja();

Wprawdzie zastosowanie takiej funkcji jest żadne, niemniej powyższy kod daje pogląd na to jak funkcja anonimowa jest definiowana.

Co tak naprawdę powyższy kod robi? Korzysta z wbudowanej w PHP klasy Closure (oznaczonej jako finalna), która zawiera magiczną metodę __invoke. Innymi słowy funkcja anonimowa jest obiektem klasy Closure, co doskonale widać na poniższym przykładzie.

// zmienna $funkcja została zdefinowana w poprzednim przykładzie
var_dump($funkcja);
/*
wynik działa funkcji var_dump:

object(Closure)#1 (0) {
}
*/

Metoda __invoke znajdująca się w klasie Closure, wywoływana jest w momencie, gdy do obiektu odwołujemy się tak, jakby był funkcją. I to jest cały sekret funkcji anonimowych. Tak naprawdę w tle dzieje się coś takiego

$funkcja->__invoke();

Do anonimowych funkcji można przekazywać argumenty w taki sam sposób, jak do standardowych funkcji.

$funkcja = function($arg1, $arg2)
{
	echo $arg1;
	echo $arg2;
};

$funkcja(123, 'abc');

Innym sposobem przekazania danych do funkcji anonimowej jest skorzystanie z zmiennych dostępnych w tym samym zasięgu, w którym znajduje się funkcja.

$zmienna = 123;
$funkcja = function()
{
	echo $zmienna;
};

$funkcja();

Niestety (a może i stety) funkcja anonimowa nie ma do nich bezpośredniego dostępu i to my musimy wskazać jakich zmiennych chcemy użyć. Z tego właśnie względu powyższy kod nic nie wyświetli oraz zgłosi notice.

$zmienna = 123;
$funkcja = function() use ($zmienna)
{
	echo $zmienna;
};

$funkcja();

Dopiero użycie use spowodowało, że zmienna jest widoczna wewnątrz funkcji anonimowej. W celu przekazania większej ilości zmiennych wystarczy oddzielić je od siebie przecinkiem.

W tym momencie ujawniają się dwie poważne wady funkcji anonimowych. Po pierwsze, do funkcji przekazywana jest kopia zmiennej, wykonana w momencie definiowania funkcji, a nie w momencie jest użycia.

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

Autor wpisu: Kamil, dodany: 04.01.2011 01:29, tagi: php

Jeszcze kilka dni temu pisałem o atrybucie httpOnly dla ciasteczek, dzięki któremu częściowo (minimalnie) możemy się zabezpieczyć przed atakami typu XSS, czyli przed wstrzykiwaniem niebezpiecznego kodu do naszej strony. Dzisiaj uderzymy w temat z nieco innej strony, mowa bowiem o filtrowaniu danych wchodzących do aplikacji przy pomocy świetniej biblioteki, HTML Purifier. Czym jest HTML Purifier? [...]

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

Tabele w Windows Azure są trzecim i ostatnim sposobem przechowywania danych w Azure Storage. Pozostałe dwa (bloby oraz kolejki) poznaliśmy w poprzednich dwóch częściach serii. Wbrew pozorom tabele nie są bazą danych. Cechuje ją nierelacyjna struktura służąca do przechowywania danych w postaci encji, gdzie każda z encji może składać się z innych właściwości. Przez encję należy rozumieć pojedynczy wiersz w tabeli, której reprezentacją w kodzie jest pojedyncza klasa złożona z właściwości.

Definiowanie encji

W przypadku PHP encję możemy zdefiniować na dwa sposoby – z określonym schematem oraz ze schematem dynamicznym. Jedyną różnicą w obu podejściach jest to, że encja z określonym schematem wymaga utworzenia klasy będącej jej reprezentacją. Schemat dynamiczny pozwala tworzyć encje w locie.

Encja z określonym schematem

Jak już wspomniałem, ten typ encji wymaga utworzenia klasy. Klasa ta musi dziedziczyć po Microsoft_WindowsAzure_Storage_TableEntity i składać się z właściwości odpowiadających poszczególnym informacjom na temat opisywanego obiektu. Każda właściwość, która ma być przechowywana w Azure Storage, musi być publiczna i poprawnie oznaczona przy pomocy komentarza w stylu PHPDoc. Zamiast właściwości można zastosować publiczne setery i getery, które również wymagają odpowiedniego komentarza.

Przykładowa encja będzie wyglądać nastęująco

class Encja extends Microsoft_WindowsAzure_Storage_TableEntity
{
    /**
     * @azure Imie
     */
    public $imie;

    /**
     * @azure Nazwisko
     */
    public $nazwisko;

    /**
     * @azure Wiek Edm.Int32
     */
    public $wiek;
}

Komentarz opisujący każdą właściwość musi zawierać tag @azure, po którym znajduje się nazwa właściwości (nie musi być taka sama jak nazwa zmiennej). Opcjonalną informacją zawartą w komentarzu jest typ danych. Do dyspozycji mamy:

  • Edm.Binary – dane binarne w postaci tablicy o maksymalnym rozmiarze 64KB
  • Edm.Boolean – wartość logincza
  • Edm.DateTime – data w formacie UTC
  • Edm.Double – wartość zmiennoprzecinkowa
  • Edm.Guid – unikatowy identyfikator
  • Edm.Int32 – liczba całkowita 32 bitowa
  • Edm.Int64 – liczba całkowita 64 bitowa
  • Edm.String – ciąg znaków

Jeśli nie zdefiniujemy żadnego typu, dane zostaną zapisane jako Edm.String.

Encja z dynamicznym schematem

Ten rodzaj encji nie wymaga definiowania klasy encji. Podczas korzystania z tego rodzaju encji wystarczy utworzyć obiekt typu Microsoft_WindowsAzure_Storage_DynamicTableEntity, który dziedziczy po klasie Microsoft_WindowsAzure_Storage_TableEntity, dzięki czemu wszystkie funkcjonalności encji są zachowane. Korzystanie z takiego obiektu jest identyczne jak w przypadku encji o określonym schemacie z tą różnicą, że typ danych definiuje się przy pomocy metody setAzurePropertyType.

$encja = new Microsoft_WindowsAzure_Storage_DynamicTableEntity();
$encja->Imie = 'Jan';
$encja->Nazwisko = 'Kowalski';
$encja->Wiek = 30;
$encja->setAzurePropertyType('Wiek', 'Edm.Int64');
Wbudowane właściwości encji

Oprócz właściwości opisujących dany obiekt, encje zawierają cztery dodatkowe:

  • PartitionKey – klucz partycji określający partycję, w której znajduje się encja
  • RowKey – klucz wiersza, który musi być unikatowy w obrębie partycji
  • Timestamp – określa datę ostatniej zmiany encji
  • Etag – znacznik określający wersję encji

Najważniejszymi są PartitionKey oraz RowKey, stanowiące klucz główny tabeli. Kombinacja tych dwóch właściwości musi być unikatowa.

Korzystanie z tabel i encji

Operacje na tabelach nie różnią się niczym od operacji na blobach i kolejkach. Podobnie jak w przypadku pozostałych mechanizmów przechowywania danych, wszystko sprowadza się do utworzenia pojemnika (w tym przypadku tabeli) i zapisania w nim danych (encji). Tabele dodały do tego schematu możliwość korzystania z transakcji oraz mechanizm filtrowania danych.

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

Autor wpisu: Śpiechu, dodany: 02.01.2011 21:47, tagi: php

To pierwszy wpis w tym roku, mam nadzieję, że wyda się Wam na poziomie. Czytam co nieco na temat wzorca memento i trochę ubolewam, że nie znam C++, gdyż wszystkie przykłady we Wzorcach projektowych1 napisane są właśnie w tym języku (część gwiazdek i innych dwukropków w kodzie jest dla mnie trochę niezrozumiała).

Na warsztat wziąłem dzisiaj wzorzec memento (wg mnie tłumaczenie jako „pamiątka” jest trochę śmieszne; memento to memento i koniec). Za pomocą tego wzorca możemy sporządzić coś na kształt kopii przywracania stanu obiektu. Ma to zastosowanie głównie jako mechanizm wstecz/cofnij w standardowych aplikacjach. Jak ktoś się uprze, to na pewno w PHP również znajdzie zastosowanie.

Napisanie kodu obiektu trzymającego stan innego obiektu jest dosyć proste, dlatego podniosłem trochę poprzeczkę o sprawdzanie kto wywołuje dany obiekt i czy dane memento jest na pewno dla niego przeznaczone. W/w mądra książka mówi do mnie, że tworzyć i przywracać stan ma obiekt, którego stan dotyczy. Za to przechowywaniem stanów zajmować się odrębny obiekt — CareTaker (u mnie PrzechowywaczMemento :-) ).

Najpierw idzie obiekt zainteresowany przechowywaniem swojego stanu. Stan każdego obiektu to przypisane wartości do jego zmiennych. U mnie będzie to tylko zmienna $komunikat.

class JakisObiekt {
 
    /**
     * @var string komunikat do wyswietlenia
     */
    protected $komunikat;
 
    /**
     * @return string komunikat
     */
    public function getKomunikat() {
        return $this->komunikat;
    }
 
    /**
     * @param string $k komunikat do ustawienia
     */
    public function setKomunikat($k) {
        $this->komunikat = $k;
    }
 
    /**
     * @return Memento memento z aktualnym komunikatem obiektu
     */
    public function getMemento() {
        return new Memento($this);
    }
 
    /**
     * @param Memento $memento zawierajace poprzedni komunikat
     */
    public function setMemento(Memento $memento) {
        try {
            $this->komunikat = $memento->getKomunikat(spl_object_hash($this)) . ' (przywrocony z Memento)';
        }
        catch (Exception $e) {
            echo 'Nie udalo sie przywrocic poprzedniego stanu: ' . $e->getMessage();
        }
    }
}

Zainteresować może was funkcja spl_object_hash. Zwraca unikalny identyfikator (hash) danego obiektu. Memento zapisuje sobie identyfikator przy tworzeniu, a przy chęci wywołania getKomunikat() wymaga podanie hasha w celu sprawdzenia czy dane memento jest na pewno dla niego.

Dalej idzie kod tytułowego memento, czyli obiekt przechowujący stan obiektu. Jest ściśle powiązane z obiektem JakisObiekt (lub jego potomkami).

class Memento {
 
    /**
     * @var string hash obiektu tworzacego memento
     */
    private $hash;
 
    /**
     * @var string przechowywany komunikat
     */
    private $komunikat;
 
    public function __construct(JakisObiekt $ob) {
        if ($this->czyLegalnyWywolujacy() === true) {
            $this->hash = spl_object_hash($ob);
            $this->komunikat = $ob->getKomunikat();
        }
        else {
            throw new Exception('Tylko obiekt z rodziny JakisObiekt moze tworzyc klase Memento');
        }
    }
 
    public function getKomunikat($hash) {
        if ($this->czyLegalnyWywolujacy() !== true) {
            throw new Exception('Tylko obiekt z rodziny JakisObiekt moze wywolac funkcje getKomunikat()');
        }
        if ($this->hash !== $hash) {
            throw new Exception('Hash obiektu tworzacego Memento i wywolujacego getKomunikat() nie zgadza sie');
        }
        return $this->komunikat;
    }
 
    private function czyLegalnyWywolujacy() {
        $trace = debug_backtrace(true);
        if (!empty($trace[2]['object']) && is_a($trace[2]['object'],'JakisObiekt')) {
            return true;
        }
        else {
            return false;
        }
    }
}

Tu z kolei powinna Was zainteresować funkcja czyLegalnyWywolujacy(). To cudo wywołuje (prawdopodobnie) zasobożerną funkcję debug_backtrace i sprawdza kto 2 kroki wcześniej poprosił o wywołanie funkcji. Jeżeli jest to kto inny niż obiekt typu JakisObiekt to się obraża i daje sygnał do wywalenia wyjątku. Fajne, co?

Dla sprawdzenia czy memento jest w stanie przyjmować żądania od obiektów dziedziczonych po JakisObiekt tworzymy sobie obiekt Dziedziczony.

class Dziedziczony extends JakisObiekt { }

Na koniec podaję kod przechowywacza, który zajmuje się zapisem kolejnych wersji i odtwarzaniem ich. Po niewielkich przeróbkach kod może stać się w zasadzie uniwersalny.

class PrzechowywaczMemento {
 
    /**
     * @var array tablica asocjacyjna o konstrukcji hash => memento
     */
    private $stany;
 
    public function __construct() {
        $this->stany = array();
    }
 
    public function zapiszStan(JakisObiekt $jo) {
        $this->stany[spl_object_hash($jo)][] = $jo->getMemento();
    }
 
    public function przywrocStan(JakisObiekt $jo) {
        $hash = spl_object_hash($jo);
        $znalezionyStan = (!empty($this->stany[$hash])) ?
                array_pop($this->stany[$hash]) :
                null;
        if ($znalezionyStan !== null) {
            $jo->setMemento($znalezionyStan);
        }
        else {
            echo 'Brak zapisanego wczesniejszego stanu dla tego obiektu <br />';
        }
    }
 
    public function oczyscRejestrMemento() {
        foreach ($this->stany as $key => $val) {
            if (count($val) == 0) {
                unset($this->stany[$key]);
            }
        }
    }
}

Metoda przywrocStan() może być trochę zawiła. Najpierw sprawdza czy klucz z haszem podanego w parametrze obiektu w ogóle istnieje. Jeżeli tak to przywraca stan, a jeżeli nie to wypisuje komunikat. Na koniec mamy bezparametrową metodę oczyscRejestrMemento(). Jeżeli przez przechowywacza przeszło wiele obiektów, robi się śmietnik kluczy niezawierających stanów do przywrócenia.

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.