O que é o VichUploaderBundle?
O VichUploaderBundle é uma extensão do Symfony que permite fácil integração com bibliotecas carregadoras de arquivos como o Flysystem, o Gaufrette e o GCP/FileStorage. Ele simplifica muito a validação, o armazenamento e a recuperação de arquivos em aplicativos do Symfony. Ele também fornece alguns recursos adicionais avançados, como eventos de ciclo de upload, manipuladores de imagem e suporte ao carregamento de arquivos assíncronos.
Como instalar o VichUploaderBundle?
Para instalar o VichUploaderBundle, você pode executar o comando Composer no terminal para adicionar a dependência ao seu aplicativo do Symfony. Certifique-se de que você tenha permissões suficientes para instalar as dependências e tenha a versão correta do Symfony instalada.
composer require vich/uploader-bundle
Depois de instalar o pacote, você precisará adicioná-lo ao arquivo de configuração do Symfony no diretório /config/bundles.php. Adicione a linha a seguir:
VichUploaderBundleVichUploaderBundle::class => ['all' => true],
Como configurar o VichUploaderBundle?
Para configurar o VichUploaderBundle dentro do Symfony, a primeira coisa que você precisa fazer é adicionar as configurações necessárias ao arquivo /config/packages/vich_uploader.yaml. Este arquivo deve conter as configurações de configuração do pacote. A configuração básica é mostrar em forma de array como o diretório onde os arquivos serão armazenados.
vich_uploader:
db_driver: orm
mappings:
product_image:
uri_prefix: /images/products
upload_destination: '%kernel.project_dir%/public/images/products'
O array acima definirá a raiz de seus uploads de imagens e a rota URI que será usada para acessar esses arquivos. Além disso, você precisará configurar uma entidade para habilitar o upload de arquivos.
Como configurar uma entidade para permitir o upload de arquivos?
Para habilitar o upload de arquivos em uma entidade, você precisa adicionar uma anotação @VichUploadableField à propriedade da entidade que representará o arquivo. O VichUploaderBundle detectará essa anotação e tratará a propriedade automaticamente como um campo de upload.
/**
* @VichUploadableField(mapping="product_image", fileNameProperty="imageName")
* @var File|null
*/
private $imageFile;
/**
* @ORMColumn(type="string", length=255)
* @var string|null
*/
private $imageName;
Observe que a anotação na propriedade $imageFile deve ter o atributo mapping definido para o nome do seu mapeamento VichUploaderBundle e uma propriedade fileNameProperty definida para o nome do campo de string que salvará o nome do arquivo carregado.
Como criar um formulário que permita o upload de arquivos para uma entidade?
Para criar um formulário que permita o upload de arquivos para uma entidade no Symfony, você precisa criar uma classe de formulário que estenda a classe Symfony FormBuilderInterface e defina os campos de formulário apropriados. Neste caso, você precisará definir um campo do tipo FileType para permitir o upload de arquivos.
class ProductType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class)
->add('description', TextareaType::class)
->add('imageFile', FileType::class)
;
}
// ...
}
Observe que o campo de formulário deve ter o mesmo nome da propriedade com a anotação @VichUploadableField que representa o campo de upload de arquivos na entidade.
Como validar arquivos carregados com VichUploaderBundle?
O VichUploaderBundle adiciona algumas restrições adicionais aos arquivos carregados para garantir que eles sejam válidos. Essas restrições incluem o tamanho máximo do arquivo, o tipo de mídia permitido e a resolução mínima para imagens. Para validar esses arquivos, é necessário adicionar a anotação correta ao seu campo de upload de arquivos.
/**
* @VichUploadableField(mapping="product_image", fileNameProperty="imageName")
* @AssertNotNull
* @AssertFile(
* maxSize = "10M",
* mimeTypes = {"image/png", "image/jpeg", "image/gif", "image/svg+xml"},
* mimeTypesMessage = "Please upload a valid png, jpeg, gif, or svg file"
* )
* @var File|null
*/
private $imageFile;
Observe que a anotação @AssertFile contém as restrições adicionais mencionadas acima.
Como manipular imagens carregadas com VichUploaderBundle?
Com o VichUploaderBundle, você pode manipular imagens carregadas antes de salvá-las. Para fazer isso, você precisará adicionar uma anotação @VichImage à sua propriedade representando a imagem. Em seguida, você pode adicionar manipuladores de imagem para manipular a imagem carregada antes de salvá-la.
/**
* @VichUploadableField(mapping="product_image", fileNameProperty="imageName")
* @VichImage(
* versions={
* "thumbnail"={
* "resize"="200x200",
* "jpeg_quality"=90,
* },
* "medium"={
* "resize"="400x400",
* "jpeg_quality"=90,
* },
* }
* )
* @var File|null
*/
private $imageFile;
Observe que a anotação @VichImage contém uma chave versions, que contém uma matriz de manipuladores de imagem. Cada manipulador é definido como uma chave e o manipulador em si é definido como uma matriz de opções.
Como recuperar um URL para um arquivo carregado com VichUploaderBundle?
Com o VichUploaderBundle, recuperar um URL para um arquivo carregado em um aplicativo Symfony é muito simples. Tudo o que você precisa fazer é chamar o método getAssetUrl() na entidade que contém o arquivo carregado.
/**
* @Route("/product/{id}", name="product_show")
*/
public function show(Product $product): Response
{
$imageUrl = $this->vichUploaderHelper->asset($product, 'imageFile');
// ...
}
Observe que o primeiro argumento do método getAssetUrl() é a entidade contendo a propriedade representando o arquivo carregado. O segundo argumento é o nome do campo de upload de arquivos dentro da entidade.
Como lidar com upload de arquivos em um formulário assíncrono?
O VichUploaderBundle permite o upload de arquivos em formulários assíncronos. Para usar esta funcionalidade, você precisará primeiro incluir as bibliotecas JavaScript necessárias para processar o upload de arquivos. Em seguida, adicione uma chamada Ajax para enviar o formulário ao servidor, incluindo o arquivo carregado.
$(document).on('change', '.btn-file :file', function() {
var input = $(this),
numFiles = input.get(0).files ? input.get(0).files.length : 1,
label = input.val().replace(/\/g, '/').replace(/.*//, '');
input.trigger('fileselect', [numFiles, label]);
});
$(document).ready( function() {
$('.btn-file :file').on('fileselect', function(event, numFiles, label) {
var input = $(this).parents('.input-group').find(':text'),
log = numFiles > 1 ? numFiles + ' files selected' : label;
if( input.length ) {
input.val(log);
} else {
if( log ) alert(log);
}
});
});
Para enviar o arquivo para um controlador Symfony, você precisará criar uma nova rota que chame o método de criação de formulários adequado e adicione a anotação correta no controlador para permitir formulários POST.
Como trabalhar com eventos de ciclo de vida do upload?
O VichUploaderBundle permite que os desenvolvedores trabalhem com vários eventos de ciclo de vida, que são disparados em vários estágios durante o upload de arquivos. Esses eventos incluem pré-carregamento, pós-carregamento, pré-atualização e pós-atualização. Para trabalhar com esses eventos, você precisa adicionar um ou mais ouvintes de eventos à sua entidade ou aplicativo.
namespace AppEventListener;
use VichUploaderBundleEventEvent;
use VichUploaderBundleEventEventSubscriberInterface;
class ImageUploadSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
Event::PRE_UPLOAD => 'onPreUpload',
Event::POST_UPLOAD => 'onPostUpload',
];
}
public function onPreUpload(Event $event)
{
// ...
}
public function onPostUpload(Event $event)
{
// ...
}
}
Observe que a classe ouvinte precisa implementar a interface EventSubscriberInterface e definir um método getSubscribedEvents() que retorna uma matriz de eventos e seus respectivos manipuladores associados.