KIELMAS.COM Kielmas Jarosław

Blog głównie o programowaniu

Browsing Posts in PHP, Narzędzia, Frameworki

Dla ludzi, którzy mają problem z wygenerowaniem sobie najnowszej dokumentacji Zend Framework w polskim języku udostępniam  quickstart, pochodzący z   wersji 2.0.0dev1.

Oprócz tego dla pozostałych, pracujących na *nix (dla Windows wymagany jest CYGWIN), króciutki opis jak wygenerować sobie pełną  dokumentację ( oczywiście nie wszystko jest przetłumaczone).

Wcześniej zainstaluj sobie następujące biblioteki:

  • autoconf
  • make
  • xsltproc
  • xmllint

Następnie:

$ git clone git://git.zendframework.com/zf.git
$ cd ZendFramework-2.0.0dev1/documentation/manual/pl
$ autoconf (zostanie wygenerowany ./configure)
$ ./configure
$ make

Czekamy chwilkę, w między czasie powstaje sobie _temp_manual.xml, który potem zostanie pokrojony na odpowiednie dokumenty html w katalogu html/

Poniżej dokumentacja w postaci html do ściągnięcia

Od czterech dni dostępna  jest  wersja 2.0.0dev1 tego znakomitego frameworka dla PHP5. W ramach pierwszego   milestone’a ekipa Zend Frameworka bardzo się napracowała.

Rewolucja, przez którą nastapiła  zmiana  z „1″ na „2″ w numerze wersji już dla tego wydania, polega przede wszystkim na:

  • usunięciu (niby) wszystkich „reqiure_once” z komponentów ZF (uzywamy autoloader),
  • wprowadzenie namespace,
  • poprawa mechanizmu testów jednostkowych,
  • przepisanie od zera komponentu Zend/Session (w ramach ticketu powstał nowy nowy komponent Zend/SignalSlot,
  • wprowadzenie nowej przestrzeni nazw Zend/Stdlib,

Wydanie tak naprawdę pokazuje jedynie tyle, że ekipa rozwijająca Zend Framework nie próżnuje i można je traktować  jako możliwość zapoznania się z zaawansowaniem prac, nie jest to ukończony framework  – stawianie aplikacji na tym wydaniu, jak oznajmił zespół, jest na własne ryzyko.

Roadmap ZF z gałęzi 2.0 jest jeszcze daleki do ukończenia.

W piątek pojawiła się kolejna, już siódma,  wersja Zend Framework’a z serii 1.10. Poprawiono około 60 bug’ów, które opisane są w changelog. Zachęcam do aktualizacji Waszych projektów.

W ramach wydania wersji  dotknięto następujące pliki:

# git status
#	modified:   Application/Bootstrap/BootstrapAbstract.php
#	modified:   Application/Resource/Exception.php
 
#	modified:   Auth/Adapter/DbTable.php
 
#	modified:   Cache/Backend/Static.php
#	modified:   Cache/Backend/Test.php
#	modified:   Cache/Backend/TwoLevels.php
#	modified:   Cache/Core.php
#	modified:   Cache/Frontend/Class.php
#	modified:   Cache/Frontend/Function.php
#	modified:   Cache/Manager.php
 
#	modified:   Captcha/Image.php
 
#	modified:   Console/Getopt.php
 
#	modified:   Crypt/Math/BigInteger/Bcmath.php
 
#	modified:   Db/Adapter/Pdo/Pgsql.php
#	modified:   Db/Table/Rowset/Abstract.php
 
#	modified:   Feed/Pubsubhubbub/Model/Subscription.php
 
#	modified:   File/Transfer/Adapter/Http.php
 
#	modified:   Filter/StripTags.php
 
#	modified:   Gdata/App.php
 
#	modified:   Gdata/Gapps.php
 
#	modified:   Http/Client.php
#	modified:   Http/Client/Adapter/Socket.php
#	modified:   Http/Response.php
 
#	modified:   Json/Decoder.php
 
#	modified:   Ldap.php
 
#	modified:   Loader/PluginLoader.php
 
#	modified:   Locale.php
#	modified:   Locale/Format.php
 
#	modified:   Log.php
#	modified:   Log/Writer/Abstract.php
#	modified:   Log/Writer/Db.php
#	modified:   Log/Writer/Syslog.php
#	modified:   Log/Writer/ZendMonitor.php
 
#	modified:   Mail/Protocol/Smtp/Auth/Crammd5.php
#	modified:   Mail/Protocol/Smtp/Auth/Plain.php
 
#	modified:   OpenId.php
 
#	modified:   Paginator/AdapterAggregate.php
#	modified:   Paginator/SerializableLimitIterator.php
 
#	modified:   Pdf.php
#	modified:   Pdf/FileParser/Image/Png.php
#	modified:   Pdf/Filter/Ascii85.php
#	modified:   Pdf/Resource/Image/Png.php
 
#	modified:   Search/Lucene/Index/SegmentInfo.php
 
#	modified:   Service/Amazon/S3/Stream.php
#	modified:   Service/Flickr.php
#	modified:   Service/Twitter.php
 
#	modified:   Session.php
 
#	modified:   Test/PHPUnit/Constraint/DomQuery.php
 
#	modified:   Tool/Project/Provider/Manifest.php
 
#	modified:   Translate.php
#	modified:   Translate/Adapter.php
#	modified:   Translate/Adapter/Gettext.php
#	modified:   Translate/Plural.php
 
#	modified:   Uri.php
 
#	modified:   Validate/Alnum.php
#	modified:   Validate/Alpha.php
#	modified:   Validate/Barcode.php
#	modified:   Validate/Callback.php
#	modified:   Validate/CreditCard.php
#	modified:   Validate/Date.php
#	modified:   Validate/Db/Abstract.php
#	modified:   Validate/Digits.php
#	modified:   Validate/EmailAddress.php
#	modified:   Validate/File/Crc32.php
#	modified:   Validate/File/ExcludeExtension.php
#	modified:   Validate/File/Extension.php
#	modified:   Validate/File/Hash.php
#	modified:   Validate/File/ImageSize.php
#	modified:   Validate/File/IsCompressed.php
#	modified:   Validate/File/IsImage.php
#	modified:   Validate/File/Md5.php
#	modified:   Validate/File/MimeType.php
#	modified:   Validate/File/Sha1.php
#	modified:   Validate/File/Size.php
#	modified:   Validate/File/WordCount.php
#	modified:   Validate/Float.php
#	modified:   Validate/Hex.php
#	modified:   Validate/Hostname.php
#	modified:   Validate/Int.php
#	modified:   Validate/Ip.php
#	modified:   Validate/Isbn.php
#	modified:   Validate/NotEmpty.php
#	modified:   Validate/PostCode.php
#	modified:   Validate/Regex.php
#	modified:   Validate/Sitemap/Changefreq.php
#	modified:   Validate/Sitemap/Lastmod.php
#	modified:   Validate/Sitemap/Loc.php
#	modified:   Validate/Sitemap/Priority.php
#	modified:   Validate/StringLength.php
#	modified:   Version.php

i dodano :

	Gdata/Gapps/Extension/Property.php
#	Gdata/Gapps/GroupEntry.php
#	Gdata/Gapps/GroupFeed.php
#	Gdata/Gapps/GroupQuery.php
#	Gdata/Gapps/MemberEntry.php
#	Gdata/Gapps/MemberFeed.php
#	Gdata/Gapps/MemberQuery.php
#	Gdata/Gapps/OwnerEntry.php
#	Gdata/Gapps/OwnerFeed.php
#	Gdata/Gapps/OwnerQuery.php

Logowanie błędów jest kluczowym elementem minitoringu aplikacji. Przekonał się o tym chociażby każdy programista, który pracuje w firmie oferującej dodatkowo dla swoich produktów terminowy support.

Dzięki temu, że błędy są logowane jesteśmy w stanie szybko i czasami transparentnie wyeliminować bugi w aplikacji, tak że klient nawet się nie dowie o ich istnieniu:)

Jeśli Zend Framework jest podstawą twojego projektu oferuję Tobie bardzo wygodny i przejrzysty sposób na logowanie błędów aplikacji.

Potrzebna będzie jedna klasa, ponieważ aż się prosi aby system logowania błędów był ładowany jako resource, przez Zend_Application. Zarządzanie zasobów zaprezentowane w Zend Framework jest moim zdaniem rewelacyjne, ponieważ bardzo łatwo możemy wydzielić zasoby, dzięki czemu mamy wprowadzoną dodatkową  logikę i ład w naszej aplikacji,  ponadto  dowolny zasób  można łatwo i sprawnie włączyć/wyłączyć.

Przykładowa klasa mogłaby wygłądać następująco:

class Zextend_Application_Resource_Log extends Zend_Application_Resource_ResourceAbstract
{
 
    public function init()
    {
        /**
         * Pobranie głównej konfiguracji.
         */
        $config = $this->getBootstrap()->getContainer()->config;
 
        /**
         * Przygotowanie formatu zapisanej informacji.
         *
         * @example Postać zmiennej $config->format:
         * "%timestamp% %priorityName%: %message%"
         */
        $format = new Zend_Log_Formatter_Simple($config->format . PHP_EOL);
 
        /**
         * Sprawdzanie, ktory sposób logowania błędów został włączony.
         *
         * @example Postać zmiennej $config->log->stream:
         * "../temporary/log/error.log" 
         */
        $logger = new Zend_Log();
        if($config->log->file) {
           $logger->addWriter(
                   $this->_getStreamWriter($format, $config->log->stream));
        }
 
        if($config->log->stdoutput) {
           $logger->addWriter(
                   $this->_getStreamWriter($format, 'php://output'));
        }
 
        if($config->log->firebug) {
           $logger->addWriter(
                   $this->_getFirebugWriter($format));
        }
        if($config->log->mail) {
            $logger->addWriter($this->_getMailWriter($config));
        }
 
        /**
         * Używamy tego logger wszędzie w aplikacji.
         */
        Zend_Registry::set( 'log', $logger );
        return $logger;
    }
    /**
     * Zwraca obiekt zapisania informacja do Firebug.
     * 
     * @param Zend_Log_Formatter_Simple $format
     * @return Zend_Log_Writer_Firebug
     */
    private function _getFirebugWriter(Zend_Log_Formatter_Simple $format)
    {
        $writer = new Zend_Log_Writer_Firebug();
        $writer->setFormatter($format);
 
        return $writer;
    }
    /**
     * Zwraca obiekt zapisania informacji w postaci emaila.
     *
     * @param Zend_Config_Ini $config
     * @return Zend_Log_Writer_Mail
     */
    private function _getMailWriter(Zend_Config_Ini $config)
    {
        $mail = new Zend_Mail();
        $mail->setDefaultTransport(new Zend_Mail_Transport_Smtp());
 
        $mail->setFrom($config->email->from, $config->email->fromAlias);
        $mail->addTo($config->app->admin->email);
        $mail->addTo($config->app->webmaster->email);
        $mail->setSubject($config->app->name . ' - nastapil nieoczekiwany blad!');
 
        $writer = new Zend_Log_Writer_Mail($mail);
        $writer->addFilter(Zend_Log::WARN);
 
        return $writer;
    }
    /**
     * Zwraca obiekt zapisania informacji do PHP stream.
     * 
     * @param Zend_Log_Formatter_Simple $format
     * @param string $stream
     * @return Zend_Log_Writer_Stream
     */
    private function _getStreamWriter(Zend_Log_Formatter_Simple $format, $stream = '')
    {
        $writer = new Zend_Log_Writer_Stream($stream);
        $writer->setFormatter($format);
 
        return $writer;
    }
}

Jak widać oferuje ona możliwość logowania błędów na kilka sposobów: streaming do pliku, badź na ekran, JSON’em prosto do firebug’a (warunkiem odczytu jest zainstalowanie wtyczki FirePHP w Firefox) lub powiadomienie na email. W przykładzie część konfiguracji znajduje się w pliku /application/configs/application.ini, ktory ładowany jest poprzez Zend_Config_Ini do rejestru. Odczytany zostaje między innymi email do webmastera oraz do admina, czyli osób odpowiedzialnych za poprawne działanie aplikacji, ponadto zdefiniowane są takie parametry jak scieżka do pliku  z blędami (error.log) czy też format komunikatu z błędem.

Oczywiście trzeba tę funkcjonalność dołączyć  do projektu jako  nowy zasób. Nic prostszego – w pliku konfiguracyjnym /application/configs/application.ini dodajemy kolejny resource do listy:

resources.types      = "array()"
resources.view       = "array()"
resources.navigation = "array()"
resources.log        = "array()"

Dodatkowo musimy zdefniować ustawienia, które załączają odpowiednei przekazanie informacji o błędzie. Czyli znów w /application/configs/application.ini dopisujemy:

log.file      = true
log.firebug   = true
log.mail      = true
log.stdoutput = true

Rzecz jasna korzystamy z odpowiedniego typu logowania w zależności od potrzeb. Bardzo wygodnie jest w trakcie tworzenia kodu, czy też jego testowania, otrzymywać komunikaty do konsoli FF, wykorzystując firePHP, dodatkowo wygodne jest odczytywanie błędów z pliku error.log – otwieramy konsole i  dajemy polecenie:

# tail -f error.log

i mamy nasz system monitorujacy, w którym dokładnie zapisane jest gdzie wystąpił nieoczekiwany błąd (kupujemy telewizor LCD, który pokazuje te komunikaty przez cały czas :) oczywiście żartuje :) ).  Jeśli aplikacja jest już w wersji produkcyjnej to bardzo fajne jest rozwiązanie z przychodzącym emailem – można wtedy szybko interweniować.

Pamiętajmy jednak, że jeśli aplikacja jest już na produkcji, należy zablokować logowanie błędów do FireBug’a!!

Logowane błędy są tylko dla nas – developerów, adminów, …,  i mają stanowić wskazówkę do szybkiego ich  rozwiązania. Jeśli te informacje trafią do niepowołanych rąk to niestety możemy wskazać najsłabsze ogniwo naszej aplikacji, a tym samym stworzyć okazję do włamania się do niej np. hackerowi.

Kolejną sprawą jest miejsce, w którym nasz logger, trzymany w rejestrze, może dokonać zapisu błędu. Jednym z lepszym miejsc jest kontroler ErrorController.php i w nim metoda errorAction,  na którą domyślnie przekierowany jest błąd. Oczywiście gdzie będzie odbywało się logowanie błędów utożsamiony z tą linijką kodu:

if (Zend_Registry::isRegistered('log')) {
            $logger = Zend_Registry::get('log');
            if (!is_null($this->_error)) {
                $logger->log(
                    $this->_error->exception->getMessage() . "\n\n" .
                    $this->_error->exception->getTraceAsString(),
                    Zend_Log::ERR
                );
            }
        }

jest uzależnione od  potrzeb aplikacji i zaprojektowania jej przez programistę.

Taki sposób logowania błędów  można implementować w każdym projekcie – nie tylko opartym o Zend Framework. Po drobnych modyfikacjach, korzystając tylko z kilku komponentów (w wersji ZF 1.10.6), Log(20 plików), Wildfire (8 plików),  Json (14 plików), Config (8 plików) + Exception.php, można stworzyć taki sam system logowania błędów.