KIELMAS.COM Kielmas Jarosław

Blog głównie o programowaniu

Browsing Posts in Zend Framework

Zend_Loader_Autoloader_Resource umożliwia  łatwą ingerencję w domyślną strukturę plików i katalogów ZF, a co za tym stoi -  manipulowanie ich nazwami.

Przykładowo w Twoim projekcie przewidziałeś dwa (lub więcej) modułów, np. /application/modules/default/ oraz /application/modules/panel. Chciałbyś teraz uporządkować w ich ramach np. modele, viewhelper’y, formularze, aby zachować porządek nazewnictwa tych klas i logikę ich wywołania.  Wygłądałoby to tak:

/application/modules/default/models
 
/application/modules/default/forms
 
/application/modules/default/views/helpers

oraz

/application/modules/panel/models
 
/application/modules/panel/forms
 
/application/modules/panel/views/helpers

Kolejne nazwy klas, w takim układzie  nazywałyby się np.:  Default_Model_Foo, Default_Form_Foo, Default_View_Helper_Foo,  Panel_Model_Foo,  Panel_Form_Foo, itd …

Oczywiście, przed każdą inicjalizacją obiektu, którejś z tych  klas NIE postępujemy w ten sposób:

require_once '/application/modules/panel/forms/Foo.php';
$form = new Panel_Form_Foo();

ponieważ PHP5 (jak już kiedyś wspominałem) w wielu przypadkach sprawniej radzi sobie z
załadowaniem pliku przez __autoload niż używajać funkcji require_once.
Zatem dążymy do stworzenia instancji nowego obiektu, a jego załadowaniem niech zajmie się Zend Framework.

Możemy to zrobić na przykład dodając nowy zasób, który wskazywał by frameworkowi przestrzeń nazw, oraz lokalizację, w których te klasy się znajdują. Takie rozwiązanie, po pierwsze pozwoli nam wykorzystać świetny mechanizm Application Resource, a także zachować porządek w naszej aplikacji. Przykładowa klasa wyglądała by tak:

class Zextend_Application_Resource_Types extends Zend_Application_Resource_ResourceAbstract
{
 
    public function init()
    {
        $resourceAutoloader = new Zend_Loader_Autoloader_Resource( array(
                        'basePath'      => APPLICATION_PATH,
                        'namespace'     => 'Default',
                        'resourceTypes' => array(
                                            'form' => array(
                                                            'path'       => 'modules/default/forms',
                                                            'namespace'  => 'Form'),
                                            'viewhelper' =>  array(
                                                             'path'       => 'modules/default/views/helpers',
                                                             'namespace' =>  'View_Helper')
                            )
                        ));
        $resourceAutoloader = new Zend_Loader_Autoloader_Resource( array(
                        'basePath'      => APPLICATION_PATH,
                        'namespace'     => 'Panel',
                        'resourceTypes' => array(
                                            'form'       =>  array(
                                                                   'path'       => 'modules/panel/forms',
                                                                   'namespace'  => 'Form'),
                                            'model' =>  array(
                                                             'path'      =>  'modules/panel/models',
                                                             'namespace' =>  'Model',
 
                                            ),
                                            'viewhelper' =>  array(
                                                                   'path'       => 'modules/panel/views/helpers',
                                                                   'namespace' =>  'View_Helper')
                                                    )
        ));
    }
 
}

Pamiętajmy o  odpowiednim wpisie do applikcation.ini:

resources.types      = „array()”

Dzięki takiemu rozwiązaniu wprowadziliśmy do struktury aplikacji naszą logikę, którą bardzo łatwo możemy uruchomić lub przestać z niej korzystać.

Matipl powiadomił o najnowszej wersji ZF 1.10.4 i wskazał na wiele poprawek poprawiającaych bezpieczeństwo frameworka. Po aktualizacji i dodaniu do repo  można się przekonać ile plików zostało dotkniętych poprawkami. Oto wynik svn status

M       Zend/File/Transfer/Adapter/Http.php
M       Zend/File/Transfer/Adapter/Abstract.php
M       Zend/File/Transfer.php

M       Zend/Dom/Query.php

M       Zend/Log/Filter/Abstract.php
M       Zend/Log/Filter/Message.php
?       Zend/Log/Writer/ZendMonitor.php

M       Zend/Form.php

M       Zend/Dojo/View/Helper/Dojo/Container.php

M       Zend/Loader.php

?       Zend/Service/WindowsAzure
?       Zend/Service/LiveDocx.php
?       Zend/Service/DeveloperGarden
?       Zend/Service/LiveDocx
M       Zend/Service/Amazon/Item.php
M       Zend/Service/Amazon/Offer.php
M       Zend/Service/Amazon/Sqs.php
M       Zend/Service/Flickr.php

M       Zend/Soap/Wsdl/Strategy/ArrayOfTypeComplex.php

?       Zend/Feed/Writer.php
?       Zend/Feed/Pubsubhubbub
?       Zend/Feed/Writer
?       Zend/Feed/Pubsubhubbub.php
?       Zend/Feed/Reader/Collection.php
?       Zend/Feed/Reader/Collection
?       Zend/Feed/Reader/Feed/Atom

?       Zend/Config/Writer/FileAbstract.php

?       Zend/Pdf/Filter/RunLength.php

?       Zend/Pdf/Annotation/Markup.php

M       Zend/Pdf/Resource/Font/Extracted.php

M       Zend/Pdf/Element/String.php

?       Zend/Http/Response
M       Zend/Http/Cookie.php
M       Zend/Http/Client.php
?       Zend/Http/Client/Adapter/Stream.php
M       Zend/Http/Client/Adapter/Proxy.php
M       Zend/Http/Client/Adapter/Socket.php

M       Zend/Validate.php

M       Zend/Ldap/Attribute.php
M       Zend/Ldap/Ldif/Encoder.php

M       Zend/Oauth/Http/Utility.php
M       Zend/Oauth/Client.php

M       Zend/CodeGenerator/Php/Class.php

M       Zend/Controller/Request/Http.php
?       Zend/Controller/Action/Helper/Cache.php
M       Zend/Controller/Response/Abstract.php

M       Zend/Paginator/Adapter/Null.php

M       Zend/Db/Adapter/Sqlsrv.php
M       Zend/Db/Statement/Pdo/Oci.php
M       Zend/Db/Table/Row/Abstract.php
M       Zend/Db/Table/Abstract.php

M       Zend/Cache.php

?       Zend/Currency/CurrencyInterface.php

M       Zend/TimeSync/Ntp.php

M       Zend/Translate/Adapter/Csv.php
M       Zend/Translate/Adapter/Tmx.php
M       Zend/Translate/Adapter.php

M       Zend/Memory.php

M       Zend/Barcode/Object/Code39.php

M       Zend/Locale/Data.php
M       Zend/Locale/Math.php
M       Zend/Locale/Format.php

M       Zend/Markup/Renderer/RendererAbstract.php
M       Zend/Markup/Renderer/Html.php

M       Zend/Markup/Parser/Bbcode.php

M       Zend/Auth/Adapter/Ldap.php
M       Zend/Log.php

?       Zend/View/Helper/Currency.php
M       Zend/View/Helper/FormElement.php

M       Zend/View/Abstract.php

M       Zend/Date/DateObject.php

M       Zend/Tool/Project/Profile/Resource/Container.php
M       Zend/Tool/Project/Profile/FileParser/Xml.php

?       Zend/Tool/Project/Context/Zf/LayoutScriptFile.php
?       Zend/Tool/Project/Context/Zf/LayoutScriptsDirectory.php
?       Zend/Tool/Project/Context/Zf/AbstractClassFile.php
?       Zend/Tool/Project/Context/Zf/DocsDirectory.php
M       Zend/Tool/Project/Context/Zf/ApplicationConfigFile.php
M       Zend/Tool/Project/Context/Zf/HtaccessFile.php
M       Zend/Tool/Project/Context/Zf/ApplicationDirectory.php
M       Zend/Tool/Project/Context/Zf/DbTableFile.php
M       Zend/Tool/Project/Context/Zf/ZfStandardLibraryDirectory.php
M       Zend/Tool/Project/Context/Filesystem/File.php
M       Zend/Tool/Project/Context/System/ProjectProfileFile.php

M       Zend/Tool/Project/Profile.php
?       Zend/Tool/Project/Provider/DbTable.php
?       Zend/Tool/Project/Provider/Application.php
?       Zend/Tool/Project/Provider/Layout.php
?       Zend/Tool/Project/Provider/DbAdapter.php
M       Zend/Tool/Project/Provider/Action.php
M       Zend/Tool/Project/Provider/Model.php
M       Zend/Tool/Project/Provider/Controller.php
M       Zend/Tool/Project/Provider/Module.php
M       Zend/Tool/Project/Provider/Project.php

?       Zend/Tool/Framework/Metadata/Attributable.php
?       Zend/Tool/Framework/System/Provider/Config.php
?       Zend/Tool/Framework/Loader/Interface.php
?       Zend/Tool/Framework/Loader/BasicLoader.php
M       Zend/Tool/Framework/Loader/IncludePathLoader.php

?       Zend/Tool/Framework/Client/Manifest.php
?       Zend/Tool/Framework/Client/Console/ResponseDecorator/AlignCenter.php
?       Zend/Tool/Framework/Client/Console/ResponseDecorator/Blockize.php
?       Zend/Tool/Framework/Client/Console/ResponseDecorator/Indention.php
M       Zend/Tool/Framework/Client/Abstract.php

M       Zend/Mail/Protocol/Abstract.php

M       Zend/Mail/Transport/Sendmail.php

?       Zend/Queue/Adapter/Db/queue_sqlite.sql

?       Zend/Filter/Null.php
?       Zend/Filter/Compress.php
?       Zend/Filter/Decompress.php
?       Zend/Filter/Compress
?       Zend/Filter/Boolean.php
M       Zend/Filter/PregReplace.php
M       Zend/Filter/HtmlEntities.php
M       Zend/Filter/StripTags.php
M       Zend/Filter/StringToLower.php
M       Zend/Filter/Word/CamelCaseToSeparator.php
M       Zend/Filter/Inflector.php
M       Zend/Filter/StringToUpper.php

M       Zend/Reflection/File.php

M       Zend/Measure/Abstract.php

M       Zend/Form/Element.php
M       Zend/Form/Decorator/Fieldset.php
M       Zend/Form/Decorator/Abstract.php
M       Zend/Form/Decorator/Label.php

?       Zend/XmlRpc/Generator
M       Zend/XmlRpc/Value.php
M       Zend/XmlRpc/Value/Double.php
M       Zend/XmlRpc/Value/Array.php
M       Zend/XmlRpc/Value/Struct.php
M       Zend/XmlRpc/Value/Scalar.php

M       Zend/Wildfire/Channel/HttpHeaders.php

M       Zend/Loader/PluginLoader.php

M       Zend/Oauth.php

M       Zend/Currency.php

M       Zend/Translate.php

M       Zend/Text/MultiByte.php

M       Zend/Exception.php

M       Zend/Locale.php

?       Zend/Validate/Callback.php
?       Zend/Validate/CreditCard.php
?       Zend/Validate/PostCode.php
?       Zend/Validate/Isbn.php
M       Zend/Validate/File/MimeType.php
M       Zend/Validate/File/IsCompressed.php
M       Zend/Validate/File/ExcludeMimeType.php
M       Zend/Validate/File/IsImage.php
M       Zend/Validate/File/Count.php
M       Zend/Validate/EmailAddress.php
M       Zend/Validate/Abstract.php
M       Zend/Validate/Float.php
M       Zend/Validate/Barcode.php
M       Zend/Validate/Iban.php
?       Zend/Validate/Barcode/Royalmail.php
?       Zend/Validate/Barcode/Sscc.php
?       Zend/Validate/Barcode/Ean8.php
?       Zend/Validate/Barcode/Postnet.php
?       Zend/Validate/Barcode/Upce.php
?       Zend/Validate/Barcode/Identcode.php
?       Zend/Validate/Barcode/AdapterInterface.php
?       Zend/Validate/Barcode/Gtin12.php
?       Zend/Validate/Barcode/Code25interleaved.php
?       Zend/Validate/Barcode/AdapterAbstract.php
?       Zend/Validate/Barcode/Gtin13.php
?       Zend/Validate/Barcode/Gtin14.php
?       Zend/Validate/Barcode/Ean12.php
?       Zend/Validate/Barcode/Code39ext.php
?       Zend/Validate/Barcode/Code93ext.php
?       Zend/Validate/Barcode/Ean14.php
?       Zend/Validate/Barcode/Issn.php
?       Zend/Validate/Barcode/Ean18.php
?       Zend/Validate/Barcode/Code25.php
?       Zend/Validate/Barcode/Intelligentmail.php
?       Zend/Validate/Barcode/Planet.php
?       Zend/Validate/Barcode/Ean2.php
?       Zend/Validate/Barcode/Code39.php
?       Zend/Validate/Barcode/Code93.php
?       Zend/Validate/Barcode/Itf14.php
?       Zend/Validate/Barcode/Ean5.php
?       Zend/Validate/Barcode/Leitcode.php
?       Zend/Validate/Barcode/Upca.php
M       Zend/Validate/Regex.php
M       Zend/Validate/Sitemap/Loc.php
M       Zend/Validate/Sitemap/Priority.php
M       Zend/Validate/Sitemap/Changefreq.php
M       Zend/Validate/Sitemap/Lastmod.php
M       Zend/Validate/Hostname.php
M       Zend/Validate/Digits.php

M       Zend/Amf/Response.php
M       Zend/Amf/Parse/Serializer.php
M       Zend/Amf/Parse/Amf0/Serializer.php
M       Zend/Amf/Parse/Amf0/Deserializer.php
M       Zend/Amf/Parse/Amf3/Serializer.php
M       Zend/Amf/Parse/Amf3/Deserializer.php
M       Zend/Amf/Server.php
M       Zend/Amf/Util/BinaryStream.php

?       Zend/Application/Resource/Dojo.php
?       Zend/Application/Resource/Cachemanager.php
?       Zend/Application/Resource/Multidb.php
?       Zend/Application/Resource/Log.php
?       Zend/Application/Resource/Mail.php
M       Zend/Application/Resource/View.php
M       Zend/Application/Resource/Frontcontroller.php
M       Zend/Application/Resource/Layout.php
M       Zend/Application/Resource/Translate.php
M       Zend/Application/Resource/Locale.php
M       Zend/Application/Resource/Navigation.php
M       Zend/Application/Resource/Router.php
M       Zend/Application/Resource/Session.php
M       Zend/Application/Resource/Db.php
M       Zend/Application/Resource/Modules.php
M       Zend/Application/Bootstrap/Bootstrap.php
M       Zend/Application/Bootstrap/BootstrapAbstract.php

?       Zend/Cache/Manager.php
?       Zend/Cache/Frontend/Capture.php
?       Zend/Cache/Backend/BlackHole.php
?       Zend/Cache/Backend/Static.php
M       Zend/Cache/Backend/File.php
M       Zend/Cache/Backend/Test.php
M       Zend/Cache/Backend/TwoLevels.php
M       Zend/Cache/Backend/Memcached.php
M       Zend/Cache/Backend.php
M       Zend/Cache/Core.php

M       Zend/Date.php

M       Zend/Search/Lucene.php
M       Zend/Search/Lucene/Search/QueryParser.php
M       Zend/Search/Lucene/Document/Html.php

M       Zend/Mail.php

M       Zend/Filter.php

M       Zend/Version.php

Jak widać jest to długa lista zmian, dotyczące główne komontenty frameworka.

Bardzo często systemem, na którym pracują programiści webaplikacji (mam na myśli głównie pisane w  PHP) jest Windows.  Osobiście pracuję uzywając Linuxa (aktualnie OpenSuse v 11.2) i raczej staram się wymusić na pracodawcy tę praktykę, argumentując to tym, że mogę pracować na środowisku zbliżonym do tego, na jakim stoi produkcja, mogę chociażby uniknąć błędu związanego z nazwami plików (wielkie/małe litery plików – dla Windows to obojetne, a dla Linuxa to już znacząca różnica), czy też sprawdzić wysyłkę emaili (wystarczy mi ze zainstaluje jedynie postfixa, bądź sendmaila, ale raczej jestem za tym pierwszym).

Jeśli chodzi o test wysyłki emali naszej aplikacji to pod Windows jest troszke problematyczne. Osobiście nie znam żadnego darmowego serwera poczty dla Windows, pewnie mógłbym wygoooglać jakiś, ale niestety nie mam czasu.  Dla ludzi korzystajacych z Zend Framework i pracujących  na Windows (i nie tylko także pod Linux, jak kto woli) rozwiązanie jest proste.

Wystarczy stworzyć podklasę dla klasy Zend_Mail_Transport_Sendmail i w niej przeciążyc metodę _sendMail. Przykładowa klasa mogłaby wyglądać tak:

cclass Zextend_Mail_Transport_File extends Zend_Mail_Transport_Sendmail
{
   /**
    * Sciezka zapisu plików z email.
    * 
    * @var string
    */
   protected $_savePath;
 
   public function getSavePath()
   {
       return $this->_savePath;
   }
 
   public function setSavePath($path)
   {
       $this->_savePath = $path;
   }
   /**
    * Zapisuje cały email do plku.
    */
   function _sendMail()
   {
       $fileName = time() . '.eml';
       $data = 'Subject: ' . $this->_mail->getSubject() . "\n"
             . 'To: ' . $this->recipients . "\n"
             . $this->header . "\n"
             . $this->body;
       file_put_contents($this->getSavePath() . '/' . $fileName, $data);
   }
}

Aby utrzymać porządek w kodzie i nie zaburzyc prawidłowego działania naszej aplikacji można napisać nowy resource, np:

class Zextend_Application_Resource_MailTransport extends Zend_Application_Resource_ResourceAbstract
{
 
    public function init()
    {
       if ('development' === APPLICATION_ENV) {
            $transport = new Zextend_Mail_Transport_File();
            $transport->setSavePath(ROOT_PATH . '/temporary/mail');
        } else {
            $transport = new Zend_Mail_Transport_Sendmail();
        }
 
            Zend_Mail::setDefaultTransport($transport);
            Zend_Mail::setDefaultFrom('jarek@kielmas.com');
   }
}

Taki zasób bardzo łatwo wcielamy w życie przez dodanie linijki, obok juz istniejących (lub nie:) innych zasobów  w application.ini:

resources.types = „array()”
resources.view = „array()”
resources.mailtransport = „array()”
resources.navigation = „array()”
resources.acl = „array()”
resources.log = „array()”

Taka podmianka sposobu transportu emaili uodporni nas przed:

  1. nieposiadaniem serwera pocztowego, zainstalowanego na lokalnej maszynie,
  2. bałaganem w kodzie, wywołanym np. użyciem exit(), die() itd,
  3. dotykaniem wersji trunk w repozytorium (wystarczy tylko dodać wpis w pliku konfiguracyjnym, którego lokalna instancja i tak nie jest wersjonowana)