Autor wpisu: Marek, dodany: 06.03.2012 21: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: