je continue ma formation sur Symfony 4, et je rencontre un soucis avec l'envoi de fichier. Voici les détails :
J'ai 2 entités, album et musique. Les deux sont liés, 1 album pouvant avoir plusieurs musiques. J'aimerais que mon administrateur puisse modifier les données en base ainsi que la pochette de l'album ou l'extrait et qu'il n'ait qu'une seule page pour modifier le tout. J'arrive bien à afficher un formulaire avec mes données "album" et mes données "musique", j'arrive bien à permettre la modification de la pochette, mais ça coince sur l'extrait (le nom de ma table en base est 'url'), ou j'ai cette erreur :
Argument 1 passed to App\Service\FileUploaderMP3::upload() must be an instance of Symfony\Component\HttpFoundation\File\UploadedFile, instance of Doctrine\ORM\PersistentCollection given, called in /Library/WebServer/Documents/projets/musiconaute/src/Controller/AlbumController.php on line 65
Voici mon AlbumController pour la partie qui nous intéresse :
public function edit(Request $request, Album $album, FileUploaderAlbum $fileUploader, FileUploaderMP3 $fileUploaderMp3)
{
$form = $this->createForm(AlbumsType::class, $album);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$albumsFile = $form['couverture']->getData();
if ($albumsFile) {
$albumFileName = $fileUploader->upload($albumsFile);
$album->setCouverture($albumFileName);
}
$musiquesFile = $form['musiques']->getData();
if ($musiquesFile) {
$musiqueFileName = $fileUploaderMp3->upload($musiquesFile);
$musique->setURL($musiqueFileName);
}
// va effectuer la requête d'UPDATE en base de données
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('index');
}
return $this->render('admin/album/new.html.twig', array(
'form' => $form->createView(),
));
return new RedirectResponse($this->urlGenerator->generate('index'));
}
La ligne 65 correspond à la ligne $musiqueFileName = $fileUploaderMp3->upload($musiquesFile);
Voici mon albumType :
<?php
namespace App\Form;
use App\Entity\Album;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Validator\Constraints\File;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
class AlbumsType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('titre')
->add('couverture', FileType::class, [
'label' => 'Couverture de l\'album (en jpg ou en png)',
// unmapped means that this field is not associated to any entity property
'mapped' => false,
// make it optional so you don't have to re-upload the PDF file
// everytime you edit the Product details
'required' => false,
// unmapped fields can't define their validation using annotations
// in the associated entity, so you can use the PHP constraint classes
'constraints' => [
new File([
'maxSize' => '1024k',
'mimeTypes' => [
'image/*',
'application/jpg',
'application/jpeg',
'application/png',
'application/x-png',
],
'notFoundMessage' => 'L\'image n\'a pas été trouvé',
'maxSizeMessage' => 'L\'image est trop grosse ({{ size }} {{ suffix }}). La taille maximum est de {{ limit }} {{ suffix }}.',
'disallowEmptyMessage' => 'Il n\'est pas possible d\'envoyer un fichier vide',
'uploadNoFileErrorMessage' => 'L\'image n\'a pas été envoyée',
])
],
]);
$builder->add('musiques', CollectionType::class, [
'entry_type' => MusiquesType::class,
'entry_options' => ['label' => false],
'allow_add' => true,
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Album::class,
]);
}
}
Je crois comprendre que l'argument que je lui passe n'est pas bon puisqu'il est de type "PersistentCollection", mais je ne comprends pas trop et je ne vois pas comment corriger cela.
Est ce que quelqu'un pourrait m'aider s'il vous plait ?
Et du coup je pense que mon problème vient du fait que j'essaye de mettre à jour 'url', qui est dans la base musique, mais que je lui envoi un champ collection, du coup, il ne peut pas faire ce que je lui demande. Le truc c'est que je vois pas comment lui passer directement 'url' et non pas 'musiques' qui est une collection :/
Désolée pour la réponse un peu tardive, un autre truc à gérer^^
Dans mon MusiquesType j'ai ceci :
<?php
namespace App\Form;
use [...]
class MusiquesType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('titre')
->add('annee')
->add('auteur')
->add('body', TextareaType::class, array('attr' => array('class' => 'ckeditor'), 'required' => false,))
->add('url', FileType::class, [
'label' => 'Musique de l\'album (en mp3)',
// unmapped means that this field is not associated to any entity property
'mapped' => false,
// make it optional so you don't have to re-upload the PDF file
// everytime you edit the Product details
'required' => false,
// unmapped fields can't define their validation using annotations
// in the associated entity, so you can use the PHP constraint classes
'constraints' => [
new File([
'maxSize' => '6024k',
'mimeTypes' => [
'audio/mpeg',
],
'notFoundMessage' => 'Le mp3 n\'a pas été trouvé',
'maxSizeMessage' => 'Le mp3 est trop gros ({{ size }} {{ suffix }}). La taille maximum est de {{ limit }} {{ suffix }}.',
'disallowEmptyMessage' => 'Il n\'est pas possible d\'envoyer un fichier vide',
'uploadNoFileErrorMessage' => 'Le mp3 n\'a pas été envoyé',
])
],
])
->add('blindtest', ChoiceType::class, [
'choices' => [
'Oui' => 1,
'Non' => 0,
],
])
->add('actif', ChoiceType::class, [
'choices' => [
'Oui' => 1,
'Non' => 0,
],
])
->add('visite')
->add('support', ChoiceType::class, [
'choices' => [
'Oui' => 1,
'Non' => 0,
],
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Musique::class,
]);
}
}
Je pense en effet que mon soucis vient de l'utilisation d'une collection, que je ne maitrise pas
<?php
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Intl\Intl;
class FileUploaderAlbum
{
private $targetDirectory;
public function __construct($targetDirectory)
{
$this->targetDirectory = $targetDirectory;
}
public function upload(UploadedFile $file)
{
$originalFilename = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
$fileName = $originalFilename.'-'.uniqid().'.'.$file->guessExtension();
try {
$file->move($this->getTargetDirectory(), $fileName);
} catch (FileException $e) {
// ... handle exception if something happens during file upload
}
return $fileName;
}
public function getTargetDirectory()
{
return $this->targetDirectory;
}
}
L'ajout de musique seul fonctionne, l'entrée se fait bien en base et le fichier est bien uploadé là ou il faut avec un changement de nom pour rajouter un id unique à la fin. L'ajout d'une musique se fait sur une page à part qui n'ajoute que la musique, pas l'album.
C'est vraiment à la modification, ou je veux qu'on puisse modifier album et musique sur la même page que ça coince.
Alors je confirme, c'est parce que tu gères une collection d'objets Musique comme si c'était un seul fichier uploadé, et ce n'est pas le cas
FileUploaderAlbum::upload attend en paramètre un objet UploadedFile, mais tu lui passes le contenu du champ musiques de AlbumsType, qui est défini comme une collection d'objets Musique.
Il faut que tu boucles sur $musiquesFile pour vérifier s'il y a un fichier uploadé dans le champ url, et si oui c'est ce que contient ce champ qu'il faudrait uploader.
Edit
Ça y est, maintenant je ne reçois plus les notifications quand un sujet a des mises à jour…
Pourrais-je solliciter une petite aide supplémentaire s'il te plait ? J'ai bien compris que je devais boucler pour vérifier si le champ 'url' est vide ou non, mais je ne vois pas comment le vérifier. A chaque fois que je cherche à récupérer les infos du champ, j'ai une erreur comme quoi 'url' n'est pas connu, ou que l'enfant n'existe pas (Child "url" does not exist.). Du coup je ne vois pas comment faire ma boucle.
Si tu peux m'éclairer s'il te plait, ou quelqu'un d'autre passant par là.
Après de nombreux tests et un coup de main en interne, c'est désormais ok.
Merci pour les conseils
[Symfony 4] Upload de fichier
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Keep It Simple Stupid - SF4 conf Swift - Cours 1/4 SF4 - Exceptions PDO - Formes Normales
Keep It Simple Stupid - SF4 conf Swift - Cours 1/4 SF4 - Exceptions PDO - Formes Normales