W tym rozdziale pokażę w jaki sposób uploadować w Symfony wiele plików na serwer. Możesz to rozwiązanie wykorzystać do tworzenia galerii zdjęć itp.
Najpierw utworzymy katalog, do którego będą wrzucane pliki: /public/uploads oraz nadajemy mu prawa dostępu na 777.
Teraz możemy zdefiniować ten katalog, tak aby był widoczny w projekcie. W tym celu edytuj plik services.yaml (/config/services.yaml) dodając w nim parametr file_directory:
1 2 |
parameters: file_directory: '%kernel.project_dir%/public/uploads' |
W kolejnym kroku dodaj encję Upload (src/Entity/Upload.php) i zdefiniuj w niej pole file:
1 2 3 4 5 6 7 8 9 10 |
<?php // src/Entity/Upload.php namespace App\Entity; class Upload { private $file; } |
Będzie nam jeszcze potrzebny budowniczy formularza: UploadType (src/Form/UploadType.php):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<?php // src/Form/UploadType.php namespace App\Form; use App\Entity\Upload; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Form\Extension\Core\Type\FileType; use Symfony\Component\Validator\Constraints\File; class UploadType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('file', FileType::class, [ 'label' => 'Files', 'multiple' => true, 'mapped' => false, 'required' => true ]) ; } public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ 'data_class' => Upload::class, ]); } } |
W naszym przykładzie dodajemy (add) do formularza tylko jedno pole typu file (’file’,FileType::class). Dołączamy też odpowiednie klasy komponentów:
1 2 |
use Symfony\Component\Form\Extension\Core\Type\FileType; use Symfony\Component\Validator\Constraints\File; |
Aby można było wybrać wiele plików musimy ustawić w formularzu parametr multiple=”multiple”. W builderze jest to zapis: ’multiple’ => true. Parametr required oznacza, że pole z wyborem pliku/ów jest wymagane. Poniżej kod html formularza żeby to widzieć:
1 2 3 4 |
<form name="upload" method="post" enctype="multipart/form-data"> <input type="file" id="upload_file" name="upload[file][]" required="required" multiple="multiple"> <button>Submit</button> </form> |
Czas na kontroler, który ogarnie to wszystko, co dotychczas zrobiliśmy 🙂 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<?php // src/Controller/UploadController.php namespace App\Controller; use App\Entity\Upload; use App\Form\UploadType; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; class UploadController extends AbstractController { /** * @Route("/upload", name="upload_file", methods={"GET","POST"}) */ public function upload(Request $request): Response { $form = $this->createForm(UploadType::class, new Upload()); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $files = $form['file']->getData(); if ($files) { foreach ($files as $file) { $file->move( $this->getParameter('file_directory'), $file->getClientOriginalName() ); } } return $this->redirectToRoute('upload_file'); } return $this->render('upload.html.twig', [ 'form' => $form->createView(), ]); } } |
Na samym początku dołączamy klasy, które pisaliśmy: Upload i UploadType:
1 2 |
use App\Entity\Upload; use App\Form\UploadType; |
Ustawiamy uchwyt – $form do utworzonego formularza za pomocą metody createForm(). Zapis $form->handleRequest($request) odbiera żądania HTTP z naszego formularza:
1 2 |
$form = $this->createForm(UploadType::class, new Upload()); $form->handleRequest($request); |
Pobieramy listę plików do zmiennej $files:
1 |
$files = $form['file']->getData(); |
i w pętli foreach, za pomocą metody move przenosimy pliki do katalogu wskazanego w parametrze file_directory (z pliku: services.yaml). Metoda getClientOriginalName() ustawia właściwą nazwę pliku np: file.pdf.
Na koniec musimy jeszcze zbudować szablon formularza, zgodnie z tym co napisaliśmy w kontrolerze:
1 |
return $this->render('upload.html.twig', ['form' => $form->createView(),]); |
W tym celu zapisz plik upload.html.twig w lokalizacji: templates/upload.html.twig
1 2 3 4 5 6 7 8 |
{% extends 'base.html.twig' %} {% block body %} <h1>Upload Form</h1> {{ form_start(form) }} {{ form_widget(form) }} <button class="btn">{{ button_label|default('Submit') }}</button> {{ form_end(form) }} {% endblock %} |
Odpal stronę w przeglądarce i testuj: http://localhost/public/index.php/upload
PRZYKŁAD na GitHub →