Autor wpisu: Marek, dodany: 01.03.2012 19:58, tagi: zend_framework
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"> </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:
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:
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:
Kanał ATOM

