📜 ⬆️ ⬇️

Using Zend_Form_Element_File in CRUD

image

When designing applications on the Zend Framework, the use of the Zend_Form component makes it much easier to work with entities - a once-created form with configured validators, filters, etc. is used both when creating and editing data in the database.
Entities very often contain elements of the File type - whether it is a picture preview, a file name for downloading or a photo in the gallery. That's only if you want to change the entity in the form of which there is a File element, it becomes clear that the standard decorator Zend_Form_Element_File is not suitable for the form of changing the entity - because it does not allow to display the presence of the downloaded file, does not allow to delete this file, etc.

In other words, when you open an entity for change, all other elements of the form are populated with values ​​from the database - while Zend_Form_Element_File does not have this to do.
In this article I want to share my implementation of working with Zend_Form_Element_File as part of creating a CRUD (create-read-update-delete) on ZendFramework 1.11
')
Under 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 like this (standard):
image

When changing an entity, Zend_Form_Element_File by default looks similar. Our task is to bring the look of this element to this:
image
Accordingly, the current uploaded 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 uploaded file and reset 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

  1. <? php
  2. class Application_Form_Decorators_File extends Zend_Form_Decorator_Abstract
  3. {
  4. public function buildLabel ( )
  5. {
  6. $ element = $ this -> getElement ( ) ;
  7. $ label = $ element -> getLabel ( ) ;
  8. if ( $ translator = $ element -> getTranslator ( ) ) {
  9. $ label = $ translator -> translate ( $ label ) ;
  10. }
  11. if ( $ element -> isRequired ( ) ) {
  12. $ label . = '*' ;
  13. }
  14. $ label . = ':' ;
  15. return $ element -> getView ( )
  16. -> formLabel ( $ element -> getName ( ) , $ label ) ;
  17. }
  18. public function buildInput ( )
  19. {
  20. $ element = $ this -> getElement ( ) ;
  21. $ helper = $ element -> helper ;
  22. return $ element -> getView ( ) -> $ helper (
  23. $ element -> getName ( ) ,
  24. $ element -> getValue ( ) ,
  25. $ element -> getAttribs ( ) ,
  26. $ element -> options
  27. ) ;
  28. }
  29. public function buildErrors ( )
  30. {
  31. $ element = $ this -> getElement ( ) ;
  32. $ messages = $ element -> getMessages ( ) ;
  33. if ( empty ( $ messages ) ) {
  34. return '' ;
  35. }
  36. return '<div class = "errors">' .
  37. $ element -> getView ( ) -> formErrors ( $ messages ) . '</ div>' ;
  38. }
  39. public function buildDescription ( )
  40. {
  41. $ element = $ this -> getElement ( ) ;
  42. $ desc = $ element -> getDescription ( ) ;
  43. if ( empty ( $ desc ) ) {
  44. return '' ;
  45. }
  46. return '<div class = "description">' . $ desc . '</ div>' ;
  47. }
  48. public function render ( $ content )
  49. {
  50. $ element = $ this -> getElement ( ) ;
  51. if ( ! $ element instanceof Zend_Form_Element ) {
  52. return $ content ;
  53. }
  54. if ( null === $ element -> getView ( ) ) {
  55. return $ content ;
  56. }
  57. $ separator = $ this -> getSeparator ( ) ;
  58. $ placement = $ this -> getPlacement ( ) ;
  59. $ label = $ this -> buildLabel ( ) ;
  60. $ input = $ this -> buildInput ( ) ;
  61. $ errors = $ this -> buildErrors ( ) ;
  62. $ desc = $ this -> buildDescription ( ) ;
  63. $ renderedContent = $ element -> getView ( ) -> partial (
  64. 'decorators / file.phtml' ,
  65. array ( 'element' => $ element ) ) ;
  66. $ output = '<tr> <td>'
  67. . $ label . '</ td> <td>' . $ renderedContent
  68. . $ input
  69. . $ errors
  70. . $ desc
  71. . '</ td> </ tr>' ;
  72. switch ( $ placement ) {
  73. case ( self :: PREPEND ) :
  74. return $ output . $ separator . $ content ;
  75. case ( self :: APPEND ) :
  76. default :
  77. return $ content . $ separator . $ output ;
  78. }
  79. }
  80. }


Thus, we can assemble the appearance of the element “in parts” by adding the necessary information for the output. Using the instructions

  1. $ renderedContent = $ element -> getView ( ) -> partial (
  2. 'decorators / file.phtml' ,
  3. array ( 'element' => $ element ) ) ;


Along the way, we pass information about the current element (Zend_Form_Element_File) as $ element (needed for
Render the application / views / scripts / decorators / file.phtml file with the following contents:

  1. You uploaded a photo ' <? Php echo $ this -> element -> getDescription ( ) ; ?> '. <br>
  2. You can change the photo by specifying a new file. If a photo change is not required, leave this field blank. <br>
  3. To remove a photo, check the box:
  4. <input name = " <? php echo $ this -> element -> getName ( ) ; ?> _checkbox" type = "checkbox" value = "on" /> <br />


The use of decorators in the form


Since a custom decorator is needed only when the entity is changed, when adding an entity, we leave the standard decorator:
  1. if ( $ this -> _options [ 'type' ] == 'edit' && ! is_null ( $ this -> _options [ 'photo_file' ] ) ) {
  2. $ photo -> setDescription ( $ this -> _options [ 'photo_file' ] ) ;
  3. $ photo -> setDecorators ( array (
  4. array ( 'ViewScript' , array ( 'viewScript' => 'decorators / file.phtml' ) ) ,
  5. 'File' ,
  6. 'Errors' ,
  7. array ( array ( 'data' => 'HtmlTag' ) , array ( 'tag' => 'td' , 'class' => 'element' ) ) ,
  8. array ( 'Label' , array ( 'tag' => 'td' ) ) ,
  9. array ( array ( 'row' => 'HtmlTag' ) , array ( 'tag' => 'tr' ) )
  10. ) )
  11. } else {
  12. $ photo -> setDecorators ( array (
  13. 'File' ,
  14. 'Errors' ,
  15. array ( array ( 'data' => 'HtmlTag' ) , array ( 'tag' => 'td' , 'class' => 'element' ) ) ,
  16. array ( 'Label' , array ( 'tag' => 'td' ) ) ,
  17. array ( array ( 'row' => 'HtmlTag' ) , array ( 'tag' => 'tr' ) )
  18. ) )
  19. }


Using decorator in controller:


For each loaded picture, a preview is created using a filter — accordingly, when deleting a picture, you also need to delete the preview.

  1. // if a check mark for deletion is set, then delete the file and food in the database null
  2. if ( ! is_null ( $ this -> getRequest ( ) -> getParam ( 'photo_checkbox' ) ) && $ this -> getRequest ( ) -> getParam ( 'photo_checkbox' ) == 'on' ) {
  3. if ( file_exists ( PUBLIC_PATH . '/ userfiles / images / full /' . $ item -> photo ) )
  4. unlink ( PUBLIC_PATH . '/ userfiles / images / full /' . $ item -> photo ) ;
  5. if ( file_exists ( PUBLIC_PATH . '/ userfiles / images / thumb /' . $ item -> photo ) )
  6. unlink ( PUBLIC_PATH . '/ userfiles / images / thumb /' . $ item -> photo ) ;
  7. $ item -> photo = null ;
  8. }
  9. // if a new file is specified and it is loaded, then delete the old file and write a new one to the database.
  10. // if the File element is empty, $ form-> photo-> getFileName () == array (null);
  11. if ( ! is_null ( $ form -> photo -> getFileName ( ) ) && count ( $ form -> photo -> getFileName ( ) ) ! = 0 ) {
  12. if ( file_exists ( PUBLIC_PATH . '/ userfiles / images / full /' . $ item -> photo ) ) {
  13. unlink ( PUBLIC_PATH . '/ userfiles / images / full /' . $ item -> photo ) ;
  14. }
  15. if ( file_exists ( PUBLIC_PATH . '/ userfiles / images / thumb /' . $ item -> photo ) ) {
  16. unlink ( PUBLIC_PATH . '/ userfiles / images / thumb /' . $ item -> photo ) ;
  17. }
  18. $ item -> photo = $ form -> getValue ( 'photo' ) ;
  19. }


Source codes:


  1. Application_Form_Decorators_File
  2. Application_Form_Photogallery
  3. PhotogalleryController


If the topic is relevant, then there is more material about writing filters for image processing loaded via Zend_Form_Element_File (gdlib and imagic).

Thank you for your attention, comments and suggestions are accepted. Not so long ago, I began to study the Zend Framework, I did not find a solution to this problem - I had to figure it out myself. If something is done is not entirely correct and (or) not in the style of ZF - please unsubscribe in the comments, I will correct.

The current implementation is working successfully.

Source: https://habr.com/ru/post/136438/


All Articles