ldc-groupe/FILEMANAGMENT.MD
2025-11-12 16:48:20 +01:00

4.2 KiB

Intégrer des images dans un formulaire Inertia

Côté model

Le model va devoir utiliser le trait HasUploadedFile Ce trait aura pour but de mettre par défaut des évenements de model permettant de gérer la suppression des fichiers lors d'un update (en utilisant les methode de FileHelper, donc un update qui ne touche pas au fichier n'aura évidemment pas d'effet) ou d'un delete. A ce jour le trait permet de gérer :

  • Les champs simples
  • Les champs de type translatable {"fr": "storage/***, "en": ...}
  • Les champs de type tableau : medias.0.image (version bêta donc pas sûr encore pour ça)

Pour que tout fonctionne il faut renseigner dans le model un tableau avec le nom des fields images

/**
* Champs contenant des images dynamiques à gérer.
*
* @var  array
*/
protected  array  $imageFields  =  ['picture'];

// ici les methodes de nettoyages se focaliseront uniquement sur le champs picture.

Le trait par défaut va pouvoir gérer les cas de softDelete, un model qui n'a pas ce trait aura une supression de tous ses fichiers sur un delete, bien entendu dans le cas d'un model ayant le trait SoftDeletes les suppressions se feront au forceDelete.

Request et enregistrement

La storeRequest d'un model ayant des images, devra importer le trait HasInertiaPicture et utiliser la méthode mergeInertiaPicture

/**
* Prepare the data for validation.
*
* @return  void
*/
protected  function  prepareForValidation():  void
{
	$this->mergeInertiaPicture('picture');
	// cette partie est à revoir car le paramètre picture ne sera sans doute plus utile
}

Cette méthode permet de merge le fichier de la request présent dans un tableau à part des attributes classiques...dans le tableau des attributes.

La request devra aussi, par simplicité utiliser la méthode de validation proposée par le trait

'picture'  =>  $this->pictureRules("nullable|file|mimes:jpg,jpeg,png|max:5120|dimensions:width=525,height=295"),

Cette méthode permet de valider soit un fichier, utilisant les validations qu'on lui passe en paramètre, soit une string (dans le cas d'un update; avec utilisation d'une regex pour vérifier que la string correspond à l'arborescence d'un fichier sur laravel) soit null si nullable est déclaré.

Dans le controller associé à la request, il faudra utiliser une nouvelle méthode (proposée par le trait de model)

$newModel->inertiaFill($request->validated());

Deux possibilité, soit il n'y a pas de traitement spécifique à appliquer au model avant de le fill auquel cas cette méthode est envoyée au trait qui s'occupe de store les fichiers nécessaires, supprimer au besoin, et de fill le tout. Soit, une relation est présente et le fill n'est pas possible en l'état, donc il faut un traitement. Ce traitement peut être effectuer dans le controller directement :

$attributes  =  Arr::except($request->validated(),  ['categories']);
$newModel->traitInertiaFill($attributes);

Soit pour éviter le DRY (entre update et create par exemple), la méthode peut être utilisée directement dans le model, et renommé exactement pareil pour que ça reste transparent côté controller, auquel cas il faut "renommer" la méthode du trait pour éviter qu'elle ne s'appelle elle même :

use  HasUploadedFile  {
	HasUploadedFile::inertiaFill  as traitInertiaFill;
}

public  function  inertiaFill(array  $attributes)
{
	$attributes  =  Arr::except($attributes,  ['categories']);
  $this->traitInertiaFill($attributes);
}

Côté front

Un point important, lors de l'utilisation de useForm d'Inertia, il faudra utiliser un post au moment du submit (car utiliser un put ou un patch; pour l'update du form, ne fonctionne pas...la présence d'un fichier vide la request)

const  submit  =  (e:  FormEvent<HTMLFormElement>)  =>  {
	e.preventDefault();
	const  routeUrl  =  route(`back.${modelRoute}.${action}`,  model?.id);
	if (method  !==  Methods.PATCH  &&  method  !==  Methods.POST) throw  new  Error("The method must be post or patch");
	post(routeUrl); // on utilise post ici
};

Mais dans le useForm on surcharge la méthode :

const  {  post,  setData,  data,  reset  }  =  useForm({
	_method:  method  ===  Methods.POST  ?  'post'  :  'put',
	picture:  model?.picture,
});