Prestashop 1.7 : Ajouter un champ produit de type file dans l’administration

Cet article est assez ancien, malgré toute l'attention que j' apporte à mes contenus il est possible que celui-ci ne soit plus d'actualité.
N'hésitez pas à me le signaler si nécessaire via le formulaire de contact.

Suite à mon (ancien ) article (https://www.h-hennes.fr/blog/2017/10/19/prestashop-1-7-ajouter-des-champs-produit/ ) sur l’ajout de champs custom dans le formulaire d’administration d’un produit, j’ai eut pas mal de questions sur comment ajouter un champ de type file.

Il faut reconnaître que la fonctionnalité n’est pas évidente car le formulaire est soumis en ajax et le gère pas l’upload de fichiers.

Le simple fait d’ajouter un champ de type file dans le formulaire n’est donc pas suffisant pour que cela fonctionne.

Cet article présente une approche qui fonctionne, mais je ne peux pas garantir que c’est la meilleure approche.

Pour son fonctionnement je me suis inspiré de la gestion de l’upload qui est faite pour la gestion des images standard du produit via la librairie Js Dropzone

Pour le code j’ai donc repris le code de l’ancien article en y ajoutant la logique d’un champ image.

Voici visuellement comment se présente le champ d’upload

L’ensemble de la logique d’upload et de sauvegarde de la valeur du produit va être gérée directement dans le module

Voici le rendu dans le cas ou une image existe déjà.
Il est possible de la supprimer en cliquant sur le lien correspondant

Voici le code pour l’affichage et la gestion du champ dans le fichier tpl
Les commentaires devrait vous éclairer sur le fonctionnement, je l’ai pensé de manière à pouvoir ajouter facilement plusieurs champs

{* Affichage du champ Image *}
            <div class="col-lg-12 col-xl-12">
                <label class="form-control-label">{l s='my custom field file' mod='hhproduct'}</label>

                <div id="custom_field_file_thumbnail">
                {* Si une image existe déjà sur le produit *}
                    {if isset($custom_field_file) && $custom_field_file !=""}
                        <div style="border: 1px dashed #000; padding:10px; max-width: 500px; margin-bottom: 30px; margin-top: 30px" >
                            <label class="form-control-label">{l s='my current image' mod='hhproduct'}</label><br />
                        <img src="{$file_dir}{$custom_field_file}" style="max-width: 450px" /><br />
                        <a href="#" class="custom_field_file_delete">{l s='Delete this image' mod='hhproduct'}</a>
                        </div>
                {/if}
                </div>
                <input type="file" class="dropzone" name="custom_field_file_uploader" id="custom_field_file_uploader" />
            </div>
                <script>
                    $(function() {
                        //Gestion de l'upload via la librairie DropZone
                        Dropzone.autoDiscover = false;
                        var customFieldImageDropzone = $('#custom_field_file_uploader').dropzone({
                            url: '{$moduleLink}&id_product={$id_product}&uploadProductImage=1&field_name=custom_field_file',
                            paramName: "file", //Nom du champs à envoyer
                            previewTemplate : document.querySelector('#custom_field_file_dropzone_template').innerHTML,
                            thumbnailWidth : 450,
                            success : function(file){
                                alert('{l s='File uploaded with success' mod='hhproduct'}');
                                //Affichage de la nouvelle image dans l'emplacement
                                $('#custom_field_file_thumbnail').html('').html(file.previewElement);
                            }
                        });

                        //Gestion de la suppression
                        $('#custom_field_file_thumbnail').on('click','.custom_field_file_delete',function(){
                            $.ajax({
                               method: 'post',
                               url : '{$moduleLink}&id_product={$id_product}&deleteProductImage=1&field_name=custom_field_file',
                               success : function(msg){
                                   console.log(msg);
                                   alert('{l s='File delete with success' mod='hhproduct'}');
                                   $('#custom_field_file_thumbnail').html('');
                               }
                            });
                            return false;
                        });
                    });
                </script>

            {* template d'affichage dropzone *}
            <div id="custom_field_file_dropzone_template" style="display:none">
                <div style="border: 1px dashed #000; padding:10px; max-width: 500px; margin-bottom: 30px; margin-top: 30px">
                    <div class="dz-details">
                        <label class="form-control-label">{l s='my new image' mod='hhproduct'}</label><br />
                        <img data-dz-thumbnail style="max-width: 450px" /><br />
                        <a href="#" class="custom_field_file_delete">{l s='Delete this image' mod='hhproduct'}</a>
                    </div>
                </div>
            </div>

Et voici le code php de gestion de cet upload
De mon côté l’objet product a été surchargé pour ajouter ce champ mais libre à vous de faire un traitement différent

/**
     * Configuration admin du module
     * @return string
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    public function getContent()
    {
        //Gestion de l'envoi des fichiers
        if (Tools::getValue('uploadProductImage')) {
            $id_product = (int)Tools::getValue('id_product');
            $field_name = Tools::getValue('field_name');
            if ($this->_updateProductImageField($id_product, $field_name)) {
                return $this->l('Image uploaded with success');
            }
        } elseif (Tools::getValue('deleteProductImage')) {
            $id_product = (int)Tools::getValue('id_product');
            $field_name = Tools::getValue('field_name');
            if ($this->_deleteProductImageField($id_product, $field_name)) {
                return $this->l('Image deleted with success');
            }
        } else {
            return 'No configuration needed for this module';
        }
 
    }
 
    /**
     * Upload de l'image d'un produit
     * @param $id_product
     * @param $field_name
     * @return bool
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    protected function _updateProductImageField($id_product, $field_name)
    {
        //Envoi de l'image
        //@TOdo gérer le cas ou l'image existe déjà
        $savePath = dirname(__FILE__) . '/views/img/p';
        $uploader = new Uploader('file');
        $file = $uploader->setSavePath($savePath)
            ->setAcceptTypes(['jpg', 'png', 'git', 'jpeg'])
            ->process();
 
        $fileName = ltrim(str_replace($savePath, '', $file[0]['save_path']), '/');
        try {
            //Sauvegarde la valeur de l'image pour le produit
            $product = new Product($id_product);
            $product->$field_name = $fileName;
            $product->save();
        } catch (PrestaShopException $e) {
            echo $e->getMessage();
            return false;
        }
 
        return true;
    }
 
 
    /**
     * Suppression de l'image d'un produit
     * @param $id_product
     * @param $field_name
     * @return bool
     */
    protected function _deleteProductImageField($id_product, $field_name)
    {
        try {
            //Sauvegarde d'une valeur vide pour le produit
            $product = new Product($id_product);
 
 
            //Si le produit a une image et qu'elle existe on la supprime
            if ($product->$field_name != "") {
                $imagePath = dirname(__FILE__) . '/views/img/p/' . $product->$field_name;
                if (is_file($imagePath)) {
                    unlink($imagePath);
                }
            }
            $product->$field_name = '';
            $product->save();
        } catch (PrestaShopException $e) {
            echo $e->getMessage();
            return false;
        }
    }

Vous pouvez télécharger ci-dessous une version du module qui implémente ce champ (je l’ai testé uniquement sur Ps 1.7.6 )

 

3 réflexions sur “Prestashop 1.7 : Ajouter un champ produit de type file dans l’administration”

  1. Bonjour, j’ai réussi à installer votre module sur mon Presta (1.7.6.2) mais je ne vois les champs nul part côté BO produit.

    Les champs SQL eux sont bien créés sans soucis. Est ce qu’une étape en plus est nécessaire ?

    Merci d’avance

  2. Bonjour,

    J’essaye d’adapter votre module pour la partie Déclinaison d’un produit. Mais le JS ne s’execute plus .
    j’ai une petite zone d’ombre dans ce code à quoi correspond l’url si je veux executer le dropzone dans une déclinaison ?
    « url: ‘{$moduleLink}&id_product={$id_product}&uploadProductImage=1&field_name=custom_field_file’, » quel serait l’url pour une déclinaison ?

    Jai effectué le changement de Hook « displayAdminProductsMainStepLeftColumnMiddle » -> « displayAdminProductsCombinationBottom »
    $product = new Product($id_product) -> $combination = new Combination($id);

    Dans l’attente d’un retour, merci d’avance

  3. bonjour,jai un petit soucis au niveau du back office ou je veux ajouter une liste deroulante dans le formulaire d’addresse dans le processus de commande qui contient des valeurs de mon choiwx mais je n’arrive pas

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *