Thursday
25
September
2008

Subforms and multiple file elements

Hy interested ones,

when you are using Zend_Form for your file upload I have new informations for you.

*) Subforms
Using file elements in sub forms was not possible in the past. The reason was that sub forms are created by using multidimensional names, but in HTML multidimensional names are not supported for file elements.

Now this is possible. I have added a new decorator with the help of Matthew which is automatically be used for file elements. It changes the elements name in a way which is supported by HTML.

As you can see in the following example, even multi-nested subforms are supported.

$form = new Zend_Form();
$form->setEnctype('multipart/form-data');
$form->setAction('index2.php');
	
// Button
$button = new Zend_Form_Element_Submit('submit');
$form->addElement($button);
	
// File Upload Elements
$element = new Zend_Form_Element_File('firstfile');
$element2 = new Zend_Form_Element_File('secondfile');
	
// 3-Level subform
$subform0 = new Zend_Form_SubForm();
$subform0->addElement($element);
$subform0->addElement($element2);
$subform1 = new Zend_Form_SubForm();
$subform1->addSubform($subform0, 'subform0');
$subform2 = new Zend_Form_SubForm();
$subform2->addSubform($subform1, 'subform1');
$subform3 = new Zend_Form_SubForm();
$subform3->addSubform($subform2, 'subform2');
$form->addSubform($subform3, 'subform3');
	
$form->setView(new Zend_View());
echo $form;

But note that the name of the file elements you set in a form and all it’s subforms must be unique. File elements with the same name are displayed but not submitted by your form.

*) Multiple file elements

Sometimes it is usefull to have multiple file elements which uses the same settings and validators. Writing plain HTML you would simply set a name like filename[] several times. Zend_Form_Element_File can handle this for you much simpler. Just create your element like before and call setMultiFile() with the number of files you want to have.

$element = new Zend_Form_Element_File("uploaded");
$element->setMultiFile(3);

The above example will create 3 seperated file elements named uploaded[].

I hope you find these two features handy.
New things will come soon.

Greetings
Thomas, I18N Team Leader, Zend Framework

Back to top
Sunday
21
September
2008

Zend_File_Transfer and error messages

Hy interested ones,

in the last days I worked on Zend_File_Transfer to get this new component more comfortable.
I integrated several new features which will allow simpler usage specially when you use the file element helper.

So what is new:

*) breakChainOnFailure

Like it’s cousine Zend_Form, now also Zend_File_Transfer allows the usage of the breakChainOnFailure parameter when adding validators. This feature will stop the validation for defined validators.

$adapter = new Zend_File_Transfer_Adapter_Http();
$adapter->addValidator('Size', true, '1MB')
            ->addValidator('Extension', false, 'jpg,png');

This example will stop validation as soon as a file extends 1MB regardless of it’s extension. So you will not get the error for false extension when the file is for example 1.5MB.

*) Translating error messages

You can now add a translator, which will translate all error messages for you. This feature works the same way like in Zend_Form. You can set a translation with setTranslator().

$adapter = new Zend_File_Transfer_Adapter_Http();
$adapter->addValidator('Size', true, '1MB')
            ->setTranslator($mytranslator);

When you now get an error when validation occurs, all returned error messages will be routed through the translator and when you have set a translation you will get your error instead of the adapters one.
So instead of “file not found” you could write “Hey man, give me my file”.

*) Knowing if a error has been occured

I added the hasErrors() method to the adapter which will return true when an error has occured during validation.

$adapter = new Zend_File_Transfer_Adapter_Http();
$adapter->addValidator('Size', true, '1MB');
	
if ($adapter->receive()) {
    $errors = 'unknown error';
    if ($adapter->hasErrors()) {
        $errors = $adapter->getErrors();
    }
}

The example does not really need the hasErrors() method as you may mention. But sometimes there is a need of this functionality, so I added it. Also the hasErrors() method of Zend_Form_Element_File routes to the adapters hasErrors() method.

*) Seperated validation from receiving of files

The originate implementation of Zend_Form_Element_File called receive() when the element was validated.
Of course this is not true and leaded to several problems, like the file being transfered even if other form validations failed.

This has been changed by me, but does also lead to a BC break, as you have to call receive() after validation.
But this does not mean that you have to call 2 methods.

$adapter = new Zend_File_Transfer_Adapter_Http();
$adapter->addValidator('Size', true, '1MB');
	
if (!$adapter->isValid()) {
    print "Validation error";
}
if (!$adapter->receive()) {
    print "Problem receiving the file";
}

When the adapter has been validated, then the receive() method will not call isValid() again.
But when you have not validated the adapter, it will automatically call isValid() before the file will be transfered to it’s destination.

So you could simply write

$adapter = new Zend_File_Transfer_Adapter_Http();
$adapter->addValidator('Size', true, '1MB');
	
if (!$adapter->receive()) {
    print "Problem receiving the file, probably validation problem";
}

*) Checking of the destination exists

Previously you could set anything as destination path and would get an false as soon as you receive the file but you would not know why as the validation would have passed. So I added a check for existance of the destination path. You will now get an exception if the directory you set does not exist, or is not readable.

$adapter = new Zend_File_Transfer_Adapter_Http();
try {
    $adapter->setDestination('/path/does/not/exist');
} catch (Zend_File_Transfer_Exception $e) {
    print $e->getMessage();
}

More to come soon…

Greetings
Thomas
I18N Team Leader, Zend Framework

Back to top
Sunday
7
September
2008

Destination and renaming of uploaded files

Hy insterested ones,

I added for you two new improvements to Zend_File_Transfer or if you work with Forms, to the file element.

The first one is that Zend_File_Transfer allows now the usage of file filters. Note that, of course, file filters work differently to normal string filters. They do not return the content, but the location of the file, aka the real location and filename. It should also be noted that file filters will be attached AFTER the file has been received. This is due to the fact that we are not allowed to change the file before it has been received, as we would then get a attacker exception from PHP itself. Input elements, for example, will do filtering before validation. File elements will always do validation and afterwards filtering. So you could now add your own filters if you are in need. Or you wait for me to do this.

The second improvement is the first file filter.

I am happy to announce that the “Rename” filter is ready in core.
What can it do ?

Well, it will allow you to have much more influence of the behaviour of uploaded files.
Let’s see an example:

$filter = new Zend_Filter_File_Rename('C:picturesnewpics', true);

or when you use the adapter

$adapter->addFilter('Rename', array('C:picturesnewpics', true));

All uploads will now be moved to the directory C:picturesnewpics and will be overwritten if they exist.
The default is false, which means that the filter will not overwrite existing files. Beware: If the file exists, you will get a false as soon as you receive the file with an error, that the file already exists if you do not set the overwrite property.

Of course the rename adapter allows much more.
You can define the location for each single file separatly.
You can even define a new filename and extension for the uploaded file.

$adapter->addFilter('Rename', 'C:picturesnewname.txt');

For more details about supported notations look into the manual.

I hope you find this addition usefull and use it in your own projects.
PS: If you have a good idea for a additional feature to any of my components dont be shy and share your idea.

Greetings
Thomas, I18N Team Leader, Zend Framework

Back to top