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

Autor wpisu: Marek, dodany: 01.03.2012 19:58, tagi: zend_framework

zf

Wygenerowany formularz z mojego poprzedniego wpisu wygląda tak:

<form enctype="multipart/form-data" method="post" action="/zf/test/public/index/rename">
<dl class="zend_form">
  <dt id="newname-label"><label for="newname" class="optional">Zmień nazwę pliku:</label></dt>
  <dd id="newname-element"><input type="text" name="newname" id="newname" value=""></dd>
  <dt id="filename-label"><label for="filename" class="required">Plik:</label></dt>
  <dd>
    <input type="hidden" name="MAX_FILE_SIZE" value="8388608" id="MAX_FILE_SIZE">
    <input type="file" name="filename" id="filename">
  </dd>
  <dt id="submit-label">&#160;</dt>
  <dd id="submit-element">
    <input type="submit" name="submit" id="submit" value="Wyślij"></dd>
</dl>
</form>

Zend Framework podczas generowania formularzy stosuje domyślnie tagi dl, dd, dt. Ja jednak wolę przechowywać elementy formularza w tabeli. Poniżej przedstawiam kod, który chciałbym uzyskać:

<form enctype="multipart/form-data" method="post" action="/zf/test/public/index/rename">
<table>
  <tr>
    <th colspan="2">Wyślij plik</th>
  </tr>
  <tr>
    <td id="newname-label"><label for="newname">Zmień nazwę pliku:</label></td>
    <td><input type="text" name="newname" id="newname" value=""></td>
  </tr>
  <tr>
    <td id="filename-label"><label for="filename">Plik:</label></td>
    <td>
      <input type="hidden" name="MAX_FILE_SIZE" value="8388608" id="MAX_FILE_SIZE" />
      <input type="file" name="filename" id="filename" />
    </td>
  </tr>
  <tr>
    <td colspan="2"><input type="submit" name="submit" id="submit" value="Wyślij"></td>
  </tr>
</table>
</form>

Jak zatem wygenerować formularz w Zend Framework, tak aby jego elementy były zawarte w tabeli? Do tego oczywiście służą dekoratory.

Zmodyfikuję jeszcze tylko formularz dodając do niego opis:

$this->setDescription('Wyślij plik');

Po dodaniu elementów do formularza:

$this->addElements(array($newName, $file, $submit));

Ustawmy mu dekoratory:

// dekoratory formularza
$this->setDecorators(array(
    array('Description', array('tag' => 'th', 'colspan' => 2)),
    array(array('tr' => 'HtmlTag'), array('tag' => 'tr')),
    'FormElements',
    array('HtmlTag', array('tag' => 'table')),
    'Form'
));

Nasz opis będzie znajdował się wewnątrz znaczników th. Po opisie zostaną wygenerowane elementy formularza, które razem z opisem zostaną zawarte w znaczniku table, a ten zostanie otoczony znacznikiem form.

Tutaj jedna uwaga. Dekoratory dodawane są do zmiennej tablicowej _decorators klasy formularza. A więc skoro raz używamy HtmlTag, będzie on użyty jako klucz w tablicy __decorators. Jeśli ponownie chcemy użyć tego samego dekoratora, musimy podać unikalny klucz (tutaj: array(‘tr’ => ‘HtmlTag’) )

Dalej ustawmy dekoratory kontrolek:

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

Autor wpisu: Marek, dodany: 01.03.2012 19:56, tagi: zend_framework

Aby wyłączyć renderowanie layoutu w kontrolerze wpisujemy:

$this->_helper->layout->disableLayout();

Metodę disableLayout znajdziemy w klasie Zend_Layout.

Aby wyłączyć renderowanie danego widoku w kontrolerze wpisujemy:

$this->_helper->viewRenderer->setNoRender();

Wywołujemy tutaj przy użyciu helpera metodę setNoRender() klasy Zend_Controller_Action_Helper_ViewRenderer

Autor wpisu: Marek, dodany: 01.03.2012 19:56, tagi: zend_framework

Poniżej przedstawiam maksymalnie uproszczony sposób przesyłania plików na serwer przy pomocy Zend Framework. Zakładam zapis pliku na serwerze, oraz zapis informacji o jego nazwie w bazie danych. Jest to pierwszy z serii artykułów – mam nadzieję, że w prosty sposób wprowadzi w to rozbudowane zagadnienie. A więc do dzieła.

Tworzymy bazę danych. Tutaj użyję SZBD SQLITE3. Bazę umieszczę w katalogu:

data/db/

i nazwę ją:

testfile.db

A więc z katalogu głównego aplikacji wykonujemy:

mkdir -p data/db

A potem:

sqlite3 testfile.db

W konsoli sqlite tworzymy tabelę files:

create table files (
id integer primary key autoincrement,
filename varchar(150));

Gdzie w kolumnie „filename” będziemy przechowywać nazwę pliku. Teraz poinformujemy naszą aplikację o wybranym adapterze bazy danych i jej lokalizacji.

W pliku:

application/configs/application.ini

wpisujemy:

resources.db.adapter = "pdo_sqlite"
resources.db.params.dbname = APPLICATION_PATH "/../data/db/testfile.db"

W pliku:

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

Autor wpisu: Marek, dodany: 01.03.2012 19:56, tagi: zend_framework

W poprzednim wpisie przedstawiłem podstawy przesyłania pliku na serwer przy pomocy Zend Framework. Czas zagłębić się bardziej w to zagadnienie.

Kolejnym przypadkiem, którym się zajmę jest rozbudowa formularza o pole tekstowe przechowujące opcjonalną nową nazwę dla wysyłanego pliku.

Skoro możemy zmienić nazwę pliku, użyty poprzednio walidator Zend_Validate_File_NotExists() już nie spełni swojej roli, bo możemy przesłać plik o takiej samej nazwie jak w katalogu docelowym, o ile podamy w formularzu nową nazwę (którą de facto musimy również zweryfikować).

A więc użyjemy własnego walidatora, który będzie dziedziczył po wcześniej wspomnianym, wprowadzając dodatkowe sprawdzanie dla nowej nazwy pliku. Walidator umieszczam w katalogu /library/My/Validate/File/

require_once 'Zend/Validate/File/NotExists.php';

class My_Validate_File_NotExists extends Zend_Validate_File_NotExists {

    /**     
     * @var string nowa nazwa dla pliku     
     */
     protected $_newName = null;

    public function __construct($directory = array(), $newName = null) {
        $this->_newName = $newName;
        parent::__construct($directory);
    }

    public function isValid($value, $file = null) {
        // ustawienie nowej nazwy pliku, jeśli podana
        if (!empty($this->_newName)) {
            $fileName = isset($file['name']) ? $file['name'] : $value;
            $file['name'] = $this->_newName . '.' . pathinfo($fileName, PATHINFO_EXTENSION);
        }
        parent::isValid($value, $file);
    }

}

Co tu się dzieje? Dzięki dziedziczeniu i w myśl zasady DRY nasz walidator jest bardzo prosty. W konstruktorze przekazujemy do niego nową nazwę pliku i wywołujemy konstruktor klasy rodzica. Metoda isValid() to serce naszej klasy. Sprawdzamy w niej czy została ustawiona nowa nazwa dla pliku. Jeśli tak, modyfikujemy nazwę przetrzymywaną w tablicy $file, dodając do niej rozszerzenie przesłanego pliku (które wyciągamy przy pomocy funkcji pathinfo()). Tak zmodyfikowane dane poddajemy walidacji klasy Zend_Validate_File_NotExists.

Przejdźmy do klasy formularza:

class Application_Form_Rename extends Zend_Form {

    public function init() {
        $this->setMethod('post');

        $newName = new Zend_Form_Element_Text('newname');
        $newName->setLabel('Zmień nazwę pliku:')
                ->addFilters(array('StringTrim', 'StripTags'));

        $file = new Zend_Form_Element_File('filename');
        $file->addPrefixPath('My_Validate', '/My/Validate', 'validate')
                ->setLabel('Plik:')
                ->setRequired()
                ->setDestination(APPLICATION_PATH . '/../public/uploads')
                ->addValidator('Size', true, 1048576)
                ->addValidator('Extension', false, 'pdf');

        $submit = new Zend_Form_Element_Submit('submit');
        $submit->setLabel('Wyślij')
                ->setIgnore(true);

        $this->addElements(array($newName, $file, $submit));
    }

    public function addRenameValidator($newName) {
        $destination = $this->filename->getDestination();
        if (!empty($newName)) {
            $this->filename->addFilter('Rename', array(
                'target' => $destination . DIRECTORY_SEPARATOR . $newName . '.'
                . pathinfo($this->filename->getFileName(), PATHINFO_EXTENSION),
                'overwrite' => false));
        }
        $this->filename->addValidator(new My_Validate_File_NotExists($destination, $newName));
    }
}

W metodzie init(), inicjującej pola formularza, dodajemy obiekt Zend_Form_Element_Text, który będzie odpowiadał za kontrolkę nowej nazwy pliku. Dalej na obiekcie $file wywołujemy metodę addPrefixPath(), która pomoże później znaleźć klasę naszego walidatora. Kolejna metoda addRenameValidator() dodaje filtr Zend_Filter_File_Rename(), który zmieni nazwę przesyłanego pliku na nową (o ile ją podaliśmy). Dalej dodajemy do obiektu $filename  walidator My_Validate_File_NotExists(), przekazując mu nową nazwę dla pliku.

Przyjrzyjmy się teraz kontrolerowi:

public function renameAction() {
        $form = new Application_Form_Rename();
        $form->setAction($this->view->url());
        if ($this->getRequest()->isPost()) {
            $data = $this->getRequest()->getPost();
            $form->addRenameValidator($data['newname']);
            if ($form->isValid($data)) {
                if (!$form->filename->receive()) {    //odbieramy plik
                    throw new Zend_Exception('Wystąpił błąd przy odbieraniu pliku!');
                }
                $db = new Application_Model_DbTable_File();
                $db->insertRenamed($form->getValues());
                $this->view->msg = 'Plik został pomyślnie zapisany';
            } else {
                $this->view->msg = 'Wystąpił błąd!';
            }
        }
        $this->view->form = $form;
    }

Akcja rename naszego kontrolera bardzo przypomina akcję index z poprzedniego wpisu. Z tym, że:

  • przed sprawdzeniem poprawności danych przesłanych z formularza, wywołujemy metodę addRenameValidator(), podając jej nową nazwę pliku (co prowadzi do dodania wyżej opisanego walidatora)
  • jeśli wystąpił błąd podczas odbierania pliku, wyrzucamy wyjątek
  • jeśli plik został prawidłowo przesłany na serwer, zapisujemy dane do bazy

Został jeszcze model:

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

Autor wpisu: Athlan, dodany: 14.02.2012 15:33, tagi: zend_framework

Zend_Mail provides a great and simple in use and configuration mechanizm to send emails. The problem begins when you would like to specify fully templated and layouted messages.

In my current project I have several kinds of mails: customer invoices and messages, users notifications, admin notifications, webmaster email about critical errors in scheduled system tasks. In this case the Zend_Layout fits perfectly to redner rich text content by Zend_View, but it is implemented in Zend_Mail, wchih provies simply setBodyText() and setBodyHTML() methods.

This inconvenience is understandable by the way, mainly in context simpe, clear and flexible extendable code of Zend Framework. We will strive to extend the functionality od Zend_Mail following ZF developers concepts.

Overview

Writing class extending Zend_Mail I kept a several concepts:

  • Messages should be both templated and layouted using Zend_View and Zend_Layout.
  • The email view scripts (templates) there are in main view scripts directory nested in subdirectory (as deep as you want).
  • … The same path story with layouts.
  • You can use this object excatly the same way as Zend_Mail. It behaviour the same way as parent until you set special options (like point to view script path or file to render in body).
  • … and object should keep Zend_Mail fluent interface (returning $this in setters) to provide method chaining fluent interface.
  • Pointed view file is rendered as a mail body.
  • You can use this object excatly the same way as Zend_Mail. It behaviour the same way as parent until you set special options (like point to view script path or file to render in body).

Zend_Mail application.ini configuration and extending application

Simply paste several lines to application.ini configuration, theare are self-commented, description is not neccessary at this point. We will use SMTP transport:

resources.mail.transport.type = smtp
resources.mail.transport.host = YOUR_HOSTNAME
resources.mail.transport.auth = login
resources.mail.transport.username = "YOUR_ACCOUNT"
resources.mail.transport.password = "YOUR_PASSWORD"
resources.mail.transport.register = true
 
resources.mail.defaultFrom.email = YOUR_ACCOUNT
resources.mail.defaultFrom.name = "MyService.com"
resources.mail.defaultReplyTo.email = YOUR_ACCOUNT
resources.mail.defaultReplyTo.name = "MyService.com"

In addition we will create tho additional directories and files:

  • /application/views/scripts/email/-  just add a subdirectory /email to existing view scripts directory.
  • /application/layouts/scripts/email/ – the same story as above
TIP: I have moved default configured layouts direcotry to /application/views/layouts/ to unify structure of application. Just change in application.ini this line:
resources.layout.layoutPath = APPLICATION_PATH "/modules/default/views/layouts/scripts/"

To test our class let’s create additional two files:

/application/layouts/scripts/email/html.phtml

< ?php echo $this->layout()->content ?>
<p>--<br />Best Regards,<br />MyService.com</p>

and scond one, the information about successfull account register with your own content:

/application/views/scripts/email/AccountRegister.phtml

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

Autor wpisu: Athlan, dodany: 14.02.2012 00:45, tagi: zend_framework

I have just started introducing Zend Framework when I had to face the problem with output multiple error messages in form while email address validation. Checking domain (whith is enabled by default) causes additional error messages indicates anomalies in hostname segment of provided by user email address. In result, we receive several errors assigned to one email field.

The problem is easy to slove by overriding default behaviour of Zend_Validate_EmailAddress clearing all messages generating while validation and setup a new single error message.

Simply add namespace MyOwn_ for own needs and provide class in file /libraries/MyOwn/Validate/EmailAddess.php

class MyOwn_Validate_EmailAddress extends Zend_Validate_EmailAddress
{
  const INVALID = 'emailAddressInvalid';
 
  protected $_messageTemplates = array(
    self::INVALID => "Invalid Email Address."
  );
 
  public function isValid($value)
  {
    parent::setOptions(array(
      'allow' => Zend_Validate_Hostname::ALLOW_DNS,
      'domain' => true,
      'mx' => true,
      'deep' => true)
    );
 
    if(!parent::isValid($value)) {
      $this->_messages = array(); // clear all previous messages
      $this->_error(self::INVALID);
      return false;
    }
 
    return true;
  }
}

And provide above custom validator to form element in /application/forms/AccountRegister.php:

class Form_AccountRegister extends Zend_Form
{
  public function init()
  {
    $this->setMethod('post')
         ->setName('Account_Register');
 
    $email = new Zend_Form_Element_Text('email');
    $email
      ->setLabel('Email address')
      ->addValidator(new ZendUtil_Validate_EmailAddress)
      ->setRequired(true);
 
    $this->addElement($email);
 
  }
}

NOTE:

  • In addition, you can simply translate the emailAddressInvalid message.
  • For sticklers, setting options in isValid method is hardcoded with look like a messy code, but it is quick-fix

Hope it will help.

Autor wpisu: Load, dodany: 30.01.2012 12:35, tagi: php, framework, zend_framework

Wstęp

Od czasu do czasu pomiędzy obszernymi wpisami będą się pojawiać tz. mini wpisy których treść nie nadaje się na cały wpis, a informacje w nich zawarte są dość użyteczne i nie chciał bym ich wykładać poza kurs. Ten wpis będzie pierwszym takim mini wpisem, w tytule będę podawać pomiędzy jakimi wpisami został opublikowany z racji na inną numerację. ;-)

Konfiguracja wyświetlania błędów w Zend Framework

Miejscem w jakim ustalamy czy Zend ma nas informować o szczegółach błędów jest plik .htaccess w katalogu public każdego projektu, jego standardwa zawartość to:

RewriteEngine On RewriteCond %{REQUEST_FILENAME} -s [OR] RewriteCond %{REQUEST_FILENAME} -l [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^.*$ – [NC,L] RewriteRule ^.*$ index.php [NC,L]

Jak widać są to zwykłe regułki .htaccess, przed nimi mamy pustą linię wpisując w niej:

SetEnv APPLICATION_ENV development

Mówimy naszej aplikacji, że pracujemy w trybie deweloperskim dzięki czemu wyświetlanie błędów zostanie uruchomione, aplikacja posiada również inne tryby w jakich może pracować, wszystko jest opisane w plikach konfiguracyjnych, podam przykład by wyjaśnić na czym to polega, plik z projketu użytego w ostatniej części kursu (#03):

H:\zf\application\configs\application.ini

I jego zawartość:

[production] phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 includePaths.library = APPLICATION_PATH „/../library” bootstrap.path = APPLICATION_PATH „/Bootstrap.php” bootstrap.class = „Bootstrap” appnamespace = „Application” resources.frontController.controllerDirectory = APPLICATION_PATH „/controllers” resources.frontController.params.displayExceptions = 0

[staging : production]

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.