
Using Zend_Form_Element_File in CRUD

When designing applications on the Zend Framework, using the Zend_Form component greatly facilitates the work with entities - once a form is created, with configured validators, filters, etc., it is used both when creating and editing data in the database.
Very often, entities contain elements of the File type — whether it is a preview image, a file name to download, or a photo in a gallery. But only if you want to change the entity in the form of which there is a File element, it becomes clear that the standard Zend_Form_Element_File decorator is not suitable for the entity change form - because it does not allow to display the presence of a downloaded file, does not make it possible to delete this file, etc.
In other words, when you open an entity for change, all other elements of the form are filled with values from the database - while Zend_Form_Element_File does not have this.
In this article I want to share my implementation of working with Zend_Form_Element_File as part of creating CRUD (create-read-update-delete) on ZendFramework 1.11.
Under the habrakat, you will find a detailed description of how to create a decorator, how to attach it to the form and instructions for working with the controller.
Zend_Form_Element_File - general information, features
When adding a new entity to the database, Zend_Form_Element_File looks as follows (standard):

When changing an entity, Zend_Form_Element_File looks similar by default. Our task is to reduce the appearance of this element to the following:

Accordingly, the current loaded file name is displayed, the element itself to indicate the new file (the old one will be replaced by it) and the checkbox to delete the already downloaded file and zero the photo column for the entity being edited.
Create your own decorator for Zend_Form_Element_File
To do this, in the application / forms / Decorators folder, create a File.php file with the following class
- class Application_Form_Decorators_File extends Zend_Form_Decorator_Abstract
- {
- public function buildLabel ()
- {
- $ element = $ this-> getElement ();
- $ label = $ element-> getLabel ();
- if ($ translator = $ element-> getTranslator ()) {
- $ label = $ translator-> translate ($ label);
- }
- if ($ element-> isRequired ()) {
- $ label. = '*';
- }
- $ label. = ':';
- return $ element-> getView ()
- -> formLabel ($ element-> getName (), $ label);
- }
- public function buildInput ()
- {
- $ element = $ this-> getElement ();
- $ helper = $ element-> helper;
- return $ element-> getView () -> $ helper (
- $ element-> getName (),
- $ element-> getValue (),
- $ element-> getAttribs (),
- $ element-> options
- );
- }
- public function buildErrors ()
- {
- $ element = $ this-> getElement ();
- $ messages = $ element-> getMessages ();
- if (empty ($ messages)) {
- return '';
- }
- return '
'.- $ element-> getView () -> formErrors ($ messages). ''
'. $ desc. ''
Thus, we can collect the appearance of the element "in parts" by adding the necessary information for output. Using instructions
- $ renderedContent = $ element-> getView () -> partial (
- 'decorators / file.phtml',
- array ('element' => $ element));
Along the way, we pass information about the current element (Zend_Form_Element_File) as $ element (needed for and
render the file application / views / scripts / decorators / file.phtml with the following contents:
- You uploaded the photo ' element-> getDescription (); ?> '.
- You can change the photo by specifying a new file. If photo changes are not required, leave this field blank.
- To delete a photo, check the box:
- element-> getName (); ?> _ checkbox "type =" checkbox "value =" on "/>
Using decorators in the form
Since a custom decorator is needed only when changing an entity, when adding an entity, we leave the standard decorator:
- if ($ this -> _ options ['type'] == 'edit' &&! is_null ($ this -> _ options ['photo_file'])) {
- $ photo-> setDescription ($ this -> _ options ['photo_file']);
- $ photo-> setDecorators (array (
- array ('ViewScript', array ('viewScript' => 'decorators / file.phtml')),
- 'File',
- 'Errors',
- array (array ('data' => 'HtmlTag'), array ('tag' => 'td', 'class' => 'element')),
- array ('Label', array ('tag' => 'td')),
- array (array ('row' => 'HtmlTag'), array ('tag' => 'tr'))
- ));
- } else {
- $ photo-> setDecorators (array (
- 'File',
- 'Errors',
- array (array ('data' => 'HtmlTag'), array ('tag' => 'td', 'class' => 'element')),
- array ('Label', array ('tag' => 'td')),
- array (array ('row' => 'HtmlTag'), array ('tag' => 'tr'))
- ));
- }
Using the decorator in the controller:
For each uploaded image, a preview is created using the filter - accordingly, when deleting the image, the preview must also be deleted.
- // if the checkbox for deletion is checked, then delete the file and null it into the database
- if (! is_null ($ this-> getRequest () -> getParam ('photo_checkbox')) && $ this-> getRequest () -> getParam ('photo_checkbox') == 'on') {
- if (file_exists (PUBLIC_PATH. '/ userfiles / images / full /'. $ item-> photo))
- unlink (PUBLIC_PATH. '/ userfiles / images / full /'. $ item-> photo);
- if (file_exists (PUBLIC_PATH. '/ userfiles / images / thumb /'. $ item-> photo))
- unlink (PUBLIC_PATH. '/ userfiles / images / thumb /'. $ item-> photo);
- $ item-> photo = null;
- }
- // if a new file is specified and it is uploaded, then delete the old file and write a new one in the database.
- // in case the File element is not filled, $ form-> photo-> getFileName () == array (null);
- if (! is_null ($ form-> photo-> getFileName ()) && count ($ form-> photo-> getFileName ())! = 0) {
- if (file_exists (PUBLIC_PATH. '/ userfiles / images / full /'. $ item-> photo)) {
- unlink (PUBLIC_PATH. '/ userfiles / images / full /'. $ item-> photo);
- }
- if (file_exists (PUBLIC_PATH. '/ userfiles / images / thumb /'. $ item-> photo)) {
- unlink (PUBLIC_PATH. '/ userfiles / images / thumb /'. $ item-> photo);
- }
- $ item-> photo = $ form-> getValue ('photo');
- }
Source Codes:
If the topic is relevant, then there is still material about writing filters for processing images downloaded via Zend_Form_Element_File (gdlib and imagic).
Thank you for your comments, comments and suggestions are accepted. Not so long ago I began to study the Zend Framework, I did not find a solution to a similar problem - I had to figure it out myself. If something is done not quite correctly and (or) not in the ZF style - please unsubscribe in the comments, I will correct it.
The current implementation is working successfully.