You can find a base value object that you can use to upload files.
It can be used in combination with the form type Common\Form\FileType
While most of the things you need to do are already written for you, you will still need to add some configuration for each implementation.
Not all files are created equal. The file you want to upload has a specific meaning in your application and therefor your implementation should reflect that.
- Create a new class
- Extend the class
Common\Doctrine\ValueObject\AbstractFile
- Implement the
getUploadDir()
method (for documentation about this see the phpdoc)
After implementing this your value object will be transformed into the web path of your file when it is sent to the template.
This way you can just use it like myEntity.myFile
<?php
namespace Backend\Modules\Users\ValueObject;
use Common\Doctrine\ValueObject\AbstractFile;
final class CV extends AbstractFile
{
/**
* @return string
*/
protected function getUploadDir()
{
return 'user/cv';
}
}
In order to save the file to the database using doctrine we need a DBALType
- Create a new class
- Extend the class
Common\Doctrine\Type\AbstractFileType
- Implement the methods
createFromString()
andgetName()
- Register your DBALType (doctrine.dbal.types)
<?php
namespace Backend\Modules\Users\DBALType;
use Common\Doctrine\Type\AbstractFileType;
use Backend\Modules\Users\ValueObject\CV;
final class CVType extends AbstractFileType
{
/**
* @param string $fileName
*
* @return CV
*/
protected function createFromString($fileName)
{
return CV::fromString($fileName);
}
/**
* @return string
*/
public function getName()
{
return 'cv';
}
}
app/config/config.yml or the config file you load via DependencyInjection in the prepend method
doctrine:
dbal:
types:
user_cv_type: Backend\Modules\Users\DBALType\CVType
Now that we have our DBAL type and our value object we can add it to our entity
- Add a property to your class for your value object
- Set the column type to the name your DBAL type is registered on
- Add the
@ORM\HasLifecycleCallbacks
annotation to the entity - Add the lifecycle callbacks to your entity as described in the phpdoc of the
Common\Doctrine\ValueObject\AbstractFile
class
<?php
namespace Backend\Modules\Users\Entity;
use Doctrine\ORM\Mapping as ORM;
use Backend\Modules\Users\ValueObject\CV;
/**
* User entity
*
* @ORM\Table()
* @ORM\Entity
* @ORM\HasLifecycleCallbacks()
*/
class User
{
/**
* @var CV
*
* @ORM\Column(type="user_cv_type")
*/
protected $cv;
/**
* @return CV
*/
public function getCv()
{
return $this->cv;
}
/**
* @param CV $cv
* @return self
*/
public function setCv($cv)
{
$this->cv = $cv;
return $this;
}
/**
* @ORM\PreUpdate()
* @ORM\PrePersist()
*/
public function prepareToUploadCV()
{
$this->cv->prepareToUpload();
}
/**
* @ORM\PostUpdate()
* @ORM\PostPersist()
*/
public function uploadCV()
{
$this->cv->upload();
}
/**
* @ORM\PostRemove()
*/
public function removeCV()
{
$this->cv->remove();
}
}
For the last step you need to add your file to your form.
- Use
Common\Form\FileType
as the form type - Set the fully qualified class name (FQCN) of your value object in the option
file_class
(tip: you can useMyFile::class
for that)
<?php
namespace Backend\Modules\Users\Form;
use Common\Form\FileType;
use Backend\Modules\Users\ValueObject\CV;
use Symfony\Component\Form\FormBuilderInterface;
class UserType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('cv', FileType::class, ['file_class' => CV::class]);
}
}
If you want you can use events on the form that has the file type and set a prefix on the generated filename with the method setNamePrefix
on the file value object
To make your life even easier, the form FileType has some interesting configuration options on top of the default options that the Symfony FileType already has.
-
show_preview
: By default we will show a link to view the current file if there is one. You can disable this using this option. -
preview_label
: You can use it to change the translation label that will be in the link to view your current file. -
show_remove_file
: If your file is not required we will automatically add the option for the user to remove the file, You can disable this using this option. -
remove_file_label
: You can use it to change the translation label of the remove file checkbox. -
required_file_error
: You can use it to change the translation label of the error when the file is required but no file was uploaded. -
help_text_message
: You can use it to change the help text below the file. This will by default show the max upload size in a nice message -
help_text_argument
: You can use it to change the argument used in the help text below the file. This will by default contain max upload size in a human readable format -
accept
: You can use this to set the accept attribute on the input field and limit the files that can be selected.