Jump to content

Créer un module d'autocomplétion à l'étape 2 "Adresse" de la page commande grace à l'API Google Maps ou l'API Adresse


Recommended Posts

Bonjour, voilà depuis quelques jours je suis sur un projet de développement de mon premier module PrestaShop, qui consiste à utiliser l'API Adresse du gouvernement, afin de récupérer les données : adresse, code postal, ville et pays lorsque l'utilisateur commence à taper son adresse dans le champ "adresse" 

L'objectif est d'autoremplir les champs ou j'ai mis un trait rouge.

image.thumb.png.03696689b64fe4351fb782111db5b949.png

 

Pour la partie technique, j'ai suivi un tuto pour la base de création de mon module, donc j'ai crée un dossier dans modules, et toute la structure conventionnel au bon fonctionnement (cf ci dessous )

 

image.thumb.png.c1ce025e15de56c0ecf0f3d72dc12de3.png

 

Le soucis est que j'ai développer toute la partie du module, mais je suis au stade de le connecter au front du site web pour le rendre fonctionnel (donc j'ai cru lire qu'il faut ciblé un Hook?)

 

Pour plus de compréhension je vous partage mon développement du module :

Voici le fichier principal du module en PHP :

<?php
if (!defined('_PS_VERSION_')) {
    exit;
}
class AdressAutocomplete extends Module
{
    public function __construct()
    {
        $this->name = 'adressautocomplete';
        $this->tab = 'front_office_features';
        $this->version = '1.0.0';
        $this->author = 'Dylan Brisson';
        $this->need_instance = 0;
        $this->ps_versions_compliancy = [
            'min' => '1.7',
            'max' => _PS_VERSION_
        ];
        $this->bootstrap = true;

        parent::__construct();

        $this->displayName = $this->l('Address Autocomplete');
        $this->description = $this->l('Module qui permet de compléter automatiquement les adresses afin de faciliter les clients');

        $this->confirmUninstall = $this->l('Êtes-vous sûr de vouloir désinstaller ce module ?');

        if (!Configuration::get('ADRESSAUTOCOMPLETE_PAGENAME')) {
            $this->warning = $this->l('Aucun nom fourni');
        }

       // $this->context->controller->addJS('https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places');

    }
    public function install()
{
    if (Shop::isFeatureActive()) {
        Shop::setContext(Shop::CONTEXT_ALL);
    }
 
    if (!parent::install() ||
        !$this->registerHook('leftColumn') ||
        !$this->registerHook('header') ||
        !Configuration::updateValue('ADRESSAUTOCOMPLETE_PAGENAME', 'Mentions légales')
    ) {
        return false;
    }
 
    return true;
}

public function uninstall()
{
    if (!parent::uninstall() ||
        !Configuration::deleteByName('ADRESSAUTOCOMPLETE_PAGENAME')
    ) {
        return false;
    }
 
    return true;
}
public function hookDisplayHeader()
{
    $this->context->controller->addJS($this->_path.'js/adressautocomplete.js');
}

public function autocompleteAddress($query)
    {
        $url = 'https://api-adresse.data.gouv.fr/search/?q=' . urlencode($query);

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($ch);
        curl_close($ch);
    
        $data = json_decode($response, true);
    
        $suggestions = array();
        foreach ($data['features'] as $feature) {
            $suggestions[] = array(
                'address' => $feature['properties']['name'],
                'postcode' => $feature['properties']['postcode'],
                'city' => $feature['properties']['city'],
                'country' => 'France' // L'API Adresse est spécifique à la France
            );
        }
    
        return $suggestions;
        }
    }

 

Pour le JavaScript le code suivant (j'ai laissé mes test de console log mais il ne s'affiche pas sur ma boutique car pour le moment le module ne cible aucune page ? il cherche bien input field-adress1 de la page commande mais c'est tout) :

$(document).ready(function() {
    // Vérifiez si l'URL de la page contient 'commande?controller=order'
    if (window.location.href.indexOf('commande?controller=order') > -1) {
        console.log('Le script est chargé et exécuté.');
        $('#field-address1').on('input', function() {
            var query = $(this).val();

            var url = prestashop.urls.base_url + 'index.php?fc=module&module=adressautocomplete&controller=autocomplete';
            console.log('URL AJAX : ' + url);

            $.ajax({
                url: url,
                data: {
                    query: query
                },
                success: function(data) {
                    var suggestions = data;

                    // Clear the old suggestions.
                    $('#address-suggestions').empty();

                    // Add the new suggestions.
                    for (var i = 0; i < suggestions.length; i++) {
                        var suggestion = suggestions[i];

                        // Fill the corresponding fields.
                        $('#field-address1').val(suggestion.address);
                        $('#field-postcode').val(suggestion.postcode);
                        $('#field-city').val(suggestion.city);
                    }
                }
            });
        });
    }
});

 

Puis le controller front en PHP :

 

<?php
class AdressautocompleteAutocompleteModuleFrontController extends ModuleFrontController
{
    public function initContent()
    {
        parent::initContent();

        $query = Tools::getValue('query');
        $module = Module::getInstanceByName('adressautocomplete');
        $suggestions = $module->autocompleteAddress($query);

        header('Content-Type: application/json');
        echo json_encode($suggestions);
    }
}

 

Il faut savoir que c'est une fonctionnalité test sur une boutique test et que je n'ai toucher donc qu'à ces fichier présent sur le premier screen, à savoir crée le dossier de mon module et développer le module.
La problématique pour moi maintenant, et je n'ai pas trouver de tuto Prestashop pour connecter le back au front de son module prestashop, je ne peut le tester car je n'arrive pas à le connecter au front de ma boutique test.

 

Merci de vos retours et aide ! 😁

Bonne journée à tous et à toutes.

Link to comment
Share on other sites

Bonjour,

En effet pour utiliser votre module il vous faut le configurer pour qu'il se greffe sur un hook qui existe déjà sur la page (par exemple le hook displayCustomerLoginFormAfter) ou alors créer un hook dans le module, et l'afficher dans votre template, par exemple avec un code  comme {hook h='myCustomHook'}

Depuis votre fichier module il faut le greffer au hook que vous voulez utiliser comme vous avez déjà enregistré les autres hooks :

!$this->registerHook('myCustomHook') ||
 

Ensuite dans votre module, il vous faut définir qu'est-ce qu'il doit se passer lorsque vous appelez ce hook, avec une fonction du genre :

public function hookMyCustomHook($params) {

//Vous pouvez appeler un template ou jouer une fonction php

}


Si vous ne vous en sortez pas, il sera sans doute nécessaire de reprendre le module dans son intégralité pour bien comprendre ce que vous voulez faire (à priori c'est surtout basé sur du js et une requête ajax), et de structurer le code correctement. Vous pouvez me contacter en privé, si vous souhaitez que je m'en occupe.

Bonne journée.

David.

 

  • Like 1
Link to comment
Share on other sites

Sinon, si des modules existants peuvent faire l'affaire, alors je vous conseille de les utiliser, cela vous fera gagner pas mal de temps. Par exemple :

https://addons.prestashop.com/fr/inscription-processus-de-commande/24894-suggestion-d-adresse-par-google.html

ou

https://addons.prestashop.com/fr/processus-rapide-commande/93565-auto-completion-adresse-google-places.html

 

 

 

  • Like 1
Link to comment
Share on other sites

1 hour ago, DavidCKW said:

Bonjour,

En effet pour utiliser votre module il vous faut le configurer pour qu'il se greffe sur un hook qui existe déjà sur la page (par exemple le hook displayCustomerLoginFormAfter) ou alors créer un hook dans le module, et l'afficher dans votre template, par exemple avec un code  comme {hook h='myCustomHook'}

Depuis votre fichier module il faut le greffer au hook que vous voulez utiliser comme vous avez déjà enregistré les autres hooks :

!$this->registerHook('myCustomHook') ||
 

Ensuite dans votre module, il vous faut définir qu'est-ce qu'il doit se passer lorsque vous appelez ce hook, avec une fonction du genre :

public function hookMyCustomHook($params) {

//Vous pouvez appeler un template ou jouer une fonction php

}


Si vous ne vous en sortez pas, il sera sans doute nécessaire de reprendre le module dans son intégralité pour bien comprendre ce que vous voulez faire (à priori c'est surtout basé sur du js et une requête ajax), et de structurer le code correctement. Vous pouvez me contacter en privé, si vous souhaitez que je m'en occupe.

Bonne journée.

David.

 

Re David, merci de ta réponse déjà, j'ai suivi ta suggestion et j'ai donc crée un hook displayAddressAutoComplete que j'ai enregistrer et j'ai défini le hook pour appeler le javascript qui effectue la requête AJAX, voici les modifications que j'ai effectuée, je sais pas si je suis sur la bonne voie mais je penses déjà avoir compris le problème du pourquoi je n'arrive pas à utiliser le module, ni même de voir le script de mon module dans l'inspecteur sur ma page commande.. Voici ce que j'ai fais :

 

<?php
if (!defined('_PS_VERSION_')) {
    exit;
}
class AdressAutoComplete extends Module
{
    public function __construct()
    {
        $this->name = 'adressautocomplete';
        $this->version = '1.0.0';
        $this->author = 'Dylan Brisson';
        $this->need_instance = 0;
        $this->ps_versions_compliancy = [
            'min' => '1.7',
            'max' => _PS_VERSION_
        ];
        $this->bootstrap = true;

        parent::__construct();

        $this->displayName = $this->l('Address Autocomplete');
        $this->description = $this->l('Module qui permet de compléter automatiquement les adresses afin de faciliter les clients');

        $this->confirmUninstall = $this->l('Êtes-vous sûr de vouloir désinstaller ce module ?');

    }
    public function install()
{
    if (Shop::isFeatureActive()) {
        Shop::setContext(Shop::CONTEXT_ALL);
    }

    if (!parent::install() ||
        !$this->registerHook('leftColumn') ||
        !$this->registerHook('header') ||
        !$this->registerHook('displayAddressAutoComplete') || // Enregistrement du nouveau hook
        !Configuration::updateValue('ADRESSAUTOCOMPLETE_PAGENAME', 'Mentions légales')
    ) {
        return false;
    }

    return true;
}

public function hookDisplayAddressAutoComplete($params)
{
    $this->context->controller->registerJavascript('modules', 'adressautocomplete/js/adressautocomplete.js', ['position' => 'bottom', 'priority' => 200]);
}

public function autocompleteAddress($query)
    {
        $url = 'https://api-adresse.data.gouv.fr/search/?q=' . urlencode($query);

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($ch);
        curl_close($ch);

        $data = json_decode($response, true);

        $suggestions = array();
        foreach ($data['features'] as $feature) {
            $suggestions[] = array(
                'address' => $feature['properties']['name'],
                'postcode' => $feature['properties']['postcode'],
                'city' => $feature['properties']['city'],
                'country' => 'France' // L'API Adresse est spécifique à la France
            );
        }

        return $suggestions;
        }
    }

Et du coup j'appelle le hook dans la page addresses.tpl avant la fin de la balise form comme ci dessous :

 

 {hook h='displayAddressAutoComplete'} <!-- Nouveau hook -->
    </form>
  </div>
{/block}

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...